V0.8.0 add wine tools #46

Merged
ton merged 19 commits from v0.8.0-add_wine_tools into v0.8.0 2026-09-07 22:51:23 +00:00
2 changed files with 25 additions and 25 deletions
Showing only changes of commit 4ac5b97d53 - Show all commits
+21 -17
View File
@@ -19,6 +19,7 @@ mutable struct yiemAgent <: agent # High-level agent wrapper
# user sends prompt message to agent. if agent is idle, it process user message right away.
# if agent is running, it process user message after the current tool call finished.
# Expect each message in OpenAI chat format
inputChannel::Channel
# Buffers messages the user sends while the agent is busy. Processed after all inputChannel
@@ -422,7 +423,7 @@ function _processMessage(
response = JSON.Object{String, Any}("finish_reason" => "tool_calls", "index" => 0, "message" => JSON.Object{String, Any}("role" => "assistant", "content" => "", "reasoning_content" => "Here's a thinking process:\n\n1. **Identify User Request**: The user is asking for the weather in Bangkok.\n2. **Locate Relevant Tool**: I have a `getWeather` function available.\n3. **Check Function Parameters**:\n - `city` (required): City and country, e.g., 'San Francisco, CA' or 'Tokyo, Japan'\n - `units` (optional, default \"celsius\"): Temperature scale (\"celsius\" or \"fahrenheit\")\n4. **Prepare Parameters**:\n - `city`: \"Bangkok, Thailand\" (adding country for clarity, though just \"Bangkok\" might work, following the example format is safer)\n - `units`: Not specified, so I'll use the default (\"celsius\")\n5. **Execute Tool Call**: Call `getWeather` with `city: \"Bangkok, Thailand\"`\n6. **Anticipate Response**: The function will return current weather and forecast data for Bangkok. I'll then format it nicely for the user.\n - *Self-Correction/Verification during thought*: The prompt says \"city: City and country, e.g., 'San Francisco, CA' or 'Tokyo, Japan'\". I'll use \"Bangkok, Thailand\". The `units` parameter is optional, so I'll omit it to use the default.\n - Proceed with tool call.✅\n", "tool_calls" => Any[JSON.Object{String, Any}("type" => "function", "function" => JSON.Object{String, Any}("name" => "getWeather", "arguments" => "{\"city\":\"Bangkok, Thailand\"}"), "id" => "6fOilR5QPcdppbAAHluhkRyUDu3oWMAL")]))
"""
response = llmCall(formattedMessages)
eventSink("LLM response " * string(response); publish=false, log=true)
# eventSink("LLM response " * string(response); publish=false, log=true)
eventSink("_processMessage 11 _state.messages length $(length(agentMsgHistory))"; publish=false, log=true)
# Extract tool calls from LLM response content blocks
@@ -453,7 +454,7 @@ function _processMessage(
# save toolResults to messages
for toolResult in toolResultBatch.messages
eventSink("toolResult " * string(toolResult); publish=false, log=true)
# eventSink("toolResult " * string(toolResult); publish=false, log=true)
push!(agentMsgHistory, toolResult)
end
eventSink("_processMessage 14 _state.messages length $(length(agentMsgHistory))"; publish=false, log=true)
@@ -538,7 +539,7 @@ agentToolResult([textContent("text", "Tool not found")], Dict{Any,Any}())
```
"""
function createErrorToolResult(msg::String)::agentToolResult
return agentToolResult([textContent("text", msg)], dict{any,any}())
return agentToolResult([textContent("text", msg)], Dict{Any,Any}())
end
"""
@@ -830,10 +831,10 @@ stopping the agent when other tools in the batch did not intend to terminate.
julia> shouldTerminate(finalizedOutcome[])
false
julia> shouldTerminate([finalizedOutcome(tc, agentToolResult([], dict{any,any}(), dict{any,any}(), false), false) for _ in 1:2])
julia> shouldTerminate([finalizedOutcome(tc, agentToolResult([], Dict{Any,Any}(), Dict{Any,Any}(), false), false) for _ in 1:2])
false
julia> shouldTerminate([finalizedOutcome(tc, agentToolResult([], dict{any,any}(), dict{any,any}(), true), false) for _ in 1:2])
julia> shouldTerminate([finalizedOutcome(tc, agentToolResult([], Dict{Any,Any}(), Dict{Any,Any}(), true), false) for _ in 1:2])
true
```
"""
@@ -972,7 +973,8 @@ function prepareToolCall(
before = config.beforeToolCall(
beforeToolCallContext(assistantMsg, toolCall, validatedArgs, context),
signal
signal,
eventSink
)
eventSink("prepareToolCall 7"; publish=false, log=true)
if signal.aborted
@@ -1034,7 +1036,7 @@ emitted after the result has already been captured.
```julia
# Successful execution
executePreparedToolCall(prep, nothing, emit)
# => executedOutcome(agentToolResult([textContent("text", "Found 3 wines")], dict{any,any}(), dict{any,any}()), false)
# => executedOutcome(agentToolResult([textContent("text", "Found 3 wines")], Dict{Any,Any}(), Dict{Any,Any}()), false)
# Execution error
executePreparedToolCall(prep, nothing, emit)
@@ -1049,8 +1051,11 @@ function executePreparedToolCall(
)::executedOutcome
eventSink("executePreparedToolCall 1"; publish=false, log=true)
try #WORKING pass sessionId from yiemAgent to tool call
try
result = prep.tool.execute(prep.toolCall.id, prep.args, signal, eventSink)
eventSink("executePreparedToolCall 2"; publish=false, log=true)
eventSink("tool execute raw result: " * sprint(show, result); publish=false, log=true)
eventSink("executePreparedToolCall 3"; publish=false, log=true)
@@ -1065,6 +1070,7 @@ function executePreparedToolCall(
return executedOutcome(createErrorToolResult(sprint(showerror, e)), true)
end
end
@@ -1136,20 +1142,18 @@ function finalizeExecutedToolCall(
eventSink("finalizeExecutedToolCall 1"; publish=false, log=true)
result = executed.result
isError = executed.isError
eventSink("finalizeExecutedToolCall 2"; publish=false, log=true)
eventSink("finalizeExecutedToolCall result before afterToolCall\n$result"; publish=false, log=true)
if config.afterToolCall !== nothing
try
after = config.afterToolCall(
afterToolCallContext(assistantMsg, prep.toolCall, prep.args, result, isError, context),
signal
signal,
eventSink
)
eventSink("finalizeExecutedToolCall 3"; publish=false, log=true)
if after !== nothing
result = merge(result, dict(:content=>get(after,:content,result.content),
:details=>get(after,:details,result.details),
:usage=>get(after,:usage,result.usage),
:terminate=>get(after,:terminate,result.terminate)))
isError = get(after, :isError, isError)
result = after
isError = false
end
catch e
bt = catch_backtrace()
@@ -1252,8 +1256,8 @@ function executeToolCallsSequential(
eventSink("executeToolCallsSequential 3-2"; publish=false, log=true)
end
eventSink("executeToolCallsSequential 4"; publish=false, log=true)
eventSink("finalized $(finalized.toolCall.id), $(finalized.toolCall.name),
$(finalized.result), $(finalized.isError)"; publish=false, log=true)
# eventSink("finalized $(finalized.toolCall.id), $(finalized.toolCall.name),
# $(finalized.result), $(finalized.isError)"; publish=false, log=true)
push!(messages, createToolResultMessage(finalized))
push!(finalizedCalls, finalized)
eventSink("executeToolCallsSequential 5"; publish=false, log=true)
+4 -8
View File
@@ -275,14 +275,10 @@ function beforeToolCall(context::beforeToolCallContext, signal::abortSignal)
end
```
"""
function beforeToolCall(context::beforeToolCallContext, signal::abortSignal
function beforeToolCall(context::beforeToolCallContext, signal::abortSignal, eventSink
)::beforeToolCallResult
# final context check
# seek user approval via UI
# other check
eventSink("beforeToolCall: $(context.toolCall.name) args=$(context.args)")
return beforeToolCallResult(false, "N/A")
end
@@ -311,10 +307,10 @@ Common use cases:
terminate flag can all be overridden).
""" #WORKING arrange result from searchWine tool
function afterToolCall(context::afterToolCallContext, signal::abortSignal
function afterToolCall(context::afterToolCallContext, signal::abortSignal, eventSink
)::Union{agentToolResult, Nothing}
# modify context.result if needed and return agentToolResult
eventSink("afterToolCall: $(context.toolCall.name) result=$(context.result) error=$(context.isError)")
return nothing
end