perf(zara-027): stream LLM and agent output with cancellation-safe text events #283
Closed
nsaspy
wants to merge 0 commits from
perf/zara-027-streaming-llm-impl into master
pull from: perf/zara-027-streaming-llm-impl
merge into: nsaspy:master
nsaspy:master
nsaspy:agent/pi-coder-plugin-2026-09-17
nsaspy:fix/android-remote-listener
nsaspy:ui/chat-message-bubbles
nsaspy:release/v0.1.1-alpha-20260908
nsaspy:fix/default-daemon-endpoint-20260908
nsaspy:ui/650-outrun-shell
nsaspy:fix/400-plugin-capability-composition
nsaspy:fix/tts-idle-cpu-spin
nsaspy:design/android-canonical-reference-2026-09-07
nsaspy:fixtures/voice-recordings
nsaspy:rage/core/388-tool-cancellation-r18
nsaspy:rage/core/388-tool-cancellation-r1
nsaspy:release/v0.1.0-alpha
nsaspy:rage/android/175-terminal-transcript-fence-r4
nsaspy:rage/core/324-expanded-history-sidebar-r2
nsaspy:rage/android/175-terminal-transcript-fence-r3
nsaspy:rage/android/175-focus-release-retry-r2
nsaspy:rage/android/175-focus-release-retry
nsaspy:ci/desktop-idle-cpu-budget
nsaspy:rage/android/175-terminal-transcript-fence-r2
nsaspy:rage/android/175-route-stop-retry-r3
nsaspy:rage/575-transient-send-backpressure-r3
nsaspy:rage/575-transient-send-backpressure-r2
nsaspy:rage/android/175-terminal-transcript-fence
nsaspy:rage/android/175-route-stop-retry-r2
nsaspy:rage/android/175-sink-self-close-r2
nsaspy:rage/android/175-route-stop-retry
nsaspy:rage/android/175-sink-self-close
nsaspy:rage/android/175-audio-focus-sync-loss-r2
nsaspy:rage/android/175-stock-voice-interop-r3
nsaspy:rage/android/175-stock-voice-interop-r2
nsaspy:rage/android/175-audio-focus-sync-loss
nsaspy:rage/android/175-recover-stack-current-4
nsaspy:rage/android/175-stock-voice-interop-r1
nsaspy:rage/android/175-recover-stack-current-2
nsaspy:rage/587-vulkan-current-master-r2
nsaspy:rage/587-dictation-vulkan-current2
nsaspy:rage/575-transient-send-backpressure-r1
nsaspy:tmp-do-not-use-587
nsaspy:tmp-do-not-use-587-2
nsaspy:tmp-do-not-use-587-3
nsaspy:tmp-do-not-use-587-4
nsaspy:rage/587-dictation-vulkan-current2-tree
nsaspy:fix/dictation-ggml-vulkan-rage587
nsaspy:rage/android-campaign-batch-20260906
nsaspy:rage/587-dictation-ggml-vulkan-current
nsaspy:rage/388-toolnode-forwarding-r17-current2
nsaspy:rage/587-dictation-ggml-vulkan-r1
nsaspy:rage/388-toolnode-forwarding-r17-current
nsaspy:rage/575-gateway-send-diagnostics-current
nsaspy:rage/178-device-action-json-depth-r7
nsaspy:rage/175-recorder-failure-precedence-r8
nsaspy:rage/175-terminal-capture-cleanup-r8
nsaspy:rage/175-playback-write-failure-cleanup-r8
nsaspy:rage/575-gateway-send-diagnostics
nsaspy:rage/388-toolnode-forwarding-r17
nsaspy:rage/575-stock-interop-diagnostics-r2
nsaspy:fix/dictate-whisper-cpp-vulkan
nsaspy:rage/575-stock-interop-diagnostics-r1
nsaspy:rage/324-expanded-history-sidebar-r1
nsaspy:rage/178-device-action-json-depth-r6
nsaspy:rage/388-plugin-cancellation-r16
nsaspy:rage/175-recorder-failure-precedence-r7
nsaspy:rage/175-terminal-capture-cleanup-r7
nsaspy:rage/175-playback-write-failure-cleanup-r7
nsaspy:rage/324-native-chrome-r1
nsaspy:rage/175-recorder-failure-precedence-r6
nsaspy:rage/175-terminal-capture-cleanup-r6
nsaspy:rage/175-playback-write-failure-cleanup-r6
nsaspy:rage/324-independent-geometry-r2
nsaspy:rage/175-close-resource-precedence
nsaspy:rage/178-device-action-json-depth-r5
nsaspy:rage/175-recorder-failure-precedence-r5
nsaspy:rage/175-terminal-capture-cleanup-r5
nsaspy:rage/175-playback-write-failure-cleanup-r5
nsaspy:rage/324-independent-geometry-r1
nsaspy:rage/324-screenshot-provenance-r1
nsaspy:rage/324-history-parity-r1
nsaspy:rage/178-device-action-json-depth-r4
nsaspy:rage/175-preserve-recorder-primary-failure-r2
nsaspy:rage/175-capture-terminal-failure-cleanup-r3
nsaspy:rage/175-playback-write-failure-cleanup-r4
nsaspy:rage/324-screenshot-ci-r1
nsaspy:rage/324-unified-copilot-r4
nsaspy:rage/175-capture-terminal-failure-cleanup-r2
nsaspy:rage/175-playback-write-failure-cleanup-r3
nsaspy:rage/324-unified-copilot-r3
nsaspy:rage/175-preserve-recorder-primary-failure
nsaspy:rage/175-capture-terminal-failure-cleanup
nsaspy:rage/178-device-action-json-depth-r3
nsaspy:rage/175-playback-write-failure-cleanup-r2
nsaspy:rage/178-voice-stream-json-depth-r5
nsaspy:rage/160-semantic-first-runtime-r2
nsaspy:rage/175-playback-write-failure-cleanup
nsaspy:rage/178-voice-stream-json-depth-r4
nsaspy:rage/324-unified-copilot-r2
nsaspy:rage/178-device-action-json-depth-r2
nsaspy:rage/178-voice-json-depth-r3
nsaspy:rage/178-voice-ack-json-depth-r3
nsaspy:rage/160-semantic-first-runtime
nsaspy:rage/492-device-action-replay-r6
nsaspy:rage/178-device-action-json-depth
nsaspy:rage/178-voice-json-depth-r2
nsaspy:rage/178-voice-ack-json-depth-r2
nsaspy:rage/178-voice-json-depth-bound
nsaspy:rage/178-voice-ack-json-depth
nsaspy:rage/178-voice-hello-json-depth
nsaspy:rage/178-device-json-depth-bound
nsaspy:rage/178-capability-json-depth-bound
nsaspy:rage/178-android-daemon-restart-stale-turn-r2
nsaspy:rage/492-device-action-replay-r5
nsaspy:rage/492-device-action-replay-r4
nsaspy:rage/178-android-daemon-restart-stale-turn-r1
nsaspy:rage/178-android-json-depth-bound-r2
nsaspy:rage/178-android-json-depth-bound-r1
nsaspy:rage/203-android-playback-session-invalidation-r3
nsaspy:rage/492-device-action-replay-r3
nsaspy:rage/178-android-audio-payload-bound-r4
nsaspy:rage/203-android-playback-session-invalidation-r2
nsaspy:rage/178-android-audio-payload-bound-r3
nsaspy:rage/492-device-action-replay-r2
nsaspy:rage/203-android-ui-close-runtime-ownership-r3
nsaspy:rage/203-android-playback-session-invalidation
nsaspy:rage/178-android-audio-payload-bound-r2
nsaspy:rage/203-android-ui-close-runtime-ownership-r2
nsaspy:rage/178-android-uri-intent-abuse-r4
nsaspy:rage/178-android-audio-payload-bound
nsaspy:rage/203-android-ui-close-runtime-ownership
nsaspy:rage/492-device-action-replay-r1
nsaspy:rage/178-android-uri-intent-abuse-r3
nsaspy:rage/178-android-no-raw-logging-r5
nsaspy:rage/492-device-action-replay-horizon
nsaspy:rage/218-normalizer-config-r4
nsaspy:rage/178-android-uri-intent-abuse-r2
nsaspy:rage/178-android-no-raw-logging-r4
nsaspy:rage/178-android-uri-intent-abuse-r1
nsaspy:rage/218-normalizer-config-r3
nsaspy:rage/178-android-no-raw-logging-r3
nsaspy:rage/178-android-prolog-lifecycle-r3
nsaspy:rage/178-android-no-raw-logging-r2
nsaspy:rage/178-android-prolog-lifecycle-r2
nsaspy:rage/178-android-principal-target-abuse-r2
nsaspy:rage/178-android-no-raw-logging-r1
nsaspy:rage/178-android-prolog-lifecycle-r1
nsaspy:rage/178-android-principal-target-abuse-r1
nsaspy:rage/178-android-device-action-replay-r4
nsaspy:rage/178-android-device-action-replay-r3
nsaspy:rage/178-android-capability-revocation-r3
nsaspy:rage/218-normalizer-config-r2
nsaspy:rage/178-android-trealla-result-overflow-r1
nsaspy:rage/178-android-device-action-replay-r2
nsaspy:rage/178-android-capability-revocation-r2
nsaspy:rage/178-android-auth-revocation-r2
nsaspy:rage/178-android-device-action-replay-r1
nsaspy:rage/178-android-capability-revocation-r1
nsaspy:rage/178-android-auth-revocation-r1
nsaspy:rage/178-android-reconnect-storm-r3
nsaspy:rage/218-normalizer-config-r1
nsaspy:rage/218-normalizer-config-status-r1
nsaspy:rage/324-unified-copilot-r1
nsaspy:rage/217-s1-mini-normalizer-r4
nsaspy:rage/178-android-reconnect-storm-r2
nsaspy:rage/178-reconnect-storm-red-proof
nsaspy:rage/217-s1-mini-normalizer-r3
nsaspy:rage/178-android-release-matrix-r1
nsaspy:rage/217-s1-mini-normalizer-r2
nsaspy:rage/203-android-recorder-failure-diagnostics-r3
nsaspy:rage/217-s1-mini-normalizer-r1
nsaspy:rage/203-android-assistant-role-loss-wiring-r3
nsaspy:rage/216-transcript-normalization-contract-r2
nsaspy:rage/203-android-recorder-failure-diagnostics-r2
nsaspy:rage/203-android-assistant-role-loss-wiring-r2
nsaspy:rage/216-transcript-normalization-contract-r1
nsaspy:rage/203-android-reconnect-scheduler-failure-r2
nsaspy:rage/388-plugin-tool-cancellation-r15
nsaspy:rage/203-android-reconnect-scheduler-failure
nsaspy:rage/203-android-voice-session-invalidation-r4
nsaspy:rage/203-android-voice-session-invalidation-r3
nsaspy:rage/203-android-ui-error-redaction-r3
nsaspy:rage/388-plugin-tool-cancellation-r14
nsaspy:rage/388-plugin-tool-cancellation-r13
nsaspy:rage/400-plugin-capability-composition-r1
nsaspy:rage/203-android-ui-error-redaction-r2
nsaspy:rage/388-plugin-tool-cancellation-r12
nsaspy:rage/203-android-audio-route-rollback-failure-r2
nsaspy:rage/325-atomic-durable-message-append
nsaspy:rage/203-android-state-store-temp-isolation-r2
nsaspy:rage/388-plugin-tool-cancellation-r11
nsaspy:rage/388-plugin-tool-cancellation-r10
nsaspy:rage/203-android-audio-route-rollback-failure
nsaspy:rage/203-android-recorder-failure-diagnostics
nsaspy:rage/203-android-voice-runtime-invalidation-r2
nsaspy:rage/203-android-assistant-role-loss-wiring
nsaspy:rage/203-android-voice-session-invalidation-r2
nsaspy:rage/203-android-ui-error-redaction
nsaspy:rage/388-plugin-tool-cancellation-r9
nsaspy:rage/203-android-state-store-temp-isolation
nsaspy:rage/203-android-connection-error-redaction
nsaspy:rage/203-android-assistant-role-loss-r3
nsaspy:rage/388-plugin-tool-cancellation-r8
nsaspy:rage/203-android-voice-runtime-invalidation-primitives
nsaspy:rage/203-android-assistant-role-loss-r2
nsaspy:rage/203-android-voice-diagnostic-redaction-r2
nsaspy:rage/388-plugin-tool-cancellation-r7
nsaspy:rage/203-android-assistant-role-loss
nsaspy:rage/203-android-voice-session-invalidation
nsaspy:rage/203-android-voice-diagnostic-redaction
nsaspy:rage/174-android-open-app-aliases
nsaspy:rage/388-plugin-tool-cancellation-r6
nsaspy:rage/203-android-assistant-shutdown-fence
nsaspy:rage/388-plugin-tool-cancellation-r5
nsaspy:rage/29-streaming-tts-provider-recovery-r10
nsaspy:rage/203-android-mic-permission-lifecycle
nsaspy:rage/203-android-audio-route-lifecycle
nsaspy:rage/175-android-audio-focus-lifecycle
nsaspy:rage/174-android-device-capabilities
nsaspy:rage/29-streaming-tts-provider-recovery-r9
nsaspy:rage/388-plugin-tool-cancellation-r4
nsaspy:rage/388-plugin-tool-cancellation-r3
nsaspy:rage/29-streaming-tts-provider-recovery-r8
nsaspy:rage/326-desktop-toggle
nsaspy:rage/388-plugin-tool-cancellation-r2
nsaspy:rage/388-plugin-tool-cancellation
nsaspy:rage/29-streaming-tts-current-r7
nsaspy:rage/29-streaming-tts-current-r6
nsaspy:rage/371-plugin-approval-current
nsaspy:rage/29-streaming-tts-current-r5
nsaspy:rage/371-plugin-approval-contract
nsaspy:rage/371-plugin-approval-red
nsaspy:rage/29-streaming-tts-current-r4
nsaspy:rage/196-ui-closed-runtime
nsaspy:rage/196-android-assistant-role
nsaspy:rage/29-streaming-tts-current-r3
nsaspy:rage/175-android-barge-in
nsaspy:rage/175-android-streamed-voice
nsaspy:rage/175-android-manual-voice
nsaspy:rage/29-streaming-tts-current-r2
nsaspy:rage/29-streaming-tts-current
nsaspy:rage/327-bounded-target-edit-distance-recovery-r2
nsaspy:rage/348-dash-prefixed-z85-cli-r2
nsaspy:rage/197-compose-first-usable
nsaspy:rage/348-dash-prefixed-z85-cli
nsaspy:rage/173-android-client-continuity
nsaspy:rage/327-bounded-target-edit-distance-recovery
nsaspy:rage/329-production-secure-listener
nsaspy:rage/329-merge-probe
nsaspy:rage/159-zara1-device-actions-current
nsaspy:docs/refresh-20260905
nsaspy:rage/159-zara1-device-actions-recovery
nsaspy:rage/324-unified-copilot
nsaspy:rage/173-android-auth
nsaspy:rage/327-bounded-target-edit-distance
nsaspy:research/unified-copilot-20260905
nsaspy:rage/133-desktop-daemon-default-regression
nsaspy:rage/133-daemon-default-regression
nsaspy:rage/13-open-app-allowlist-regression
nsaspy:rage/165-user-command-runtime
nsaspy:rage/315-route-backpressure-test-contract
nsaspy:rage/164-user-command-authoring
nsaspy:rage/163-user-command-compiler
nsaspy:rage/162-user-command-persistence
nsaspy:rage/309-prolog-config-recovery
nsaspy:docs/260-customization-wiki
nsaspy:rage/260-customization-diagnostics
nsaspy:rage/159-zara1-device-actions
nsaspy:rage/260-agent-loop-backend-registry
nsaspy:rage/260-backend-registry
nsaspy:rage/260-service-plugin-advice
nsaspy:backup/rage-260-service-plugin-advice-pre-android-merge-20260903
nsaspy:rage/android-172-cross-runtime-parity
nsaspy:rage/zara-004-config-durability
nsaspy:rage/260-prolog-command-advice
nsaspy:feature/long-horizon-tasks
nsaspy:rage/264-config-delta
nsaspy:rage/264-host-delta
nsaspy:rage/264-config-host-delta
nsaspy:rage/rebase-264-long-horizon-tasks
nsaspy:backup/rage-260-prolog-command-advice-pre-rebase-20260903
nsaspy:rage/android-172-resolver-parity
nsaspy:rage/260-python-user-hooks
nsaspy:rage/260-agent-loop-integration
nsaspy:rage/android-172-asset-staging
nsaspy:rage/android-172-native-adapter
nsaspy:rage/260-python-hooks-advice
nsaspy:rage/android-172-jni-bridge
nsaspy:rage/android-172-trealla-runtime
nsaspy:rage/260-hooks-prolog-config
nsaspy:rage/android-172-fixture-runner
nsaspy:fork/prolog-rlm-agentic-runtime
nsaspy:rage/android-172-normalized-results
nsaspy:rage/android-172-assets-v2
nsaspy:rage/core-246-todo-toggle-current
nsaspy:rage/android-172-assets
nsaspy:rage/core-246-todo-toggle-refresh
nsaspy:rage/android-172-portable-prolog-refresh
nsaspy:feature/agent-mode-core
nsaspy:rage/recover-259-run10
nsaspy:rage/android-172-portable-prolog
nsaspy:docs/244-merge-evidence
nsaspy:backup/feature-long-horizon-tasks-pre-rebase-20260902
nsaspy:feat/zara-031-context-management
nsaspy:docs/250-merge-evidence
nsaspy:rage/250-amd-stt-device-routing
nsaspy:rage/159-zara1-capability-advertisement
nsaspy:feat/unified-agent-tui
nsaspy:fix/discord-tools-bash
nsaspy:rage/158-api-service-providers
nsaspy:docs/249-merge-evidence
nsaspy:rage/249-latency-trace-checkpoint
nsaspy:fix/246-disable-todo-surface
nsaspy:codex/zara-discord-plugin-guidance
nsaspy:rage/157-execution-plans
nsaspy:rage/156-prolog-frames
nsaspy:rage/28-post-merge-evidence
nsaspy:rage/155-typed-slots
nsaspy:test/live-smoke-reasoning-budgets
nsaspy:feature/openrouter-rlm-directmode
nsaspy:rage/154-intentframe-contract
nsaspy:chore/backlog-import
nsaspy:rage/195-samsung-assistant-research
nsaspy:feat/android-app
nsaspy:research/aradr-local-tts-voice-cloning
nsaspy:feature/wake-words-edit-distance
nsaspy:perf/zara-027-streaming-llm
nsaspy:docs/134-reentry-assessment
nsaspy:rage/134-daemon-release-gate
nsaspy:rage/131-merge-closeout
nsaspy:docs/rage-130-merge-outcome
nsaspy:docs/rage-17-merge-outcome
nsaspy:fix/zara-016-llm-provider-contracts
nsaspy:build/flake-update-2026-08
nsaspy:rage/191-zara1-tool-approvals
nsaspy:rage/132-visible-stt-regression
nsaspy:codex/copilot-redesign
nsaspy:codex/default-daemon-cli
nsaspy:rage/132-transcript-events
nsaspy:rage/133-post-merge-evidence
nsaspy:rage/133-client-migration
nsaspy:rage/132-post-merge-evidence
nsaspy:rage/132-live-voice
nsaspy:rage/132-live-voice-zara1
nsaspy:rage/131-principal-isolation
nsaspy:rage/131-principal-scope
nsaspy:rage/130-curve-zap-security
nsaspy:rage/130-auth-security
nsaspy:docs/rage-129-merge-outcome
nsaspy:rage/129-zara1-protocol
nsaspy:rage/129-slice-e-lifecycle-red
nsaspy:rage/129-slice-e-endpoint-red
nsaspy:docs/rage-128-merge-outcome
nsaspy:rage/139-daemon
nsaspy:docs/full-feature-sweep
nsaspy:feature/mcp-client-support-current
nsaspy:remove-prolog-rlm
nsaspy:research/daemon-zeromq-voice-service
nsaspy:feature/autoresearch-bootstrap
nsaspy:agent/VAD-patch
nsaspy:agent/prolog-capability-reasoner
nsaspy:agent/whisper-cpp-vulkan-stt
nsaspy:agent/remove-pet-notification-spam
nsaspy:codex/service-plugin-runtime
nsaspy:agent/stt-backends
nsaspy:agent/fix-laptop-stt-quality
nsaspy:feature/prolog-rlm-integration
nsaspy:agent/fix-speaker-echo-loop
nsaspy:agent/stt-gpu-rocm-support
nsaspy:agent/fix-ubuntu-wayland-pets
nsaspy:feature/desktop-theme-contrast
nsaspy:fix/whisper-load-state
nsaspy:agent/mcp-client-support
nsaspy:fix/wake-model-readiness-debug
nsaspy:fix/wake-capture-failure-propagation
nsaspy:fix/wake-audio-health
nsaspy:agent/readme-current-zara
nsaspy:fix/desktop-conversation-migration-repair
nsaspy:agent/fix-voice-runtime-noise
nsaspy:feature/desktop-launch-surface
nsaspy:feature/quick-copilot
nsaspy:feature/conversation-full-chat
nsaspy:feature/desktop-shell
nsaspy:feature/runtime-host
nsaspy:feature/runtime-events
nsaspy:research/desktop-copilot
nsaspy:agent/overhaul-memory-forgetting
nsaspy:agent/fix-command-context-routing
nsaspy:agent/fix-streaming-vad-wake
nsaspy:agent/pets-post-merge-fixes
nsaspy:feature/pets
nsaspy:revert/wake-throughput
nsaspy:fix/wake-word-detection
nsaspy:fix/pulse-shared-mic-ci
nsaspy:fix/shared-mic-capture
nsaspy:feat/zara-timer-alarm-sounds
nsaspy:fix/zara-017-todo-correctness
nsaspy:fix/zara-015-prolog-engine-contract
nsaspy:fix/zara-018-ack-result-events
nsaspy:agent/readme-rewrite
nsaspy:fix/zara-014-wake-lifecycle
nsaspy:fix/zara-013-file-tool-sandbox
nsaspy:fix/zara-012-process-safety
nsaspy:fix/recover-zara-006-011-to-master
nsaspy:revert-36-fix/zara-005-dictation-lifecycle
nsaspy:revert-44-fix/zara-011-dictation-ordering
nsaspy:fix/zara-010-tts-contracts
nsaspy:fix/zara-011-dictation-ordering
nsaspy:fix/zara-007-intent-precedence
nsaspy:fix/zara-008-multi-tool-history
nsaspy:fix/zara-009-memory-fallback
nsaspy:fix/zara-006-timers
nsaspy:fix/zara-005-dictation-lifecycle
nsaspy:fix/zara-003-fail-closed-commands
nsaspy:fix/zara-004-prolog-config-overrides
nsaspy:agent/ci-test-gate
nsaspy:fix/zara-002-config-toml
nsaspy:fix/zara-001-wake-entrypoint
nsaspy:memory
nsaspy:cleanup
No reviewers
Labels
Clear labels
bug
Something isn't working
documentation
Improvements or additions to documentation
duplicate
This issue or pull request already exists
enhancement
New feature or request
good first issue
Good for newcomers
help wanted
Extra attention is needed
invalid
This doesn't seem right
question
Further information is requested
wontfix
This will not be worked on
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
nsaspy/zara!283
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "perf/zara-027-streaming-llm-impl"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #28
Architecture summary
Implements ZARA-027 following the merged RAGE design (
rage/28-streaming-llm-design.org, PR #227) from current master (ec89bd4):zara/agent/stream_events.py): frozen dataclassestext_delta,sentence_ready(text, is_final),tool_call_started(name, id),tool_result(name, id),completed(full_text),cancelled,failed(error_type). No SSE frames, raw tool protocol payloads, hidden reasoning, or provider metadata escape into the event contract.zara/agent/sentence_chunker.py): sentence breaks on. ! ? … 。 ! ?with abbreviation guards (Dr., e.g., i.e., vs., St., initials), decimal guards, URL guards (scheme +www.), backtick code span/fence suppression, CJK breaks without whitespace, emoji grapheme safety. Bounded forced flushes:max_chars(180 default, last word boundary) andmax_wait_ms(500 default, fake-clock tested). Conservation invariant (emitted + flush == fed text exactly) is property-tested.zara/agent/graph.py): when a stream publisher is wired and the bound LLM exposesastream, the node consumes real provider chunks via a producer-task + bounded-wait queue (making the chunker's max-wait flush genuinely time-driven), publishes deltas before the response completes, and returns the exact aggregatedAIMessage(content, additional_kwargs, tool_calls, id, response_metadata) so graph/history semantics are unchanged. No fake slicing of completed responses.Actual streaming behavior
text_deltais published while the provider stream is still open (proven inside the fake stream before it returns, test A1).AssistantDeltaviaruntime_bridge.model_streamingwith turn/conversation correlation, and populatesAssistantComplete.textwith the exact final text (codec already mapsassistant.delta/assistant.completed; desktopConversationServicereduces them into streaming messages — e2e test proves final persisted message content is exact with no duplication).sentence_readyflows through the typedstream_publishercontract (also now threaded throughAgentManager.process_async) for #29 to consume.Buffered fallback behavior
astream(or nodes without a publisher) keep the exact bufferedainvokepath with a single honestcompleted(full_text)typed event andbuffered_proxy=Truelatency records. No fabricated deltas.Provider matrix
astream; OpenRouter continues to work through its configured family (no provider configuration redesign in this PR).zara.llm.LLMClient.stream_events_async()(new;query_asyncintact): OpenAI-compatible SSE (data:/[DONE]), OpenRouter through the same OpenAI-compatible contract, Anthropic SSE (content_block_delta/message_stop/error), Ollama NDJSON. Single attempt (no retry duplication); terminals:completed(non-empty),cancelled(re-raised),failed(http,rate_limit,malformed_response,provider_error,empty_response,timeout,connection). All tested against local fake HTTP servers — no credentials, no network.Cancellation semantics
cancelledtyped terminal, re-raisesCancelledError, closes the provider stream promptly (producer task cancelled,stream.aclose()awaited), and no later deltas or stale runtime events appear (A4).completed,cancelled, orfailed— mutually exclusive, tested.History-integrity proof
tool_call_chunksand are rebuilt into parsedtool_calls; no protocol JSON in deltas, sentences, or persisted history; no orphaned partial history after ordinary completion; transient deltas never become independent messages (single aggregatedAIMessageappended by the existing reducer).Test/gate results
t/test_sentence_chunker.py(36 tests),t/test_llm_streaming.py(27 tests: A1–A9 incl. latency boundaries with fake clock, desktop-service e2e, AgentManager wiring),scripts/test-streaming-llm.sh(wired intotest-all.shphase 6).llm_first_sentenceevent +llm_request_to_first_sentencestage added;scripts/benchmark-voice.pyemits both first-token and first-sentence metrics;buffered_proxy=Falseon the genuine streaming path.c72a930:NIX_CONFIG=... nix develop -c bash scripts/test-all.sh→ ALL PHASES PASSED (10/10), 1190 pytest tests passed / 5 skipped;nix flake check→ all checks passed;nix build→ success.Deviations from the existing RAGE design (evidence recorded in
rage/28-streaming-llm.org)sentence_readyis not mirrored onto the runtime event bus/wire protocol: the daemon codec rejects unmapped event types and wire semantics are frozen for this issue; it stays in the typedstream_publishercontract that #29 consumes (design point 4 ambiguity, recorded with rationale).stream_publisheronly;latency_traceremains state-passed because the preservedwip/latency-trace-ctorbranch never landed on master and every existing node test constructscreate_agent_node(llm, registry)directly.Pull request closed