Skip to content
Merged
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
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@alphaxiv/agents",
"version": "0.7.4",
"version": "0.7.5",
"license": "MIT",
"fmt": {
"lineWidth": 120
Expand Down
9 changes: 7 additions & 2 deletions src/adapters/open_responses/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,17 @@ export interface OpenResponsesFiles extends OpenResponsesFilesConfig {
uploaded: Set<string>;
}

/** Providers check the filename extension on upload, and the last segment of a URL often has none. */
/**
* Providers check the filename extension on upload, and the last segment of a URL often has none.
* OpenAI compares it case-sensitively and rejects ".JPG", so the extension is always sent lowercase.
*/
function uploadFileName(url: string, mimeType: string): string {
const name = getFileNameFromUrl(url) ?? "file";
const subtype = mimeType.split("/")[1];
const accepted = subtype === "jpeg" ? ["jpeg", "jpg"] : [subtype];
if (accepted.some((extension) => name.toLowerCase().endsWith(`.${extension}`))) return name;
const dotIndex = name.lastIndexOf(".");
const extension = dotIndex > 0 ? name.slice(dotIndex + 1).toLowerCase() : "";
if (accepted.includes(extension)) return `${name.slice(0, dotIndex)}.${extension}`;
return `${name}.${accepted.at(-1)}`;
}

Expand Down
4 changes: 2 additions & 2 deletions tests/adapters/provider-files.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ Deno.test("without a fileStore the input keeps image_url and file_data", async (
});
});

Deno.test("an upload is named with the extension for its mime type when the URL has none", async () => {
Deno.test("an upload is named with the lowercase extension for its mime type", async () => {
using _fetch = stubFetch();
const fake = createFakeClient("file");
const adapter = openAIModel({ model: "gpt-5.6-luna", client: fake.client, fileStore: createMemoryStore() });
Expand All @@ -343,7 +343,7 @@ Deno.test("an upload is named with the extension for its mime type when the URL
assertEquals(fake.created.map((c) => c.filename), [
"1706.03762v7.pdf",
"abc.jpg",
"Logo.PNG",
"Logo.png",
"photo.jpeg",
"photo.jpg",
]);
Expand Down
Loading