Skip to content

Commit a1487b0

Browse files
committed
fix(translator): handle non-string types in tools result processing
- Skip setting values for non-string `type` fields to prevent runtime errors. Closes: #2226
1 parent 82ebe24 commit a1487b0

2 files changed

Lines changed: 83 additions & 1 deletion

File tree

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package geminiCLI
2+
3+
import (
4+
"testing"
5+
6+
"github.com/tidwall/gjson"
7+
)
8+
9+
func TestConvertGeminiCLIRequestToCodex_PreservesSchemaPropertyNamedType(t *testing.T) {
10+
input := []byte(`{
11+
"request": {
12+
"tools": [
13+
{
14+
"functionDeclarations": [
15+
{
16+
"name": "ask_user",
17+
"description": "Ask the user one or more questions.",
18+
"parametersJsonSchema": {
19+
"type": "object",
20+
"properties": {
21+
"questions": {
22+
"type": "array",
23+
"items": {
24+
"type": "object",
25+
"properties": {
26+
"header": {
27+
"type": "string"
28+
},
29+
"type": {
30+
"default": "choice",
31+
"description": "Question type.",
32+
"enum": [
33+
"choice",
34+
"text",
35+
"yesno"
36+
],
37+
"type": "string"
38+
}
39+
},
40+
"required": [
41+
"question",
42+
"header",
43+
"type"
44+
]
45+
}
46+
}
47+
},
48+
"required": [
49+
"questions"
50+
]
51+
}
52+
}
53+
]
54+
}
55+
]
56+
}
57+
}`)
58+
59+
out := ConvertGeminiCLIRequestToCodex("gpt-5.2", input, true)
60+
tool := gjson.GetBytes(out, "tools.0")
61+
if got := tool.Get("type").String(); got != "function" {
62+
t.Fatalf("expected tool type %q, got %q; output=%s", "function", got, string(out))
63+
}
64+
65+
typeProperty := tool.Get("parameters.properties.questions.items.properties.type")
66+
if !typeProperty.IsObject() {
67+
t.Fatalf("expected schema property named type to stay an object; output=%s", string(out))
68+
}
69+
if got := typeProperty.Get("type").String(); got != "string" {
70+
t.Fatalf("expected schema property type %q, got %q; output=%s", "string", got, string(out))
71+
}
72+
if got := typeProperty.Get("default").String(); got != "choice" {
73+
t.Fatalf("expected default %q, got %q; output=%s", "choice", got, string(out))
74+
}
75+
if got := typeProperty.Get("enum.2").String(); got != "yesno" {
76+
t.Fatalf("expected enum value %q, got %q; output=%s", "yesno", got, string(out))
77+
}
78+
}

internal/translator/codex/gemini/codex_gemini_request.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,11 @@ func ConvertGeminiRequestToCodex(modelName string, inputRawJSON []byte, _ bool)
284284
util.Walk(toolsResult, "", "type", &pathsToLower)
285285
for _, p := range pathsToLower {
286286
fullPath := fmt.Sprintf("tools.%s", p)
287-
out, _ = sjson.SetBytes(out, fullPath, strings.ToLower(gjson.GetBytes(out, fullPath).String()))
287+
typeValue := gjson.GetBytes(out, fullPath)
288+
if typeValue.Type != gjson.String {
289+
continue
290+
}
291+
out, _ = sjson.SetBytes(out, fullPath, strings.ToLower(typeValue.String()))
288292
}
289293

290294
return out

0 commit comments

Comments
 (0)