feat(desktop): Telegram bot media support both ways - #922
Conversation
Image sending was dropped from main in 1224a4c as part of a discovery refactor cleanup. Restore it and extend the bridge to handle media in both directions: - /image <prompt> generates via the best openai-images seller; drafts a Generating status and delivers the result as a photo (document fallback for oversized or non-inline formats) - Assistant replies with image file blocks now send those images instead of collapsing to Done (no text reply) - Incoming photos and documents are downloaded, stored as conversation attachments, and passed through the same multimodal pipeline as the app's paper-clip attachments; captions become the message text - Voice/video/audio get an explicit unsupported notice instead of the generic text-only error - Image-only sellers are excluded from the bot's text-model picker and default-route fallback; /stop also cancels image generations
|
@claude review |
|
Claude finished @kotevcode's task in 3m 25s —— View job Review complete
Overall this is a clean, well-scoped restoration + extension of Telegram media support. One correctness issue worth fixing before merge: Missing busy-check in
const runUserText = async (chatId: number, text: string, attachments?: PreparedChatAttachment[]): Promise<void> => {
if (activeTurn) {
void sendToOwner('Still working on the previous message — send /stop to cancel it first.');
return;
}
...Its two siblings, if (activeTurn || activeImageRunConversationId || mediaInFlight) { ... }But the direct text path at Suggested fix: apply the same Minor/non-blocking notes:
I wasn't able to run |
Description
The Telegram bridge was text-only: generated images were dropped ("Done (no text reply)"), and inbound photos/documents hit a generic "Only text messages are supported" error. Part of this feature existed before (image sending, removed in #831's follow-up 1224a4c as an unrelated change during the discovery refactor); this PR restores it and extends it to full two-way media support.
Outgoing:
/image <prompt>generates via the bestopenai-imagesseller within the buyer routing policy and delivers the result as a Telegram photo (document fallback for oversized/non-inline formats), with a live "Generating…" draft. Assistant replies that contain image file blocks now send those images instead of collapsing to a text placeholder.Incoming: photos and documents are downloaded (Bot API 20 MB limit enforced), persisted as conversation attachments, and passed through the same multimodal attachment pipeline as the app's paper-clip flow — images reach vision-capable models, documents get text extraction. Captions become the message text; voice/video/audio get an explicit "not supported yet" notice instead of a generic error.
Also: image-only sellers are excluded from the bot's text-model picker and default-route fallback (they remain reachable via
/image), and/stopnow cancels in-flight image generations too.PiChatEngine.sendMessageStreamgained anattachmentsoption and a newgenerateImage()entry point so non-renderer surfaces can use both flows.Release Notes
/image <prompt>generates pictures on the network and delivers them as photos, and image attachments in agent replies are sent instead of being droppedTypes of Changes
Checklist