* fix(telegram): fall back to text when voice messages forbidden
When TTS auto mode is enabled, slash commands like /status would fail
silently because sendVoice was rejected with VOICE_MESSAGES_FORBIDDEN.
The entire reply would fail without any text being sent.
This adds error handling to catch VOICE_MESSAGES_FORBIDDEN specifically
and fall back to sending the text content as a regular message instead
of failing completely.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: handle telegram voice fallback errors (#1725) (thanks @foeken)
---------
Co-authored-by: Echo <andre.foeken@Donut.local>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(voice-call): prevent audio overlap with TTS queue
Add a TTS queue to serialize audio playback and prevent overlapping
speech during voice calls. Previously, concurrent speak() calls could
send audio chunks simultaneously, causing garbled/choppy output.
Changes:
- Add queueTts() to MediaStreamHandler for sequential TTS playback
- Wrap playTtsViaStream() audio sending in the queue
- Clear queue on barge-in (when user starts speaking)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(voice-call): use iterative queue processing to prevent heap exhaustion
The recursive processQueue() pattern accumulated stack frames, causing
JavaScript heap out of memory errors on macOS CI. Convert to while loop
for constant stack usage regardless of queue depth.
* fix: prevent voice-call TTS overlap (#1713) (thanks @dguido)
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix: detect Anthropic 'Request size exceeds model context window' as context overflow
Anthropic now returns 'Request size exceeds model context window' instead of
the previously detected 'prompt is too long' format. This new error message
was not recognized by isContextOverflowError(), causing auto-compaction to
NOT trigger. Users would see the raw error twice without any recovery attempt.
Changes:
- Add 'exceeds model context window' and 'request size exceeds' to
isContextOverflowError() detection patterns
- Add tests that fail without the fix, verifying both the raw error
string and the JSON-wrapped format from Anthropic's API
- Add test for formatAssistantErrorText to ensure the friendly
'Context overflow' message is shown instead of the raw error
Note: The upstream pi-ai package (@mariozechner/pi-ai) also needs a fix
in its OVERFLOW_PATTERNS regex: /exceeds the context window/i should be
changed to /exceeds.*context window/i to match both 'the' and 'model'
variants for triggering auto-compaction retry.
* fix(tests): remove unused imports and helper from test files
Remove WorkspaceBootstrapFile references and _makeFile helper that were
incorrectly copied from another test file. These caused type errors and
were unrelated to the context overflow detection tests.
* fix: trigger auto-compaction on context overflow promptError
When the LLM rejects a request with a context overflow error that surfaces
as a promptError (thrown exception rather than streamed error), the existing
auto-compaction in pi-coding-agent never triggers. This happens because the
error bypasses the agent's message_end → agent_end → _checkCompaction path.
This fix adds a fallback compaction attempt directly in the run loop:
- Detects context overflow in promptError (excluding compaction_failure)
- Calls compactEmbeddedPiSessionDirect (bypassing lane queues since already in-lane)
- Retries the prompt after successful compaction
- Limits to one compaction attempt per run to prevent infinite loops
Fixes: context overflow errors shown to user without auto-compaction attempt
* style: format compact.ts and run.ts with oxfmt
* fix: tighten context overflow match (#1627) (thanks @rodrigouroz)
---------
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>