Truncate voice-transcript echo so Telegram doesn't reject long messages
The bot re-emits the transcript back to the owner as a preview
(`🎤 …`). Telegram's sendMessage caps at 4096 chars, so a long audio
message crashed the handler with a 400. Trim the echo to 200 chars
with an ellipsis; the agent still receives the full transcript via
result.input.text.
This commit is contained in:
@@ -262,6 +262,22 @@ describe("registerBridge", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("echoes a truncated transcript but sends the full text to the agent", async () => {
|
||||||
|
const long = "a".repeat(5000);
|
||||||
|
const transcriber = { transcribe: async () => long };
|
||||||
|
const h = harness({ debounceMs: 5, transcriber });
|
||||||
|
const voiceUpdate = textUpdate("");
|
||||||
|
delete (voiceUpdate.message as { text?: string }).text;
|
||||||
|
(voiceUpdate.message as { voice?: unknown }).voice = { file_id: "v1", file_unique_id: "u", duration: 3, mime_type: "audio/ogg" };
|
||||||
|
await h.bot.handleUpdate(voiceUpdate);
|
||||||
|
const echoed = h.texts().find((t) => t.startsWith("🎤 "));
|
||||||
|
expect(echoed).toBeDefined();
|
||||||
|
// Emoji + space + 199 chars + ellipsis = 202 code points.
|
||||||
|
expect(Array.from(echoed as string)).toHaveLength(202);
|
||||||
|
expect((echoed as string).endsWith("…")).toBe(true);
|
||||||
|
await vi.waitFor(() => expect(h.host.sent).toEqual([{ text: long, images: undefined }]));
|
||||||
|
});
|
||||||
|
|
||||||
it("drops buffered messages when /new starts a fresh session", async () => {
|
it("drops buffered messages when /new starts a fresh session", async () => {
|
||||||
const h = harness({ debounceMs: 100 });
|
const h = harness({ debounceMs: 100 });
|
||||||
await h.bot.handleUpdate(textUpdate("hold this thought"));
|
await h.bot.handleUpdate(textUpdate("hold this thought"));
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ import type { Outbound } from "./outbound.js";
|
|||||||
/** How long we wait after the last message before delivering the merged batch to the agent. */
|
/** How long we wait after the last message before delivering the merged batch to the agent. */
|
||||||
const DEFAULT_DEBOUNCE_MS = 600;
|
const DEFAULT_DEBOUNCE_MS = 600;
|
||||||
|
|
||||||
|
/** Longest transcript we echo back to the owner before truncating with an ellipsis. Telegram caps sendMessage at 4096 chars. */
|
||||||
|
const MAX_TRANSCRIPT_ECHO_CHARS = 200;
|
||||||
|
|
||||||
export type HostLike = Pick<AgentHost, "busy" | "send" | "abort" | "newSession" | "compact" | "status" | "subscribe">;
|
export type HostLike = Pick<AgentHost, "busy" | "send" | "abort" | "newSession" | "compact" | "status" | "subscribe">;
|
||||||
export type SchedulerLike = Pick<Scheduler, "list" | "delete">;
|
export type SchedulerLike = Pick<Scheduler, "list" | "delete">;
|
||||||
|
|
||||||
@@ -211,7 +214,7 @@ export function registerBridge(deps: BridgeDeps): void {
|
|||||||
botUserId: bot.botInfo?.id,
|
botUserId: bot.botInfo?.id,
|
||||||
});
|
});
|
||||||
for (const note of result.notes) await ctx.reply(note);
|
for (const note of result.notes) await ctx.reply(note);
|
||||||
if (result.transcript) await ctx.reply(`🎤 ${result.transcript}`);
|
if (result.transcript) await ctx.reply(`🎤 ${truncateForEcho(result.transcript)}`);
|
||||||
if (!result.input) {
|
if (!result.input) {
|
||||||
if (result.notes.length === 0) await ctx.reply("I can handle text, photos, voice notes, and files.");
|
if (result.notes.length === 0) await ctx.reply("I can handle text, photos, voice notes, and files.");
|
||||||
return;
|
return;
|
||||||
@@ -282,3 +285,9 @@ export async function downloadFile(
|
|||||||
function errorText(err: unknown): string {
|
function errorText(err: unknown): string {
|
||||||
return err instanceof Error ? err.message : String(err);
|
return err instanceof Error ? err.message : String(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function truncateForEcho(text: string): string {
|
||||||
|
const chars = Array.from(text);
|
||||||
|
if (chars.length <= MAX_TRANSCRIPT_ECHO_CHARS) return text;
|
||||||
|
return `${chars.slice(0, MAX_TRANSCRIPT_ECHO_CHARS - 1).join("")}…`;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user