Skip to content

Commit c020e2d

Browse files
committed
feat(translator): drop apply_patch custom tool in OpenAI responses
- Added logic in `ConvertOpenAIResponsesRequestToClaude` to exclude `apply_patch` custom tools. - Introduced `isOpenAIResponsesApplyPatchCustomTool` helper function to identify and filter the tool. - Added `TestConvertOpenAIResponsesRequestToClaude_DropsApplyPatchCustomTool` to validate the behavior. Closes: router-for-me#3243
1 parent 1d0551a commit c020e2d

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

internal/translator/claude/openai/responses/claude_openai-responses_request.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,9 @@ func convertResponsesToolToClaudeTools(tool gjson.Result, toolNameMap map[string
522522
return [][]byte{tJSON}
523523
}
524524
default:
525+
if isOpenAIResponsesApplyPatchCustomTool(toolType, tool) {
526+
return nil
527+
}
525528
if isUnsupportedOpenAIBuiltinToolType(toolType) {
526529
return nil
527530
}
@@ -532,6 +535,10 @@ func convertResponsesToolToClaudeTools(tool gjson.Result, toolNameMap map[string
532535
return nil
533536
}
534537

538+
func isOpenAIResponsesApplyPatchCustomTool(toolType string, tool gjson.Result) bool {
539+
return toolType == "custom" && strings.TrimSpace(tool.Get("name").String()) == "apply_patch"
540+
}
541+
535542
func convertResponsesNamespaceToolToClaude(tool gjson.Result, toolNameMap map[string]string) [][]byte {
536543
namespaceName := strings.TrimSpace(tool.Get("name").String())
537544
children := tool.Get("tools")

internal/translator/claude/openai/responses/claude_openai-responses_request_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,40 @@ func TestConvertOpenAIResponsesRequestToClaude_KeepsToolUseAdjacentToToolResult(
202202
}
203203
}
204204

205+
func TestConvertOpenAIResponsesRequestToClaude_DropsApplyPatchCustomTool(t *testing.T) {
206+
raw := []byte(`{
207+
"model":"claude-test",
208+
"input":[{"role":"user","content":[{"type":"input_text","text":"hi"}]}],
209+
"tools":[
210+
{
211+
"type":"custom",
212+
"name":"apply_patch",
213+
"description":"Use the apply_patch tool to edit files.",
214+
"format":{"type":"grammar","syntax":"lark","definition":"start: patch"}
215+
},
216+
{
217+
"type":"function",
218+
"name":"exec_command",
219+
"description":"Runs a command.",
220+
"parameters":{"type":"object","properties":{"cmd":{"type":"string"}},"required":["cmd"]}
221+
}
222+
]
223+
}`)
224+
225+
out := ConvertOpenAIResponsesRequestToClaude("claude-test", raw, false)
226+
root := gjson.ParseBytes(out)
227+
228+
if got := root.Get("tools.#").Int(); got != 1 {
229+
t.Fatalf("tools count = %d, want 1. Output: %s", got, string(out))
230+
}
231+
if got := root.Get("tools.0.name").String(); got != "exec_command" {
232+
t.Fatalf("tools.0.name = %q, want exec_command. Output: %s", got, string(out))
233+
}
234+
if got := root.Get("tools.#(name==\"apply_patch\")").Raw; got != "" {
235+
t.Fatalf("apply_patch custom tool should be dropped. Output: %s", string(out))
236+
}
237+
}
238+
205239
func testClaudeResponsesThinkingSignature(t *testing.T) (string, string) {
206240
t.Helper()
207241
channelBlock := []byte{}

0 commit comments

Comments
 (0)