Compare commits

...

3 Commits

Author SHA1 Message Date
Luis Pater
eb2549a782 fix(gemini): update response template to omit finishReason until known
Some checks failed
docker-image / docker (push) Has been cancelled
goreleaser / goreleaser (push) Has been cancelled
2025-10-16 06:41:04 +08:00
Luis Pater
c419264a70 fix(responses): handle empty and invalid rawJSON in ConvertOpenAIChatCompletionsResponseToOpenAIResponses 2025-10-16 06:34:00 +08:00
Luis Pater
6b23e2da74 feat(claude): add Claude 4.5 Haiku model definition
Some checks failed
docker-image / docker (push) Has been cancelled
goreleaser / goreleaser (push) Has been cancelled
2025-10-16 04:53:07 +08:00
3 changed files with 26 additions and 6 deletions

View File

@@ -8,6 +8,15 @@ import "time"
// GetClaudeModels returns the standard Claude model definitions
func GetClaudeModels() []*ModelInfo {
return []*ModelInfo{
{
ID: "claude-haiku-4-5-20251001",
Object: "model",
Created: 1759276800, // 2025-10-01
OwnedBy: "anthropic",
Type: "claude",
DisplayName: "Claude 4.5 Haiku",
},
{
ID: "claude-sonnet-4-5-20250929",
Object: "model",

View File

@@ -97,8 +97,8 @@ func ConvertOpenAIResponseToGemini(_ context.Context, _ string, originalRequestR
var results []string
choices.ForEach(func(choiceIndex, choice gjson.Result) bool {
// Base Gemini response template
template := `{"candidates":[{"content":{"parts":[],"role":"model"},"finishReason":"STOP","index":0}]}`
// Base Gemini response template without finishReason; set when known
template := `{"candidates":[{"content":{"parts":[],"role":"model"},"index":0}]}`
// Set model if available
if model := root.Get("model"); model.Exists() {
@@ -514,8 +514,8 @@ func tryParseNumber(s string) (interface{}, bool) {
func ConvertOpenAIResponseToGeminiNonStream(_ context.Context, _ string, originalRequestRawJSON, requestRawJSON, rawJSON []byte, _ *any) string {
root := gjson.ParseBytes(rawJSON)
// Base Gemini response template
out := `{"candidates":[{"content":{"parts":[],"role":"model"},"finishReason":"STOP","index":0}]}`
// Base Gemini response template without finishReason; set when known
out := `{"candidates":[{"content":{"parts":[],"role":"model"},"index":0}]}`
// Set model if available
if model := root.Get("model"); model.Exists() {

View File

@@ -67,9 +67,20 @@ func ConvertOpenAIChatCompletionsResponseToOpenAIResponses(ctx context.Context,
rawJSON = bytes.TrimSpace(rawJSON[5:])
}
rawJSON = bytes.TrimSpace(rawJSON)
if len(rawJSON) == 0 {
return []string{}
}
if bytes.Equal(rawJSON, []byte("[DONE]")) {
return []string{}
}
root := gjson.ParseBytes(rawJSON)
obj := root.Get("object").String()
if obj != "chat.completion.chunk" {
obj := root.Get("object")
if obj.Exists() && obj.String() != "" && obj.String() != "chat.completion.chunk" {
return []string{}
}
if !root.Get("choices").Exists() || !root.Get("choices").IsArray() {
return []string{}
}