elkindev commited on
Commit
bee6e1b
·
1 Parent(s): dadd335

Pass file input from /chat/completions and /responses to codex and claude

Browse files
internal/translator/claude/openai/chat-completions/claude_openai_request.go CHANGED
@@ -199,6 +199,21 @@ func ConvertOpenAIRequestToClaude(modelName string, inputRawJSON []byte, stream
199
  msg, _ = sjson.SetRaw(msg, "content.-1", imagePart)
200
  }
201
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  }
203
  return true
204
  })
 
199
  msg, _ = sjson.SetRaw(msg, "content.-1", imagePart)
200
  }
201
  }
202
+
203
+ case "file":
204
+ fileData := part.Get("file.file_data").String()
205
+ if strings.HasPrefix(fileData, "data:") {
206
+ semicolonIdx := strings.Index(fileData, ";")
207
+ commaIdx := strings.Index(fileData, ",")
208
+ if semicolonIdx != -1 && commaIdx != -1 && commaIdx > semicolonIdx {
209
+ mediaType := strings.TrimPrefix(fileData[:semicolonIdx], "data:")
210
+ data := fileData[commaIdx+1:]
211
+ docPart := `{"type":"document","source":{"type":"base64","media_type":"","data":""}}`
212
+ docPart, _ = sjson.Set(docPart, "source.media_type", mediaType)
213
+ docPart, _ = sjson.Set(docPart, "source.data", data)
214
+ msg, _ = sjson.SetRaw(msg, "content.-1", docPart)
215
+ }
216
+ }
217
  }
218
  return true
219
  })
internal/translator/claude/openai/responses/claude_openai-responses_request.go CHANGED
@@ -155,6 +155,7 @@ func ConvertOpenAIResponsesRequestToClaude(modelName string, inputRawJSON []byte
155
  var textAggregate strings.Builder
156
  var partsJSON []string
157
  hasImage := false
 
158
  if parts := item.Get("content"); parts.Exists() && parts.IsArray() {
159
  parts.ForEach(func(_, part gjson.Result) bool {
160
  ptype := part.Get("type").String()
@@ -207,6 +208,30 @@ func ConvertOpenAIResponsesRequestToClaude(modelName string, inputRawJSON []byte
207
  hasImage = true
208
  }
209
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  }
211
  return true
212
  })
@@ -228,7 +253,7 @@ func ConvertOpenAIResponsesRequestToClaude(modelName string, inputRawJSON []byte
228
  if len(partsJSON) > 0 {
229
  msg := `{"role":"","content":[]}`
230
  msg, _ = sjson.Set(msg, "role", role)
231
- if len(partsJSON) == 1 && !hasImage {
232
  // Preserve legacy behavior for single text content
233
  msg, _ = sjson.Delete(msg, "content")
234
  textPart := gjson.Parse(partsJSON[0])
 
155
  var textAggregate strings.Builder
156
  var partsJSON []string
157
  hasImage := false
158
+ hasFile := false
159
  if parts := item.Get("content"); parts.Exists() && parts.IsArray() {
160
  parts.ForEach(func(_, part gjson.Result) bool {
161
  ptype := part.Get("type").String()
 
208
  hasImage = true
209
  }
210
  }
211
+ case "input_file":
212
+ fileData := part.Get("file_data").String()
213
+ if fileData != "" {
214
+ mediaType := "application/octet-stream"
215
+ data := fileData
216
+ if strings.HasPrefix(fileData, "data:") {
217
+ trimmed := strings.TrimPrefix(fileData, "data:")
218
+ mediaAndData := strings.SplitN(trimmed, ";base64,", 2)
219
+ if len(mediaAndData) == 2 {
220
+ if mediaAndData[0] != "" {
221
+ mediaType = mediaAndData[0]
222
+ }
223
+ data = mediaAndData[1]
224
+ }
225
+ }
226
+ contentPart := `{"type":"document","source":{"type":"base64","media_type":"","data":""}}`
227
+ contentPart, _ = sjson.Set(contentPart, "source.media_type", mediaType)
228
+ contentPart, _ = sjson.Set(contentPart, "source.data", data)
229
+ partsJSON = append(partsJSON, contentPart)
230
+ if role == "" {
231
+ role = "user"
232
+ }
233
+ hasFile = true
234
+ }
235
  }
236
  return true
237
  })
 
253
  if len(partsJSON) > 0 {
254
  msg := `{"role":"","content":[]}`
255
  msg, _ = sjson.Set(msg, "role", role)
256
+ if len(partsJSON) == 1 && !hasImage && !hasFile {
257
  // Preserve legacy behavior for single text content
258
  msg, _ = sjson.Delete(msg, "content")
259
  textPart := gjson.Parse(partsJSON[0])
internal/translator/codex/openai/chat-completions/codex_openai_request.go CHANGED
@@ -180,7 +180,19 @@ func ConvertOpenAIRequestToCodex(modelName string, inputRawJSON []byte, stream b
180
  msg, _ = sjson.SetRaw(msg, "content.-1", part)
181
  }
182
  case "file":
183
- // Files are not specified in examples; skip for now
 
 
 
 
 
 
 
 
 
 
 
 
184
  }
185
  }
186
  }
 
180
  msg, _ = sjson.SetRaw(msg, "content.-1", part)
181
  }
182
  case "file":
183
+ if role == "user" {
184
+ fileData := it.Get("file.file_data").String()
185
+ filename := it.Get("file.filename").String()
186
+ if fileData != "" {
187
+ part := `{}`
188
+ part, _ = sjson.Set(part, "type", "input_file")
189
+ part, _ = sjson.Set(part, "file_data", fileData)
190
+ if filename != "" {
191
+ part, _ = sjson.Set(part, "filename", filename)
192
+ }
193
+ msg, _ = sjson.SetRaw(msg, "content.-1", part)
194
+ }
195
+ }
196
  }
197
  }
198
  }