update
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
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
|
||||
Reference in New Issue
Block a user