Skip to content

Commit 7c43b97

Browse files
feat: queue-aware speak() with enriched return metadata (#4)
* feat: queue-aware speak() with enriched return metadata Replace the barge-in-on-self behavior with a serial speech queue. When speak() is called while audio is already playing, the new request is queued and plays automatically when the current item finishes. The return value now includes full queue state (position, currently playing info, estimated wait, suggested actions) so the agent never needs a separate status call to understand the output channel. - Add SpeechQueue class with thread-safe enqueue/cancel/drain - speak() returns "queued" status with enriched metadata when busy - speech_status() always includes queue depth and currently_playing - stop(job_id) can cancel a specific queued item or interrupt current - stop() with no args interrupts current + clears entire queue - Add 18 tests covering queue mechanics, return formats, edge cases Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: resolve ruff lint and format errors for CI - Remove unused import `resolve_model` in http_api.py (F401) - Remove unused variable `player` in server.py (F841) - Remove unused import `pytest` in test_speech_queue.py (F401) - Remove unused variable `original_drain` in test_speech_queue.py (F841) - Fix unsorted import block in test_speech_status_no_jobs (I001) - Apply ruff format to server.py, tests/test_bus_wiring.py, tests/test_speech_queue.py Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add threshold attribute to Gate ABC for pyright compliance The abstract Gate class was missing a threshold type annotation that VoiceGate defines in __init__. Pyright flagged server.py accesses to voice_module.gate.threshold as unknown attribute errors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 966e02f commit 7c43b97

5 files changed

Lines changed: 669 additions & 124 deletions

File tree

http_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from pydantic import BaseModel, Field
2525

2626
from bus import ModalityBus
27-
from engine import MODELS, generate_audio, get_loaded_engines, resolve_model
27+
from engine import MODELS, generate_audio, get_loaded_engines
2828
from modality import EncodedOutput, ModalityType
2929
from modules.text import TextModule
3030
from modules.voice import VoiceModule

modality.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ class ModuleState:
115115
class Gate(ABC):
116116
"""Input gate — decides if raw input contains signal worth decoding."""
117117

118+
threshold: float
119+
118120
@abstractmethod
119121
def check(self, raw: bytes, **kwargs) -> GateResult:
120122
"""Check if this input should pass through to the decoder."""

0 commit comments

Comments
 (0)