mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
4.0 KiB
4.0 KiB
03 — Streaming Improvements (vendor crate work)
Goal: the harness exposes a real caller-consumable stream, sub-agent deltas
propagate to the parent with lineage attribution, and tool calls get explicit
lifecycle events — so OpenHuman's AgentProgress layer becomes a thin
projection and the C4 progress_tracing deletion has full-fidelity input.
Current state (from 01)
- Provider SSE is genuinely incremental (
openai/mod.rs:1020-1073) and tool-call arg fragments stream (ToolCallDelta,:796-799). - But
invoke_streamingreturns a completedAgentRun(agent_loop/mod.rs:195-241); consumers must attach anEventSinkor middleware to see deltas. - Sub-agents run the non-streaming path (
subagent/mod.rs:535,:179-189) — a child's tokens/thinking/tool activity are invisible until it returns. - No tool-call started/completed events;
MockModel::streamreplays a completed response (model/types.rs:536-549).
Step 1 — invoke_stream: a Stream-returning entry point
- New API:
AgentHarness::invoke_stream(...) -> (impl Stream<Item = AgentStreamItem>, JoinHandle<Result<AgentRun>>)(or a single stream whose terminal item carries theAgentRun). AgentStreamItem(new enum,harness/stream/):TurnStarted,ModelDelta(ModelDelta)(text + reasoning + tool_call, post doc 02),ToolCallStarted { call_id, tool_name },ToolCallArgsDelta,ToolCallCompleted { call_id, outcome },AssistantMessage,UsageUpdated,RunCompleted/Failed— each stamped withrun_id / parent_run_id / root_run_id / depth.- Implementation: a bounded
mpscfed from the existing emit points ininvoke_model_streaming_once(agent_loop/mod.rs:929-994) and the tool execution section (:526-659). TheEventSinkpath stays; this is a convenience projection over the same events, not a parallel system. - Backpressure: bounded channel + documented drop-oldest vs block policy (default: block; the loop already awaits network).
Step 2 — Sub-agent delta propagation
SubAgentTool::callswitches to the streaming child path and forwards childAgentStreamItems into the parent's stream/sink with the child'srun_id+ inheritedroot_run_idanddepth+1(subagent/mod.rs:535→SubAgent::invoke_stream).- Recursion-safe: items flow through the parent's channel; no unbounded fan-in (children are executed serially today; revisit with doc 04 §4).
- Closes goal.md §3's "attribute every delta to parent/root run id".
Step 3 — Tool-call lifecycle events
- Emit
ToolCallStartedas soon as the terminalCompleted(or the first namedToolCallDelta, with doc 02's tool-name-on-start) identifies the tool — this is what OpenHuman's UI needs to show "running X…" before args finish streaming. - Emit
ToolCallCompletedwith outcome + duration after the wrap-onion tool call returns.
Step 4 — Test/mock fidelity
MockModel::streamgains scripted incremental emission (list ofModelStreamItems with optional delays) so streaming tests are truly incremental (model/types.rs:536-549).- Tests: caller consumes
invoke_streamand observes interleaved model/tool items; nested sub-agent test asserts child deltas arrive with correct lineage before the parent's final message.
Step 5 — OpenHuman follow-through
run_turn_via_tinyagents_sharedadapters consumeinvoke_stream(or the sink projection) and map 1:1 ontoAgentProgress— deleting theProviderDeltabridge insession/tool_progress.rs(252).SubagentThinkingDelta/subagent progress becomes lineage-filtered projection — removes bespoke child-progress plumbing insubagent_runner/ops/runner.rs.- C4 (journal-backed web progress) gains the missing fidelity: journals +
live stream share one event vocabulary, enabling the
progress_tracing.rs+langfuse.rsdeletion (~2k).
Effort: L crate-side (Steps 1–4), M OpenHuman follow-through.
Depends on: doc 02 for reasoning-in-deltas (can land in either order; both
touch invoke_model_streaming_once, so sequence the merges).