fix: restore Telegram DM voice-note transcription (#61008) (thanks @manueltarouca)

* fix(telegram): enable voice-note transcription in DMs

The preflight transcription condition only triggered for group chats
(isGroup && requireMention), so voice notes sent in direct messages
were never transcribed -- they arrived as raw <media:audio> placeholders.

This regression was introduced when the Telegram channel was moved from
src/telegram/ to extensions/telegram/, losing the fix from c15385fc94.

Widen the condition to fire whenever there is audio and no accompanying
text, regardless of chat type. Group-specific guards (requireMention,
disableAudioPreflight, senderAllowedForAudioPreflight) still apply
only in group contexts.

* fix: restore Telegram DM voice-note transcription (#61008) (thanks @manueltarouca)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
This commit is contained in:
tarouca
2026-04-05 05:19:44 +01:00
committed by GitHub
parent 0a71ac5d3c
commit bf0f4d93f0
3 changed files with 50 additions and 5 deletions

View File

@@ -110,6 +110,7 @@ Docs: https://docs.openclaw.ai
- Agents/exec: restore `host=node` routing for node-pinned and `host=auto` sessions, while still blocking sandboxed `auto` sessions from jumping to gateway. (#60788) Thanks @openperf.
- Agents/compaction: keep assistant tool calls and displaced tool results in the same compaction chunk so strict summarization providers stop rejecting orphaned tool pairs. (#58849) Thanks @openperf.
- Outbound/sanitizer: strip leaked `<tool_call>`, `<function_calls>`, and model special tokens from shared user-visible assistant text, including truncated tool-call streams, so internal scaffolding no longer bleeds into replies across surfaces. (#60619) Thanks @oliviareid-svg.
- Telegram: restore DM voice-note preflight transcription so direct-message audio stops arriving as raw `<media:audio>` placeholders. (#61008) Thanks @manueltarouca.
- Control UI/avatar: honor `ui.assistant.avatar` when serving `/avatar/:agentId` so Appearance UI avatar paths stop falling back to initials placeholders. (#60778) Thanks @hannasdev.
- Control UI/Overview: prevent gateway access token/password visibility toggle buttons from overlapping their inputs at narrow widths. (#56924) Thanks @bbddbb1.
- Control UI/cron: highlight the Cron refresh button while refresh is in flight so the page's loading state stays visible even when prior data remains on screen. (#60394) Thanks @coder-zhuzm.

View File

@@ -145,4 +145,48 @@ describe("resolveTelegramInboundBody", () => {
effectiveWasMentioned: true,
});
});
it("transcribes DM voice notes via preflight (not only groups)", async () => {
transcribeFirstAudioMock.mockReset();
transcribeFirstAudioMock.mockResolvedValueOnce("hello from a voice note");
const result = await resolveTelegramInboundBody({
cfg: {
channels: { telegram: {} },
tools: { media: { audio: { enabled: true } } },
} as never,
primaryCtx: {
me: { id: 7, username: "bot" },
} as never,
msg: {
message_id: 10,
date: 1_700_000_010,
chat: { id: 42, type: "private", first_name: "Pat" },
from: { id: 42, first_name: "Pat" },
voice: { file_id: "voice-dm-1" },
entities: [],
} as never,
allMedia: [{ path: "/tmp/voice-dm.ogg", contentType: "audio/ogg" }],
isGroup: false,
chatId: 42,
senderId: "42",
senderUsername: "",
routeAgentId: undefined,
effectiveGroupAllow: normalizeAllowFrom([]),
effectiveDmAllow: normalizeAllowFrom([]),
groupConfig: undefined,
topicConfig: undefined,
requireMention: false,
options: undefined,
groupHistories: new Map(),
historyLimit: 0,
logger: { info: vi.fn() },
});
expect(transcribeFirstAudioMock).toHaveBeenCalledTimes(1);
expect(result).toMatchObject({
bodyText: "hello from a voice note",
});
expect(result?.bodyText).not.toContain("<media:audio>");
});
});

View File

@@ -181,13 +181,13 @@ export async function resolveTelegramInboundBody(params: {
let preflightTranscript: string | undefined;
const needsPreflightTranscription =
isGroup &&
requireMention &&
hasAudio &&
!hasUserText &&
mentionRegexes.length > 0 &&
!disableAudioPreflight &&
senderAllowedForAudioPreflight;
(!isGroup ||
(requireMention &&
mentionRegexes.length > 0 &&
!disableAudioPreflight &&
senderAllowedForAudioPreflight));
if (needsPreflightTranscription) {
try {