This commit is contained in:
2026-08-08 09:38:05 +07:00
parent 04e75e61b8
commit 0ddbcf9ca1
5 changed files with 548 additions and 27 deletions
+101 -2
View File
@@ -1,6 +1,6 @@
module utils
export clearhistory, availableWineToText, prepareContext, formatMsgForLLM, _userMessageToOpenAI,
export clearhistory, availableWineToText, prepareContext, formatMsgForLLM, validateRequiredArgs, validateToolArguments, _userMessageToOpenAI,
_assistantMessageToOpenAI, _toolResultMessageToOpenAI, _messageContentToBlocks
using UUIDs, Dates, DataStructures, HTTP, JSON
@@ -275,10 +275,109 @@ function _messageContentToBlocks(contents::Vector{messageContent})::Vector{Dict{
end
end
return blocks
return blocks
end
"""
validateRequiredArgs(args::Dict{String,Any}, inputSchema::Dict{String,Any}) -> Union{Nothing,String}
Validates that all required fields listed in the tool's JSON Schema are present
in `args`. Returns `nothing` if validation passes, or a descriptive error string
listing the missing required fields.
This is the default `validateRequiredArgs` hook. Tool authors can override it
with a custom validation function that performs additional checks (e.g. type
coercion, format validation, cross-field constraints).
# Arguments
- `args::Dict{String,Any}`: The arguments provided by the LLM
- `inputSchema::Dict{String,Any}`: The tool's `inputSchema` (JSON Schema format)
# Returns
- `nothing` if all required args are present
- `String` error message listing missing fields otherwise
# Examples
```julia
schema = Dict("required" => ["city"])
args = Dict{String,Any}()
validateRequiredArgs(args, schema) # => "Missing required arguments: city"
args2 = Dict("city" => "Tokyo")
validateRequiredArgs(args2, schema) # => nothing
```
"""
function validateRequiredArgs(args::Dict{String,Any}, inputSchema::Dict{String,Any})::Union{Nothing,String}
required = get(inputSchema, "required", Any[])
if isempty(required)
return nothing
end
missing = String[]
for field in required
if !(field in keys(args))
push!(missing, field)
end
end
if !isempty(missing)
return "Missing required arguments: $(join(missing, ", "))"
end
return nothing
end
"""
validateToolArguments(tool::agentTool, prepared::agentToolCall) -> Dict{String,Any}
Validates the prepared tool call arguments by calling the tool's
`validateRequiredArgs` hook (or the default implementation). If validation
fails, returns a modified `agentToolCall` with an empty arguments dict
so downstream code can detect the failure. If the hook exists on the tool
and returns an error string, that error is returned.
This runs **before** the `beforeToolCall` hook, allowing the agent to
reject invalid calls without invoking lifecycle callbacks or logging
false `toolExecutionStart` events.
# Arguments
- `tool::agentTool`: The resolved tool definition
- `prepared::agentToolCall`: The prepared tool call with potentially transformed arguments
# Returns
- `Dict{String,Any}`: The validated arguments if successful
# Errors
- Throws `ArgumentError` if validation fails — this is caught by `prepareToolCall`
and converted to an `immediateOutcome`
# Examples
```julia
# With validateRequiredArgs hook set on the tool
validateToolArguments(toolWithHook, tc) # => validated args or throws
# With default validation (nothing on tool)
validateToolArguments(toolDefault, tc) # => args or throws
```
"""
function validateToolArguments(tool::agentTool, prepared::agentToolCall)::Dict{String,Any}
# Use default (2-arg: args + schema) or tool-specific hook (1-arg: args only)
if isnothing(tool.validateRequiredArgs)
result = validateRequiredArgs(prepared.arguments, tool.inputSchema)
else
result = tool.validateRequiredArgs(prepared.arguments)
end
if result !== nothing
throw(ArgumentError(result))
end
return prepared.arguments
end