diff --git a/src/agentCore.jl b/src/agentCore.jl index c5cde25..2a55205 100644 --- a/src/agentCore.jl +++ b/src/agentCore.jl @@ -12,9 +12,9 @@ using ..type, ..util, ..llmfunction """ Private agent loop. Runs in a background `@spawn` task. -Waits on `input_ch` and `followUpQueue`, processing whichever has a message first. +Waits on `inputChannel` and `followUpChannel`, processing whichever has a message first. On each iteration, dispatches the message through `_process_message` and sends the result -to `output_ch`. Exits on `:shutdown` signal. +to `outputChannel`. Exits on `:shutdown` signal. # Arguments - `agent::yiemAgent`: The agent whose loop to run @@ -25,22 +25,26 @@ to `output_ch`. Exits on `:shutdown` signal. # Notes - This function is automatically spawned as a background task when a `yiemAgent` is created. - On any error, logs the error with `@error` and exits the loop. -- Message priority: `input_ch` messages are checked before `followUpQueue` messages. +- Message priority: `inputChannel` messages are checked before `followUpChannel` messages. # Examples ```jldoctest julia> # Called automatically by yiemAgent constructor ``` """ -function _agent_loop(agent::yiemAgent) #WORKING +function _agent_loop(agent::yiemAgent) try while true # Wait on either channel — the one with a message fires first # Wait on either channel — the one with a message is taken first msg = nothing while msg === nothing - if isready(agent.input_ch) - msg = take!(agent.input_ch) + if isready(agent.inputChannel) + msg = take!(agent.inputChannel) + + #TODO convert raw user msg to userMessage type + + #TODO add userMessage to agent._state.messages else yield() end @@ -52,20 +56,19 @@ function _agent_loop(agent::yiemAgent) #WORKING break end - #TODO convert raw user msg to userMessage type - - #TODO add userMessage to agent._state.messages - - - if isready(agent.followUpQueue) - msg = take!(agent.followUpQueue) - end - - # @spawn. Dispatch message through the processing pipeline. + # Dispatch message through the processing pipeline result = _process_message(agent, msg) - # Send response to user - put!(agent.output_ch, result) + + + # check followUp message. if there are, add them all to agent.inputChannel + + + + + # Send response to user if no user message in both agent.inputChannel and agent.followUpChannel, + # output the result + put!(agent.outputChannel, result) end catch e # On any error, send error response and exit the loop @@ -73,6 +76,7 @@ function _agent_loop(agent::yiemAgent) #WORKING end end + """ Process a single message through the agent pipeline. @@ -81,7 +85,7 @@ should be implemented. Currently a placeholder that echoes back the received mes # Arguments - `agent::yiemAgent`: The agent processing the message -- `msg`: The message to process (from `input_ch` or `followUpQueue`) +- `msg`: The message to process (from `inputChannel` or `followUpChannel`) # Returns - An `assistantMessage` instance with the processed response @@ -102,14 +106,12 @@ julia> # Currently returns a placeholder echo response """ function _process_message(agent::yiemAgent, msg) # WORKING Replace with actual processing logic - # check steering message + + while (# ) - - - # 1. call agent. # 2. Call agent.formatMsgForLLM(agent._state) to format for LLM # 3. If preprocessMessages is set, call agent.preprocessMessages(...) # 4. Call the LLM (blocking — the task waits here) diff --git a/src/api.jl b/src/api.jl index f8769bb..9412301 100644 --- a/src/api.jl +++ b/src/api.jl @@ -15,7 +15,7 @@ using ..type, ..util, ..llmfunction Send a message to the agent's input channel. Blocks if the input channel buffer is full (capacity 16 by default). -The agent processes messages from `input_ch` in the background task. +The agent processes messages from `inputChannel` in the background task. # Arguments - `agent::yiemAgent`: The agent instance to send a message to @@ -35,7 +35,7 @@ yiemAgent(...) ``` """ function run_agent(agent::yiemAgent, msg) - put!(agent.input_ch, msg) + put!(agent.inputChannel, msg) return agent end @@ -60,13 +60,13 @@ assistantMessage(...) ``` """ function take_response(agent::yiemAgent) - return take!(agent.output_ch) + return take!(agent.outputChannel) end """ Send a follow-up message while the agent is still processing. -Follow-up messages are queued and processed after all `input_ch` messages +Follow-up messages are queued and processed after all `inputChannel` messages and before any tool call results are sent. # Arguments @@ -88,7 +88,7 @@ yiemAgent(...) ``` """ function follow_up(agent::yiemAgent, msg) - put!(agent.followUpQueue, msg) + put!(agent.followUpChannel, msg) return agent end @@ -96,7 +96,7 @@ end Gracefully stop the agent. Sends a `:shutdown` signal to the input channel, waits for the background task to finish, -then closes all channels (`input_ch`, `output_ch`, `followUpQueue`). +then closes all channels (`inputChannel`, `outputChannel`, `followUpChannel`). # Arguments - `agent::yiemAgent`: The agent instance to stop @@ -115,7 +115,7 @@ julia> stop_agent(agent) ``` """ function stop_agent(agent::yiemAgent) - put!(agent.input_ch, :shutdown) + put!(agent.inputChannel, :shutdown) try fetch(agent._task) catch e @@ -123,9 +123,9 @@ function stop_agent(agent::yiemAgent) rethrow(e) end end - close(agent.input_ch) - close(agent.output_ch) - close(agent.followUpQueue) + close(agent.inputChannel) + close(agent.outputChannel) + close(agent.followUpChannel) return nothing end diff --git a/src/type.jl b/src/type.jl index 6e57efc..1856a56 100644 --- a/src/type.jl +++ b/src/type.jl @@ -353,18 +353,17 @@ docstring mutable struct yiemAgent <: agent # High-level agent wrapper _state::agentState # Current state (prompt, model, messages, tools, etc.) - input_ch::Channel # user sends prompt message to agent. + inputChannel::Channel # user sends prompt message to agent. # if agent is idle, it process user message right away. # if agent is running, it process user message after # the current tool call finished. - followUpQueue::Channel # Messages queued via follow_up() during agent is - # running. After the agent loop process all input_ch - # and the agent isn't using tool call, it processes - # followUp messages + followUpChannel::Channel # Buffers messages the user sends while the agent is busy. + # Processed after all inputChannel messages are handled + # and the agent is idle (not using a tool call). - output_ch::Channel # agent sends response message to user after processing - # all user messages in input_ch and all followUp messages. + outputChannel::Channel # agent sends response message to user after processing + # all user messages in inputChannel and all followUp messages. _task::Union{Task, Nothing} # Background task running the agent loop @@ -383,7 +382,7 @@ end Create a new yiemAgent instance with a background loop task. Spawns a background `@spawn` task that runs the agent loop, listening -on `input_ch` and `followUpQueue` channels concurrently. +on `inputChannel` and `followUpChannel` channels concurrently. # Keyword Arguments - `systemPrompt::String`: System prompt for the agent @@ -425,16 +424,16 @@ function yiemAgent( toolExecution=nothing, ) # Create channels: input (user -> agent), followUp (async queue), output (agent -> user) - input_ch = Channel(16) + inputChannel = Channel(16) followUp = Channel(32) - output_ch = Channel(16) + outputChannel = Channel(16) # Create struct with a placeholder task, then spawn and replace it agent = yiemAgent( agentState(systemPrompt, model, tools, messages), - input_ch, + inputChannel, followUp, - output_ch, + outputChannel, nothing, # placeholder — replaced below formatMsgForLLM, preprocessMessages,