Summary
This branch introduces infrastructure to maintain multiple parallel workers. This infrastructure is also agnostic of UI implementation, and allows to work with various UIs.
The ultimate goals of this effort are:
- give Q CLI an ultimate version of 'Delagate' tool, that would spawn background workers, executing delegated tasks in parallel
- allow easy swap between UI modes - structured (output everything in JSON), normal (similar to current CX), advanced (full blown TUI with panes, widgets, etc)
- allow to easily plug in web API provider, that could be used by external local web app, providing user a fancy UI torun one or more Q CLI instances in different folders
Demo
TBD
Structure
1: Core Execution Components
Session
Purpose: Central orchestrator managing all workers and jobs in the system.
Key Responsibilities:
- Creates and tracks workers with configured model providers
- Launches jobs by combining workers with tasks
- Manages job lifecycle (active/inactive tracking, cleanup)
- Provides shared resources (model providers, thread pools)
Key Methods:
build_worker(name) - Creates new worker with model provider
run_agent_loop(worker, input, ui_interface) - Launches agent loop task
cancel_all_jobs() - Cancels all active jobs
cleanup_inactive_jobs() - Removes old completed jobs (keeps last 3)
wait_for_all_jobs() - Blocks until all jobs complete
Location: crates/chat-cli/src/agent_env/session.rs
Worker
Purpose: Complete AI agent configuration containing state, context, and model provider.
Key Components:
id: Uuid - Unique identifier
name: String - Human-readable name
context_container: ContextContainer - Conversation history and context
model_provider: Arc<dyn ModelProvider> - LLM communication interface
state: WorkerStates - Current execution state
last_failure: Option<String> - Error tracking
State Machine:
Inactive → Working → Requesting → Receiving → [Waiting/UsingTool]* → Inactive
↓
InactiveFailed
States:
Inactive - Ready for new task
Working - Preparing request
Requesting - Sending to LLM
Receiving - Streaming response
Waiting - Awaiting user input
UsingTool - Executing tool
InactiveFailed - Task failed
Location: crates/chat-cli/src/agent_env/worker.rs
WorkerTask (Trait)
Purpose: Interface for executable work units that run on workers.
Contract:
#[async_trait]
pub trait WorkerTask: Send + Sync {
fn get_worker(&self) -> &Worker;
async fn run(&self) -> Result<(), eyre::Error>;
}
Implementations:
AgentLoop - Main conversational agent loop (worker_tasks/agent_loop.rs)
ProtoLoop - Demo/prototype task (demo/proto_loop.rs)
Location: crates/chat-cli/src/agent_env/worker_task.rs
WorkerJob
Purpose: Running instance combining Worker + Task + execution infrastructure.
Key Components:
worker: Arc<Worker> - Worker executing the task
worker_task: Arc<dyn WorkerTask> - Task being executed
cancellation_token: CancellationToken - Cancellation mechanism
task_handle: JoinHandle - Tokio task handle
worker_job_continuations: Continuations - Completion callbacks
Lifecycle:
new() - Create job (not started)
launch() - Spawn async task
cancel() - Request cancellation
wait() - Block until completion
- Continuations execute on completion
Job States:
Active - Currently running
Completed - Finished successfully
Cancelled - User/system cancelled
Failed - Error occurred
Continuations: Callbacks registered via worker_job_continuations.add_or_run_now() that execute when job completes. Used to chain actions (e.g., re-queue prompt after agent response).
Locations:
crates/chat-cli/src/agent_env/worker_job.rs
crates/chat-cli/src/agent_env/worker_job_continuations.rs
2: Model and Context Infrastructure
ModelProvider (Trait)
Purpose: Abstraction for LLM communication supporting streaming responses.
Contract:
#[async_trait]
pub trait ModelProvider: Send + Sync {
async fn request(
&self,
request: ModelRequest,
when_receiving_begin: Box<dyn Fn() + Send>,
when_received: Box<dyn Fn(ModelResponseChunk) + Send>,
cancellation_token: CancellationToken,
) -> Result<ModelResponse, eyre::Error>;
}
Key Types:
ModelRequest - Contains prompt string
ModelResponseChunk - Streaming chunks (text or tool requests)
ModelResponse - Complete response with tool requests
Implementations:
BedrockConverseStream - AWS Bedrock integration (model_providers/bedrock_converse_stream.rs)
Location: crates/chat-cli/src/agent_env/model_providers/model_provider.rs
ContextContainer
Purpose: Manages all contextual information available to a worker.
Structure:
pub struct ContextContainer {
pub conversation_history: Arc<Mutex<ConversationHistory>>,
}
ConversationHistory:
- Stores alternating user/assistant messages
push_input_message(content) - Add user message
push_assistant_message(assistant) - Add assistant response
get_entries() - Retrieve all messages
ConversationEntry:
- Represents single message (user OR assistant)
- Contains
UserMessage or AssistantMessage
Location: crates/chat-cli/src/agent_env/context_container/
4: User Interface and web support
TBD
Summary
This branch introduces infrastructure to maintain multiple parallel workers. This infrastructure is also agnostic of UI implementation, and allows to work with various UIs.
The ultimate goals of this effort are:
Demo
TBD
Structure
1: Core Execution Components
Session
Purpose: Central orchestrator managing all workers and jobs in the system.
Key Responsibilities:
Key Methods:
build_worker(name)- Creates new worker with model providerrun_agent_loop(worker, input, ui_interface)- Launches agent loop taskcancel_all_jobs()- Cancels all active jobscleanup_inactive_jobs()- Removes old completed jobs (keeps last 3)wait_for_all_jobs()- Blocks until all jobs completeLocation:
crates/chat-cli/src/agent_env/session.rsWorker
Purpose: Complete AI agent configuration containing state, context, and model provider.
Key Components:
id: Uuid- Unique identifiername: String- Human-readable namecontext_container: ContextContainer- Conversation history and contextmodel_provider: Arc<dyn ModelProvider>- LLM communication interfacestate: WorkerStates- Current execution statelast_failure: Option<String>- Error trackingState Machine:
States:
Inactive- Ready for new taskWorking- Preparing requestRequesting- Sending to LLMReceiving- Streaming responseWaiting- Awaiting user inputUsingTool- Executing toolInactiveFailed- Task failedLocation:
crates/chat-cli/src/agent_env/worker.rsWorkerTask (Trait)
Purpose: Interface for executable work units that run on workers.
Contract:
Implementations:
AgentLoop- Main conversational agent loop (worker_tasks/agent_loop.rs)ProtoLoop- Demo/prototype task (demo/proto_loop.rs)Location:
crates/chat-cli/src/agent_env/worker_task.rsWorkerJob
Purpose: Running instance combining Worker + Task + execution infrastructure.
Key Components:
worker: Arc<Worker>- Worker executing the taskworker_task: Arc<dyn WorkerTask>- Task being executedcancellation_token: CancellationToken- Cancellation mechanismtask_handle: JoinHandle- Tokio task handleworker_job_continuations: Continuations- Completion callbacksLifecycle:
new()- Create job (not started)launch()- Spawn async taskcancel()- Request cancellationwait()- Block until completionJob States:
Active- Currently runningCompleted- Finished successfullyCancelled- User/system cancelledFailed- Error occurredContinuations: Callbacks registered via
worker_job_continuations.add_or_run_now()that execute when job completes. Used to chain actions (e.g., re-queue prompt after agent response).Locations:
crates/chat-cli/src/agent_env/worker_job.rscrates/chat-cli/src/agent_env/worker_job_continuations.rs2: Model and Context Infrastructure
ModelProvider (Trait)
Purpose: Abstraction for LLM communication supporting streaming responses.
Contract:
Key Types:
ModelRequest- Contains prompt stringModelResponseChunk- Streaming chunks (text or tool requests)ModelResponse- Complete response with tool requestsImplementations:
BedrockConverseStream- AWS Bedrock integration (model_providers/bedrock_converse_stream.rs)Location:
crates/chat-cli/src/agent_env/model_providers/model_provider.rsContextContainer
Purpose: Manages all contextual information available to a worker.
Structure:
ConversationHistory:
push_input_message(content)- Add user messagepush_assistant_message(assistant)- Add assistant responseget_entries()- Retrieve all messagesConversationEntry:
UserMessageorAssistantMessageLocation:
crates/chat-cli/src/agent_env/context_container/4: User Interface and web support
TBD