diff --git a/.changeset/fuzzy-responses-reason.md b/.changeset/fuzzy-responses-reason.md new file mode 100644 index 000000000000..b1552472d773 --- /dev/null +++ b/.changeset/fuzzy-responses-reason.md @@ -0,0 +1,5 @@ +--- +'@ai-sdk/open-responses': patch +--- + +Stream Open Responses reasoning summary text deltas as reasoning output. diff --git a/packages/open-responses/src/responses/__fixtures__/openai-reasoning-summary-text.1.chunks.txt b/packages/open-responses/src/responses/__fixtures__/openai-reasoning-summary-text.1.chunks.txt new file mode 100644 index 000000000000..951e808cfcb0 --- /dev/null +++ b/packages/open-responses/src/responses/__fixtures__/openai-reasoning-summary-text.1.chunks.txt @@ -0,0 +1,6 @@ +{"type":"response.output_item.added","sequence_number":0,"output_index":0,"item":{"id":"rs_1","type":"reasoning","summary":[]}} +{"type":"response.reasoning_summary_text.delta","sequence_number":1,"item_id":"rs_1","output_index":0,"summary_index":0,"delta":"Think"} +{"type":"response.reasoning_summary_text.delta","sequence_number":2,"item_id":"rs_1","output_index":0,"summary_index":0,"delta":"ing."} +{"type":"response.reasoning_summary_text.done","sequence_number":3,"item_id":"rs_1","output_index":0,"summary_index":0,"text":"Thinking."} +{"type":"response.output_item.done","sequence_number":4,"output_index":0,"item":{"id":"rs_1","type":"reasoning","summary":[{"type":"summary_text","text":"Thinking."}]}} +{"type":"response.completed","sequence_number":5,"response":{"id":"resp_1","status":"completed","incomplete_details":null,"usage":{"input_tokens":1,"output_tokens":1}}} diff --git a/packages/open-responses/src/responses/open-responses-language-model.test.ts b/packages/open-responses/src/responses/open-responses-language-model.test.ts index 199e32b9eb7c..38de1730e751 100644 --- a/packages/open-responses/src/responses/open-responses-language-model.test.ts +++ b/packages/open-responses/src/responses/open-responses-language-model.test.ts @@ -1052,6 +1052,51 @@ describe('OpenResponsesLanguageModel', () => { }); }); + it('should stream reasoning summary text deltas', async () => { + prepareChunksFixtureResponse('openai-reasoning-summary-text.1'); + + const result = await createModel().doStream({ + prompt: TEST_PROMPT, + }); + + const parts = await convertReadableStreamToArray(result.stream); + + expect( + parts.filter(part => part.type.startsWith('reasoning')), + ).toStrictEqual([ + { + type: 'reasoning-start', + id: 'rs_1', + }, + { + type: 'reasoning-delta', + id: 'rs_1', + delta: 'Think', + }, + { + type: 'reasoning-delta', + id: 'rs_1', + delta: 'ing.', + }, + { + type: 'reasoning-end', + id: 'rs_1', + providerMetadata: { + lmstudio: { + itemId: 'rs_1', + reasoningSummary: [ + { + type: 'summary_text', + text: 'Thinking.', + }, + ], + reasoningContent: null, + }, + }, + }, + ]); + }); + it.each([ { event: { diff --git a/packages/open-responses/src/responses/open-responses-language-model.ts b/packages/open-responses/src/responses/open-responses-language-model.ts index ebdf045f0bf1..413b453b5a01 100644 --- a/packages/open-responses/src/responses/open-responses-language-model.ts +++ b/packages/open-responses/src/responses/open-responses-language-model.ts @@ -554,8 +554,9 @@ export class OpenResponsesLanguageModel implements LanguageModelV4 { }); activeReasoningId = chunk.item.id; } else if ( + chunk.type === 'response.reasoning_summary_text.delta' || (chunk as { type: string }).type === - 'response.reasoning_text.delta' + 'response.reasoning_text.delta' ) { const reasoningChunk = chunk as { item_id: string;