diff --git a/extensions/acpx/src/runtime.ts b/extensions/acpx/src/runtime.ts index 4f7ff263a2a..9e711c530b3 100644 --- a/extensions/acpx/src/runtime.ts +++ b/extensions/acpx/src/runtime.ts @@ -311,9 +311,16 @@ export class AcpxRuntime implements AcpRuntime { }); if (input.attachments && input.attachments.length > 0) { - const blocks: unknown[] = [{ type: "text", text: input.text }]; + const blocks: unknown[] = []; + if (input.text) { + blocks.push({ type: "text", text: input.text }); + } for (const attachment of input.attachments) { - blocks.push({ type: "image", mimeType: attachment.mediaType, data: attachment.data }); + if (attachment.mediaType.startsWith("image/")) { + blocks.push({ type: "image", mimeType: attachment.mediaType, data: attachment.data }); + } + // Non-image attachments (documents, PDFs, audio, video) are not supported + // as binary content blocks in the ACP protocol — skip silently. } child.stdin.end(JSON.stringify(blocks)); } else { diff --git a/src/auto-reply/reply/dispatch-acp.ts b/src/auto-reply/reply/dispatch-acp.ts index 94bf9c83c4e..1f5b69beb6f 100644 --- a/src/auto-reply/reply/dispatch-acp.ts +++ b/src/auto-reply/reply/dispatch-acp.ts @@ -63,6 +63,8 @@ function resolveAcpPromptText(ctx: FinalizedMsgContext): string { ]).trim(); } +const ACP_ATTACHMENT_MAX_BYTES = 10 * 1024 * 1024; // 10 MB — consistent with Telegram mediaMaxMb default + async function resolveAcpAttachments(ctx: FinalizedMsgContext): Promise { const mediaAttachments = normalizeAttachments(ctx); const results: AcpTurnAttachment[] = []; @@ -72,6 +74,13 @@ async function resolveAcpAttachments(ctx: FinalizedMsgContext): Promise ACP_ATTACHMENT_MAX_BYTES) { + logVerbose( + `dispatch-acp: skipping attachment ${filePath} (${stat.size} bytes exceeds ${ACP_ATTACHMENT_MAX_BYTES} byte limit)`, + ); + continue; + } const buf = await fs.readFile(filePath); results.push({ mediaType: attachment.mime ?? "application/octet-stream", data: buf.toString("base64") }); } catch {