using Test using YiemAgent using YiemAgent.toolRegistry using YiemAgent.type TOOLS_DIR = joinpath(@__DIR__, "..", "src", "tools") @testset "loadTools" begin # ------------------------------------------------------------------ # # 1. loadTools throws on non-existent directory # # ------------------------------------------------------------------ # @test_throws ArgumentError loadTools("/nonexistent/dir/that/does/not/exist") # ------------------------------------------------------------------ # # 2. loadTools throws if a .jl file does not define getTool() # # ------------------------------------------------------------------ # bad_dir = mktempdir() write(joinpath(bad_dir, "noTool.jl"), "x = 42\n") @test_throws ArgumentError loadTools(bad_dir) # ------------------------------------------------------------------ # # 3. Load all tools from src/tools/ # # ------------------------------------------------------------------ # clearTools() loaded = loadTools(TOOLS_DIR) @test !isempty(loaded) @test length(loaded) == 3 # getTime.jl, getWeather.jl, writeTool.jl # ------------------------------------------------------------------ # # 4. Each loaded tool has an isolated _tool_module # # ------------------------------------------------------------------ # for tool in loaded @test tool._tool_module isa Module end # Verify modules are unique (not shared) modules = [t._tool_module for t in loaded] @test length(unique(modules)) == length(modules) # ------------------------------------------------------------------ # # 5. Each tool's executeTool is callable # # ------------------------------------------------------------------ # function run_all_execution_tests(loaded) sig = nothing op = x -> x # no-op partial result callback for tool in loaded @test tool.execute !== nothing @test tool._tool_module isa Module # Verify the module actually defines executeTool @test isdefined(tool._tool_module, :executeTool) # Execute the tool — must return agentToolResult without throwing result = try tool.execute("call-$(tool.name)", Dict{String,Any}("city" => "Tokyo"), sig, op) catch err tool.execute("call-$(tool.name)", Dict{String,Any}(), sig, op) end @test result isa agentToolResult @test result.content[1] isa textContent end end run_all_execution_tests(loaded) # ------------------------------------------------------------------ # # 6. Specific tool assertions based on known tool names # # ------------------------------------------------------------------ # time_tool = filter(t -> t.name == "getTime", loaded) @test !isempty(time_tool) @test time_tool[1].validateRequiredArgs !== nothing getWeather_tool = filter(t -> t.name == "getWeather", loaded) @test !isempty(getWeather_tool) @test getWeather_tool[1].inputSchema["required"] == ["city"] write_tool = filter(t -> t.name == "writeTool", loaded) @test !isempty(write_tool) @test "name" in write_tool[1].inputSchema["required"] # ------------------------------------------------------------------ # # 7. getTools / registerTool / clearTools # # ------------------------------------------------------------------ # registry_tools = getTools() @test !isempty(registry_tools) @test length(registry_tools) == 3 # only the loaded tools clearTools() @test isempty(getTools()) test_tool = agentTool( name = "manualTool", label = "Manual Tool", description = "Registered manually", inputSchema = Dict{String,Any}("type" => "object", "properties" => Dict{String,Any}(), "required" => Any[]), execute = (toolCallId, args, signal, onPartialResult) -> agentToolResult([textContent("manual")], Dict{Any,Any}(), nothing, false), prepareArguments = nothing, validateRequiredArgs = nothing, parallelToolExecute = true, _tool_module = nothing ) registerTool(test_tool) reg = getTools() @test any(t -> t.name == "manualTool", reg) @test count(t -> t.name == "manualTool", reg) == 1 @test reg[1].parallelToolExecute == true @test reg[1]._tool_module === nothing # ------------------------------------------------------------------ # # 8. getTools returns new vector (mutations don't affect registry) # # ------------------------------------------------------------------ # clearTools() @test isempty(getTools()) end