Merge pull request #2068 from Ogannesson/fix/openai-drop-reasoning-items-from-input
fix(openai): drop reasoning items from /v1/responses input on OAuth path
This commit is contained in:
commit
8d6d31545f
@ -907,6 +907,14 @@ func filterCodexInput(input []any, preserveReferences bool) []any {
|
|||||||
}
|
}
|
||||||
typ, _ := m["type"].(string)
|
typ, _ := m["type"].(string)
|
||||||
|
|
||||||
|
// chatgpt.com codex backend (OAuth path) does not persist reasoning
|
||||||
|
// items because applyCodexOAuthTransform forces store=false. Any rs_*
|
||||||
|
// reference replayed in input is guaranteed to 404 upstream
|
||||||
|
// ("Item with id 'rs_...' not found"). Drop reasoning items entirely.
|
||||||
|
if typ == "reasoning" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// 仅修正真正的 tool/function call 标识,避免误改普通 message/reasoning id;
|
// 仅修正真正的 tool/function call 标识,避免误改普通 message/reasoning id;
|
||||||
// 若 item_reference 指向 legacy call_* 标识,则仅修正该引用本身。
|
// 若 item_reference 指向 legacy call_* 标识,则仅修正该引用本身。
|
||||||
fixCallIDPrefix := func(id string) string {
|
fixCallIDPrefix := func(id string) string {
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -1132,3 +1134,54 @@ func TestIsInstructionsEmpty(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFilterCodexInput_DropsReasoningItemsRegardlessOfPreserveReferences(t *testing.T) {
|
||||||
|
// Reasoning items in input[] reference rs_* IDs that were emitted by
|
||||||
|
// chatgpt.com under store=false (forced by applyCodexOAuthTransform).
|
||||||
|
// They are never persisted upstream, so forwarding them produces a
|
||||||
|
// guaranteed 404 ("Item with id 'rs_...' not found"). Drop them
|
||||||
|
// regardless of preserveReferences. See: Wei-Shaw/sub2api issue #1957.
|
||||||
|
|
||||||
|
build := func() []any {
|
||||||
|
return []any{
|
||||||
|
map[string]any{"type": "message", "id": "msg_0", "role": "user", "content": "hi"},
|
||||||
|
map[string]any{
|
||||||
|
"type": "reasoning",
|
||||||
|
"id": "rs_0672f12450da0b9c0169f07220a6c08198b68c2455ced99344",
|
||||||
|
"summary": []any{},
|
||||||
|
},
|
||||||
|
map[string]any{"type": "function_call", "id": "fc_1", "call_id": "call_1", "name": "tool"},
|
||||||
|
map[string]any{"type": "function_call_output", "call_id": "call_1", "output": "{}"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, preserve := range []bool{true, false} {
|
||||||
|
preserve := preserve
|
||||||
|
t.Run(fmt.Sprintf("preserveReferences=%v", preserve), func(t *testing.T) {
|
||||||
|
filtered := filterCodexInput(build(), preserve)
|
||||||
|
|
||||||
|
for _, raw := range filtered {
|
||||||
|
item, ok := raw.(map[string]any)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotEqual(t, "reasoning", item["type"],
|
||||||
|
"reasoning items must be dropped from input on the OAuth path")
|
||||||
|
if id, ok := item["id"].(string); ok {
|
||||||
|
require.False(t, strings.HasPrefix(id, "rs_"),
|
||||||
|
"no item carrying an rs_* id should survive the filter")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check: the non-reasoning items should still be present.
|
||||||
|
gotTypes := make(map[string]int)
|
||||||
|
for _, raw := range filtered {
|
||||||
|
item, ok := raw.(map[string]any)
|
||||||
|
require.True(t, ok)
|
||||||
|
gotTypes[item["type"].(string)]++
|
||||||
|
}
|
||||||
|
require.Equal(t, 1, gotTypes["message"])
|
||||||
|
require.Equal(t, 1, gotTypes["function_call"])
|
||||||
|
require.Equal(t, 1, gotTypes["function_call_output"])
|
||||||
|
require.Equal(t, 0, gotTypes["reasoning"])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user