diff --git a/internal/runtime/executor/helps/codex_input_ids.go b/internal/runtime/executor/helps/codex_input_ids.go index 1ee2bac4..05c011e9 100644 --- a/internal/runtime/executor/helps/codex_input_ids.go +++ b/internal/runtime/executor/helps/codex_input_ids.go @@ -12,10 +12,11 @@ import ( ) const ( - codexInputItemIDLimit = 64 - codexMessageItemIDPrefix = "msg" - codexReasoningItemIDPrefix = "rs" - codexFunctionCallItemIDPrefix = "fc" + codexInputItemIDLimit = 64 + codexMessageItemIDPrefix = "msg" + codexReasoningItemIDPrefix = "rs" + codexFunctionCallItemIDPrefix = "fc" + codexCustomToolCallItemIDPrefix = "ctc" ) // SanitizeCodexInputItemIDs normalizes supported input item IDs for Codex, removes encrypted @@ -103,6 +104,8 @@ func normalizeCodexInputItemID(item gjson.Result, id string) string { prefix = codexReasoningItemIDPrefix case "function_call": prefix = codexFunctionCallItemIDPrefix + case "custom_tool_call": + prefix = codexCustomToolCallItemIDPrefix default: return id } diff --git a/internal/runtime/executor/helps/codex_input_ids_test.go b/internal/runtime/executor/helps/codex_input_ids_test.go index c9f4434e..ba9cb92f 100644 --- a/internal/runtime/executor/helps/codex_input_ids_test.go +++ b/internal/runtime/executor/helps/codex_input_ids_test.go @@ -94,6 +94,16 @@ func TestSanitizeCodexInputItemIDsNormalizesResponseItemIDs(t *testing.T) { } } +func TestSanitizeCodexInputItemIDsNormalizesCustomToolCallIDs(t *testing.T) { + const invalidID = "item_44e13caebc1ddf25f1337cbe" + body := []byte(`{"input":[{"type":"custom_tool_call","id":"` + invalidID + `","call_id":"call-1","name":"lookup","input":"{}"}]}`) + + got := SanitizeCodexInputItemIDs(body) + if actual := gjson.GetBytes(got, "input.0.id").String(); actual != "ctc_"+invalidID { + t.Fatalf("custom_tool_call ID = %q, want ctc-prefixed ID", actual) + } +} + func TestSanitizeCodexInputItemIDsDropsOverlongEncryptedReasoningItem(t *testing.T) { longReasoningID := "rs_" + strings.Repeat("a", 64) shortReasoningID := "rs_" + strings.Repeat("b", 48)