Skip to content

fix(gateway): pass explicit .ogg output_path for Telegram auto-TTS - #860

Open
hashbender wants to merge 1 commit into
mainfrom
mirror/pr-57071
Open

fix(gateway): pass explicit .ogg output_path for Telegram auto-TTS#860
hashbender wants to merge 1 commit into
mainfrom
mirror/pr-57071

Conversation

@hashbender

Copy link
Copy Markdown
Owner

What does this PR do?

Fixes a bug where the base platform adapter's auto-TTS path calls text_to_speech_tool without an explicit output_path, causing Telegram voice replies to be sent as regular audio attachments (sendAudio) instead of native voice bubbles (sendVoice).

The root cause: text_to_speech_tool uses get_session_env("HERMES_SESSION_PLATFORM") to detect the platform and choose the output format. The session contextvar is set by _set_session_env() inside _handle_message_with_agent() and cleared on return. The auto-TTS code in base.py's _process_message_background runs after the agent returns, so the contextvar is empty — the tool defaults to .mp3 regardless of platform.

The fix: pass an explicit output_path with the correct extension (.ogg for Telegram, .mp3 otherwise) based on self.platform, which is always available on the adapter instance.

Related Issue

Fixes NousResearch#57049

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • gateway/platforms/base.py: Build an explicit output_path with the correct extension based on self.platform before calling text_to_speech_tool in the auto-TTS block. Added import tempfile.
  • tests/gateway/test_base_topic_sessions.py: Added regression test test_telegram_auto_tts_passes_explicit_ogg_output_path verifying that the TTS tool receives an .ogg output_path on Telegram.

How to Test

  1. Run python -m pytest tests/gateway/test_base_topic_sessions.py -q — all 11 tests should pass
  2. The new test specifically validates: when self.platform == Platform.TELEGRAM and auto-TTS is enabled, text_to_speech_tool is called with output_path ending in .ogg
  3. On a live Telegram gateway with voice.auto_tts: true and tts.provider: edge, voice replies should render as native voice bubbles (tap-to-play) instead of audio file attachments

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run python -m pytest tests/gateway/test_base_topic_sessions.py -q and all 11 tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 26.4.1

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — N/A (fix uses existing self.platform attribute)
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

N/A — regression test validates the fix programmatically.


Mirror-of: NousResearch#57071
NousResearch#57071

hashbender pushed a commit that referenced this pull request Jul 13, 2026
…ousResearch#58327)

Strict providers (DeepSeek) reject a payload where the same tool_call_id
appears more than once with HTTP 400 'Duplicate value for tool_call_id'.
The issue was filed as an 'orphaned tool message' compression bug, but the
pasted error is a DUPLICATE tool_call_id — orphans are already handled on
main; duplicates were not. Reproduced live on main: both shapes leaked
through repair_message_sequence and sanitize_api_messages.

Two chokepoints, two shapes:
- repair_message_sequence: consume the id from known_tool_ids on first
  match so a SECOND tool result reusing it falls into the drop branch
  (duplicate tool-result shape). This is @Robinlovelace's kernel from
  NousResearch#55436 (applied manually — that PR was ~800 commits stale and bundled
  an unrelated duplicate-DB-write change for #860, which is dropped here).
- sanitize_api_messages (final pre-API pass): add a dedup pass covering
  BOTH (a) duplicate tool_calls sharing an id WITHIN one assistant message
  (the message[6] shape) and (b) later tool result messages reusing an
  already-seen id. NousResearch#55436 covered neither of these at this chokepoint.

Tests: duplicate-tool-result dedup at both functions, duplicate-assistant-
tool_call-id collapse, and a negative control proving distinct ids are
never dropped (no over-dedup).

Credit: @Robinlovelace (NousResearch#55436) for the repair_message_sequence dedup kernel.
Closes NousResearch#58327.
hashbender pushed a commit that referenced this pull request Jul 27, 2026
- codex app-server sibling path: surface a WARNING (was silent debug) when
  the projected-message flush fails — same bug class as the main fix, but
  codex output has already streamed so fail-closed and agent_persisted=False
  are both wrong here (#860/NousResearch#42039 duplicate-write hazard); loud durability
  gap logging instead.
- map session_persistence_failed in _format_turn_completion_explanation so
  the user sees an actionable reason instead of 'The request failed:
  unknown error' + explainer test.
- contributors/emails mapping for elco@thedaoist.gg (attribution CI).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant