mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-15 23:22:59 +08:00
fix(openai): 兼容历史任务委派续聊
This commit is contained in:
@@ -1600,14 +1600,17 @@ func (h *OpenAIGatewayHandler) validateFunctionCallOutputRequest(c *gin.Context,
|
||||
}
|
||||
|
||||
func normalizeCodexDelegationBootstrap(body []byte) ([]byte, bool) {
|
||||
return normalizeCodexCallOutputBootstrap(body, isCodexDelegationCandidate)
|
||||
// 已有任务通过 send_message_to_thread 唤醒时会携带 previous_response_id;
|
||||
// 完整历史回放还会带有已配对的调用项。delegation 仍是客户端注入的用户输入,
|
||||
// 不属于这些历史调用的结果,因此允许它与可明确配对的历史上下文共存。
|
||||
return normalizeCodexCallOutputBootstrap(body, isCodexDelegationCandidate, true)
|
||||
}
|
||||
|
||||
func normalizeCodexAutomationBootstrap(body []byte) ([]byte, bool) {
|
||||
return normalizeCodexCallOutputBootstrap(body, isCodexAutomationCandidate)
|
||||
return normalizeCodexCallOutputBootstrap(body, isCodexAutomationCandidate, false)
|
||||
}
|
||||
|
||||
func normalizeCodexCallOutputBootstrap(body []byte, isCandidate func(map[string]any) bool) ([]byte, bool) {
|
||||
func normalizeCodexCallOutputBootstrap(body []byte, isCandidate func(map[string]any) bool, allowHistoricalContext bool) ([]byte, bool) {
|
||||
if !hasUniqueJSONMembers(body) {
|
||||
return body, false
|
||||
}
|
||||
@@ -1619,7 +1622,7 @@ func normalizeCodexCallOutputBootstrap(body []byte, isCandidate func(map[string]
|
||||
}
|
||||
if previousResponseID, exists := request["previous_response_id"]; exists {
|
||||
value, ok := previousResponseID.(string)
|
||||
if !ok || strings.TrimSpace(value) != "" {
|
||||
if !ok || (!allowHistoricalContext && strings.TrimSpace(value) != "") {
|
||||
return body, false
|
||||
}
|
||||
}
|
||||
@@ -1628,27 +1631,35 @@ func normalizeCodexCallOutputBootstrap(body []byte, isCandidate func(map[string]
|
||||
return body, false
|
||||
}
|
||||
|
||||
// Any call/reference anchor makes a call-less output ambiguous. Responses
|
||||
// built-ins follow the *_call / *_call_output naming convention, so classify
|
||||
// by the wire type shape instead of maintaining an incomplete allowlist.
|
||||
// Responses built-ins follow the *_call / *_call_output naming convention,
|
||||
// so classify by the wire type shape instead of maintaining an incomplete
|
||||
// allowlist. Delegation may coexist with historical anchors only when their
|
||||
// IDs make them unambiguous; automation retains the bootstrap-only boundary.
|
||||
for _, raw := range input {
|
||||
item, ok := raw.(map[string]any)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
typ := stringField(item, "type")
|
||||
if typ == "item_reference" || strings.HasSuffix(typ, "_call") {
|
||||
return body, false
|
||||
}
|
||||
if isResponsesCallOutputType(typ) {
|
||||
if isCandidate(item) {
|
||||
callIDValue, exists := item["call_id"]
|
||||
callID, isString := callIDValue.(string)
|
||||
if exists && (!isString || strings.TrimSpace(callID) != "") {
|
||||
return body, false
|
||||
}
|
||||
if !isCandidate(item) {
|
||||
return body, false
|
||||
continue
|
||||
}
|
||||
if typ == "item_reference" {
|
||||
if allowHistoricalContext && strings.TrimSpace(stringField(item, "id")) != "" {
|
||||
continue
|
||||
}
|
||||
return body, false
|
||||
}
|
||||
if strings.HasSuffix(typ, "_call") || isResponsesCallOutputType(typ) {
|
||||
if allowHistoricalContext && strings.TrimSpace(stringField(item, "call_id")) != "" {
|
||||
continue
|
||||
}
|
||||
return body, false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user