Skip to content

Commit 7f77466

Browse files
committed
Fix CommandCode message content schema conversion
1 parent d246c84 commit 7f77466

2 files changed

Lines changed: 76 additions & 20 deletions

File tree

internal/api/commandcode.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ package api
55
type CCContentPart struct {
66
Type string `json:"type"`
77
Text *string `json:"text,omitempty"`
8+
ID *string `json:"id,omitempty"`
9+
Name *string `json:"name,omitempty"`
10+
Input any `json:"input,omitempty"`
811
ToolCallID *string `json:"toolCallId,omitempty"`
912
ToolName *string `json:"toolName,omitempty"`
1013
}

internal/proxy/convert.go

Lines changed: 73 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package proxy
22

33
import (
4+
"encoding/json"
45
"strings"
56

67
"github.com/dev2k6/command-code-proxy-server/internal/api"
@@ -29,10 +30,10 @@ func ConvertMessages(openAIMsgs []api.OpenAIMessage) []api.CCMessage {
2930
contentParts := parseContent(m.Content)
3031
for _, tc := range m.ToolCalls {
3132
contentParts = append(contentParts, api.CCContentPart{
32-
Type: "tool_use",
33-
ToolCallID: strPtr(tc.ID),
34-
ToolName: strPtr(tc.Function.Name),
35-
Text: strPtr(tc.Function.Arguments),
33+
Type: "tool_use",
34+
ID: strPtr(tc.ID),
35+
Name: strPtr(tc.Function.Name),
36+
Input: parseToolInput(tc.Function.Arguments),
3637
})
3738
}
3839
ccMsgs = append(ccMsgs, api.CCMessage{
@@ -97,6 +98,17 @@ func ConvertTools(openAITools []any) []any {
9798
return tools
9899
}
99100

101+
func parseToolInput(arguments string) any {
102+
if arguments == "" {
103+
return map[string]any{}
104+
}
105+
var input any
106+
if err := json.Unmarshal([]byte(arguments), &input); err != nil {
107+
return map[string]any{"arguments": arguments}
108+
}
109+
return input
110+
}
111+
100112
func strPtr(s string) *string {
101113
if s == "" {
102114
return nil
@@ -120,6 +132,29 @@ func contentToString(content interface{}) string {
120132
return ""
121133
}
122134

135+
func contentPartToString(content any) string {
136+
switch v := content.(type) {
137+
case string:
138+
return v
139+
case []any:
140+
var b strings.Builder
141+
for _, item := range v {
142+
if m, ok := item.(map[string]any); ok {
143+
if text, ok := m["text"].(string); ok {
144+
b.WriteString(text)
145+
}
146+
}
147+
}
148+
return b.String()
149+
default:
150+
data, err := json.Marshal(v)
151+
if err != nil {
152+
return ""
153+
}
154+
return string(data)
155+
}
156+
}
157+
123158
func parseContent(content interface{}) []api.CCContentPart {
124159
switch v := content.(type) {
125160
case string:
@@ -130,24 +165,42 @@ func parseContent(content interface{}) []api.CCContentPart {
130165
case []any:
131166
var parts []api.CCContentPart
132167
for _, part := range v {
133-
if partMap, ok := part.(map[string]any); ok {
134-
if typ, ok := partMap["type"].(string); ok {
135-
p := api.CCContentPart{Type: typ}
136-
if text, ok := partMap["text"].(string); ok {
137-
p.Text = strPtr(text)
138-
}
139-
if imgURL, ok := partMap["image_url"].(map[string]any); ok {
140-
if url, ok := imgURL["url"].(string); ok {
141-
merged := ""
142-
if p.Text != nil {
143-
merged = *p.Text
144-
}
145-
merged = merged + "\n[Image URL: " + url + "]"
146-
p.Text = strPtr(merged)
147-
}
168+
partMap, ok := part.(map[string]any)
169+
if !ok {
170+
continue
171+
}
172+
typ, _ := partMap["type"].(string)
173+
switch typ {
174+
case "text":
175+
if text, ok := partMap["text"].(string); ok && text != "" {
176+
parts = append(parts, api.CCContentPart{Type: "text", Text: strPtr(text)})
177+
}
178+
case "image_url":
179+
if imgURL, ok := partMap["image_url"].(map[string]any); ok {
180+
if url, ok := imgURL["url"].(string); ok && url != "" {
181+
parts = append(parts, api.CCContentPart{Type: "text", Text: strPtr("[Image URL: " + url + "]")})
148182
}
149-
parts = append(parts, p)
150183
}
184+
case "tool_use":
185+
id, _ := partMap["id"].(string)
186+
name, _ := partMap["name"].(string)
187+
input := partMap["input"]
188+
parts = append(parts, api.CCContentPart{Type: "tool_use", ID: strPtr(id), Name: strPtr(name), Input: input})
189+
case "tool-call":
190+
id, _ := partMap["id"].(string)
191+
name, _ := partMap["name"].(string)
192+
input := partMap["input"]
193+
if input == nil {
194+
input = partMap["arguments"]
195+
}
196+
parts = append(parts, api.CCContentPart{Type: "tool-call", ID: strPtr(id), Name: strPtr(name), Input: input})
197+
case "tool_result", "tool-result":
198+
toolID, _ := partMap["tool_use_id"].(string)
199+
if toolID == "" {
200+
toolID, _ = partMap["toolCallId"].(string)
201+
}
202+
toolName, _ := partMap["toolName"].(string)
203+
parts = append(parts, api.CCContentPart{Type: "tool-result", ToolCallID: strPtr(toolID), ToolName: strPtr(toolName), Text: strPtr(contentPartToString(partMap["content"]))})
151204
}
152205
}
153206
return parts

0 commit comments

Comments
 (0)