@@ -166,7 +166,8 @@ func (o responsesLanguageModel) prepareParams(call fantasy.Call) (*responses.Res
166166 params .Store = param .NewOpt (false )
167167 }
168168
169- if openaiOptions != nil && openaiOptions .PreviousResponseID != nil && * openaiOptions .PreviousResponseID != "" {
169+ hasPreviousResponseID := openaiOptions != nil && openaiOptions .PreviousResponseID != nil && * openaiOptions .PreviousResponseID != ""
170+ if hasPreviousResponseID {
170171 if err := validatePreviousResponseIDPrompt (call .Prompt ); err != nil {
171172 return nil , warnings , err
172173 }
@@ -177,7 +178,7 @@ func (o responsesLanguageModel) prepareParams(call fantasy.Call) (*responses.Res
177178 }
178179
179180 storeEnabled := openaiOptions != nil && openaiOptions .Store != nil && * openaiOptions .Store
180- input , inputWarnings , err := toResponsesPrompt (call .Prompt , modelConfig .systemMessageMode , storeEnabled )
181+ input , inputWarnings , err := toResponsesPrompt (call .Prompt , modelConfig .systemMessageMode , storeEnabled , hasPreviousResponseID )
181182 warnings = append (warnings , inputWarnings ... )
182183 if err != nil {
183184 return nil , warnings , err
@@ -400,9 +401,10 @@ func responsesUsage(resp responses.Response) fantasy.Usage {
400401 return usage
401402}
402403
403- func toResponsesPrompt (prompt fantasy.Prompt , systemMessageMode string , store bool ) (responses.ResponseInputParam , []fantasy.CallWarning , error ) {
404+ func toResponsesPrompt (prompt fantasy.Prompt , systemMessageMode string , store bool , allowOrphanFunctionOutputs ... bool ) (responses.ResponseInputParam , []fantasy.CallWarning , error ) {
404405 var input responses.ResponseInputParam
405406 var warnings []fantasy.CallWarning
407+ allowOrphanOutputs := len (allowOrphanFunctionOutputs ) > 0 && allowOrphanFunctionOutputs [0 ]
406408
407409 // First pass: collect raw JSON for computer_call output items.
408410 // This enables faithful round-tripping via param.Override.
@@ -741,7 +743,7 @@ func toResponsesPrompt(prompt fantasy.Prompt, systemMessageMode string, store bo
741743 }
742744 }
743745
744- if err := validateResponsesInput (input ); err != nil {
746+ if err := validateResponsesInput (input , allowOrphanOutputs ); err != nil {
745747 return nil , warnings , err
746748 }
747749
@@ -753,14 +755,15 @@ func isResponsesWebSearchToolCall(toolCallPart fantasy.ToolCallPart) bool {
753755 toolCallPart .ToolName == "web_search_preview"
754756}
755757
756- func validateResponsesInput (input responses.ResponseInputParam ) error {
757- if err := validateResponsesFunctionCallOutputs (input ); err != nil {
758+ func validateResponsesInput (input responses.ResponseInputParam , allowOrphanFunctionOutputs ... bool ) error {
759+ allowOrphanOutputs := len (allowOrphanFunctionOutputs ) > 0 && allowOrphanFunctionOutputs [0 ]
760+ if err := validateResponsesFunctionCallOutputs (input , allowOrphanOutputs ); err != nil {
758761 return err
759762 }
760763 return validateResponsesItemReferences (input )
761764}
762765
763- func validateResponsesFunctionCallOutputs (input responses.ResponseInputParam ) error {
766+ func validateResponsesFunctionCallOutputs (input responses.ResponseInputParam , allowOrphanOutputs bool ) error {
764767 type callState struct {
765768 calls int
766769 outputs int
@@ -818,6 +821,9 @@ func validateResponsesFunctionCallOutputs(input responses.ResponseInputParam) er
818821 for _ , callID := range outputIDs {
819822 state := states [callID ]
820823 if state .calls == 0 {
824+ if allowOrphanOutputs {
825+ continue
826+ }
821827 return fmt .Errorf ("openai responses prompt has function_call_output without function_call for call_id %q" , callID )
822828 }
823829 if state .firstOutput < state .firstCall {
0 commit comments