mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-10-19 22:19:12 +08:00
fix(interactions): bridge apply_patch tool calls in responses translation
- Handle apply_patch custom tool call streaming deltas and snapshots for Responses API translation - Track and resolve step indexes, function call identities, and error states across stream events - Propagate apply_patch tool input errors and upstream failure states in stream and non-stream responses
This commit is contained in:
@@ -22,6 +22,7 @@ import (
|
||||
)
|
||||
|
||||
type metaPreparedRequest struct {
|
||||
applyPatch *helps.ApplyPatchResponsesState
|
||||
baseModel string
|
||||
from sdktranslator.Format
|
||||
responseFormat sdktranslator.Format
|
||||
@@ -61,12 +62,19 @@ func (e *MetaExecutor) prepareResponsesRequest(ctx context.Context, req cliproxy
|
||||
body, _ = sjson.DeleteBytes(body, "safety_identifier")
|
||||
body, _ = sjson.DeleteBytes(body, "stream_options")
|
||||
body, _ = sjson.DeleteBytes(body, "client_metadata")
|
||||
applyPatch := helps.NewApplyPatchResponsesState(from, originalPayload, originalTranslated)
|
||||
var errNormalizePatch error
|
||||
body, errNormalizePatch = helps.NormalizeApplyPatchResponsesRequest(body, originalPayload)
|
||||
if errNormalizePatch != nil {
|
||||
return nil, errNormalizePatch
|
||||
}
|
||||
body = normalizeCodexInstructions(body)
|
||||
body = sanitizeOpenAIResponsesReasoningEncryptedContent(ctx, "meta executor", body)
|
||||
body = helps.SanitizeMetaWebSearchTools(body)
|
||||
body = helps.NormalizeCodexToolIntegerTypes(body, opts.Headers)
|
||||
|
||||
return &metaPreparedRequest{
|
||||
applyPatch: applyPatch,
|
||||
baseModel: baseModel,
|
||||
from: from,
|
||||
responseFormat: responseFormat,
|
||||
@@ -170,25 +178,47 @@ func (e *MetaExecutor) translateMetaCompleted(ctx context.Context, req cliproxye
|
||||
if errEvent := metaStreamEventError(eventData); errEvent != nil {
|
||||
return metaCompletedTranslation{}, errEvent
|
||||
}
|
||||
eventType := gjson.GetBytes(eventData, "type").String()
|
||||
switch eventType {
|
||||
case "response.output_item.done":
|
||||
xaiCollectOutputItemDone(eventData, outputItemsByIndex, &outputItemsFallback)
|
||||
case "response.completed", "response.incomplete":
|
||||
completedData := patchCodexCompletedOutput(eventData, outputItemsByIndex, outputItemsFallback)
|
||||
var param any
|
||||
out := sdktranslator.TranslateNonStream(ctx, prepared.to, prepared.responseFormat, req.Model, prepared.originalPayload, prepared.body, completedData, ¶m)
|
||||
return metaCompletedTranslation{payload: out, sourceEvent: completedData}, nil
|
||||
events, errBridge := prepared.applyPatch.Transform(eventData)
|
||||
if errBridge != nil {
|
||||
errBridge = statusErr{code: http.StatusBadGateway, msg: helps.ApplyPatchUpstreamErrorMessage}
|
||||
return metaCompletedTranslation{}, errBridge
|
||||
}
|
||||
for _, eventData := range events {
|
||||
eventType := gjson.GetBytes(eventData, "type").String()
|
||||
switch eventType {
|
||||
case "response.output_item.done":
|
||||
xaiCollectOutputItemDone(eventData, outputItemsByIndex, &outputItemsFallback)
|
||||
case "response.completed", "response.incomplete":
|
||||
completedData := patchCodexCompletedOutput(eventData, outputItemsByIndex, outputItemsFallback)
|
||||
var param any
|
||||
out := sdktranslator.TranslateNonStream(ctx, prepared.to, prepared.responseFormat, req.Model, prepared.originalPayload, prepared.body, completedData, ¶m)
|
||||
if helps.ApplyPatchTranslationError(param) != nil || len(out) == 0 {
|
||||
return metaCompletedTranslation{}, statusErr{code: http.StatusBadGateway, msg: helps.ApplyPatchUpstreamErrorMessage}
|
||||
}
|
||||
return metaCompletedTranslation{payload: out, sourceEvent: completedData}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if completedData, ok := metaAsCompletedEvent(data); ok {
|
||||
completedData = patchCodexCompletedOutput(completedData, outputItemsByIndex, outputItemsFallback)
|
||||
var errBridge error
|
||||
completedData, errBridge = prepared.applyPatch.Bridge.TransformNonStream(completedData)
|
||||
if errBridge != nil {
|
||||
errBridge = statusErr{code: http.StatusBadGateway, msg: helps.ApplyPatchUpstreamErrorMessage}
|
||||
return metaCompletedTranslation{}, errBridge
|
||||
}
|
||||
var param any
|
||||
out := sdktranslator.TranslateNonStream(ctx, prepared.to, prepared.responseFormat, req.Model, prepared.originalPayload, prepared.body, completedData, ¶m)
|
||||
if helps.ApplyPatchTranslationError(param) != nil || len(out) == 0 {
|
||||
return metaCompletedTranslation{}, statusErr{code: http.StatusBadGateway, msg: helps.ApplyPatchUpstreamErrorMessage}
|
||||
}
|
||||
return metaCompletedTranslation{payload: out, sourceEvent: completedData}, nil
|
||||
}
|
||||
|
||||
if errFinish := prepared.applyPatch.Finish(); errFinish != nil {
|
||||
return metaCompletedTranslation{}, statusErr{code: http.StatusBadGateway, msg: helps.ApplyPatchUpstreamErrorMessage}
|
||||
}
|
||||
return metaCompletedTranslation{}, statusErr{code: http.StatusRequestTimeout, msg: "meta stream error: stream disconnected before response.completed or response.incomplete"}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user