fix(openai): avoid inferred WS continuation on explicit tool replay

This commit is contained in:
KnowSky404
2026-04-29 17:38:08 +08:00
parent 4d676dddd1
commit 28dc34b6a3
3 changed files with 356 additions and 46 deletions
@@ -1366,16 +1366,25 @@ func setPreviousResponseIDToRawPayload(payload []byte, previousResponseID string
func shouldInferIngressFunctionCallOutputPreviousResponseID(
storeDisabled bool,
turn int,
hasFunctionCallOutput bool,
signals ToolContinuationSignals,
currentPreviousResponseID string,
expectedPreviousResponseID string,
) bool {
if !storeDisabled || turn <= 1 || !hasFunctionCallOutput {
if !storeDisabled || turn <= 1 || !signals.HasFunctionCallOutput {
return false
}
if strings.TrimSpace(currentPreviousResponseID) != "" {
return false
}
if signals.HasFunctionCallOutputMissingCallID {
return false
}
// If the client already sent tool-call context or item_reference anchors,
// treat this as a full replay / self-contained continuation payload rather
// than downgrading it into an inferred delta continuation.
if signals.HasToolCallContext || signals.HasItemReferenceForAllCallIDs {
return false
}
return strings.TrimSpace(expectedPreviousResponseID) != ""
}
@@ -3179,13 +3188,22 @@ func (s *OpenAIGatewayService) ProxyResponsesWebSocketFromClient(
skipBeforeTurn = false
currentPreviousResponseID := openAIWSPayloadStringFromRaw(currentPayload, "previous_response_id")
expectedPrev := strings.TrimSpace(lastTurnResponseID)
hasFunctionCallOutput := gjson.GetBytes(currentPayload, `input.#(type=="function_call_output")`).Exists()
toolSignals := ToolContinuationSignals{
HasFunctionCallOutput: gjson.GetBytes(currentPayload, `input.#(type=="function_call_output")`).Exists(),
}
if toolSignals.HasFunctionCallOutput {
var currentReqBody map[string]any
if err := json.Unmarshal(currentPayload, &currentReqBody); err == nil {
toolSignals = AnalyzeToolContinuationSignals(currentReqBody)
}
}
hasFunctionCallOutput := toolSignals.HasFunctionCallOutput
// store=false + function_call_output 场景必须有续链锚点。
// 若客户端未传 previous_response_id,优先回填上一轮响应 ID,避免上游报 call_id 无法关联。
if shouldInferIngressFunctionCallOutputPreviousResponseID(
storeDisabled,
turn,
hasFunctionCallOutput,
toolSignals,
currentPreviousResponseID,
expectedPrev,
) {