refactor: runner owns stream routing, suppress tool call XML from display

Split the streaming pipeline: API backends yield StreamEvents through
a channel, the runner reads them and routes to the appropriate UI pane.

- Add StreamEvent enum (Content, Reasoning, ToolCallDelta, etc.)
- API start_stream() spawns backend as a task, returns event receiver
- Runner loops over events, sends content to conversation pane but
  suppresses <tool_call> XML with a buffered tail for partial tags
- OpenAI backend refactored to stream_events() — no more UI coupling
- Anthropic backend gets a wrapper that synthesizes events from the
  existing stream() (TODO: native event streaming)
- chat_completion_stream() kept for subconscious agents, reimplemented
  on top of the event stream
- Usage derives Clone

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
ProofOfConcept 2026-03-29 21:22:42 -04:00
parent 912626c5f0
commit 13453606ae
6 changed files with 338 additions and 114 deletions

View file

@ -10,7 +10,6 @@
use crate::agent::api::ApiClient;
use crate::agent::types::*;
use crate::thought::{self, ProcessTracker};
use crate::agent::ui_channel::StreamTarget;
use std::sync::OnceLock;
@ -72,7 +71,6 @@ pub async fn call_api_with_tools(
&messages,
Some(&tool_defs),
&ui_tx,
StreamTarget::Autonomous,
&reasoning,
temperature,
).await {