From d693d7993b576e9b639c9ca95904f92afcbf0b70 Mon Sep 17 00:00:00 2001 From: ciberponk Date: Sat, 21 Feb 2026 12:56:10 +0800 Subject: [PATCH 1/2] feat: support responses compaction payload compatibility for codex translator --- .../codex_openai-responses_request.go | 40 +++++++++++++++++++ .../codex_openai-responses_request_test.go | 38 ++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/internal/translator/codex/openai/responses/codex_openai-responses_request.go b/internal/translator/codex/openai/responses/codex_openai-responses_request.go index f0407149..3762f152 100644 --- a/internal/translator/codex/openai/responses/codex_openai-responses_request.go +++ b/internal/translator/codex/openai/responses/codex_openai-responses_request.go @@ -2,6 +2,7 @@ package responses import ( "fmt" + "strings" "github.com/tidwall/gjson" "github.com/tidwall/sjson" @@ -26,6 +27,8 @@ func ConvertOpenAIResponsesRequestToCodex(modelName string, inputRawJSON []byte, rawJSON, _ = sjson.DeleteBytes(rawJSON, "temperature") rawJSON, _ = sjson.DeleteBytes(rawJSON, "top_p") rawJSON, _ = sjson.DeleteBytes(rawJSON, "service_tier") + rawJSON, _ = sjson.DeleteBytes(rawJSON, "truncation") + rawJSON = applyResponsesCompactionCompatibility(rawJSON) // Delete the user field as it is not supported by the Codex upstream. rawJSON, _ = sjson.DeleteBytes(rawJSON, "user") @@ -36,6 +39,43 @@ func ConvertOpenAIResponsesRequestToCodex(modelName string, inputRawJSON []byte, return rawJSON } +// applyResponsesCompactionCompatibility handles OpenAI Responses context_management.compaction +// for Codex upstream compatibility. +// +// Codex /responses currently rejects context_management with: +// {"detail":"Unsupported parameter: context_management"}. +// +// Compatibility strategy: +// 1) Remove context_management before forwarding to Codex upstream. +// 2) Remove truncation as Codex upstream currently rejects it as unsupported. +func applyResponsesCompactionCompatibility(rawJSON []byte) []byte { + contextManagement := gjson.GetBytes(rawJSON, "context_management") + if !contextManagement.Exists() { + return rawJSON + } + + hasCompactionRule := false + switch { + case contextManagement.IsArray(): + for _, item := range contextManagement.Array() { + if strings.EqualFold(item.Get("type").String(), "compaction") { + hasCompactionRule = true + break + } + } + case contextManagement.IsObject(): + hasCompactionRule = strings.EqualFold(contextManagement.Get("type").String(), "compaction") + } + + if hasCompactionRule { + // no-op marker: compaction hint detected and consumed for compatibility. + } + + rawJSON, _ = sjson.DeleteBytes(rawJSON, "context_management") + rawJSON, _ = sjson.DeleteBytes(rawJSON, "truncation") + return rawJSON +} + // convertSystemRoleToDeveloper traverses the input array and converts any message items // with role "system" to role "developer". This is necessary because Codex API does not // accept "system" role in the input array. diff --git a/internal/translator/codex/openai/responses/codex_openai-responses_request_test.go b/internal/translator/codex/openai/responses/codex_openai-responses_request_test.go index 4f562486..65732c3f 100644 --- a/internal/translator/codex/openai/responses/codex_openai-responses_request_test.go +++ b/internal/translator/codex/openai/responses/codex_openai-responses_request_test.go @@ -280,3 +280,41 @@ func TestUserFieldDeletion(t *testing.T) { t.Errorf("user field should be deleted, but it was found with value: %s", userField.Raw) } } + +func TestContextManagementCompactionCompatibility(t *testing.T) { + inputJSON := []byte(`{ + "model": "gpt-5.2", + "context_management": [ + { + "type": "compaction", + "compact_threshold": 12000 + } + ], + "input": [{"role":"user","content":"hello"}] + }`) + + output := ConvertOpenAIResponsesRequestToCodex("gpt-5.2", inputJSON, false) + outputStr := string(output) + + if gjson.Get(outputStr, "context_management").Exists() { + t.Fatalf("context_management should be removed for Codex compatibility") + } + if gjson.Get(outputStr, "truncation").Exists() { + t.Fatalf("truncation should be removed for Codex compatibility") + } +} + +func TestTruncationRemovedForCodexCompatibility(t *testing.T) { + inputJSON := []byte(`{ + "model": "gpt-5.2", + "truncation": "disabled", + "input": [{"role":"user","content":"hello"}] + }`) + + output := ConvertOpenAIResponsesRequestToCodex("gpt-5.2", inputJSON, false) + outputStr := string(output) + + if gjson.Get(outputStr, "truncation").Exists() { + t.Fatalf("truncation should be removed for Codex compatibility") + } +} From afc8a0f9be7f261c4df6322dfe156913558934d0 Mon Sep 17 00:00:00 2001 From: fan Date: Sat, 21 Feb 2026 22:20:48 +0800 Subject: [PATCH 2/2] refactor: simplify context_management compatibility handling --- .../codex_openai-responses_request.go | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/internal/translator/codex/openai/responses/codex_openai-responses_request.go b/internal/translator/codex/openai/responses/codex_openai-responses_request.go index 3762f152..1161c515 100644 --- a/internal/translator/codex/openai/responses/codex_openai-responses_request.go +++ b/internal/translator/codex/openai/responses/codex_openai-responses_request.go @@ -2,7 +2,6 @@ package responses import ( "fmt" - "strings" "github.com/tidwall/gjson" "github.com/tidwall/sjson" @@ -47,32 +46,12 @@ func ConvertOpenAIResponsesRequestToCodex(modelName string, inputRawJSON []byte, // // Compatibility strategy: // 1) Remove context_management before forwarding to Codex upstream. -// 2) Remove truncation as Codex upstream currently rejects it as unsupported. func applyResponsesCompactionCompatibility(rawJSON []byte) []byte { - contextManagement := gjson.GetBytes(rawJSON, "context_management") - if !contextManagement.Exists() { + if !gjson.GetBytes(rawJSON, "context_management").Exists() { return rawJSON } - hasCompactionRule := false - switch { - case contextManagement.IsArray(): - for _, item := range contextManagement.Array() { - if strings.EqualFold(item.Get("type").String(), "compaction") { - hasCompactionRule = true - break - } - } - case contextManagement.IsObject(): - hasCompactionRule = strings.EqualFold(contextManagement.Get("type").String(), "compaction") - } - - if hasCompactionRule { - // no-op marker: compaction hint detected and consumed for compatibility. - } - rawJSON, _ = sjson.DeleteBytes(rawJSON, "context_management") - rawJSON, _ = sjson.DeleteBytes(rawJSON, "truncation") return rawJSON }