| name | maintain-chat |
| description | Maintain Chat rendering, composer submission, Local/ChatGPT/OpenRouter turns, streaming/tool events, visible statuses, speech controls, and Chat accessibility. Use when changing typed prompts, message rendering, send gating, or Chat reply behavior. |
Maintain Chat
Role and boundary
Keep Chat as the typed conversation surface for the active ChatStore session. It coordinates composer admission, visible message projection, and optional Chat speech through existing owners; it must not invent provider policy, persistence, native playback, or Live state.
Source map
src/main.ts: renderApp() Chat markup, app composition, wireStatusChrome, and initializeVoiceFeatures; src/chat.ts: required element lookup, transcript/session rendering, DOM listeners, copy actions, composer gate, and the single wireChat composition seam; src/chat-turn.ts: ChatController, provider admission, speech replacement, shared Stop-speaking settlement, mutually exclusive turn/session mutations, user-message commit, draft/provenance handling, tool projection, and final UI settlement.
src/chat-store.ts: message/session types and appendUser, streaming/complete/interrupted/error assistant updates, tool call/result/toggle, persistence, and subscribers.
src/chat-message-view.ts: text, voice-provenance, tool, streaming, error, and diagnostic-reference rendering.
src/composer-send-gate.ts, src/voice.ts, src/voice-draft-provenance.ts: send enablement, editable transcription insertion, and provenance admission.
src/assistant-coordinator.ts, src/assistant-ipc.ts, src/llm.ts, src/tts.ts, src/sentence-chunks.ts: correlated generation and optional ordered speech; tests in tests/chat-turn.test.ts, tests/chat-store.test.ts, tests/assistant-coordinator.test.ts, tests/llm.test.ts, tests/composer-send-gate.test.ts, and tests/assistant-activity.test.ts.
Cover
- Keep the complete submission transaction in
ChatController: trim and reserve provider work before appending/persisting a non-empty prompt; keep blocked account operations from creating orphan turns, retain the draft and voice provenance when admission fails, and always release busy/focus state on settlement.
- Route Stop speaking, New task, activation, deletion, and clear-all through the same controller. Keep one controller-level in-flight speech-stop promise for UI ordering, and keep the underlying
ChatReplySpeechController cancellation promise shared across direct user, replacement, navigation, and Live callers. Make session mutations mutually exclusive with turn admission while native speech or Live teardown is pending; disabled DOM buttons are a projection of that guard, not the guard itself.
- Snapshot provider/model/thinking/verbosity/tool route at generation start. Stream only correlated visible deltas; surface tool calls/results as expandable local messages without putting tool records into provider history.
- Persist partial assistant text as
interrupted on replacement/cancel and error with a diagnostic reference on failures; keep speech cancellation separate from visible LLM cancellation when Stop speaking is used.
- Keep composer accessibility, send gating, Enter/Shift+Enter behavior, editable transcription insertion (never auto-submit), scroll preservation,
aria-busy, and focus restoration.
- Keep Chat speech outside the composer and preserve
speechSessionId/requestId correlation, bounded sentence chunking, and local-first privacy. Inspect current source when markup differs from older prose.
Validate and accept
- Run
bun test tests/chat-turn.test.ts tests/tts.test.ts tests/chat-store.test.ts tests/assistant-coordinator.test.ts tests/llm.test.ts tests/composer-send-gate.test.ts tests/assistant-activity.test.ts.
- Run
git diff --check against the actual files changed; run just check when the change crosses TypeScript/Rust/build boundaries. Exercise typed, empty, blocked-account, tool, interrupted, and speech-stop paths in the packaged app via $test-voice-layer-app.
- Treat real local
llama-server/ChatGPT account routing, audible Chat playback, and human keyboard/accessibility acceptance as separate gates.
Relationships
Use $maintain-assistant-orchestration for request/cancellation sequencing, $maintain-assistant-providers for provider policy, $maintain-sessions for persistence, $maintain-voice-input for recording/drafts, $maintain-voice-output for playback, and $maintain-local-tools for native tools.