This commit is contained in:
2026-08-06 15:32:56 +07:00
parent 4cb01c71bb
commit 8a2da0f5c3
6 changed files with 458 additions and 630 deletions
+175 -39
View File
@@ -1,15 +1,11 @@
module type
export agent, sommelier, companion, virtualcustomer, agentContext, yiemAgent,
export agentContext, yiemAgent,
run_agent, take_response, follow_up, stop_agent
using Dates, UUIDs, DataStructures, JSON, NATS
using GeneralUtils
# ============================================================================
# Simple type aliases / definitions
# ============================================================================
const Timestamp = DateTime
struct Usage
@@ -17,12 +13,10 @@ struct Usage
outputTokens::Int64
end
# ---------------------------------------------- 100 --------------------------------------------- #
# ============================================================================
# Message types
# ============================================================================
# ------------------------------------------------------------------------------------------------ #
# Message types #
# ------------------------------------------------------------------------------------------------ #
abstract type agentMessage end # Base type for all agent messages
struct userMessage <: agentMessage # Message from the user
@@ -135,9 +129,9 @@ function toolResultMessage(; role="tool", toolCallId="", toolName="",
end
# ============================================================================
# Message content types
# ============================================================================
# ------------------------------------------------------------------------------------------------ #
# Message content types #
# ------------------------------------------------------------------------------------------------ #
abstract type messageContent end # Base type for message content
@@ -190,9 +184,9 @@ function imageContent(; data="", mimeType="")
end
# ============================================================================
# Tool types
# ============================================================================
# ------------------------------------------------------------------------------------------------ #
# Tool types #
# ------------------------------------------------------------------------------------------------ #
"""
A tool available to the agent.
@@ -220,9 +214,9 @@ struct agentTool{TParameters, TDetails} # A tool available to the agent
end
# ============================================================================
# Agent context
# ============================================================================
# ------------------------------------------------------------------------------------------------ #
# Agent context #
# ------------------------------------------------------------------------------------------------ #
"""
Snapshot of the agent's conversation context.
@@ -242,15 +236,18 @@ struct agentContext # Snapshot of the agent's conversa
end
# ============================================================================
# Agent state
# ============================================================================
# ------------------------------------------------------------------------------------------------ #
# Agent state #
# ------------------------------------------------------------------------------------------------ #
mutable struct agentState # Mutable runtime state of an agent
systemPrompt::String # System prompt text
model::llmModel # LLM model to use
tools::Vector{agentTool} # Available tools
messages::Vector{agentMessage} # Conversation messages
# messages history includes userMessage, assistantMessage, toolResultMessage
messages::Vector{agentMessage}
pendingToolCalls::Vector{String} # Tool call IDs waiting for results
activeRun::Bool # is agent processing user message?
errorMessage::Union{String, Nothing} # Last error message
@@ -343,9 +340,148 @@ struct llmModel{Api} # LLM model configuration
maxTokens::Int64 # Maximum output tokens per completion
end
# ============================================================================
# Agent struct
# ============================================================================
# ------------------------------------------------------------------------------------------------ #
# Agent loop configuration & tool execution types #
# ------------------------------------------------------------------------------------------------ #
"""
Configuration for the agent tool execution loop.
# Arguments
- `tools::Vector{agentTool}`: Available tools
- `beforeToolCall::Union{Function, Nothing}`: Callback before tool execution
- `afterToolCall::Union{Function, Nothing}`: Callback after tool execution
- `toolExecution::String`: Execution mode — "sequential" or "parallel"
"""
struct agentLoopConfig
tools::Vector{agentTool}
beforeToolCall::Union{Function, Nothing}
afterToolCall::Union{Function, Nothing}
toolExecution::String
end
"""
Signal for aborting ongoing operations.
# Arguments
- `aborted::Bool`: Whether the operation has been aborted
"""
struct abortSignal
aborted::Bool
end
"""
Result returned by tool execution before the `afterToolCall` hook.
# Arguments
- `content::Vector{messageContent}`: Tool output content
- `details::Dict{Any,Any}`: Tool-specific details
- `usage::Union{Usage, Nothing}`: Token usage if applicable
- `terminate::Bool`: Whether tool requests termination of the agent loop
"""
struct agentToolResult
content::Vector{messageContent}
details::Dict{Any,Any}
usage::Union{Usage, Nothing}
terminate::Bool
end
"""
Function type for parallel execution override on a tool.
# Arguments
- Context for parallel execution
# Returns
- `agentToolCallBatch`: The result batch from parallel execution
"""
const toolparallelExecute = Function
"""
Context passed to the `beforeToolCall` hook.
# Arguments
- `message::assistantMessage`: The assistant message containing the tool call
- `toolCall::agentToolCall`: The tool call being prepared
- `args::Dict{String,Any}`: Validated tool arguments
- `context::agentContext`: Current conversation context
"""
struct assistantMsgCtx
message::assistantMessage
toolCall::agentToolCall
args::Dict{String,Any}
context::agentContext
end
"""
Context passed to the `afterToolCall` hook.
# Arguments
- `message::assistantMessage`: The assistant message containing the tool call
- `toolCall::agentToolCall`: The tool call that was executed
- `args::Dict{String,Any}`: Tool arguments
- `result::agentToolResult`: The raw tool result
- `isError::Bool`: Whether execution resulted in an error
- `context::agentContext`: Current conversation context
"""
struct afterCtx
message::assistantMessage
toolCall::agentToolCall
args::Dict{String,Any}
result::agentToolResult
isError::Bool
context::agentContext
end
"""
Event emitted when a tool call execution starts.
# Arguments
- `toolCallId::String`: ID of the tool call
- `toolName::String`: Name of the tool
- `arguments::Dict{String,Any}`: Tool arguments
"""
struct toolExecStartEvent
toolCallId::String
toolName::String
arguments::Dict{String,Any}
end
"""
Event emitted with partial results during tool execution.
# Arguments
- `toolCallId::String`: ID of the tool call
- `toolName::String`: Name of the tool
- `arguments::Dict{String,Any}`: Tool arguments
- `partialResult::Any`: The partial result data
"""
struct toolExecUpdateEvent
toolCallId::String
toolName::String
arguments::Dict{String,Any}
partialResult::Any
end
"""
Event emitted when a tool call execution ends.
# Arguments
- `toolCallId::String`: ID of the tool call
- `toolName::String`: Name of the tool
- `result::agentToolResult`: The final tool result
- `isError::Bool`: Whether execution resulted in an error
"""
struct toolExecEndEvent
toolCallId::String
toolName::String
result::agentToolResult
isError::Bool
end
# ------------------------------------------------------------------------------------------------ #
# Agent struct #
# ------------------------------------------------------------------------------------------------ #
abstract type agent end
@@ -367,14 +503,14 @@ mutable struct yiemAgent <: agent # High-level agent wrapper
# and all followUp messages.
outputChannel::Channel
_task::Union{Task, Nothing} # Background task running the agent loop
_agent_loop::Union{Task, Nothing} # agent loop running in the background
# Preprocess/transform messages and context (modify, filter, prune, inject context from memory,
# reorder, ...) for a single LLM call in _process_message()'s loop.
# returns new Vector{agentMessage}
preprocessContext ::Union{Function, Nothing}
prepareContext ::Union{Function, Nothing}
# Convert preprocessContext()'s new Vector{agentMessage} to LLM message format
# Convert prepareContext()'s new Vector{agentMessage} to LLM message format
formatMsgForLLM::Function
# Actually invoke the LLM to get a completion response. The LLM response comes back as an
@@ -391,8 +527,8 @@ mutable struct yiemAgent <: agent # High-level agent wrapper
# Callback invoked after executing a tool call to sanitize tools output so the output is ready
# to be converted into toolResults message
afterToolCall::Union{Function, Nothing}
prepareNextTurn::Union{Function, Nothing} # Callback to prepare the next conversation turn
prepareNextTurnWithContext::Union{Function, Nothing} # Same but receives context
# prepareNextTurn::Union{Function, Nothing} # Callback to prepare the next conversation turn
# prepareNextTurnWithContext::Union{Function, Nothing} # Same but receives context
sessionId::Union{String, Nothing} # Optional session identifier
maxRetryDelayMs::Union{Int64, Nothing} # Maximum delay between retries (ms)
parallelToolExecute::Bool # Default: false
@@ -412,7 +548,7 @@ on `inputChannel` and `followUpChannel` channels concurrently.
- `messages::Vector{agentMessage}`: Initial conversation messages (default: empty)
- `formatMsgForLLM::Function`: Convert agent messages to LLM message format (default: `defaultformatMsgForLLM`)
- `llmCall::Function`: Function to invoke the LLM (required)
- `preprocessContext::Union{Function, Nothing}`: Preprocess/transform messages before sending to LLM (default: `nothing`)
- `prepareContext::Union{Function, Nothing}`: Preprocess/transform messages before sending to LLM (default: `nothing`)
- `beforeToolCall::Union{Function, Nothing}`: Callback invoked before executing a tool call (default: `nothing`)
- `afterToolCall::Union{Function, Nothing}`: Callback invoked after executing a tool call (default: `nothing`)
- `prepareNextTurn::Union{Function, Nothing}`: Callback to prepare the next conversation turn (default: `nothing`)
@@ -436,13 +572,13 @@ function yiemAgent(
model=nothing,
tools::Vector{agentTool}=agentTool[],
messages::Vector{agentMessage}=agentMessage[],
preprocessContext::Union{Function, Nothing}=nothing,
prepareContext::Union{Function, Nothing}=nothing,
formatMsgForLLM::Function=defaultformatMsgForLLM,
llmCall::Function,
beforeToolCall::Union{Function, Nothing}=nothing,
afterToolCall::Union{Function, Nothing}=nothing,
prepareNextTurn::Union{Function, Nothing}=nothing,
prepareNextTurnWithContext::Union{Function, Nothing}=nothing,
# prepareNextTurn::Union{Function, Nothing}=nothing,
# prepareNextTurnWithContext::Union{Function, Nothing}=nothing,
sessionId::Union{String, Nothing}=nothing,
maxRetryDelayMs::Union{Int64, Nothing}=nothing,
parallelToolExecute::Bool=false,
@@ -460,13 +596,13 @@ function yiemAgent(
followUp,
outputChannel,
nothing, # placeholder — replaced below
preprocessContext,
prepareContext,
formatMsgForLLM,
llmCall,
beforeToolCall,
afterToolCall,
prepareNextTurn,
prepareNextTurnWithContext,
# prepareNextTurn,
# prepareNextTurnWithContext,
sessionId,
maxRetryDelayMs,
parallelToolExecute,
@@ -474,7 +610,7 @@ function yiemAgent(
)
# Spawn the background loop and attach it
agent._task = @spawn _agent_loop(agent)
agent._agent_loop = @spawn _agent_loop(agent)
return agent
end