update
This commit is contained in:
+265
-106
@@ -11,37 +11,36 @@ using GeneralUtils
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Message types
|
# Message types
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
abstract type agentMessage end
|
abstract type agentMessage end # Base type for all agent messages
|
||||||
|
|
||||||
struct userMessage <: agentMessage
|
struct userMessage <: agentMessage # Message from the user
|
||||||
role::String
|
role::String # Always "user"
|
||||||
content::Vector{messageContent}
|
content::Vector{messageContent} # Text and/or image content
|
||||||
timestamp::Timestamp
|
timestamp::Timestamp # When the message was sent
|
||||||
end
|
end
|
||||||
|
|
||||||
struct assistantMessage <: agentMessage
|
struct assistantMessage <: agentMessage # Message from the AI assistant
|
||||||
role::String
|
role::String # Always "assistant"
|
||||||
content::Vector{messageContent}
|
content::Vector{messageContent} # Text and/or image content
|
||||||
api::String
|
api::String # API name used (e.g., "openai")
|
||||||
provider::String
|
provider::String # Provider name (e.g., "anthropic")
|
||||||
model::String
|
model::String # Model identifier
|
||||||
usage::Usage
|
usage::Usage # Token usage for this message
|
||||||
stop_reason::String
|
stopReason::String # Why generation stopped (e.g., "end_turn")
|
||||||
error_message::Union{String, Nothing}
|
errorMessage::Union{String, Nothing} # Error if generation failed
|
||||||
timestamp::Timestamp
|
timestamp::Timestamp # When the message was received
|
||||||
end
|
end
|
||||||
|
|
||||||
struct toolResultMessage <: agentMessage
|
struct toolResultMessage <: agentMessage # Result returned from a tool execution
|
||||||
|
role::String # Always "tool"
|
||||||
role::String
|
toolCallId::String # ID matching the tool call
|
||||||
tool_call_id::String
|
toolName::String # Name of the executed tool
|
||||||
tool_name::String
|
content::Vector{messageContent} # Tool output content
|
||||||
content::Vector{messageContent}
|
details::Any # Additional tool-specific details
|
||||||
details::Any
|
usage::Union{Usage, Nothing} # Token usage if applicable
|
||||||
usage::Union{Usage, Nothing}
|
addedToolNames::Union{Vector{String}, Nothing} # Tools added during execution
|
||||||
added_tool_names::Union{Vector{String}, Nothing}
|
isError::Bool # Whether the tool call resulted in an error
|
||||||
is_error::Bool
|
timestamp::Timestamp # When the result was recorded
|
||||||
timestamp::Timestamp
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -49,15 +48,15 @@ end
|
|||||||
# Message content types
|
# Message content types
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
abstract type messageContent end
|
abstract type messageContent end # Base type for message content
|
||||||
|
|
||||||
struct textContent <: messageContent
|
struct textContent <: messageContent # Plain text message content
|
||||||
text::String
|
text::String # The text content
|
||||||
end
|
end
|
||||||
|
|
||||||
struct imageContent <: messageContent
|
struct imageContent <: messageContent # Image message content
|
||||||
data::String
|
data::String # Base64-encoded image data
|
||||||
mime_type::String
|
mimeType::String # MIME type (e.g., "image/png")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -65,14 +64,14 @@ end
|
|||||||
# Tool types
|
# Tool types
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
struct agentTool{TParameters, TDetails}
|
struct agentTool{TParameters, TDetails} # A tool available to the agent
|
||||||
name::String
|
name::String # Tool identifier
|
||||||
label::String
|
label::String # Human-readable tool name
|
||||||
description::String
|
description::String # What the tool does
|
||||||
parameters::TParameters
|
parameters::TParameters # Tool parameters schema (JSON schema)
|
||||||
execute::Function
|
execute::Function # Tool execution function
|
||||||
prepare_arguments::Union{Function, Nothing}
|
prepareArguments::Union{Function, Nothing} # Optional argument preparation callback
|
||||||
execution_mode::Union{ToolExecutionMode, Nothing}
|
executionMode::Union{toolExecutionMode, Nothing} # Override: run tool calls sequentially or in parallel
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -80,10 +79,10 @@ end
|
|||||||
# Agent context
|
# Agent context
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
struct agentContext
|
struct agentContext # Snapshot of the agent's conversation context
|
||||||
system_prompt::String
|
systemPrompt::String # System prompt for the agent
|
||||||
messages::Vector{agentMessage}
|
messages::Vector{agentMessage} # Conversation messages
|
||||||
tools::Union{Vector{agentTool}, Nothing}
|
tools::Union{Vector{agentTool}, Nothing} # Available tools
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -92,35 +91,35 @@ end
|
|||||||
# Assistant message event types
|
# Assistant message event types
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
abstract type assistantMessageEvent end
|
abstract type assistantMessageEvent end # Base type for assistant message streaming events
|
||||||
|
|
||||||
struct startEvent <: assistantMessageEvent
|
struct startEvent <: assistantMessageEvent # Message generation started
|
||||||
partial::assistantMessage
|
partial::assistantMessage # The partial message at this point
|
||||||
end
|
end
|
||||||
struct textStartEvent <: assistantMessageEvent
|
struct textStartEvent <: assistantMessageEvent # Text content block started
|
||||||
content_index::Int64
|
contentIndex::Int64 # Index of the content block
|
||||||
partial::assistantMessage
|
partial::assistantMessage # The partial message at this point
|
||||||
end
|
end
|
||||||
struct textDeltaEvent <: assistantMessageEvent
|
struct textDeltaEvent <: assistantMessageEvent # Text content block received a chunk
|
||||||
content_index::Int64
|
contentIndex::Int64 # Index of the content block
|
||||||
delta::String
|
delta::String # New text chunk
|
||||||
partial::assistantMessage
|
partial::assistantMessage # The partial message at this point
|
||||||
end
|
end
|
||||||
struct textEndEvent <: assistantMessageEvent
|
struct textEndEvent <: assistantMessageEvent # Text content block completed
|
||||||
content_index::Int64
|
contentIndex::Int64 # Index of the content block
|
||||||
content::String
|
content::String # Complete text content
|
||||||
partial::assistantMessage
|
partial::assistantMessage # The partial message at this point
|
||||||
end
|
end
|
||||||
struct doneEvent <: assistantMessageEvent
|
struct doneEvent <: assistantMessageEvent # Message generation completed successfully
|
||||||
reason::String
|
reason::String # Why generation stopped
|
||||||
usage::Usage
|
usage::Usage # Token usage
|
||||||
message::assistantMessage
|
message::assistantMessage # The completed message
|
||||||
end
|
end
|
||||||
struct errorEvent <: assistantMessageEvent
|
struct errorEvent <: assistantMessageEvent # Message generation encountered an error
|
||||||
reason::String
|
reason::String # Error reason
|
||||||
error_message::Union{String, Nothing}
|
errorMessage::Union{String, Nothing} # Human-readable error
|
||||||
usage::Usage
|
usage::Usage # Token usage (partial)
|
||||||
error::assistantMessage
|
error::assistantMessage # The error message
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -129,48 +128,41 @@ end
|
|||||||
# Agent state
|
# Agent state
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
mutable struct agentState
|
mutable struct agentState # Mutable runtime state of an agent
|
||||||
system_prompt::String
|
systemPrompt::String # System prompt text
|
||||||
model::Model
|
model::llmModel # LLM model to use
|
||||||
thinking_level::ThinkingLevel
|
tools::Vector{agentTool} # Available tools
|
||||||
tools::Vector{agentTool}
|
messages::Vector{agentMessage} # Conversation messages
|
||||||
messages::Vector{agentMessage}
|
pendingToolCalls::Vector{String} # Tool call IDs waiting for results
|
||||||
is_streaming::Bool
|
errorMessage::Union{String, Nothing} # Last error message
|
||||||
streaming_message::Union{agentMessage, Nothing}
|
end
|
||||||
pending_tool_calls::Set{String}
|
|
||||||
error_message::Union{String, Nothing}
|
|
||||||
|
|
||||||
function agentState(
|
function agentState(
|
||||||
system_prompt::String="",
|
systemPrompt::String="",
|
||||||
model::Model=Model("", "", "unknown", "unknown", "", false, String[], ModelCost(0.0, 0.0, 0.0, 0.0), 0, 0),
|
model::llmModel=llmModel{String}("", "", "unknown", "unknown", "", false, String[], modelCost(0.0, 0.0, 0.0, 0.0), 0, 0),
|
||||||
thinking_level::ThinkingLevel=THINKING_OFF,
|
tools::Vector{agentTool}=agentTool[],
|
||||||
tools::Vector{agentTool}=agentTool[],
|
messages::Vector{agentMessage}=agentMessage[],
|
||||||
messages::Vector{agentMessage}=agentMessage[],
|
)
|
||||||
|
agentState(
|
||||||
|
systemPrompt,
|
||||||
|
model,
|
||||||
|
deepcopy(tools),
|
||||||
|
deepcopy(messages),
|
||||||
|
Vector{String}(),
|
||||||
|
nothing,
|
||||||
)
|
)
|
||||||
new(
|
|
||||||
system_prompt,
|
|
||||||
model,
|
|
||||||
thinking_level,
|
|
||||||
copy(tools),
|
|
||||||
copy(messages),
|
|
||||||
false,
|
|
||||||
nothing,
|
|
||||||
Set{String}(),
|
|
||||||
nothing,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Tool call types
|
# Tool call types
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
struct toolCall
|
struct toolCall # A tool invocation from the LLM
|
||||||
type::String
|
type::String # Always "function"
|
||||||
id::String
|
id::String # Unique tool call identifier
|
||||||
name::String
|
name::String # Tool name
|
||||||
arguments::Dict{String, Any}
|
arguments::Dict{String, Any} # Parsed tool arguments
|
||||||
partial_json::Union{String, Nothing}
|
partialJson::Union{String, Nothing} # Raw JSON string during streaming
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -178,12 +170,179 @@ end
|
|||||||
# Next turn context
|
# Next turn context
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
struct nextTurnContext
|
struct nextTurnContext # Context for preparing the next conversation turn
|
||||||
message::assistantMessage
|
message::assistantMessage # The assistant's message that just completed
|
||||||
tool_results::Vector{toolResultMessage}
|
toolResults::Vector{toolResultMessage} # Tool results from this turn
|
||||||
context::agentContext
|
context::agentContext # Current conversation context
|
||||||
new_messages::Vector{agentMessage}
|
newMessages::Vector{agentMessage} # Messages to append to the context
|
||||||
|
end
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# llmModel types
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
struct modelCost # Model pricing per 1M tokens
|
||||||
|
input::Float64 # Price per 1M input tokens
|
||||||
|
output::Float64 # Price per 1M output tokens
|
||||||
|
cache_read::Float64 # Price per 1M cached read tokens
|
||||||
|
cache_write::Float64 # Price per 1M cache write tokens
|
||||||
|
end
|
||||||
|
|
||||||
|
struct llmModel{Api} # LLM model configuration
|
||||||
|
id::String # Unique model identifier
|
||||||
|
name::String # Human-readable model name
|
||||||
|
api::Api # API type (parametric type)
|
||||||
|
provider::String # Provider name (e.g., "anthropic", "openai")
|
||||||
|
baseUrl::String # API endpoint base URL
|
||||||
|
reasoning::Bool # Whether the model supports chain-of-thought
|
||||||
|
input::Vector{String} # Supported input modalities (e.g., "text", "image")
|
||||||
|
cost::modelCost # Pricing information
|
||||||
|
contextWindow::Int64 # Maximum context length in tokens
|
||||||
|
maxTokens::Int64 # Maximum output tokens per completion
|
||||||
|
end
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Agent struct
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
mutable struct yiemAgent # High-level agent wrapper
|
||||||
|
_state::agentState # Current state (prompt, model, messages, tools, etc.)
|
||||||
|
conn::NATS.Connection # NATS connection for messaging
|
||||||
|
followUpQueue::pendingMessageQueue # Messages queued via followUp() when agent would stop
|
||||||
|
|
||||||
|
formatMsgForLLM::Function # Convert agent messages to LLM message format
|
||||||
|
preprocessMessages ::Union{Function, Nothing} # Preprocess/transform messages before sending
|
||||||
|
streamFunction::streamFn # Stream function for streaming responses
|
||||||
|
getApiKey::Union{Function, Nothing} # Callback to retrieve API key
|
||||||
|
onPayload::Union{Function, Nothing} # Callback when a payload is sent to the API
|
||||||
|
onResponse::Union{Function, Nothing} # Callback when a full response is received
|
||||||
|
beforeToolCall::Union{Function, Nothing} # Callback invoked before executing a tool call
|
||||||
|
afterToolCall::Union{Function, Nothing} # Callback invoked after executing a tool call
|
||||||
|
prepareNextTurn::Union{Function, Nothing} # Callback to prepare the next conversation turn
|
||||||
|
prepareNextTurnWithContext::Union{Function, Nothing} # Same but receives context
|
||||||
|
activeRun::Union{activeRun, Nothing} # Active run state (promise, abort controller)
|
||||||
|
sessionId::Union{String, Nothing} # Optional session identifier
|
||||||
|
thinkingBudgets::Union{Dict{String, Int64}, Nothing} # Per-model thinking token budgets
|
||||||
|
transport::String # Transport mode ("auto" or explicit)
|
||||||
|
maxRetryDelayMs::Union{Int64, Nothing} # Maximum delay between retries (ms)
|
||||||
|
toolExecution::toolExecutionMode # Default: run tool calls sequentially or in parallel
|
||||||
|
end
|
||||||
|
|
||||||
|
# Outer constructor — clean keyword API
|
||||||
|
function yiemAgent(
|
||||||
|
; systemPrompt::String="",
|
||||||
|
model::llmModel=llmModel{String}("", "", "unknown", "unknown", "", false, String[], modelCost(0.0, 0.0, 0.0, 0.0), 0, 0),
|
||||||
|
thinkingLevel::thinkingLevel=THINKING_OFF,
|
||||||
|
tools::Vector{agentTool}=agentTool[],
|
||||||
|
messages::Vector{agentMessage}=agentMessage[],
|
||||||
|
formatMsgForLLM::Function=defaultformatMsgForLLM,
|
||||||
|
preprocessMessages ::Union{Function, Nothing}=nothing,
|
||||||
|
streamFunction::streamFn=getDefaultStreamFn(),
|
||||||
|
getApiKey::Union{Function, Nothing}=nothing,
|
||||||
|
onPayload::Union{Function, Nothing}=nothing,
|
||||||
|
onResponse::Union{Function, Nothing}=nothing,
|
||||||
|
beforeToolCall::Union{Function, Nothing}=nothing,
|
||||||
|
afterToolCall::Union{Function, Nothing}=nothing,
|
||||||
|
prepareNextTurn::Union{Function, Nothing}=nothing,
|
||||||
|
prepareNextTurnWithContext::Union{Function, Nothing}=nothing,
|
||||||
|
sessionId::Union{String, Nothing}=nothing,
|
||||||
|
thinkingBudgets::Union{Dict{String, Int64}, Nothing}=nothing,
|
||||||
|
transport::String="auto",
|
||||||
|
maxRetryDelayMs::Union{Int64, Nothing}=nothing,
|
||||||
|
toolExecution::toolExecutionMode=EXECUTION_PARALLEL,
|
||||||
|
)
|
||||||
|
new(
|
||||||
|
agentState(systemPrompt, model, tools, messages),
|
||||||
|
Set{Tuple{Function, Ref{Bool}}}(),
|
||||||
|
pendingMessageQueue(QUEUE_ONE_AT_A_TIME),
|
||||||
|
pendingMessageQueue(QUEUE_ONE_AT_A_TIME),
|
||||||
|
formatMsgForLLM,
|
||||||
|
preprocessMessages ,
|
||||||
|
streamFunction,
|
||||||
|
getApiKey,
|
||||||
|
onPayload,
|
||||||
|
onResponse,
|
||||||
|
beforeToolCall,
|
||||||
|
afterToolCall,
|
||||||
|
prepareNextTurn,
|
||||||
|
prepareNextTurnWithContext,
|
||||||
|
nothing,
|
||||||
|
sessionId,
|
||||||
|
thinkingBudgets,
|
||||||
|
transport,
|
||||||
|
maxRetryDelayMs,
|
||||||
|
toolExecution,
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end # module type
|
end # module type
|
||||||
|
|||||||
Reference in New Issue
Block a user