@@ -106,6 +106,7 @@ type MockOpenAiRequestSnapshot = {
106106 plannedToolName ?: string ;
107107 plannedToolArgs ?: Record < string , unknown > ;
108108 toolOutputCallId ?: string ;
109+ toolOutputStructuredError ?: true ;
109110} ;
110111
111112// Anthropic /v1/messages request/response shapes the mock actually needs.
@@ -125,6 +126,7 @@ type AnthropicMessageContentBlock =
125126 | {
126127 type : "tool_result" ;
127128 tool_use_id : string ;
129+ is_error ?: boolean ;
128130 content : string | Array < { type : "text" ; text : string } > ;
129131 }
130132 | { type : "image" ; source : Record < string , unknown > } ;
@@ -395,6 +397,13 @@ function extractFunctionCallOutputCallId(item: ResponsesInputItem) {
395397 ) ;
396398}
397399
400+ function functionCallOutputIsStructuredError ( item : ResponsesInputItem ) {
401+ if ( item . type !== "function_call_output" ) {
402+ return false ;
403+ }
404+ return item . is_error === true || item . isError === true ;
405+ }
406+
398407function extractToolOutput ( input : ResponsesInputItem [ ] ) {
399408 const lastUserIndex = findLastUserIndex ( input ) ;
400409 for ( let index = input . length - 1 ; index > lastUserIndex ; index -= 1 ) {
@@ -425,6 +434,35 @@ function extractToolOutput(input: ResponsesInputItem[]) {
425434 return "" ;
426435}
427436
437+ function extractToolOutputStructuredError ( input : ResponsesInputItem [ ] ) {
438+ const lastUserIndex = findLastUserIndex ( input ) ;
439+ for ( let index = input . length - 1 ; index > lastUserIndex ; index -= 1 ) {
440+ const item = input [ index ] ;
441+ const output = extractFunctionCallOutputText ( item ) ;
442+ if ( output ) {
443+ return functionCallOutputIsStructuredError ( item ) ;
444+ }
445+ }
446+ for ( let index = input . length - 1 ; index >= 0 ; index -= 1 ) {
447+ const item = input [ index ] ;
448+ const output = extractFunctionCallOutputText ( item ) ;
449+ if ( output ) {
450+ const laterUserTexts = input
451+ . slice ( index + 1 )
452+ . filter ( ( laterItem ) => laterItem . role === "user" && Array . isArray ( laterItem . content ) )
453+ . map ( ( laterItem ) => extractInputText ( laterItem . content as unknown [ ] ) )
454+ . filter ( Boolean ) ;
455+ if (
456+ laterUserTexts . length > 0 &&
457+ laterUserTexts . every ( ( text ) => isToolOutputContinuationText ( text ) )
458+ ) {
459+ return functionCallOutputIsStructuredError ( item ) ;
460+ }
461+ }
462+ }
463+ return false ;
464+ }
465+
428466function extractToolOutputCallId ( input : ResponsesInputItem [ ] ) {
429467 const lastUserIndex = findLastUserIndex ( input ) ;
430468 for ( let index = input . length - 1 ; index > lastUserIndex ; index -= 1 ) {
@@ -2867,6 +2905,7 @@ function convertAnthropicMessagesToResponsesInput(params: {
28672905 type : "function_call_output" ,
28682906 call_id : block . tool_use_id ,
28692907 output,
2908+ ...( block . is_error === true ? { is_error : true } : { } ) ,
28702909 } ) ;
28712910 }
28722911 continue ;
@@ -3235,6 +3274,7 @@ export async function startQaMockOpenAiServer(params?: { host?: string; port?: n
32353274 plannedToolName : extractPlannedToolName ( events ) ,
32363275 plannedToolArgs : extractPlannedToolArgs ( events ) ,
32373276 toolOutputCallId : extractToolOutputCallId ( input ) || undefined ,
3277+ ...( extractToolOutputStructuredError ( input ) ? { toolOutputStructuredError : true } : { } ) ,
32383278 } ;
32393279 requests . push ( lastRequest ) ;
32403280 if ( requests . length > MOCK_OPENAI_DEBUG_REQUEST_LIMIT ) {
@@ -3293,6 +3333,7 @@ export async function startQaMockOpenAiServer(params?: { host?: string; port?: n
32933333 plannedToolName : extractPlannedToolName ( events ) ,
32943334 plannedToolArgs : extractPlannedToolArgs ( events ) ,
32953335 toolOutputCallId : extractToolOutputCallId ( input ) || undefined ,
3336+ ...( extractToolOutputStructuredError ( input ) ? { toolOutputStructuredError : true } : { } ) ,
32963337 } ;
32973338 requests . push ( lastRequest ) ;
32983339 if ( requests . length > MOCK_OPENAI_DEBUG_REQUEST_LIMIT ) {
0 commit comments