update
This commit is contained in:
+257
-143
@@ -392,30 +392,29 @@ function _processMessage(
|
||||
|
||||
agentEventSink("_processMessage 11")
|
||||
# Extract tool calls from LLM response content blocks
|
||||
hasToolCalls, toolCallList = _extractToolCalls(response)
|
||||
hasToolCalls, toolCallList, assistant_msg = _extractToolCalls(response)
|
||||
agentEventSink("hasToolCalls: $hasToolCalls\ntoolCallList: $toolCallList")
|
||||
error("debug marker")
|
||||
|
||||
if hasToolCalls && length(toolCallList) > 0
|
||||
# Build context and config for executeToolCalls
|
||||
context = agentContext(
|
||||
systemPrompt,
|
||||
messages,
|
||||
tools,
|
||||
)
|
||||
#WORKING Build context and config for executeToolCalls
|
||||
|
||||
config = agentLoopConfig(
|
||||
tools,
|
||||
beforeToolCall,
|
||||
afterToolCall,
|
||||
parallelToolExecute ? "parallel" : "sequential",
|
||||
)
|
||||
|
||||
signal = nothing
|
||||
emit = agentEventSink
|
||||
signal = abortSignal(false)
|
||||
agentEventSink("_processMessage 12")
|
||||
|
||||
# call executeToolCalls()
|
||||
batch = executeToolCalls(context, response, toolCallList, config, signal, emit)
|
||||
|
||||
batch = executeToolCalls(preparedContext, assistant_msg, toolCallList, config, signal,
|
||||
agentEventSink)
|
||||
|
||||
|
||||
agentEventSink("_processMessage 13")
|
||||
error("debug marker")
|
||||
# save toolResults to messages
|
||||
for tool_result in batch.messages
|
||||
push!(messages, tool_result)
|
||||
@@ -438,9 +437,9 @@ function _processMessage(
|
||||
final_response = assistantMessage(
|
||||
role="assistant",
|
||||
content=final_content,
|
||||
api=response.api,
|
||||
model=response.model,
|
||||
usage=response.usage,
|
||||
api=assistant_msg.api,
|
||||
model=assistant_msg.model,
|
||||
usage=assistant_msg.usage,
|
||||
stopReason="tool_use_terminated",
|
||||
errorMessage=if any(x -> x.isError, batch.messages)
|
||||
"One or more tool calls failed"
|
||||
@@ -453,7 +452,7 @@ function _processMessage(
|
||||
end
|
||||
else
|
||||
# LLM did not use tool calls — this is the final response
|
||||
final_response = response
|
||||
final_response = assistant_msg
|
||||
break
|
||||
end
|
||||
end
|
||||
@@ -488,7 +487,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
|
||||
|
||||
"""
|
||||
@@ -530,9 +529,10 @@ function createToolResultMessage(f::finalizedOutcome)::toolResultMessage
|
||||
end
|
||||
|
||||
"""
|
||||
_extractToolCalls(response) -> Tuple{Bool, Vector{agentToolCall}}
|
||||
_extractToolCalls(response) -> Tuple{Bool, Vector{agentToolCall}, assistantMessage}
|
||||
|
||||
Extracts tool calls from the LLM response. Supports two response formats:
|
||||
Extracts tool calls from the LLM response and constructs an `assistantMessage`.
|
||||
Supports two response formats:
|
||||
|
||||
1. **Message format** (e.g. from LMStudio.jl / vLLM):
|
||||
`response["message"]["tool_calls"]` — array of tool call objects with
|
||||
@@ -544,14 +544,19 @@ Extracts tool calls from the LLM response. Supports two response formats:
|
||||
contain a `"tool_calls"` array in format 1. Blocks with `"type" => "tool_call"`
|
||||
have `"name"`, `"arguments"`, `"id"` at the top level (already-parsed args dict).
|
||||
|
||||
Returns `(hasToolCalls, toolCallList)` where `hasToolCalls` is `true` if any
|
||||
tool calls were found, and `toolCallList` is a vector of `agentToolCall` structs.
|
||||
The `assistantMessage` is constructed from:
|
||||
- `reasoning_content` (string) → added as a `textContent` block
|
||||
- `response.content` blocks (text/ reasoning) → added to content
|
||||
- Top-level `api`, `provider`, `model`, `usage` → copied to the message
|
||||
- `finish_reason` → used as `stopReason`
|
||||
|
||||
# Arguments
|
||||
- `response`: LLM response object (Dict/JSON.Object or struct with `.content` field)
|
||||
|
||||
# Returns
|
||||
- `Tuple{Bool, Vector{agentToolCall}}`: `(hasToolCalls, toolCallList)`
|
||||
- `Tuple{Bool, Vector{agentToolCall}, assistantMessage}`: `(hasToolCalls, toolCallList, assistantMsg)`
|
||||
|
||||
# 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")]))
|
||||
"""
|
||||
function _extractToolCalls(response)
|
||||
hasToolCalls = false
|
||||
@@ -600,9 +605,9 @@ function _extractToolCalls(response)
|
||||
for content_block in content
|
||||
if content_block isa AbstractDict
|
||||
if get(content_block, "type", "") == "tool_calls"
|
||||
hasToolCalls = true
|
||||
for tc_data in get(content_block, "tool_calls", [])
|
||||
if tc_data isa AbstractDict
|
||||
hasToolCalls = true
|
||||
push!(toolCallList, make_tc(tc_data))
|
||||
end
|
||||
end
|
||||
@@ -621,7 +626,88 @@ function _extractToolCalls(response)
|
||||
end
|
||||
end
|
||||
|
||||
return hasToolCalls, toolCallList
|
||||
# ── Construct assistantMessage from response ──────────────────────
|
||||
# Check Format 1 nested message for reasoning_content, role, etc.
|
||||
reasoning = get(response, "reasoning_content", nothing)
|
||||
if reasoning === nothing && msg !== nothing && msg isa AbstractDict
|
||||
reasoning = get(msg, "reasoning_content", nothing)
|
||||
end
|
||||
if reasoning isa String
|
||||
reasoning_text = reasoning
|
||||
elseif reasoning isa textContent
|
||||
reasoning_text = reasoning.text
|
||||
else
|
||||
reasoning_text = ""
|
||||
end
|
||||
reasoning_block = !isempty(reasoning_text) ? [textContent(reasoning_text)] : textContent[]
|
||||
|
||||
finish_reason = get(response, "finish_reason", nothing)
|
||||
stop_reason = finish_reason isa AbstractString ? String(finish_reason) : "end_turn"
|
||||
|
||||
api = get(response, "api", "")
|
||||
provider = get(response, "provider", "")
|
||||
model = get(response, "model", nothing)
|
||||
usage = get(response, "usage", nothing)
|
||||
|
||||
content_from_response = get(response, "content", nothing)
|
||||
content_blocks = Vector{messageContent}()
|
||||
if content_from_response isa Vector
|
||||
for block in content_from_response
|
||||
if block isa AbstractDict
|
||||
if get(block, "type", "") == "text"
|
||||
push!(content_blocks, textContent(get(block, "text", "")))
|
||||
elseif get(block, "type", "") == "tool_call"
|
||||
# tool_call blocks — don't add text content for these
|
||||
elseif get(block, "type", "") == "tool_calls"
|
||||
# tool_calls blocks — don't add text content for these
|
||||
elseif get(block, "type", "") == "reasoning"
|
||||
push!(content_blocks, textContent(get(block, "text", "")))
|
||||
else
|
||||
push!(content_blocks, textContent(get(block, "text", "")))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Combine content blocks and reasoning
|
||||
if !isempty(content_blocks) && !isempty(reasoning_block)
|
||||
all_content = vcat(reasoning_block, content_blocks)
|
||||
elseif !isempty(content_blocks)
|
||||
all_content = content_blocks
|
||||
elseif !isempty(reasoning_block)
|
||||
all_content = reasoning_block
|
||||
else
|
||||
all_content = textContent[]
|
||||
end
|
||||
|
||||
error_msg = get(response, "error_message", get(response, "errorMessage", nothing))
|
||||
|
||||
if usage === nothing || !(usage isa llmUsage)
|
||||
usage = llmUsage(0, 0)
|
||||
end
|
||||
|
||||
# Role: prefer Format 1 nested message, fallback to top-level, default "assistant"
|
||||
role = get(response, "role", "assistant")
|
||||
if role == "assistant" && msg !== nothing && msg isa AbstractDict
|
||||
nested_role = get(msg, "role", nothing)
|
||||
if nested_role isa AbstractString
|
||||
role = nested_role
|
||||
end
|
||||
end
|
||||
|
||||
assistant_msg = assistantMessage(
|
||||
role = role,
|
||||
content = all_content,
|
||||
api = api isa AbstractString ? String(api) : "",
|
||||
provider = provider isa AbstractString ? String(provider) : "",
|
||||
model = model,
|
||||
usage = usage,
|
||||
stopReason = stop_reason,
|
||||
errorMessage = error_msg,
|
||||
timestamp = now(),
|
||||
)
|
||||
|
||||
return hasToolCalls, toolCallList, assistant_msg
|
||||
end
|
||||
|
||||
"""
|
||||
@@ -689,14 +775,14 @@ prepareToolCallArguments(normalizeTool, tc)
|
||||
```
|
||||
"""
|
||||
function prepareToolCallArguments(tool::agentTool, toolCall::agentToolCall)::agentToolCall
|
||||
if tool.prepareArguments === nothing
|
||||
return toolCall
|
||||
end
|
||||
prepared = tool.prepareArguments(toolCall.arguments)
|
||||
if prepared == toolCall.arguments
|
||||
return toolCall
|
||||
end
|
||||
return merge(toolCall, dict(:arguments => prepared))
|
||||
if tool.prepareArguments === nothing
|
||||
return toolCall
|
||||
end
|
||||
prepared = tool.prepareArguments(toolCall.arguments)
|
||||
if prepared == toolCall.arguments
|
||||
return toolCall
|
||||
end
|
||||
return merge(toolCall, dict(:arguments => prepared))
|
||||
end
|
||||
|
||||
"""
|
||||
@@ -759,37 +845,55 @@ function prepareToolCall(
|
||||
assistantMsg::assistantMessage,
|
||||
toolCall::agentToolCall,
|
||||
config::agentLoopConfig,
|
||||
signal::Union{Nothing, abortSignal},
|
||||
signal::abortSignal,
|
||||
agentEventSink
|
||||
)::Union{preparedToolCall,immediateOutcome}
|
||||
|
||||
agentEventSink("prepareToolCall 1")
|
||||
tool = get(context.tools, toolCall.name, nothing)
|
||||
if tool === nothing
|
||||
agentEventSink("prepareToolCall 2")
|
||||
return immediateOutcome(createErrorToolResult("Tool $toolCall.name not found"), true)
|
||||
end
|
||||
|
||||
try
|
||||
agentEventSink("prepareToolCall 3")
|
||||
# 1. prepare arguments (tool-specific transform)
|
||||
prepared = prepareToolCallArguments(tool, toolCall)
|
||||
agentEventSink("prepareToolCall 4")
|
||||
validatedArgs = validateToolArguments(tool, prepared)
|
||||
|
||||
agentEventSink("prepareToolCall 5")
|
||||
# 2. beforeToolCall hook — can block
|
||||
if config.beforeToolCall !== nothing
|
||||
agentEventSink("prepareToolCall 6")
|
||||
|
||||
before = config.beforeToolCall(
|
||||
beforeToolCallContext(assistantMsg, toolCall, validatedArgs, context),
|
||||
signal
|
||||
)
|
||||
if signal !== nothing && signal.aborted
|
||||
agentEventSink("prepareToolCall 7")
|
||||
if signal.aborted
|
||||
agentEventSink("prepareToolCall 8")
|
||||
return immediateOutcome(createErrorToolResult("Operation aborted"), true)
|
||||
end
|
||||
|
||||
if before !== nothing && before.block
|
||||
agentEventSink("prepareToolCall 9")
|
||||
return immediateOutcome(
|
||||
createErrorToolResult(get(before, :reason, "Tool execution was blocked")), true)
|
||||
end
|
||||
end
|
||||
|
||||
agentEventSink("prepareToolCall 10")
|
||||
return preparedToolCall(tool, toolCall, validatedArgs)
|
||||
catch err
|
||||
return immediateOutcome(createErrorToolResult(sprint(showerror, err)), true)
|
||||
catch e
|
||||
bt = catch_backtrace()
|
||||
err_msg = sprint() do io
|
||||
showerror(io, e, bt)
|
||||
println(io)
|
||||
end
|
||||
|
||||
agentEventSink(err_msg)
|
||||
|
||||
return immediateOutcome(createErrorToolResult(sprint(showerror, e)), true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -836,31 +940,31 @@ executePreparedToolCall(prep, nothing, emit)
|
||||
function executePreparedToolCall(
|
||||
prep::preparedToolCall,
|
||||
signal::Union{Nothing,abortSignal},
|
||||
emit::Function,
|
||||
)::executedOutcome
|
||||
agentEventSink,
|
||||
)::executedOutcome
|
||||
agentEventSink("executePreparedToolCall 1")
|
||||
updateEvents = promise[]
|
||||
accepting = true
|
||||
|
||||
updateEvents = promise[]
|
||||
accepting = true
|
||||
|
||||
try
|
||||
result = prep.tool.execute(
|
||||
prep.toolCall.id, prep.args, signal,
|
||||
partialResult -> begin
|
||||
if accepting
|
||||
push!(updateEvents,
|
||||
emit(toolExecUpdateEvent(prep.toolCall.id, prep.toolCall.name,
|
||||
prep.toolCall.arguments, partialResult)))
|
||||
end
|
||||
end
|
||||
)
|
||||
accepting = false
|
||||
wait.(updateEvents)
|
||||
return executedOutcome(result, false)
|
||||
catch err
|
||||
accepting = false
|
||||
wait.(updateEvents)
|
||||
return executedOutcome(createErrorToolResult(sprint(showerror, err)), true)
|
||||
end
|
||||
try
|
||||
result = prep.tool.execute(
|
||||
prep.toolCall.id, prep.args, signal,
|
||||
partialResult -> begin
|
||||
if accepting
|
||||
push!(updateEvents,
|
||||
agentEventSink(toolExecUpdateEvent(prep.toolCall.id, prep.toolCall.name,
|
||||
prep.toolCall.arguments, partialResult)))
|
||||
end
|
||||
end
|
||||
)
|
||||
accepting = false
|
||||
wait.(updateEvents)
|
||||
return executedOutcome(result, false)
|
||||
catch err
|
||||
accepting = false
|
||||
wait.(updateEvents)
|
||||
return executedOutcome(createErrorToolResult(sprint(showerror, err)), true)
|
||||
end
|
||||
end
|
||||
|
||||
# ── per-call finalization ───────────────────────────────────────
|
||||
@@ -1011,36 +1115,41 @@ function executeToolCallsSequential(
|
||||
assistantMsg::assistantMessage,
|
||||
toolCalls::Vector{agentToolCall},
|
||||
config::agentLoopConfig,
|
||||
signal::Union{Nothing,abortSignal},
|
||||
emit::Function,
|
||||
signal::abortSignal,
|
||||
agentEventSink,
|
||||
)::agentToolCallBatch
|
||||
agentEventSink("executeToolCallsSequential 1")
|
||||
finalizedCalls = finalizedOutcome[]
|
||||
messages = toolResultMessage[]
|
||||
|
||||
finalizedCalls = finalizedOutcome[]
|
||||
messages = toolResultMessage[]
|
||||
|
||||
for tc in toolCalls
|
||||
emit(toolExecStartEvent(tc.id, tc.name, tc.arguments))
|
||||
|
||||
prep = prepareToolCall(context, assistantMsg, tc, config, signal)
|
||||
|
||||
if prep isa immediateOutcome
|
||||
finalized = finalizedOutcome(tc, prep.result, prep.isError)
|
||||
else
|
||||
executed = executePreparedToolCall(prep, signal, emit)
|
||||
finalized = finalizeExecutedToolCall(context, assistantMsg, prep, executed, config, signal)
|
||||
end
|
||||
|
||||
emit(toolExecEndEvent(finalized.toolCall.id, finalized.toolCall.name,
|
||||
finalized.result, finalized.isError))
|
||||
push!(messages, createToolResultMessage(finalized))
|
||||
push!(finalizedCalls, finalized)
|
||||
|
||||
if signal !== nothing && signal.aborted
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return agentToolCallBatch(messages, shouldTerminate(finalizedCalls))
|
||||
for tc in toolCalls
|
||||
agentEventSink("start tool execute $(tc.id), $(tc.name), $(tc.arguments)")
|
||||
prep = prepareToolCall(context, assistantMsg, tc, config, signal, agentEventSink)
|
||||
agentEventSink("executeToolCallsSequential 2")
|
||||
if prep isa immediateOutcome
|
||||
agentEventSink("executeToolCallsSequential 2-1")
|
||||
finalized = finalizedOutcome(tc, prep.result, prep.isError)
|
||||
agentEventSink("executeToolCallsSequential 2-2")
|
||||
else
|
||||
agentEventSink("executeToolCallsSequential 3")
|
||||
executed = executePreparedToolCall(prep, signal, agentEventSink)
|
||||
agentEventSink("executeToolCallsSequential 3-1")
|
||||
finalized = finalizeExecutedToolCall(context, assistantMsg, prep, executed, config,
|
||||
signal)
|
||||
agentEventSink("executeToolCallsSequential 3-2")
|
||||
end
|
||||
agentEventSink("executeToolCallsSequential 4")
|
||||
agentEventSink("$(finalized.toolCall.id), $(finalized.toolCall.name),
|
||||
$(finalized.result), $(finalized.isError)")
|
||||
push!(messages, createToolResultMessage(finalized))
|
||||
push!(finalizedCalls, finalized)
|
||||
agentEventSink("executeToolCallsSequential 5")
|
||||
if signal !== nothing && signal.aborted
|
||||
break
|
||||
end
|
||||
end
|
||||
agentEventSink("executeToolCallsSequential 6")
|
||||
return agentToolCallBatch(messages, shouldTerminate(finalizedCalls))
|
||||
end
|
||||
|
||||
# ── parallel execution ──────────────────────────────────────────
|
||||
@@ -1105,51 +1214,51 @@ function executeToolCallsParallel(
|
||||
assistantMsg::assistantMessage,
|
||||
toolCalls::Vector{agentToolCall},
|
||||
config::agentLoopConfig,
|
||||
signal::Union{Nothing,abortSignal},
|
||||
emit::Function,
|
||||
signal::abortSignal,
|
||||
agentEventSink,
|
||||
)::agentToolCallBatch
|
||||
|
||||
entries = union{finalizedOutcome,task{finalizedOutcome}}[]
|
||||
entries = union{finalizedOutcome,task{finalizedOutcome}}[]
|
||||
|
||||
for tc in toolCalls
|
||||
emit(toolExecStartEvent(tc.id, tc.name, tc.arguments))
|
||||
for tc in toolCalls
|
||||
agentEventSink(toolExecStartEvent(tc.id, tc.name, tc.arguments))
|
||||
|
||||
prep = prepareToolCall(context, assistantMsg, tc, config, signal)
|
||||
prep = prepareToolCall(context, assistantMsg, tc, config, signal)
|
||||
|
||||
if prep isa immediateOutcome
|
||||
finalized = finalizedOutcome(tc, prep.result, prep.isError)
|
||||
emit(toolExecEndEvent(finalized.toolCall.id, finalized.toolCall.name,
|
||||
finalized.result, finalized.isError))
|
||||
push!(entries, finalized)
|
||||
else
|
||||
task = task() do
|
||||
executed = executePreparedToolCall(prep, signal, emit)
|
||||
finalized = finalizeExecutedToolCall(context, assistantMsg, prep, executed, config, signal)
|
||||
emit(toolExecEndEvent(finalized.toolCall.id, finalized.toolCall.name,
|
||||
finalized.result, finalized.isError))
|
||||
return finalized
|
||||
end
|
||||
schedule(task)
|
||||
push!(entries, task)
|
||||
end
|
||||
|
||||
if signal !== nothing && signal.aborted
|
||||
break
|
||||
end
|
||||
if prep isa immediateOutcome
|
||||
finalized = finalizedOutcome(tc, prep.result, prep.isError)
|
||||
agentEventSink(toolExecEndEvent(finalized.toolCall.id, finalized.toolCall.name,
|
||||
finalized.result, finalized.isError))
|
||||
push!(entries, finalized)
|
||||
else
|
||||
task = task() do
|
||||
executed = executePreparedToolCall(prep, signal, agentEventSink)
|
||||
finalized = finalizeExecutedToolCall(context, assistantMsg, prep, executed, config, signal)
|
||||
agentEventSink(toolExecEndEvent(finalized.toolCall.id, finalized.toolCall.name,
|
||||
finalized.result, finalized.isError))
|
||||
return finalized
|
||||
end
|
||||
schedule(task)
|
||||
push!(entries, task)
|
||||
end
|
||||
|
||||
finalizedCalls = finalizedOutcome[]
|
||||
for entry in entries
|
||||
outcome = entry isa task ? fetch(entry) : entry
|
||||
push!(finalizedCalls, outcome)
|
||||
if signal !== nothing && signal.aborted
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
messages = toolResultMessage[]
|
||||
for f in finalizedCalls
|
||||
push!(messages, createToolResultMessage(f))
|
||||
end
|
||||
finalizedCalls = finalizedOutcome[]
|
||||
for entry in entries
|
||||
outcome = entry isa task ? fetch(entry) : entry
|
||||
push!(finalizedCalls, outcome)
|
||||
end
|
||||
|
||||
return agentToolCallBatch(messages, shouldTerminate(finalizedCalls))
|
||||
messages = toolResultMessage[]
|
||||
for f in finalizedCalls
|
||||
push!(messages, createToolResultMessage(f))
|
||||
end
|
||||
|
||||
return agentToolCallBatch(messages, shouldTerminate(finalizedCalls))
|
||||
end
|
||||
|
||||
|
||||
@@ -1207,24 +1316,29 @@ function executeToolCalls(
|
||||
assistantMsg::assistantMessage,
|
||||
toolCalls::Vector{agentToolCall},
|
||||
config::agentLoopConfig,
|
||||
signal::Union{Nothing,abortSignal},
|
||||
emit::Function,
|
||||
)::agentToolCallBatch
|
||||
signal::abortSignal,
|
||||
agentEventSink,
|
||||
)::agentToolCallBatch
|
||||
|
||||
hasSequential = false
|
||||
for tc in toolCalls
|
||||
t = get(context.tools, tc.name, nothing)
|
||||
if t !== nothing && !t.parallelToolExecute
|
||||
hasSequential = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if config.toolExecution == "sequential" || hasSequential
|
||||
return executeToolCallsSequential(context, assistantMsg, toolCalls, config, signal, emit)
|
||||
else
|
||||
return executeToolCallsParallel(context, assistantMsg, toolCalls, config, signal, emit)
|
||||
end
|
||||
agentEventSink("_executeToolCalls 1")
|
||||
hasSequential = false
|
||||
for tc in toolCalls
|
||||
t = get(context.tools, tc.name, nothing)
|
||||
if t !== nothing && !t.parallelToolExecute
|
||||
hasSequential = true
|
||||
break
|
||||
end
|
||||
end
|
||||
agentEventSink("_executeToolCalls 2")
|
||||
if config.toolExecution == "sequential" || hasSequential
|
||||
agentEventSink("_executeToolCalls 3")
|
||||
return executeToolCallsSequential(context, assistantMsg, toolCalls, config, signal,
|
||||
agentEventSink)
|
||||
else
|
||||
agentEventSink("_executeToolCalls 4")
|
||||
return executeToolCallsParallel(context, assistantMsg, toolCalls, config, signal,
|
||||
agentEventSink)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user