| @@ -22,8 +22,9 @@ var ( · 21 unmodified lines |
| 22 | | 22 | |
| 23 | // ConvertCodexResponseToClaudeParams holds parameters for response conversion. | 23 | // ConvertCodexResponseToClaudeParams holds parameters for response conversion. |
| 24 | type ConvertCodexResponseToClaudeParams struct { | 24 | type ConvertCodexResponseToClaudeParams struct { |
| 25 | HasToolCall bool | 25 | HasToolCall bool |
| 26 | BlockIndex int | 26 | BlockIndex int |
| | 27 | HasReceivedArgumentsDelta bool |
| 27 | } | 28 | } |
| 28 | | 29 | |
| 29 | // ConvertCodexResponseToClaude performs sophisticated streaming response format conversion. | 30 | // ConvertCodexResponseToClaude performs sophisticated streaming response format conversion. |
| @@ -137,6 +138,7 @@ func ConvertCodexResponseToClaude(_ context.Context, _ string, originalRequestRa · 107 unmodified lines |
| 137 | itemType := itemResult.Get("type").String() | 138 | itemType := itemResult.Get("type").String() |
| 138 | if itemType == "function_call" { | 139 | if itemType == "function_call" { |
| 139 | (*param).(*ConvertCodexResponseToClaudeParams).HasToolCall = true | 140 | (*param).(*ConvertCodexResponseToClaudeParams).HasToolCall = true |
| | 141 | (*param).(*ConvertCodexResponseToClaudeParams).HasReceivedArgumentsDelta = false |
| 140 | template = `{"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"","name":"","input":{}}}` | 142 | template = `{"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"","name":"","input":{}}}` |
| 141 | template, _ = sjson.Set(template, "index", (*param).(*ConvertCodexResponseToClaudeParams).BlockIndex) | 143 | template, _ = sjson.Set(template, "index", (*param).(*ConvertCodexResponseToClaudeParams).BlockIndex) |
| 142 | template, _ = sjson.Set(template, "content_block.id", itemResult.Get("call_id").String()) | 144 | template, _ = sjson.Set(template, "content_block.id", itemResult.Get("call_id").String()) |
| @@ -171,12 +173,29 @@ func ConvertCodexResponseToClaude(_ context.Context, _ string, originalRequestRa · 28 unmodified lines |
| 171 | output += fmt.Sprintf("data: %s\n\n", template) | 173 | output += fmt.Sprintf("data: %s\n\n", template) |
| 172 | } | 174 | } |
| 173 | } else if typeStr == "response.function_call_arguments.delta" { | 175 | } else if typeStr == "response.function_call_arguments.delta" { |
| | 176 | (*param).(*ConvertCodexResponseToClaudeParams).HasReceivedArgumentsDelta = true |
| 174 | template = `{"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""}}` | 177 | template = `{"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""}}` |
| 175 | template, _ = sjson.Set(template, "index", (*param).(*ConvertCodexResponseToClaudeParams).BlockIndex) | 178 | template, _ = sjson.Set(template, "index", (*param).(*ConvertCodexResponseToClaudeParams).BlockIndex) |
| 176 | template, _ = sjson.Set(template, "delta.partial_json", rootResult.Get("delta").String()) | 179 | template, _ = sjson.Set(template, "delta.partial_json", rootResult.Get("delta").String()) |
| 177 | | 180 | |
| 178 | output += "event: content_block_delta\n" | 181 | output += "event: content_block_delta\n" |
| 179 | output += fmt.Sprintf("data: %s\n\n", template) | 182 | output += fmt.Sprintf("data: %s\n\n", template) |
| | 183 | } else if typeStr == "response.function_call_arguments.done" { |
| | 184 | // Some models (e.g. gpt-5.3-codex-spark) send function call arguments |
| | 185 | // in a single "done" event without preceding "delta" events. |
| | 186 | // Emit the full arguments as a single input_json_delta so the |
| | 187 | // downstream Claude client receives the complete tool input. |
| | 188 | // When delta events were already received, skip to avoid duplicating arguments. |
| | 189 | if !(*param).(*ConvertCodexResponseToClaudeParams).HasReceivedArgumentsDelta { |
| | 190 | if args := rootResult.Get("arguments").String(); args != "" { |
| | 191 | template = `{"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""}}` |
| | 192 | template, _ = sjson.Set(template, "index", (*param).(*ConvertCodexResponseToClaudeParams).BlockIndex) |
| | 193 | template, _ = sjson.Set(template, "delta.partial_json", args) |
| | 194 | |
| | 195 | output += "event: content_block_delta\n" |
| | 196 | output += fmt.Sprintf("data: %s\n\n", template) |
| | 197 | } |
| | 198 | } |
| 180 | } | 199 | } |
| 181 | | 200 | |
| 182 | return []string{output} | 201 | return []string{output} |