V0.8.0 async think loop #40

Merged
ton merged 50 commits from v0.8.0-async_think_loop into v0.8.0 2026-08-08 04:13:05 +00:00
Showing only changes of commit c626d2cec5 - Show all commits
+38 -14
View File
@@ -6,6 +6,17 @@ module type
using Dates, UUIDs, DataStructures, JSON, NATS
using GeneralUtils
# ============================================================================
# Simple type aliases / definitions
# ============================================================================
const Timestamp = DateTime
struct Usage
inputTokens::Int64
outputTokens::Int64
end
# ---------------------------------------------- 100 --------------------------------------------- #
@@ -20,6 +31,10 @@ struct userMessage <: agentMessage # Message from the user
timestamp::Timestamp # When the message was sent
end
function userMessage(; role="user", content=Vector{messageContent}(), timestamp=now())
return userMessage(role, content, timestamp)
end
struct assistantMessage <: agentMessage # Message from the AI assistant
role::String # Always "assistant"
content::Vector{messageContent} # Text and/or image content
@@ -32,6 +47,12 @@ struct assistantMessage <: agentMessage # Message from the AI assistant
timestamp::Timestamp # When the message was received
end
function assistantMessage(; role="assistant", content=Vector{messageContent}(),
api="", provider="", model="", usage=Usage(0, 0), stopReason="end_turn",
errorMessage=nothing, timestamp=now())
return assistantMessage(role, content, api, provider, model, usage, stopReason, errorMessage, timestamp)
end
struct toolResultMessage <: agentMessage # Result returned from a tool execution
role::String # Always "tool"
toolCallId::String # ID matching the tool call
@@ -44,6 +65,12 @@ struct toolResultMessage <: agentMessage # Result returned from a tool execut
timestamp::Timestamp # When the result was recorded
end
function toolResultMessage(; role="tool", toolCallId="", toolName="",
content=Vector{messageContent}(), details=nothing, usage=nothing,
addedToolNames=nothing, isError=false, timestamp=now())
return toolResultMessage(role, toolCallId, toolName, content, details, usage, addedToolNames, isError, timestamp)
end
# ============================================================================
# Message content types
@@ -55,11 +82,19 @@ struct textContent <: messageContent # Plain text message content
text::String # The text content
end
function textContent(; text="")
return textContent(text)
end
struct imageContent <: messageContent # Image message content
data::String # Base64-encoded image data
mimeType::String # MIME type (e.g., "image/png")
end
function imageContent(; data="", mimeType="")
return imageContent(data, mimeType)
end
# ============================================================================
# Tool types
@@ -256,7 +291,7 @@ end
Private agent loop. Runs in a background @task.
Waits on input_ch and followUpQueue concurrently via select().
"""
function _agent_loop(agent::yiemAgent)
function _agent_loop(agent::yiemAgent) #WORKING
try
while true
# Wait on either channel — the one with a message fires first
@@ -275,18 +310,7 @@ function _agent_loop(agent::yiemAgent)
end
catch e
# On any error, send error response and exit the loop
try
put!(agent.output_ch, assistantMessage(
role="assistant",
content=[textContent("Agent error: $(sprint(showerror, e))")],
api="", model="", usage=nothing,
stopReason="error",
errorMessage=strip(sprint(showerror, e)),
timestamp=now(),
))
catch e2
@error "Failed to send error response" error=e2
end
@error "Agent loop failed" error=e
end
end
@@ -295,7 +319,7 @@ Process a single message through the agent pipeline.
This is where you add your LLM call, tool execution, etc.
"""
function _process_message(agent::yiemAgent, msg)
# TODO: Replace with actual processing logic
# PENDING Replace with actual processing logic
#
# 1. Add msg to agent._state.messages
# 2. Call agent.formatMsgForLLM(agent._state) to format for LLM