Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/telegram-attachment-media-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eve": patch
---

Telegram channel: prefer the known attachment media type over the HTTP `content-type` header when fetching files. Telegram's file endpoint frequently returns `application/octet-stream` (or no content-type) for photos, which broke image recognition in vision models that key off the declared media type.
35 changes: 35 additions & 0 deletions packages/eve/src/public/channels/telegram/attachments.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,39 @@ describe("createTelegramFetchFile", () => {

await expect(fetchFile("https://example.com/file.png")).resolves.toBeNull();
});

it("prefers the known attachment media type over the HTTP content-type header", async () => {
// Telegram's file endpoint frequently returns `application/octet-stream`
// (or no content-type) for photos. The channel already knows the photo is
// `image/jpeg` from the inbound message; that known type must win so vision
// models receive a recognized image media type.
const fetchMock = vi
.fn()
.mockResolvedValueOnce(
new Response(JSON.stringify({ ok: true, result: { file_path: "photos/file.jpg" } }), {
headers: { "content-type": "application/json" },
}),
)
.mockResolvedValueOnce(
new Response("JFIF", { headers: { "content-type": "application/octet-stream" } }),
);

const fetchFile = createTelegramFetchFile({
api: { apiBaseUrl: "https://telegram.example", fetch: fetchMock },
credentials: { botToken: "123456:ABCDEF" },
policy: { allowedMediaTypes: ["image/*"], maxBytes: 1024 },
});

const result = await fetchFile(
String(
createTelegramFileUrl({
fileId: "photo-id",
filename: "photo.jpg",
mediaType: "image/jpeg",
}),
),
);

expect(result?.mediaType).toBe("image/jpeg");
});
});
7 changes: 6 additions & 1 deletion packages/eve/src/public/channels/telegram/attachments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,13 @@ export function createTelegramFetchFile(input: {
}

const bytes = Buffer.from(await response.arrayBuffer());
// Prefer the media type the channel already knows (from the attachment
// metadata, e.g. `image/jpeg` for photos) over the HTTP `content-type`
// header returned by Telegram's file endpoint, which is frequently
// `application/octet-stream` or unset. Using the latter breaks image
// recognition in vision models that key off the declared media type.
const mediaType =
response.headers.get("content-type") ?? ref.mediaType ?? "application/octet-stream";
ref.mediaType ?? response.headers.get("content-type") ?? "application/octet-stream";
const result: FetchFileResult = {
bytes,
filename: ref.filename,
Expand Down