Files
CyberGril/deploy/voice
..
HEL-877: wire the audited .12 voice base into the one CyberGril chat chain as backend-only code (no deploy, no real voice call) - new independent src/cybergril/voice module: session+router add POST /api/voice/session / DELETE end / GET honest status on the unified instance (server-side room + dedicated cybergril-voice-agent dispatch + short-TTL join token via zero-new-dependency livekit_wire HS256/Twirp matching the installed SDK's wire format verified claim-for-claim on the .12 agent venv stdin-only; keys never reach the browser; unconfigured/no-profile/TTS-down refuse honestly and capabilities.voice stays false), chat_api_client speaks the exact real.ts RealChatAdapter protocol (per-turn health epoch, bounded 409 resync, robust incremental SSE parsing across multibyte/CRLF/multi-data chunk splits, fixed turn_id idempotency, immediate HTTP-stream close on barge-in without waiting for the next ASR final), llm_chat_api is a livekit llm.LLM adapter whose only backend is POST /api/chat so persona/mood/dyad/memory/life-sharing/budget gates and the one same-turn chat_lock govern text and voice identically (phi spoken verbatim via ChatChunk, never archived, no receipt), receipt.py confirms a sharing receipt only after real SDK playback completion with every negative (interrupted/failed/mid-playout/phi/incomplete/stale-epoch) fail-closed and exactly once per turn, stt_funasr/tts_cosyvoice reuse the proven .12 adapters verbatim with provenance, worker.py assembles the dedicated worker (independent voice_state_cybergril.json so D1 stays undecided, no second persona, cg.subtitle data-channel contract for the visual lead, CG-011 proactive seam left as an explicit no-op hook, built-in health port 8082); app.py keeps a minimal registration with voice_service injection for isolated tests; deployment drafts only (config/voice.example.yaml, worker.env.example, restart_cybergril.sh.example with exact-pattern process matching, serve_dual_8360_8361.py keeping HTTP 8360 and the HTTPS voice entry on ONE process sharing state/locks, runbook-hel877-voice.md contract+startup+rollback incl. the >=6GB GPU precondition and the do-not-copy historical fuser warning) - verification: 281 pytest pass on 3.11 venv + requirements.lock after merging the chief engineer's mid-flight HEL-874 rework e978e87 in full (parallel work preserved), verify_hel877_voice_chain.py 8/8 offline full-chain incl. socket-level barge-in fail-close and text/voice mutual same-gate cancellation, real-SDK check on the .12 livekit-agents 1.8.8 venv 8/8 ALL PASS via SSH stdin with zero writes zero network, dual-port single-process smoke on loopback 18360/18361 with a throwaway self-signed cert then stopped, ruff clean on all new code, dual-target requirement checks pass vs origin/hel-870-assembly (current tip e978e87) and origin/main with handoff-HEL-877.json; zero real LLM/embed/TTS/ASR requests, no mic/camera, no downloads/installs, no service start/stop, no 4080 access, no third-account or profile writes, web/ untouched, not merged, not deployed
2026-10-26 22:42:19 +08:00
HEL-879 rework: fix the four manager-review edges - (1) dual-port launcher owns the app lifecycle exactly once: uvicorn listeners run with lifespan=off, either listener ending stops the other BEFORE the shared store closes, cancellation cleans up listeners first, and create_app's lifespan gains a fail-closed double-entry guard (the old shape silently re-initialized Store/epoch/life/chat_lock on the second entry); (2) room ownership survives delete failures: end_session keeps the session in a bounded persisted cleanup ledger until the remote delete lands (retry/idempotent, LiveKit 404 = already gone = settled), expiry moves rooms into that ledger instead of silently dropping them (the manager measured zero DELETE attempts on expired ends), graceful shutdown does not hang up live calls, restart compensates only this instance's own recorded rooms bounded by attempts/TTL+grace with abandonment recorded, and the router answers 503 (not 404) while a room is still owned so the browser keeps its owed DELETE; (3) TurnLedger binds each speech handle to its own generation stream explicitly (oldest pending handle gets the stream the SDK starts; a newer speech retires an older generation-less handle) - a handle without a generation can no longer steal the next turn's stream/receipt, the worker discards interrupted/failed bindings fail-closed before consuming; (4) release snapshot v3: verify requires three-way count equality (manifest source = manifest snapshot = restored actual; rows_match is an extra constraint, never an OR bypass), the rollback drill actually restores by source path into a persistent isolated tree and opens the restored DBs there, same-basename DBs get collision-free archive names, duplicate sources are refused; new regression file tests/test_voice_rework_hel879.py 14/14 reproducing every edge first, full pytest 338/338
2026-10-27 04:10:23 +08:00
HEL-877: wire the audited .12 voice base into the one CyberGril chat chain as backend-only code (no deploy, no real voice call) - new independent src/cybergril/voice module: session+router add POST /api/voice/session / DELETE end / GET honest status on the unified instance (server-side room + dedicated cybergril-voice-agent dispatch + short-TTL join token via zero-new-dependency livekit_wire HS256/Twirp matching the installed SDK's wire format verified claim-for-claim on the .12 agent venv stdin-only; keys never reach the browser; unconfigured/no-profile/TTS-down refuse honestly and capabilities.voice stays false), chat_api_client speaks the exact real.ts RealChatAdapter protocol (per-turn health epoch, bounded 409 resync, robust incremental SSE parsing across multibyte/CRLF/multi-data chunk splits, fixed turn_id idempotency, immediate HTTP-stream close on barge-in without waiting for the next ASR final), llm_chat_api is a livekit llm.LLM adapter whose only backend is POST /api/chat so persona/mood/dyad/memory/life-sharing/budget gates and the one same-turn chat_lock govern text and voice identically (phi spoken verbatim via ChatChunk, never archived, no receipt), receipt.py confirms a sharing receipt only after real SDK playback completion with every negative (interrupted/failed/mid-playout/phi/incomplete/stale-epoch) fail-closed and exactly once per turn, stt_funasr/tts_cosyvoice reuse the proven .12 adapters verbatim with provenance, worker.py assembles the dedicated worker (independent voice_state_cybergril.json so D1 stays undecided, no second persona, cg.subtitle data-channel contract for the visual lead, CG-011 proactive seam left as an explicit no-op hook, built-in health port 8082); app.py keeps a minimal registration with voice_service injection for isolated tests; deployment drafts only (config/voice.example.yaml, worker.env.example, restart_cybergril.sh.example with exact-pattern process matching, serve_dual_8360_8361.py keeping HTTP 8360 and the HTTPS voice entry on ONE process sharing state/locks, runbook-hel877-voice.md contract+startup+rollback incl. the >=6GB GPU precondition and the do-not-copy historical fuser warning) - verification: 281 pytest pass on 3.11 venv + requirements.lock after merging the chief engineer's mid-flight HEL-874 rework e978e87 in full (parallel work preserved), verify_hel877_voice_chain.py 8/8 offline full-chain incl. socket-level barge-in fail-close and text/voice mutual same-gate cancellation, real-SDK check on the .12 livekit-agents 1.8.8 venv 8/8 ALL PASS via SSH stdin with zero writes zero network, dual-port single-process smoke on loopback 18360/18361 with a throwaway self-signed cert then stopped, ruff clean on all new code, dual-target requirement checks pass vs origin/hel-870-assembly (current tip e978e87) and origin/main with handoff-HEL-877.json; zero real LLM/embed/TTS/ASR requests, no mic/camera, no downloads/installs, no service start/stop, no 4080 access, no third-account or profile writes, web/ untouched, not merged, not deployed
2026-10-26 22:42:19 +08:00