V0.9.0 agent status #50

Merged
ton merged 2 commits from v0.9.0-agent_status into v0.9.0 2026-09-12 13:04:59 +00:00
4 changed files with 15 additions and 95 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
name = "YiemAgent" name = "YiemAgent"
uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2" uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2"
version = "0.8.0" version = "0.9.0"
authors = ["narawat lamaiin <narawat@outlook.com>"] authors = ["narawat lamaiin <narawat@outlook.com>"]
[deps] [deps]
+9 -81
View File
@@ -264,18 +264,14 @@ function _agentLoop(agent::yiemAgent)
while true while true
while newUserMsg === nothing while newUserMsg === nothing
if isready(agent.inputChannel) if isready(agent.inputChannel)
agent.eventSink("_agentLoop 1 agent._state.messages length $(length(agent._state.messages))"; publish=true)
# agent process new user msg immediately after the current tool call finished. # agent process new user msg immediately after the current tool call finished.
newUserMsg = take!(agent.inputChannel) newUserMsg = take!(agent.inputChannel)
# agent.eventSink("new user msg\n$newUserMsg"; publish=true)
else else
# check followUp message after _processMessage() is done # check followUp message after _processMessage() is done
if typeof(processingTask) == Task && istaskdone(processingTask) == true if typeof(processingTask) == Task && istaskdone(processingTask) == true
agent.eventSink("_agentLoop 2 agent._state.messages length $(length(agent._state.messages))"; publish=true)
# if agent runs is done but followUpChannel has messages, # if agent runs is done but followUpChannel has messages,
# put new message in inputChannel instead # put new message in inputChannel instead
if isready(agent.followUpChannel) if isready(agent.followUpChannel)
agent.eventSink("_agentLoop 3 agent._state.messages length $(length(agent._state.messages))"; publish=true)
while isready(agent.followUpChannel) while isready(agent.followUpChannel)
followUpMsg = take!(agent.followUpChannel) followUpMsg = take!(agent.followUpChannel)
put!(agent.inputChannel, followUpMsg) put!(agent.inputChannel, followUpMsg)
@@ -283,19 +279,12 @@ function _agentLoop(agent::yiemAgent)
processingTask = nothing # reset processingTask = nothing # reset
result = nothing # reset result = nothing # reset
else # _processMessage() done and no followUp message. else # _processMessage() done and no followUp message.
agent.eventSink("_agentLoop 4 agent._state.messages length $(length(agent._state.messages))"; publish=true)
result = deepcopy(agent._state.messages[end]) result = deepcopy(agent._state.messages[end])
agent.eventSink("_agentLoop 4-1 "; publish=true)
# filter out reasoningContent in-place # filter out reasoningContent in-place
filter!(c -> !(c isa reasoningContent), result.content) filter!(c -> !(c isa reasoningContent), result.content)
agent.eventSink("_agentLoop 5 "; publish=true)
# format output # format output
respondToUI = _assistantMessageToOpenAI(result) respondToUI = _assistantMessageToOpenAI(result)
agent.eventSink("_agentLoop 6 "; publish=true)
put!(agent.outputChannel, respondToUI) put!(agent.outputChannel, respondToUI)
if !isempty(result.content) && result.content[1] isa textContent
agent.eventSink(result.content[1].text; publish=true)
end
processingTask = nothing # reset processingTask = nothing # reset
result = nothing # reset result = nothing # reset
end end
@@ -325,7 +314,6 @@ function _agentLoop(agent::yiemAgent)
else else
# spawn new _processMessage() if it is not already running. # spawn new _processMessage() if it is not already running.
if processingTask === nothing if processingTask === nothing
agent.eventSink("_agentLoop 5 agent._state.messages length $(length(agent._state.messages))"; publish=true)
# discard all messages in followUpChannel # discard all messages in followUpChannel
while isready(agent.followUpChannel) while isready(agent.followUpChannel)
_ = take!(agent.followUpChannel) _ = take!(agent.followUpChannel)
@@ -404,7 +392,6 @@ function _processMessage(
afterToolCall::Union{Function, Nothing}, afterToolCall::Union{Function, Nothing},
parallelToolExecute::Bool, parallelToolExecute::Bool,
)::Nothing )::Nothing
eventSink("_processMessage 1 _state.messages length $(length(agentMsgHistory))"; publish=true)
# loop until llmCall() response didn't use tool calls # loop until llmCall() response didn't use tool calls
final_response = nothing final_response = nothing
@@ -425,43 +412,29 @@ function _processMessage(
try try
# Drain inputChannel and convert OpenAI-format messages to userMessage type # Drain inputChannel and convert OpenAI-format messages to userMessage type
while isready(inputChannel) while isready(inputChannel)
eventSink("_processMessage 2 _state.messages length $(length(agentMsgHistory))"; publish=true)
newUserMsg_openai = take!(inputChannel) newUserMsg_openai = take!(inputChannel)
eventSink("_processMessage 3 _state.messages length $(length(agentMsgHistory))"; publish=true)
if newUserMsg_openai === :shutdown if newUserMsg_openai === :shutdown
eventSink("_processMessage 4 _state.messages length $(length(agentMsgHistory))"; publish=true)
# Re-emit shutdown signal for the loop to handle # Re-emit shutdown signal for the loop to handle
put!(inputChannel, :shutdown) put!(inputChannel, :shutdown)
break break
end end
eventSink("_processMessage 5 _state.messages length $(length(agentMsgHistory))"; publish=true)
newUserMsg = OpenAiToUserMessage(newUserMsg_openai) newUserMsg = OpenAiToUserMessage(newUserMsg_openai)
push!(agentMsgHistory, newUserMsg) push!(agentMsgHistory, newUserMsg)
eventSink("_processMessage 6 _state.messages length $(length(agentMsgHistory))"; publish=true)
end end
eventSink("_processMessage 7 _state.messages length $(length(agentMsgHistory))"; publish=true)
# call prepareContext() # call prepareContext()
state = agentState(systemPrompt, nothing, tools, agentMsgHistory) state = agentState(systemPrompt, nothing, tools, agentMsgHistory)
eventSink("_processMessage 8 _state.messages length $(length(agentMsgHistory))"; publish=true)
preparedContext = prepareContext(state, eventSink) preparedContext = prepareContext(state, eventSink)
eventSink("_processMessage 9 _state.messages length $(length(agentMsgHistory))"; publish=true)
# Call formatMessagesForLLM() to format for LLM # Call formatMessagesForLLM() to format for LLM
formattedMessages = formatMessagesForLLM(preparedContext, eventSink) formattedMessages = formatMessagesForLLM(preparedContext, eventSink)
# eventSink("_processMessage 10 formattedMessages $formattedMessages"; publish=true)
eventSink("Thinking...")
""" response example """ response example
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 = 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=eventSink) response = llmCall(formattedMessages, eventSink=eventSink)
# eventSink("LLM response " * string(response); publish=true)
eventSink("_processMessage 11 _state.messages length $(length(agentMsgHistory))"; publish=true)
# Extract tool calls from LLM response content blocks # Extract tool calls from LLM response content blocks
hasToolCalls, toolCallList, assistant_msg = _extractToolCalls(response) hasToolCalls, toolCallList, assistant_msg = _extractToolCalls(response)
eventSink("hasToolCalls: $hasToolCalls\ntoolCallList: $toolCallList _state.messages length $(length(agentMsgHistory))"; publish=true)
eventSink("assistant_msg " * string(assistant_msg); publish=true)
eventSink("_processMessage 11-1"; publish=true)
# Add assistant message (tool calls or text) to history for next LLM turn # Add assistant message (tool calls or text) to history for next LLM turn
push!(agentMsgHistory, assistant_msg) push!(agentMsgHistory, assistant_msg)
@@ -476,21 +449,14 @@ function _processMessage(
) )
signal = abortSignal(false) signal = abortSignal(false)
eventSink("_processMessage 12 _state.messages length $(length(agentMsgHistory))"; publish=true)
# call executeToolCalls() # call executeToolCalls()
toolResultBatch = executeToolCalls(preparedContext, assistant_msg, toolCallList, config, toolResultBatch = executeToolCalls(preparedContext, assistant_msg, toolCallList, config,
signal, eventSink) signal, eventSink)
eventSink("_processMessage 13 _state.messages length $(length(agentMsgHistory))"; publish=true)
# save toolResults to messages # save toolResults to messages
for toolResult in toolResultBatch.messages for toolResult in toolResultBatch.messages
# eventSink("toolResult " * string(toolResult); publish=true)
push!(agentMsgHistory, toolResult) push!(agentMsgHistory, toolResult)
end end
eventSink("_processMessage 14 _state.messages length $(length(agentMsgHistory))"; publish=true)
if toolResultBatch.terminate if toolResultBatch.terminate
eventSink("_processMessage 15 _state.messages length $(length(agentMsgHistory))"; publish=true)
# If toolResultBatch requested termination, build a final response # If toolResultBatch requested termination, build a final response
final_content = [textContent("Tool execution completed.")] final_content = [textContent("Tool execution completed.")]
for toolResult in toolResultBatch.messages for toolResult in toolResultBatch.messages
@@ -504,7 +470,6 @@ function _processMessage(
end end
end end
end end
eventSink("_processMessage 16 _state.messages length $(length(agentMsgHistory))"; publish=true)
final_response = assistantMessage( final_response = assistantMessage(
role="assistant", role="assistant",
content=final_content, content=final_content,
@@ -523,7 +488,6 @@ function _processMessage(
break break
end end
else else
eventSink("_processMessage 17 _state.messages length $(length(agentMsgHistory))"; publish=true)
# LLM did not use tool calls — # LLM did not use tool calls —
break break
end end
@@ -538,8 +502,6 @@ function _processMessage(
end end
end end
eventSink("_processMessage 18 _state.messages length $(length(agentMsgHistory))"; publish=true)
return nothing return nothing
end end
@@ -979,47 +941,37 @@ function prepareToolCall(
signal::abortSignal, signal::abortSignal,
eventSink eventSink
)::Union{preparedToolCall,immediateOutcome} )::Union{preparedToolCall,immediateOutcome}
eventSink("prepareToolCall 1"; publish=true)
# pick a called tool from tool store # pick a called tool from tool store
tool = get(context.tools, toolCall.name, nothing) tool = get(context.tools, toolCall.name, nothing)
if tool === nothing if tool === nothing
eventSink("prepareToolCall 2"; publish=true)
return immediateOutcome(createErrorToolResult("Tool $toolCall.name not found"), true) return immediateOutcome(createErrorToolResult("Tool $toolCall.name not found"), true)
end end
try try
eventSink("prepareToolCall 3"; publish=true)
# 1. prepare arguments (tool-specific transform) # 1. prepare arguments (tool-specific transform)
prepared = prepareToolCallArguments(tool, toolCall) prepared = prepareToolCallArguments(tool, toolCall)
eventSink("prepared " * string(prepared.arguments); publish=true)
eventSink("prepareToolCall 4"; publish=true)
validatedArgs = validateToolArguments(tool, prepared) validatedArgs = validateToolArguments(tool, prepared)
eventSink("validatedArgs " * string(validatedArgs); publish=true)
eventSink("prepareToolCall 5"; publish=true)
# 2. beforeToolCall hook — can block # 2. beforeToolCall hook — can block
if config.beforeToolCall !== nothing if config.beforeToolCall !== nothing
eventSink("prepareToolCall 6"; publish=true)
before = config.beforeToolCall( before = config.beforeToolCall(
beforeToolCallContext(assistantMsg, toolCall, validatedArgs, context), beforeToolCallContext(assistantMsg, toolCall, validatedArgs, context),
signal, signal,
eventSink eventSink
) )
eventSink("prepareToolCall 7"; publish=true)
if signal.aborted if signal.aborted
eventSink("prepareToolCall 8"; publish=true)
return immediateOutcome(createErrorToolResult("Operation aborted"), true) return immediateOutcome(createErrorToolResult("Operation aborted"), true)
end end
if before !== nothing && before.block if before !== nothing && before.block
eventSink("prepareToolCall 9"; publish=true)
return immediateOutcome( return immediateOutcome(
createErrorToolResult(get(before, :reason, "Tool execution was blocked")), true) createErrorToolResult(get(before, :reason, "Tool execution was blocked")), true)
end end
end end
eventSink("prepareToolCall 10"; publish=true)
return preparedToolCall(tool, toolCall, validatedArgs) return preparedToolCall(tool, toolCall, validatedArgs)
catch e catch e
bt = catch_backtrace() bt = catch_backtrace()
@@ -1029,7 +981,6 @@ function prepareToolCall(
end end
eventSink(errMsg; publish=true) eventSink(errMsg; publish=true)
return immediateOutcome(createErrorToolResult(sprint(showerror, e)), true) return immediateOutcome(createErrorToolResult(sprint(showerror, e)), true)
end end
end end
@@ -1080,11 +1031,9 @@ function executePreparedToolCall(
signal::Union{Nothing,abortSignal}, signal::Union{Nothing,abortSignal},
eventSink, eventSink,
)::executedOutcome )::executedOutcome
eventSink("executePreparedToolCall 1"; publish=true)
try try
result = prep.tool.execute(prep.toolCall.id, prep.args, signal, eventSink) result = prep.tool.execute(prep.toolCall.id, prep.args, signal, eventSink)
# eventSink("tool execute raw result: " * sprint(show, result); publish=true)
return executedOutcome(result, false) return executedOutcome(result, false)
catch e catch e
bt = catch_backtrace() bt = catch_backtrace()
@@ -1165,10 +1114,9 @@ function finalizeExecutedToolCall(
signal::Union{Nothing,abortSignal}, signal::Union{Nothing,abortSignal},
eventSink eventSink
)::finalizedOutcome )::finalizedOutcome
eventSink("finalizeExecutedToolCall 1"; publish=true)
result = executed.result result = executed.result
isError = executed.isError isError = executed.isError
# eventSink("finalizeExecutedToolCall result before afterToolCall\n$result"; publish=true)
if config.afterToolCall !== nothing if config.afterToolCall !== nothing
try try
after = config.afterToolCall( after = config.afterToolCall(
@@ -1176,7 +1124,6 @@ function finalizeExecutedToolCall(
signal, signal,
eventSink eventSink
) )
eventSink("finalizeExecutedToolCall 3"; publish=true)
if after !== nothing if after !== nothing
result = after result = after
isError = false isError = false
@@ -1193,7 +1140,6 @@ function finalizeExecutedToolCall(
isError = true isError = true
end end
end end
eventSink("finalizeExecutedToolCall 4"; publish=true)
return finalizedOutcome(prep.toolCall, result, isError) return finalizedOutcome(prep.toolCall, result, isError)
end end
@@ -1259,39 +1205,25 @@ function executeToolCallsSequential(
signal::abortSignal, signal::abortSignal,
eventSink, eventSink,
)::agentToolCallBatch )::agentToolCallBatch
eventSink("executeToolCallsSequential 1"; publish=true)
finalizedCalls = finalizedOutcome[] finalizedCalls = finalizedOutcome[]
messages = toolResultMessage[] messages = toolResultMessage[]
for tc in toolCalls for tc in toolCalls
eventSink("start tool execute $(tc.id), $(tc.name), $(tc.arguments)"; publish=true)
prep = prepareToolCall(context, assistantMsg, tc, config, signal, eventSink) prep = prepareToolCall(context, assistantMsg, tc, config, signal, eventSink)
eventSink("executeToolCallsSequential " * string(prep.args); publish=true)
if prep isa immediateOutcome if prep isa immediateOutcome
eventSink("executeToolCallsSequential 2-1"; publish=true)
finalized = finalizedOutcome(tc, prep.result, prep.isError) finalized = finalizedOutcome(tc, prep.result, prep.isError)
eventSink("executeToolCallsSequential 2-2"; publish=true)
else else
eventSink("executeToolCallsSequential 3"; publish=true)
executed = executePreparedToolCall(prep, signal, eventSink) executed = executePreparedToolCall(prep, signal, eventSink)
eventSink("executeToolCallsSequential 3-1"; publish=true)
finalized = finalizeExecutedToolCall(context, assistantMsg, prep, executed, config, finalized = finalizeExecutedToolCall(context, assistantMsg, prep, executed, config,
signal, eventSink) signal, eventSink)
eventSink("executeToolCallsSequential 3-2"; publish=true)
end end
eventSink("executeToolCallsSequential 4"; publish=true)
# eventSink("finalized $(finalized.toolCall.id), $(finalized.toolCall.name),
# $(finalized.result), $(finalized.isError)"; publish=true)
push!(messages, createToolResultMessage(finalized)) push!(messages, createToolResultMessage(finalized))
push!(finalizedCalls, finalized) push!(finalizedCalls, finalized)
eventSink("executeToolCallsSequential 5"; publish=true)
if signal !== nothing && signal.aborted if signal !== nothing && signal.aborted
break break
end end
end end
eventSink("executeToolCallsSequential 6"; publish=true)
return agentToolCallBatch(messages, shouldTerminate(finalizedCalls)) return agentToolCallBatch(messages, shouldTerminate(finalizedCalls))
end end
@@ -1364,21 +1296,21 @@ function executeToolCallsParallel(
entries = Union{finalizedOutcome,Task}[] entries = Union{finalizedOutcome,Task}[]
for tc in toolCalls for tc in toolCalls
eventSink(toolExecStartEvent(tc.id, tc.name, tc.arguments); publish=true) toolExecStartEvent(tc.id, tc.name, tc.arguments)
prep = prepareToolCall(context, assistantMsg, tc, config, signal, eventSink) prep = prepareToolCall(context, assistantMsg, tc, config, signal, eventSink)
if prep isa immediateOutcome if prep isa immediateOutcome
finalized = finalizedOutcome(tc, prep.result, prep.isError) finalized = finalizedOutcome(tc, prep.result, prep.isError)
eventSink(toolExecEndEvent(finalized.toolCall.id, finalized.toolCall.name, toolExecEndEvent(finalized.toolCall.id, finalized.toolCall.name,
finalized.result, finalized.isError)) finalized.result, finalized.isError)
push!(entries, finalized) push!(entries, finalized)
else else
t = Task() do t = Task() do
executed = executePreparedToolCall(prep, signal, eventSink) executed = executePreparedToolCall(prep, signal, eventSink)
finalized = finalizeExecutedToolCall(context, assistantMsg, prep, executed, config, signal) finalized = finalizeExecutedToolCall(context, assistantMsg, prep, executed, config, signal)
eventSink(toolExecEndEvent(finalized.toolCall.id, finalized.toolCall.name, toolExecEndEvent(finalized.toolCall.id, finalized.toolCall.name,
finalized.result, finalized.isError)) finalized.result, finalized.isError)
return finalized return finalized
end end
schedule(t) schedule(t)
@@ -1463,7 +1395,6 @@ function executeToolCalls(
eventSink, eventSink,
)::agentToolCallBatch )::agentToolCallBatch
eventSink("_executeToolCalls 1"; publish=true)
hasSequential = false hasSequential = false
for tc in toolCalls for tc in toolCalls
t = get(context.tools, tc.name, nothing) t = get(context.tools, tc.name, nothing)
@@ -1472,13 +1403,10 @@ function executeToolCalls(
break break
end end
end end
eventSink("_executeToolCalls 2"; publish=true)
if config.toolExecution == "sequential" || hasSequential if config.toolExecution == "sequential" || hasSequential
eventSink("_executeToolCalls 3"; publish=true)
return executeToolCallsSequential(context, assistantMsg, toolCalls, config, signal, return executeToolCallsSequential(context, assistantMsg, toolCalls, config, signal,
eventSink) eventSink)
else else
eventSink("_executeToolCalls 4"; publish=true)
return executeToolCallsParallel(context, assistantMsg, toolCalls, config, signal, return executeToolCallsParallel(context, assistantMsg, toolCalls, config, signal,
eventSink) eventSink)
end end
-3
View File
@@ -121,9 +121,7 @@ function register_mcp_tools(tools::OrderedDict{String, agentTool}, mcpserver; ev
end end
new_count = 0 new_count = 0
try try
eventSink("register_mcp_tools 1")
response = mcpserver("tools/list", sessionId; eventSink=eventSink) response = mcpserver("tools/list", sessionId; eventSink=eventSink)
eventSink("register_mcp_tools 2")
# Parse JSON-RPC 2.0 response envelope # Parse JSON-RPC 2.0 response envelope
if haskey(response, "error") if haskey(response, "error")
rpc_error = response["error"] rpc_error = response["error"]
@@ -247,7 +245,6 @@ function listTool(tools::OrderedDict{String, agentTool}, mcpserver; eventSink=no
eventSink) -> begin eventSink) -> begin
# Discover and register MCP tools (idempotent — skips already registered) # Discover and register MCP tools (idempotent — skips already registered)
new_count = register_mcp_tools(tools, mcpserver; eventSink=eventSink, sessionId=sessionId) new_count = register_mcp_tools(tools, mcpserver; eventSink=eventSink, sessionId=sessionId)
eventSink("tools dump: " * sprint(show, tools))
# Always include listTools itself in the count # Always include listTools itself in the count
total = length(tools) total = length(tools)
+5 -10
View File
@@ -208,7 +208,6 @@ function formatMsgForLLM(ctx::agentContext, eventSink)::Dict{String, Any}
openaiReadyMsg = Dict{String, Any}() openaiReadyMsg = Dict{String, Any}()
# openaiReadyMsg["model"] = "gemma-4-E4B-it-UD-Q4_K_XL" # openaiReadyMsg["model"] = "gemma-4-E4B-it-UD-Q4_K_XL"
messages = Vector{Dict{String, Any}}() messages = Vector{Dict{String, Any}}()
eventSink("formatMsgForLLM 1")
# System prompt as system message # System prompt as system message
if !isempty(ctx.systemPrompt) if !isempty(ctx.systemPrompt)
push!(messages, Dict( push!(messages, Dict(
@@ -216,7 +215,6 @@ function formatMsgForLLM(ctx::agentContext, eventSink)::Dict{String, Any}
"content" => [Dict("type" => "text", "text" => ctx.systemPrompt)] "content" => [Dict("type" => "text", "text" => ctx.systemPrompt)]
)) ))
end end
eventSink("formatMsgForLLM 2")
# Conversation messages # Conversation messages
for msg in ctx.messages for msg in ctx.messages
if msg isa userMessage if msg isa userMessage
@@ -229,10 +227,8 @@ function formatMsgForLLM(ctx::agentContext, eventSink)::Dict{String, Any}
push!(messages, _toolResultMessageToOpenAI(msg)) push!(messages, _toolResultMessageToOpenAI(msg))
end end
end end
eventSink("formatMsgForLLM 3")
# Convert ctx.tools into OpenAI tools format # Convert ctx.tools into OpenAI tools format
tools_array = _toolsToOpenAI(ctx.tools, eventSink) tools_array = _toolsToOpenAI(ctx.tools, eventSink)
eventSink("formatMsgForLLM 4")
openaiReadyMsg["messages"] = messages openaiReadyMsg["messages"] = messages
openaiReadyMsg["temperature"] = 0.7 openaiReadyMsg["temperature"] = 0.7
@@ -278,7 +274,7 @@ end
function beforeToolCall(context::beforeToolCallContext, signal::abortSignal, eventSink function beforeToolCall(context::beforeToolCallContext, signal::abortSignal, eventSink
)::beforeToolCallResult )::beforeToolCallResult
eventSink("beforeToolCall: $(context.toolCall.name) args=$(context.args)") # eventSink("beforeToolCall: $(context.toolCall.name) args=$(context.args)")
return beforeToolCallResult(false, "N/A") return beforeToolCallResult(false, "N/A")
end end
@@ -306,11 +302,11 @@ Common use cases:
- `agentToolResult(...)` to return a modified result (content, details, usage, - `agentToolResult(...)` to return a modified result (content, details, usage,
terminate flag can all be overridden). terminate flag can all be overridden).
""" #WORKING arrange result from searchWine tool """ # arrange result from searchWine tool
function afterToolCall(context::afterToolCallContext, signal::abortSignal, eventSink function afterToolCall(context::afterToolCallContext, signal::abortSignal, eventSink
)::Union{agentToolResult, Nothing} )::Union{agentToolResult, Nothing}
eventSink("afterToolCall: $(context.toolCall.name) result=$(context.result) error=$(context.isError)") # eventSink("afterToolCall: $(context.toolCall.name) result=$(context.result) error=$(context.isError)")
return nothing return nothing
end end
@@ -428,8 +424,7 @@ _toolsToOpenAI(tools) # => [Dict("type" => "function", "function" => Dict("na
""" """
function _toolsToOpenAI(tools::Union{OrderedDict{String, agentTool}, Nothing}, eventSink)::Vector{Dict{String, Any}} function _toolsToOpenAI(tools::Union{OrderedDict{String, agentTool}, Nothing}, eventSink)::Vector{Dict{String, Any}}
tools_array = Vector{Dict{String, Any}}() tools_array = Vector{Dict{String, Any}}()
eventSink("_toolsToOpenAI 1")
eventSink(string(typeof(tools)))
if tools !== nothing if tools !== nothing
for (_, tool) in tools for (_, tool) in tools
push!(tools_array, Dict( push!(tools_array, Dict(
@@ -442,7 +437,7 @@ function _toolsToOpenAI(tools::Union{OrderedDict{String, agentTool}, Nothing}, e
)) ))
end end
end end
eventSink("_toolsToOpenAI 2")
return tools_array return tools_array
end end