diff --git a/.changeset/young-birds-hammer.md b/.changeset/young-birds-hammer.md new file mode 100644 index 00000000..71bc48b3 --- /dev/null +++ b/.changeset/young-birds-hammer.md @@ -0,0 +1,6 @@ +--- +'@openai/agents-openai': patch +'@openai/agents-core': patch +--- + +Fix #216 Publicly accessible PDF file URL is not yet supported in the input_file content data diff --git a/examples/basic/package.json b/examples/basic/package.json index ca6b75bd..91a40531 100644 --- a/examples/basic/package.json +++ b/examples/basic/package.json @@ -17,6 +17,7 @@ "start:previous-response-id": "tsx previous-response-id.ts", "start:prompt": "tsx prompt-id.ts", "start:remote-image": "tsx remote-image.ts", + "start:remote-pdf": "tsx remote-pdf.ts", "start:stream-items": "tsx stream-items.ts", "start:stream-text": "tsx stream-text.ts", "start:json-schema-output-type": "tsx json-schema-output-type.ts", diff --git a/examples/basic/remote-image.ts b/examples/basic/remote-image.ts index b43023b3..52cffc64 100644 --- a/examples/basic/remote-image.ts +++ b/examples/basic/remote-image.ts @@ -1,6 +1,6 @@ import { Agent, run } from '@openai/agents'; -const URL = +const url = 'https://upload.wikimedia.org/wikipedia/commons/0/0c/GoldenGateBridge-001.jpg'; async function main() { @@ -15,7 +15,7 @@ async function main() { content: [ { type: 'input_image', - image: URL, + image: url, providerData: { detail: 'auto', }, diff --git a/examples/basic/remote-pdf.ts b/examples/basic/remote-pdf.ts new file mode 100644 index 00000000..7ff38acc --- /dev/null +++ b/examples/basic/remote-pdf.ts @@ -0,0 +1,27 @@ +import { Agent, run } from '@openai/agents'; + +const url = 'https://www.berkshirehathaway.com/letters/2024ltr.pdf'; + +async function main() { + const agent = new Agent({ + name: 'Assistant', + instructions: 'You are a helpful assistant.', + }); + + const result = await run(agent, [ + { + role: 'user', + content: [{ type: 'input_file', file: url }], + }, + { + role: 'user', + content: 'Can you summarize the letter?', + }, + ]); + + console.log(result.finalOutput); +} + +if (require.main === module) { + main().catch(console.error); +} diff --git a/packages/agents-core/src/types/protocol.ts b/packages/agents-core/src/types/protocol.ts index 577a8703..95a5a98c 100644 --- a/packages/agents-core/src/types/protocol.ts +++ b/packages/agents-core/src/types/protocol.ts @@ -91,9 +91,17 @@ export const InputFile = SharedBase.extend({ */ file: z .string() + .describe( + 'Either base64 encoded file data or a publicly accessible file URL', + ) .or( z.object({ - id: z.string(), + id: z.string().describe('OpenAI file ID'), + }), + ) + .or( + z.object({ + url: z.string().describe('Publicly accessible PDF file URL'), }), ) .describe('Contents of the file or an object with a file ID.'), diff --git a/packages/agents-openai/src/openaiResponsesModel.ts b/packages/agents-openai/src/openaiResponsesModel.ts index 3172b4f0..73c7bb87 100644 --- a/packages/agents-openai/src/openaiResponsesModel.ts +++ b/packages/agents-openai/src/openaiResponsesModel.ts @@ -266,9 +266,19 @@ function getInputMessageContent( type: 'input_file', }; if (typeof entry.file === 'string') { - fileEntry.file_data = entry.file; - } else { + if (entry.file.startsWith('data:')) { + fileEntry.file_data = entry.file; + } else if (entry.file.startsWith('https://')) { + fileEntry.file_url = entry.file; + } else { + throw new UserError( + `Unsupported string data for file input. If you're trying to pass an uploaded file's ID, use an object with the ID property instead.`, + ); + } + } else if ('id' in entry.file) { fileEntry.file_id = entry.file.id; + } else if ('url' in entry.file) { + fileEntry.file_url = entry.file.url; } return { ...fileEntry,