hermes-agent/gateway/platforms
Frowtek 753d0d77e3 fix(gateway): keep the STT echo ledger across pending-media merges
_invalidate_pending_stt_cache() clears the gateway-side transcription
cache when merge_pending_message_event() folds a follow-up message into a
still-pending event, so the next transcription picks up the merged text
and attachments.  It also cleared _gateway_pending_stt_echo_sent, but that
flag is not derived state — it records that the transcript was already
delivered to the user.

Dropping it makes the re-run transcription echo the earlier notes a second
time.  Both merge branches are affected, including the text-only follow-up
case where no new audio arrived at all: there the cache is invalidated,
the same voice note is transcribed again (a second paid STT call) and the
same line is echoed again.

Sequence:

  1. voice note arrives, interrupt monitor transcribes it and echoes
     '🎙️ "hello"'
  2. user sends a follow-up while the turn is still pending, so it merges
  3. drain path re-transcribes and echoes '🎙️ "hello"' a second time

Keep the ledger out of the invalidation set and track it as a count of
already-echoed transcripts instead of a single boolean.  A count is what
the merge case actually needs: re-running transcription over the extended
media list returns the earlier transcripts as a prefix of the new one, so
echoing only the unsent tail suppresses the repeat while still surfacing a
newly merged voice note.  A count rather than a set of seen values, so two
separate notes that transcribe identically stay two distinct deliveries —
covered by test_pending_stt_merge_echoes_two_identical_transcripts.

The guard stays within the 12-line window that
test_all_gateway_transcript_echo_sends_are_gated enforces over run.py.
2026-07-28 11:57:11 -07:00
..
qqbot fix(gateway): pass encoding="utf-8" to read_text/write_text in update path (#37423) 2026-07-24 15:47:12 -07:00
ADDING_A_PLATFORM.md
…
__init__.py
…
_http_client_limits.py
…
api_server.py fix(api): redact subagent stream fields + forward child_session_id 2026-07-26 20:37:04 -07:00
base.py fix(gateway): keep the STT echo ledger across pending-media merges 2026-07-28 11:57:11 -07:00
bluebubbles.py
…
helpers.py fix(discord): make reconnect recovery lifecycle-safe 2026-07-18 14:01:33 -07:00
msgraph_webhook.py
…
signal.py refactor: extract shared audio container sniffer to tools/audio_container.py 2026-07-28 11:52:44 -07:00
signal_format.py
…
signal_rate_limit.py
…
webhook.py refactor(gateway): promote autonomous silence matcher to shared response_filters helper 2026-07-26 16:55:42 -07:00
webhook_filters.py fix(windows): sweep remaining unguarded text-mode subprocess sites codebase-wide 2026-07-24 11:45:57 -07:00
weixin.py fix(weixin): tighten TCPConnector keepalive to drain CLOSE_WAIT sockets 2026-07-26 19:43:44 -07:00
whatsapp_cloud.py fix(approval): honor allow_session across all button adapters 2026-07-21 12:04:47 -07:00
whatsapp_common.py
…
yuanbao.py fix(gateway): guard chained .get() against None intermediate values 2026-07-23 12:01:24 -07:00
yuanbao_media.py fix(security): pin DNS resolutions for SSRF-safe fetches 2026-07-23 11:44:43 -07:00
yuanbao_proto.py
…
yuanbao_sticker.py
…