@@ -15,6 +15,7 @@ export interface ResponsesStreamState {
1515 initialInputTokens ?: number
1616 functionCallStateByOutputIndex : Map < number , FunctionCallStreamState >
1717 functionCallOutputIndexByItemId : Map < string , number >
18+ summryIndex : number
1819}
1920
2021type FunctionCallStreamState = {
@@ -32,6 +33,7 @@ export const createResponsesStreamState = (): ResponsesStreamState => ({
3233 blockHasDelta : new Set ( ) ,
3334 functionCallStateByOutputIndex : new Map ( ) ,
3435 functionCallOutputIndexByItemId : new Map ( ) ,
36+ summryIndex : 0 ,
3537} )
3638
3739export const translateResponsesStreamEvent = (
@@ -49,12 +51,18 @@ export const translateResponsesStreamEvent = (
4951 return handleResponseCreated ( rawEvent , state )
5052 }
5153
52- case "response.reasoning_summary_text.delta" :
54+ case "response.reasoning_summary_text.delta" : {
55+ return handleReasoningSummaryTextDelta ( rawEvent , state )
56+ }
57+
5358 case "response.output_text.delta" : {
5459 return handleOutputTextDelta ( rawEvent , state )
5560 }
5661
57- case "response.reasoning_summary_part.done" :
62+ case "response.reasoning_summary_part.done" : {
63+ return handleReasoningSummaryPartDone ( rawEvent , state )
64+ }
65+
5866 case "response.output_text.done" : {
5967 return handleOutputTextDone ( rawEvent , state )
6068 }
@@ -63,6 +71,10 @@ export const translateResponsesStreamEvent = (
6371 return handleOutputItemAdded ( rawEvent , state )
6472 }
6573
74+ case "response.output_item.done" : {
75+ return handleOutputItemDone ( rawEvent , state )
76+ }
77+
6678 case "response.function_call_arguments.delta" : {
6779 return handleFunctionCallArgumentsDelta ( rawEvent , state )
6880 }
@@ -143,6 +155,51 @@ const handleOutputItemAdded = (
143155 return events
144156}
145157
158+ const handleOutputItemDone = (
159+ rawEvent : Record < string , unknown > ,
160+ state : ResponsesStreamState ,
161+ ) : Array < AnthropicStreamEventData > => {
162+ const events = ensureMessageStart ( state )
163+
164+ const item = isRecord ( rawEvent . item ) ? rawEvent . item : undefined
165+ if ( ! item ) {
166+ return events
167+ }
168+
169+ const itemType = typeof item . type === "string" ? item . type : undefined
170+ if ( itemType !== "reasoning" ) {
171+ return events
172+ }
173+
174+ const outputIndex = toNumber ( rawEvent . output_index )
175+ const contentIndex = state . summryIndex
176+
177+ const blockIndex = openThinkingBlockIfNeeded ( state , {
178+ outputIndex,
179+ contentIndex,
180+ events,
181+ } )
182+
183+ const signature =
184+ typeof item . encrypted_content === "string" ? item . encrypted_content : ""
185+
186+ if ( signature ) {
187+ events . push ( {
188+ type : "content_block_delta" ,
189+ index : blockIndex ,
190+ delta : {
191+ type : "signature_delta" ,
192+ signature,
193+ } ,
194+ } )
195+ state . blockHasDelta . add ( blockIndex )
196+ }
197+
198+ closeBlockIfOpen ( state , blockIndex , events )
199+
200+ return events
201+ }
202+
146203const handleFunctionCallArgumentsDelta = (
147204 rawEvent : Record < string , unknown > ,
148205 state : ResponsesStreamState ,
@@ -257,6 +314,71 @@ const handleOutputTextDelta = (
257314 return events
258315}
259316
317+ const handleReasoningSummaryTextDelta = (
318+ rawEvent : Record < string , unknown > ,
319+ state : ResponsesStreamState ,
320+ ) : Array < AnthropicStreamEventData > => {
321+ const events = ensureMessageStart ( state )
322+
323+ const outputIndex = toNumber ( rawEvent . output_index )
324+ const contentIndex = toNumber ( rawEvent . summary_index )
325+ const deltaText = typeof rawEvent . delta === "string" ? rawEvent . delta : ""
326+
327+ if ( ! deltaText ) {
328+ return events
329+ }
330+
331+ const blockIndex = openThinkingBlockIfNeeded ( state , {
332+ outputIndex,
333+ contentIndex,
334+ events,
335+ } )
336+
337+ events . push ( {
338+ type : "content_block_delta" ,
339+ index : blockIndex ,
340+ delta : {
341+ type : "thinking_delta" ,
342+ thinking : deltaText ,
343+ } ,
344+ } )
345+ state . blockHasDelta . add ( blockIndex )
346+
347+ return events
348+ }
349+
350+ const handleReasoningSummaryPartDone = (
351+ rawEvent : Record < string , unknown > ,
352+ state : ResponsesStreamState ,
353+ ) : Array < AnthropicStreamEventData > => {
354+ const events = ensureMessageStart ( state )
355+
356+ const outputIndex = toNumber ( rawEvent . output_index )
357+ const contentIndex = toNumber ( rawEvent . summary_index )
358+ state . summryIndex = contentIndex
359+ const part = isRecord ( rawEvent . part ) ? rawEvent . part : undefined
360+ const text = part && typeof part . text === "string" ? part . text : ""
361+
362+ const blockIndex = openThinkingBlockIfNeeded ( state , {
363+ outputIndex,
364+ contentIndex,
365+ events,
366+ } )
367+
368+ if ( text && ! state . blockHasDelta . has ( blockIndex ) ) {
369+ events . push ( {
370+ type : "content_block_delta" ,
371+ index : blockIndex ,
372+ delta : {
373+ type : "thinking_delta" ,
374+ thinking : text ,
375+ } ,
376+ } )
377+ }
378+
379+ return events
380+ }
381+
260382const handleOutputTextDone = (
261383 rawEvent : Record < string , unknown > ,
262384 state : ResponsesStreamState ,
@@ -430,6 +552,39 @@ const openTextBlockIfNeeded = (
430552 return blockIndex
431553}
432554
555+ const openThinkingBlockIfNeeded = (
556+ state : ResponsesStreamState ,
557+ params : {
558+ outputIndex : number
559+ contentIndex : number
560+ events : Array < AnthropicStreamEventData >
561+ } ,
562+ ) : number => {
563+ const { outputIndex, contentIndex, events } = params
564+ const key = getBlockKey ( outputIndex , contentIndex )
565+ let blockIndex = state . blockIndexByKey . get ( key )
566+
567+ if ( blockIndex === undefined ) {
568+ blockIndex = state . nextContentBlockIndex
569+ state . nextContentBlockIndex += 1
570+ state . blockIndexByKey . set ( key , blockIndex )
571+ }
572+
573+ if ( ! state . openBlocks . has ( blockIndex ) ) {
574+ events . push ( {
575+ type : "content_block_start" ,
576+ index : blockIndex ,
577+ content_block : {
578+ type : "thinking" ,
579+ thinking : "" ,
580+ } ,
581+ } )
582+ state . openBlocks . add ( blockIndex )
583+ }
584+
585+ return blockIndex
586+ }
587+
433588const closeBlockIfOpen = (
434589 state : ResponsesStreamState ,
435590 blockIndex : number ,
0 commit comments