mirror of
https://github.com/router-for-me/CLIProxyAPIPlus.git
synced 2026-04-24 08:31:10 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
165e03f3a7 | ||
|
|
86bdb7808c | ||
|
|
b4e034be1c | ||
|
|
84fcebf538 | ||
|
|
74d9a1ffed | ||
|
|
a5a25dec57 | ||
|
|
c71905e5e8 | ||
|
|
bc78d668ac | ||
|
|
e93eebc2e9 | ||
|
|
5bd0896ad7 | ||
|
|
09ecfbcaed | ||
|
|
f0bd14b64f | ||
|
|
dbecf5330e | ||
|
|
49ef22ab78 | ||
|
|
ae4638712e |
@@ -17,6 +17,7 @@ var antigravityModelConversionTable = map[string]string{
|
|||||||
"gemini-claude-sonnet-4-5": "claude-sonnet-4-5",
|
"gemini-claude-sonnet-4-5": "claude-sonnet-4-5",
|
||||||
"gemini-claude-sonnet-4-5-thinking": "claude-sonnet-4-5-thinking",
|
"gemini-claude-sonnet-4-5-thinking": "claude-sonnet-4-5-thinking",
|
||||||
"gemini-claude-opus-4-5-thinking": "claude-opus-4-5-thinking",
|
"gemini-claude-opus-4-5-thinking": "claude-opus-4-5-thinking",
|
||||||
|
"gemini-claude-opus-4-6-thinking": "claude-opus-4-6-thinking",
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultAntigravityAliases returns the default oauth-model-alias configuration
|
// defaultAntigravityAliases returns the default oauth-model-alias configuration
|
||||||
@@ -30,6 +31,7 @@ func defaultAntigravityAliases() []OAuthModelAlias {
|
|||||||
{Name: "claude-sonnet-4-5", Alias: "gemini-claude-sonnet-4-5"},
|
{Name: "claude-sonnet-4-5", Alias: "gemini-claude-sonnet-4-5"},
|
||||||
{Name: "claude-sonnet-4-5-thinking", Alias: "gemini-claude-sonnet-4-5-thinking"},
|
{Name: "claude-sonnet-4-5-thinking", Alias: "gemini-claude-sonnet-4-5-thinking"},
|
||||||
{Name: "claude-opus-4-5-thinking", Alias: "gemini-claude-opus-4-5-thinking"},
|
{Name: "claude-opus-4-5-thinking", Alias: "gemini-claude-opus-4-5-thinking"},
|
||||||
|
{Name: "claude-opus-4-6-thinking", Alias: "gemini-claude-opus-4-6-thinking"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,9 @@ func TestMigrateOAuthModelAlias_ConvertsAntigravityModels(t *testing.T) {
|
|||||||
if !strings.Contains(content, "claude-opus-4-5-thinking") {
|
if !strings.Contains(content, "claude-opus-4-5-thinking") {
|
||||||
t.Fatal("expected missing default alias claude-opus-4-5-thinking to be added")
|
t.Fatal("expected missing default alias claude-opus-4-5-thinking to be added")
|
||||||
}
|
}
|
||||||
|
if !strings.Contains(content, "claude-opus-4-6-thinking") {
|
||||||
|
t.Fatal("expected missing default alias claude-opus-4-6-thinking to be added")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMigrateOAuthModelAlias_AddsDefaultIfNeitherExists(t *testing.T) {
|
func TestMigrateOAuthModelAlias_AddsDefaultIfNeitherExists(t *testing.T) {
|
||||||
|
|||||||
@@ -376,6 +376,18 @@ func GetKiroModels() []*ModelInfo {
|
|||||||
MaxCompletionTokens: 64000,
|
MaxCompletionTokens: 64000,
|
||||||
Thinking: &ThinkingSupport{Min: 1024, Max: 32000, ZeroAllowed: true, DynamicAllowed: true},
|
Thinking: &ThinkingSupport{Min: 1024, Max: 32000, ZeroAllowed: true, DynamicAllowed: true},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ID: "kiro-claude-opus-4-6",
|
||||||
|
Object: "model",
|
||||||
|
Created: 1736899200, // 2025-01-15
|
||||||
|
OwnedBy: "aws",
|
||||||
|
Type: "kiro",
|
||||||
|
DisplayName: "Kiro Claude Opus 4.6",
|
||||||
|
Description: "Claude Opus 4.6 via Kiro (2.2x credit)",
|
||||||
|
ContextLength: 200000,
|
||||||
|
MaxCompletionTokens: 64000,
|
||||||
|
Thinking: &ThinkingSupport{Min: 1024, Max: 32000, ZeroAllowed: true, DynamicAllowed: true},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ID: "kiro-claude-opus-4-5",
|
ID: "kiro-claude-opus-4-5",
|
||||||
Object: "model",
|
Object: "model",
|
||||||
@@ -425,6 +437,18 @@ func GetKiroModels() []*ModelInfo {
|
|||||||
Thinking: &ThinkingSupport{Min: 1024, Max: 32000, ZeroAllowed: true, DynamicAllowed: true},
|
Thinking: &ThinkingSupport{Min: 1024, Max: 32000, ZeroAllowed: true, DynamicAllowed: true},
|
||||||
},
|
},
|
||||||
// --- Agentic Variants (Optimized for coding agents with chunked writes) ---
|
// --- Agentic Variants (Optimized for coding agents with chunked writes) ---
|
||||||
|
{
|
||||||
|
ID: "kiro-claude-opus-4-6-agentic",
|
||||||
|
Object: "model",
|
||||||
|
Created: 1736899200, // 2025-01-15
|
||||||
|
OwnedBy: "aws",
|
||||||
|
Type: "kiro",
|
||||||
|
DisplayName: "Kiro Claude Opus 4.6 (Agentic)",
|
||||||
|
Description: "Claude Opus 4.6 optimized for coding agents (chunked writes)",
|
||||||
|
ContextLength: 200000,
|
||||||
|
MaxCompletionTokens: 64000,
|
||||||
|
Thinking: &ThinkingSupport{Min: 1024, Max: 32000, ZeroAllowed: true, DynamicAllowed: true},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ID: "kiro-claude-opus-4-5-agentic",
|
ID: "kiro-claude-opus-4-5-agentic",
|
||||||
Object: "model",
|
Object: "model",
|
||||||
|
|||||||
@@ -28,6 +28,18 @@ func GetClaudeModels() []*ModelInfo {
|
|||||||
MaxCompletionTokens: 64000,
|
MaxCompletionTokens: 64000,
|
||||||
Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: false},
|
Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: false},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ID: "claude-opus-4-6-20260205",
|
||||||
|
Object: "model",
|
||||||
|
Created: 1770318000, // 2026-02-05
|
||||||
|
OwnedBy: "anthropic",
|
||||||
|
Type: "claude",
|
||||||
|
DisplayName: "Claude 4.6 Opus",
|
||||||
|
Description: "Premium model combining maximum intelligence with practical performance",
|
||||||
|
ContextLength: 200000,
|
||||||
|
MaxCompletionTokens: 64000,
|
||||||
|
Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: false},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ID: "claude-opus-4-5-20251101",
|
ID: "claude-opus-4-5-20251101",
|
||||||
Object: "model",
|
Object: "model",
|
||||||
@@ -716,6 +728,20 @@ func GetOpenAIModels() []*ModelInfo {
|
|||||||
SupportedParameters: []string{"tools"},
|
SupportedParameters: []string{"tools"},
|
||||||
Thinking: &ThinkingSupport{Levels: []string{"low", "medium", "high", "xhigh"}},
|
Thinking: &ThinkingSupport{Levels: []string{"low", "medium", "high", "xhigh"}},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ID: "gpt-5.3-codex",
|
||||||
|
Object: "model",
|
||||||
|
Created: 1770307200,
|
||||||
|
OwnedBy: "openai",
|
||||||
|
Type: "openai",
|
||||||
|
Version: "gpt-5.3",
|
||||||
|
DisplayName: "GPT 5.3 Codex",
|
||||||
|
Description: "Stable version of GPT 5.3 Codex, The best model for coding and agentic tasks across domains.",
|
||||||
|
ContextLength: 400000,
|
||||||
|
MaxCompletionTokens: 128000,
|
||||||
|
SupportedParameters: []string{"tools"},
|
||||||
|
Thinking: &ThinkingSupport{Levels: []string{"low", "medium", "high", "xhigh"}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -840,6 +866,7 @@ func GetAntigravityModelConfig() map[string]*AntigravityModelConfig {
|
|||||||
"gemini-3-flash": {Thinking: &ThinkingSupport{Min: 128, Max: 32768, ZeroAllowed: false, DynamicAllowed: true, Levels: []string{"minimal", "low", "medium", "high"}}},
|
"gemini-3-flash": {Thinking: &ThinkingSupport{Min: 128, Max: 32768, ZeroAllowed: false, DynamicAllowed: true, Levels: []string{"minimal", "low", "medium", "high"}}},
|
||||||
"claude-sonnet-4-5-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000},
|
"claude-sonnet-4-5-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000},
|
||||||
"claude-opus-4-5-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000},
|
"claude-opus-4-5-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000},
|
||||||
|
"claude-opus-4-6-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000},
|
||||||
"claude-sonnet-4-5": {MaxCompletionTokens: 64000},
|
"claude-sonnet-4-5": {MaxCompletionTokens: 64000},
|
||||||
"gpt-oss-120b-medium": {},
|
"gpt-oss-120b-medium": {},
|
||||||
"tab_flash_lite_preview": {},
|
"tab_flash_lite_preview": {},
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ func (e *AIStudioExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth,
|
|||||||
URL: endpoint,
|
URL: endpoint,
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
Headers: wsReq.Headers.Clone(),
|
Headers: wsReq.Headers.Clone(),
|
||||||
Body: bytes.Clone(body.payload),
|
Body: body.payload,
|
||||||
Provider: e.Identifier(),
|
Provider: e.Identifier(),
|
||||||
AuthID: authID,
|
AuthID: authID,
|
||||||
AuthLabel: authLabel,
|
AuthLabel: authLabel,
|
||||||
@@ -156,14 +156,14 @@ func (e *AIStudioExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth,
|
|||||||
}
|
}
|
||||||
recordAPIResponseMetadata(ctx, e.cfg, wsResp.Status, wsResp.Headers.Clone())
|
recordAPIResponseMetadata(ctx, e.cfg, wsResp.Status, wsResp.Headers.Clone())
|
||||||
if len(wsResp.Body) > 0 {
|
if len(wsResp.Body) > 0 {
|
||||||
appendAPIResponseChunk(ctx, e.cfg, bytes.Clone(wsResp.Body))
|
appendAPIResponseChunk(ctx, e.cfg, wsResp.Body)
|
||||||
}
|
}
|
||||||
if wsResp.Status < 200 || wsResp.Status >= 300 {
|
if wsResp.Status < 200 || wsResp.Status >= 300 {
|
||||||
return resp, statusErr{code: wsResp.Status, msg: string(wsResp.Body)}
|
return resp, statusErr{code: wsResp.Status, msg: string(wsResp.Body)}
|
||||||
}
|
}
|
||||||
reporter.publish(ctx, parseGeminiUsage(wsResp.Body))
|
reporter.publish(ctx, parseGeminiUsage(wsResp.Body))
|
||||||
var param any
|
var param any
|
||||||
out := sdktranslator.TranslateNonStream(ctx, body.toFormat, opts.SourceFormat, req.Model, bytes.Clone(opts.OriginalRequest), bytes.Clone(translatedReq), bytes.Clone(wsResp.Body), ¶m)
|
out := sdktranslator.TranslateNonStream(ctx, body.toFormat, opts.SourceFormat, req.Model, opts.OriginalRequest, translatedReq, wsResp.Body, ¶m)
|
||||||
resp = cliproxyexecutor.Response{Payload: ensureColonSpacedJSON([]byte(out))}
|
resp = cliproxyexecutor.Response{Payload: ensureColonSpacedJSON([]byte(out))}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
@@ -199,7 +199,7 @@ func (e *AIStudioExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth
|
|||||||
URL: endpoint,
|
URL: endpoint,
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
Headers: wsReq.Headers.Clone(),
|
Headers: wsReq.Headers.Clone(),
|
||||||
Body: bytes.Clone(body.payload),
|
Body: body.payload,
|
||||||
Provider: e.Identifier(),
|
Provider: e.Identifier(),
|
||||||
AuthID: authID,
|
AuthID: authID,
|
||||||
AuthLabel: authLabel,
|
AuthLabel: authLabel,
|
||||||
@@ -225,7 +225,7 @@ func (e *AIStudioExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth
|
|||||||
}
|
}
|
||||||
var body bytes.Buffer
|
var body bytes.Buffer
|
||||||
if len(firstEvent.Payload) > 0 {
|
if len(firstEvent.Payload) > 0 {
|
||||||
appendAPIResponseChunk(ctx, e.cfg, bytes.Clone(firstEvent.Payload))
|
appendAPIResponseChunk(ctx, e.cfg, firstEvent.Payload)
|
||||||
body.Write(firstEvent.Payload)
|
body.Write(firstEvent.Payload)
|
||||||
}
|
}
|
||||||
if firstEvent.Type == wsrelay.MessageTypeStreamEnd {
|
if firstEvent.Type == wsrelay.MessageTypeStreamEnd {
|
||||||
@@ -244,7 +244,7 @@ func (e *AIStudioExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth
|
|||||||
metadataLogged = true
|
metadataLogged = true
|
||||||
}
|
}
|
||||||
if len(event.Payload) > 0 {
|
if len(event.Payload) > 0 {
|
||||||
appendAPIResponseChunk(ctx, e.cfg, bytes.Clone(event.Payload))
|
appendAPIResponseChunk(ctx, e.cfg, event.Payload)
|
||||||
body.Write(event.Payload)
|
body.Write(event.Payload)
|
||||||
}
|
}
|
||||||
if event.Type == wsrelay.MessageTypeStreamEnd {
|
if event.Type == wsrelay.MessageTypeStreamEnd {
|
||||||
@@ -274,12 +274,12 @@ func (e *AIStudioExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth
|
|||||||
}
|
}
|
||||||
case wsrelay.MessageTypeStreamChunk:
|
case wsrelay.MessageTypeStreamChunk:
|
||||||
if len(event.Payload) > 0 {
|
if len(event.Payload) > 0 {
|
||||||
appendAPIResponseChunk(ctx, e.cfg, bytes.Clone(event.Payload))
|
appendAPIResponseChunk(ctx, e.cfg, event.Payload)
|
||||||
filtered := FilterSSEUsageMetadata(event.Payload)
|
filtered := FilterSSEUsageMetadata(event.Payload)
|
||||||
if detail, ok := parseGeminiStreamUsage(filtered); ok {
|
if detail, ok := parseGeminiStreamUsage(filtered); ok {
|
||||||
reporter.publish(ctx, detail)
|
reporter.publish(ctx, detail)
|
||||||
}
|
}
|
||||||
lines := sdktranslator.TranslateStream(ctx, body.toFormat, opts.SourceFormat, req.Model, bytes.Clone(opts.OriginalRequest), translatedReq, bytes.Clone(filtered), ¶m)
|
lines := sdktranslator.TranslateStream(ctx, body.toFormat, opts.SourceFormat, req.Model, opts.OriginalRequest, translatedReq, filtered, ¶m)
|
||||||
for i := range lines {
|
for i := range lines {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: ensureColonSpacedJSON([]byte(lines[i]))}
|
out <- cliproxyexecutor.StreamChunk{Payload: ensureColonSpacedJSON([]byte(lines[i]))}
|
||||||
}
|
}
|
||||||
@@ -293,9 +293,9 @@ func (e *AIStudioExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth
|
|||||||
metadataLogged = true
|
metadataLogged = true
|
||||||
}
|
}
|
||||||
if len(event.Payload) > 0 {
|
if len(event.Payload) > 0 {
|
||||||
appendAPIResponseChunk(ctx, e.cfg, bytes.Clone(event.Payload))
|
appendAPIResponseChunk(ctx, e.cfg, event.Payload)
|
||||||
}
|
}
|
||||||
lines := sdktranslator.TranslateStream(ctx, body.toFormat, opts.SourceFormat, req.Model, bytes.Clone(opts.OriginalRequest), translatedReq, bytes.Clone(event.Payload), ¶m)
|
lines := sdktranslator.TranslateStream(ctx, body.toFormat, opts.SourceFormat, req.Model, opts.OriginalRequest, translatedReq, event.Payload, ¶m)
|
||||||
for i := range lines {
|
for i := range lines {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: ensureColonSpacedJSON([]byte(lines[i]))}
|
out <- cliproxyexecutor.StreamChunk{Payload: ensureColonSpacedJSON([]byte(lines[i]))}
|
||||||
}
|
}
|
||||||
@@ -350,7 +350,7 @@ func (e *AIStudioExecutor) CountTokens(ctx context.Context, auth *cliproxyauth.A
|
|||||||
URL: endpoint,
|
URL: endpoint,
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
Headers: wsReq.Headers.Clone(),
|
Headers: wsReq.Headers.Clone(),
|
||||||
Body: bytes.Clone(body.payload),
|
Body: body.payload,
|
||||||
Provider: e.Identifier(),
|
Provider: e.Identifier(),
|
||||||
AuthID: authID,
|
AuthID: authID,
|
||||||
AuthLabel: authLabel,
|
AuthLabel: authLabel,
|
||||||
@@ -364,7 +364,7 @@ func (e *AIStudioExecutor) CountTokens(ctx context.Context, auth *cliproxyauth.A
|
|||||||
}
|
}
|
||||||
recordAPIResponseMetadata(ctx, e.cfg, resp.Status, resp.Headers.Clone())
|
recordAPIResponseMetadata(ctx, e.cfg, resp.Status, resp.Headers.Clone())
|
||||||
if len(resp.Body) > 0 {
|
if len(resp.Body) > 0 {
|
||||||
appendAPIResponseChunk(ctx, e.cfg, bytes.Clone(resp.Body))
|
appendAPIResponseChunk(ctx, e.cfg, resp.Body)
|
||||||
}
|
}
|
||||||
if resp.Status < 200 || resp.Status >= 300 {
|
if resp.Status < 200 || resp.Status >= 300 {
|
||||||
return cliproxyexecutor.Response{}, statusErr{code: resp.Status, msg: string(resp.Body)}
|
return cliproxyexecutor.Response{}, statusErr{code: resp.Status, msg: string(resp.Body)}
|
||||||
@@ -373,7 +373,7 @@ func (e *AIStudioExecutor) CountTokens(ctx context.Context, auth *cliproxyauth.A
|
|||||||
if totalTokens <= 0 {
|
if totalTokens <= 0 {
|
||||||
return cliproxyexecutor.Response{}, fmt.Errorf("wsrelay: totalTokens missing in response")
|
return cliproxyexecutor.Response{}, fmt.Errorf("wsrelay: totalTokens missing in response")
|
||||||
}
|
}
|
||||||
translated := sdktranslator.TranslateTokenCount(ctx, body.toFormat, opts.SourceFormat, totalTokens, bytes.Clone(resp.Body))
|
translated := sdktranslator.TranslateTokenCount(ctx, body.toFormat, opts.SourceFormat, totalTokens, resp.Body)
|
||||||
return cliproxyexecutor.Response{Payload: []byte(translated)}, nil
|
return cliproxyexecutor.Response{Payload: []byte(translated)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,12 +393,13 @@ func (e *AIStudioExecutor) translateRequest(req cliproxyexecutor.Request, opts c
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, stream)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, stream)
|
||||||
payload := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), stream)
|
payload := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, stream)
|
||||||
payload, err := thinking.ApplyThinking(payload, req.Model, from.String(), to.String(), e.Identifier())
|
payload, err := thinking.ApplyThinking(payload, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, translatedPayload{}, err
|
return nil, translatedPayload{}, err
|
||||||
|
|||||||
@@ -133,12 +133,13 @@ func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Au
|
|||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("antigravity")
|
to := sdktranslator.FromString("antigravity")
|
||||||
|
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
||||||
translated := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
translated := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
translated, err = thinking.ApplyThinking(translated, req.Model, from.String(), to.String(), e.Identifier())
|
translated, err = thinking.ApplyThinking(translated, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -230,7 +231,7 @@ attemptLoop:
|
|||||||
|
|
||||||
reporter.publish(ctx, parseAntigravityUsage(bodyBytes))
|
reporter.publish(ctx, parseAntigravityUsage(bodyBytes))
|
||||||
var param any
|
var param any
|
||||||
converted := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), translated, bodyBytes, ¶m)
|
converted := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, opts.OriginalRequest, translated, bodyBytes, ¶m)
|
||||||
resp = cliproxyexecutor.Response{Payload: []byte(converted)}
|
resp = cliproxyexecutor.Response{Payload: []byte(converted)}
|
||||||
reporter.ensurePublished(ctx)
|
reporter.ensurePublished(ctx)
|
||||||
return resp, nil
|
return resp, nil
|
||||||
@@ -274,12 +275,13 @@ func (e *AntigravityExecutor) executeClaudeNonStream(ctx context.Context, auth *
|
|||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("antigravity")
|
to := sdktranslator.FromString("antigravity")
|
||||||
|
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
||||||
translated := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), true)
|
translated := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, true)
|
||||||
|
|
||||||
translated, err = thinking.ApplyThinking(translated, req.Model, from.String(), to.String(), e.Identifier())
|
translated, err = thinking.ApplyThinking(translated, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -433,7 +435,7 @@ attemptLoop:
|
|||||||
|
|
||||||
reporter.publish(ctx, parseAntigravityUsage(resp.Payload))
|
reporter.publish(ctx, parseAntigravityUsage(resp.Payload))
|
||||||
var param any
|
var param any
|
||||||
converted := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), translated, resp.Payload, ¶m)
|
converted := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, opts.OriginalRequest, translated, resp.Payload, ¶m)
|
||||||
resp = cliproxyexecutor.Response{Payload: []byte(converted)}
|
resp = cliproxyexecutor.Response{Payload: []byte(converted)}
|
||||||
reporter.ensurePublished(ctx)
|
reporter.ensurePublished(ctx)
|
||||||
|
|
||||||
@@ -665,12 +667,13 @@ func (e *AntigravityExecutor) ExecuteStream(ctx context.Context, auth *cliproxya
|
|||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("antigravity")
|
to := sdktranslator.FromString("antigravity")
|
||||||
|
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
||||||
translated := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), true)
|
translated := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, true)
|
||||||
|
|
||||||
translated, err = thinking.ApplyThinking(translated, req.Model, from.String(), to.String(), e.Identifier())
|
translated, err = thinking.ApplyThinking(translated, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -800,12 +803,12 @@ attemptLoop:
|
|||||||
reporter.publish(ctx, detail)
|
reporter.publish(ctx, detail)
|
||||||
}
|
}
|
||||||
|
|
||||||
chunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), translated, bytes.Clone(payload), ¶m)
|
chunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, translated, bytes.Clone(payload), ¶m)
|
||||||
for i := range chunks {
|
for i := range chunks {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(chunks[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(chunks[i])}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tail := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), translated, []byte("[DONE]"), ¶m)
|
tail := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, translated, []byte("[DONE]"), ¶m)
|
||||||
for i := range tail {
|
for i := range tail {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(tail[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(tail[i])}
|
||||||
}
|
}
|
||||||
@@ -872,7 +875,7 @@ func (e *AntigravityExecutor) CountTokens(ctx context.Context, auth *cliproxyaut
|
|||||||
respCtx := context.WithValue(ctx, "alt", opts.Alt)
|
respCtx := context.WithValue(ctx, "alt", opts.Alt)
|
||||||
|
|
||||||
// Prepare payload once (doesn't depend on baseURL)
|
// Prepare payload once (doesn't depend on baseURL)
|
||||||
payload := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
payload := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
payload, err := thinking.ApplyThinking(payload, req.Model, from.String(), to.String(), e.Identifier())
|
payload, err := thinking.ApplyThinking(payload, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -100,12 +100,13 @@ func (e *ClaudeExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r
|
|||||||
to := sdktranslator.FromString("claude")
|
to := sdktranslator.FromString("claude")
|
||||||
// Use streaming translation to preserve function calling, except for claude.
|
// Use streaming translation to preserve function calling, except for claude.
|
||||||
stream := from != to
|
stream := from != to
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, stream)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, stream)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), stream)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, stream)
|
||||||
body, _ = sjson.SetBytes(body, "model", baseModel)
|
body, _ = sjson.SetBytes(body, "model", baseModel)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
@@ -216,7 +217,7 @@ func (e *ClaudeExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r
|
|||||||
to,
|
to,
|
||||||
from,
|
from,
|
||||||
req.Model,
|
req.Model,
|
||||||
bytes.Clone(opts.OriginalRequest),
|
opts.OriginalRequest,
|
||||||
bodyForTranslation,
|
bodyForTranslation,
|
||||||
data,
|
data,
|
||||||
¶m,
|
¶m,
|
||||||
@@ -240,12 +241,13 @@ func (e *ClaudeExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
|
|||||||
defer reporter.trackFailure(ctx, &err)
|
defer reporter.trackFailure(ctx, &err)
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("claude")
|
to := sdktranslator.FromString("claude")
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), true)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, true)
|
||||||
body, _ = sjson.SetBytes(body, "model", baseModel)
|
body, _ = sjson.SetBytes(body, "model", baseModel)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
@@ -381,7 +383,7 @@ func (e *ClaudeExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
|
|||||||
to,
|
to,
|
||||||
from,
|
from,
|
||||||
req.Model,
|
req.Model,
|
||||||
bytes.Clone(opts.OriginalRequest),
|
opts.OriginalRequest,
|
||||||
bodyForTranslation,
|
bodyForTranslation,
|
||||||
bytes.Clone(line),
|
bytes.Clone(line),
|
||||||
¶m,
|
¶m,
|
||||||
@@ -411,7 +413,7 @@ func (e *ClaudeExecutor) CountTokens(ctx context.Context, auth *cliproxyauth.Aut
|
|||||||
to := sdktranslator.FromString("claude")
|
to := sdktranslator.FromString("claude")
|
||||||
// Use streaming translation to preserve function calling, except for claude.
|
// Use streaming translation to preserve function calling, except for claude.
|
||||||
stream := from != to
|
stream := from != to
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), stream)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, stream)
|
||||||
body, _ = sjson.SetBytes(body, "model", baseModel)
|
body, _ = sjson.SetBytes(body, "model", baseModel)
|
||||||
|
|
||||||
if !strings.HasPrefix(baseModel, "claude-3-5-haiku") {
|
if !strings.HasPrefix(baseModel, "claude-3-5-haiku") {
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ import (
|
|||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
codexClientVersion = "0.98.0"
|
||||||
|
codexUserAgent = "codex_cli_rs/0.98.0 (Mac OS 26.0.1; arm64) Apple_Terminal/464"
|
||||||
|
)
|
||||||
|
|
||||||
var dataTag = []byte("data:")
|
var dataTag = []byte("data:")
|
||||||
|
|
||||||
// CodexExecutor is a stateless executor for Codex (OpenAI Responses API entrypoint).
|
// CodexExecutor is a stateless executor for Codex (OpenAI Responses API entrypoint).
|
||||||
@@ -88,12 +93,13 @@ func (e *CodexExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, re
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("codex")
|
to := sdktranslator.FromString("codex")
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -176,7 +182,7 @@ func (e *CodexExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
var param any
|
var param any
|
||||||
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, bytes.Clone(originalPayload), body, line, ¶m)
|
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, originalPayload, body, line, ¶m)
|
||||||
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
@@ -197,12 +203,13 @@ func (e *CodexExecutor) executeCompact(ctx context.Context, auth *cliproxyauth.A
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("openai-response")
|
to := sdktranslator.FromString("openai-response")
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -265,7 +272,7 @@ func (e *CodexExecutor) executeCompact(ctx context.Context, auth *cliproxyauth.A
|
|||||||
reporter.publish(ctx, parseOpenAIUsage(data))
|
reporter.publish(ctx, parseOpenAIUsage(data))
|
||||||
reporter.ensurePublished(ctx)
|
reporter.ensurePublished(ctx)
|
||||||
var param any
|
var param any
|
||||||
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, bytes.Clone(originalPayload), body, data, ¶m)
|
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, originalPayload, body, data, ¶m)
|
||||||
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
@@ -286,12 +293,13 @@ func (e *CodexExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("codex")
|
to := sdktranslator.FromString("codex")
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), true)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, true)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -378,7 +386,7 @@ func (e *CodexExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(originalPayload), body, bytes.Clone(line), ¶m)
|
chunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, originalPayload, body, bytes.Clone(line), ¶m)
|
||||||
for i := range chunks {
|
for i := range chunks {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(chunks[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(chunks[i])}
|
||||||
}
|
}
|
||||||
@@ -397,7 +405,7 @@ func (e *CodexExecutor) CountTokens(ctx context.Context, auth *cliproxyauth.Auth
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("codex")
|
to := sdktranslator.FromString("codex")
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
body, err := thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err := thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -634,10 +642,10 @@ func applyCodexHeaders(r *http.Request, auth *cliproxyauth.Auth, token string, s
|
|||||||
ginHeaders = ginCtx.Request.Header
|
ginHeaders = ginCtx.Request.Header
|
||||||
}
|
}
|
||||||
|
|
||||||
misc.EnsureHeader(r.Header, ginHeaders, "Version", "0.21.0")
|
misc.EnsureHeader(r.Header, ginHeaders, "Version", codexClientVersion)
|
||||||
misc.EnsureHeader(r.Header, ginHeaders, "Openai-Beta", "responses=experimental")
|
misc.EnsureHeader(r.Header, ginHeaders, "Openai-Beta", "responses=experimental")
|
||||||
misc.EnsureHeader(r.Header, ginHeaders, "Session_id", uuid.NewString())
|
misc.EnsureHeader(r.Header, ginHeaders, "Session_id", uuid.NewString())
|
||||||
misc.EnsureHeader(r.Header, ginHeaders, "User-Agent", "codex_cli_rs/0.50.0 (Mac OS 26.0.1; arm64) Apple_Terminal/464")
|
misc.EnsureHeader(r.Header, ginHeaders, "User-Agent", codexUserAgent)
|
||||||
|
|
||||||
if stream {
|
if stream {
|
||||||
r.Header.Set("Accept", "text/event-stream")
|
r.Header.Set("Accept", "text/event-stream")
|
||||||
|
|||||||
@@ -119,12 +119,13 @@ func (e *GeminiCLIExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth
|
|||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini-cli")
|
to := sdktranslator.FromString("gemini-cli")
|
||||||
|
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
||||||
basePayload := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
basePayload := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
basePayload, err = thinking.ApplyThinking(basePayload, req.Model, from.String(), to.String(), e.Identifier())
|
basePayload, err = thinking.ApplyThinking(basePayload, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -223,7 +224,7 @@ func (e *GeminiCLIExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth
|
|||||||
if httpResp.StatusCode >= 200 && httpResp.StatusCode < 300 {
|
if httpResp.StatusCode >= 200 && httpResp.StatusCode < 300 {
|
||||||
reporter.publish(ctx, parseGeminiCLIUsage(data))
|
reporter.publish(ctx, parseGeminiCLIUsage(data))
|
||||||
var param any
|
var param any
|
||||||
out := sdktranslator.TranslateNonStream(respCtx, to, from, attemptModel, bytes.Clone(opts.OriginalRequest), payload, data, ¶m)
|
out := sdktranslator.TranslateNonStream(respCtx, to, from, attemptModel, opts.OriginalRequest, payload, data, ¶m)
|
||||||
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
@@ -272,12 +273,13 @@ func (e *GeminiCLIExecutor) ExecuteStream(ctx context.Context, auth *cliproxyaut
|
|||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini-cli")
|
to := sdktranslator.FromString("gemini-cli")
|
||||||
|
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
||||||
basePayload := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), true)
|
basePayload := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, true)
|
||||||
|
|
||||||
basePayload, err = thinking.ApplyThinking(basePayload, req.Model, from.String(), to.String(), e.Identifier())
|
basePayload, err = thinking.ApplyThinking(basePayload, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -399,14 +401,14 @@ func (e *GeminiCLIExecutor) ExecuteStream(ctx context.Context, auth *cliproxyaut
|
|||||||
reporter.publish(ctx, detail)
|
reporter.publish(ctx, detail)
|
||||||
}
|
}
|
||||||
if bytes.HasPrefix(line, dataTag) {
|
if bytes.HasPrefix(line, dataTag) {
|
||||||
segments := sdktranslator.TranslateStream(respCtx, to, from, attemptModel, bytes.Clone(opts.OriginalRequest), reqBody, bytes.Clone(line), ¶m)
|
segments := sdktranslator.TranslateStream(respCtx, to, from, attemptModel, opts.OriginalRequest, reqBody, bytes.Clone(line), ¶m)
|
||||||
for i := range segments {
|
for i := range segments {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
segments := sdktranslator.TranslateStream(respCtx, to, from, attemptModel, bytes.Clone(opts.OriginalRequest), reqBody, bytes.Clone([]byte("[DONE]")), ¶m)
|
segments := sdktranslator.TranslateStream(respCtx, to, from, attemptModel, opts.OriginalRequest, reqBody, []byte("[DONE]"), ¶m)
|
||||||
for i := range segments {
|
for i := range segments {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])}
|
||||||
}
|
}
|
||||||
@@ -428,12 +430,12 @@ func (e *GeminiCLIExecutor) ExecuteStream(ctx context.Context, auth *cliproxyaut
|
|||||||
appendAPIResponseChunk(ctx, e.cfg, data)
|
appendAPIResponseChunk(ctx, e.cfg, data)
|
||||||
reporter.publish(ctx, parseGeminiCLIUsage(data))
|
reporter.publish(ctx, parseGeminiCLIUsage(data))
|
||||||
var param any
|
var param any
|
||||||
segments := sdktranslator.TranslateStream(respCtx, to, from, attemptModel, bytes.Clone(opts.OriginalRequest), reqBody, data, ¶m)
|
segments := sdktranslator.TranslateStream(respCtx, to, from, attemptModel, opts.OriginalRequest, reqBody, data, ¶m)
|
||||||
for i := range segments {
|
for i := range segments {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])}
|
||||||
}
|
}
|
||||||
|
|
||||||
segments = sdktranslator.TranslateStream(respCtx, to, from, attemptModel, bytes.Clone(opts.OriginalRequest), reqBody, bytes.Clone([]byte("[DONE]")), ¶m)
|
segments = sdktranslator.TranslateStream(respCtx, to, from, attemptModel, opts.OriginalRequest, reqBody, []byte("[DONE]"), ¶m)
|
||||||
for i := range segments {
|
for i := range segments {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])}
|
||||||
}
|
}
|
||||||
@@ -485,7 +487,7 @@ func (e *GeminiCLIExecutor) CountTokens(ctx context.Context, auth *cliproxyauth.
|
|||||||
// The loop variable attemptModel is only used as the concrete model id sent to the upstream
|
// The loop variable attemptModel is only used as the concrete model id sent to the upstream
|
||||||
// Gemini CLI endpoint when iterating fallback variants.
|
// Gemini CLI endpoint when iterating fallback variants.
|
||||||
for range models {
|
for range models {
|
||||||
payload := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
payload := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
payload, err = thinking.ApplyThinking(payload, req.Model, from.String(), to.String(), e.Identifier())
|
payload, err = thinking.ApplyThinking(payload, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -116,12 +116,13 @@ func (e *GeminiExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r
|
|||||||
// Official Gemini API via API key or OAuth bearer
|
// Official Gemini API via API key or OAuth bearer
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -203,7 +204,7 @@ func (e *GeminiExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r
|
|||||||
appendAPIResponseChunk(ctx, e.cfg, data)
|
appendAPIResponseChunk(ctx, e.cfg, data)
|
||||||
reporter.publish(ctx, parseGeminiUsage(data))
|
reporter.publish(ctx, parseGeminiUsage(data))
|
||||||
var param any
|
var param any
|
||||||
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, data, ¶m)
|
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, opts.OriginalRequest, body, data, ¶m)
|
||||||
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
@@ -222,12 +223,13 @@ func (e *GeminiExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), true)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, true)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -318,12 +320,12 @@ func (e *GeminiExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
|
|||||||
if detail, ok := parseGeminiStreamUsage(payload); ok {
|
if detail, ok := parseGeminiStreamUsage(payload); ok {
|
||||||
reporter.publish(ctx, detail)
|
reporter.publish(ctx, detail)
|
||||||
}
|
}
|
||||||
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, bytes.Clone(payload), ¶m)
|
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, bytes.Clone(payload), ¶m)
|
||||||
for i := range lines {
|
for i := range lines {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, bytes.Clone([]byte("[DONE]")), ¶m)
|
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, []byte("[DONE]"), ¶m)
|
||||||
for i := range lines {
|
for i := range lines {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
|
||||||
}
|
}
|
||||||
@@ -344,7 +346,7 @@ func (e *GeminiExecutor) CountTokens(ctx context.Context, auth *cliproxyauth.Aut
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
translatedReq := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
translatedReq := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
translatedReq, err := thinking.ApplyThinking(translatedReq, req.Model, from.String(), to.String(), e.Identifier())
|
translatedReq, err := thinking.ApplyThinking(translatedReq, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -318,12 +318,13 @@ func (e *GeminiVertexExecutor) executeWithServiceAccount(ctx context.Context, au
|
|||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
|
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
||||||
body = sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
body = sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -417,7 +418,7 @@ func (e *GeminiVertexExecutor) executeWithServiceAccount(ctx context.Context, au
|
|||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
var param any
|
var param any
|
||||||
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, data, ¶m)
|
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, opts.OriginalRequest, body, data, ¶m)
|
||||||
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
@@ -432,12 +433,13 @@ func (e *GeminiVertexExecutor) executeWithAPIKey(ctx context.Context, auth *clip
|
|||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
|
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -521,7 +523,7 @@ func (e *GeminiVertexExecutor) executeWithAPIKey(ctx context.Context, auth *clip
|
|||||||
appendAPIResponseChunk(ctx, e.cfg, data)
|
appendAPIResponseChunk(ctx, e.cfg, data)
|
||||||
reporter.publish(ctx, parseGeminiUsage(data))
|
reporter.publish(ctx, parseGeminiUsage(data))
|
||||||
var param any
|
var param any
|
||||||
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, data, ¶m)
|
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, opts.OriginalRequest, body, data, ¶m)
|
||||||
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
@@ -536,12 +538,13 @@ func (e *GeminiVertexExecutor) executeStreamWithServiceAccount(ctx context.Conte
|
|||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
|
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), true)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, true)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -632,12 +635,12 @@ func (e *GeminiVertexExecutor) executeStreamWithServiceAccount(ctx context.Conte
|
|||||||
if detail, ok := parseGeminiStreamUsage(line); ok {
|
if detail, ok := parseGeminiStreamUsage(line); ok {
|
||||||
reporter.publish(ctx, detail)
|
reporter.publish(ctx, detail)
|
||||||
}
|
}
|
||||||
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, bytes.Clone(line), ¶m)
|
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, bytes.Clone(line), ¶m)
|
||||||
for i := range lines {
|
for i := range lines {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, []byte("[DONE]"), ¶m)
|
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, []byte("[DONE]"), ¶m)
|
||||||
for i := range lines {
|
for i := range lines {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
|
||||||
}
|
}
|
||||||
@@ -660,12 +663,13 @@ func (e *GeminiVertexExecutor) executeStreamWithAPIKey(ctx context.Context, auth
|
|||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
|
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), true)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, true)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -756,12 +760,12 @@ func (e *GeminiVertexExecutor) executeStreamWithAPIKey(ctx context.Context, auth
|
|||||||
if detail, ok := parseGeminiStreamUsage(line); ok {
|
if detail, ok := parseGeminiStreamUsage(line); ok {
|
||||||
reporter.publish(ctx, detail)
|
reporter.publish(ctx, detail)
|
||||||
}
|
}
|
||||||
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, bytes.Clone(line), ¶m)
|
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, bytes.Clone(line), ¶m)
|
||||||
for i := range lines {
|
for i := range lines {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, []byte("[DONE]"), ¶m)
|
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, []byte("[DONE]"), ¶m)
|
||||||
for i := range lines {
|
for i := range lines {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
|
||||||
}
|
}
|
||||||
@@ -781,7 +785,7 @@ func (e *GeminiVertexExecutor) countTokensWithServiceAccount(ctx context.Context
|
|||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
|
|
||||||
translatedReq := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
translatedReq := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
translatedReq, err := thinking.ApplyThinking(translatedReq, req.Model, from.String(), to.String(), e.Identifier())
|
translatedReq, err := thinking.ApplyThinking(translatedReq, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -865,7 +869,7 @@ func (e *GeminiVertexExecutor) countTokensWithAPIKey(ctx context.Context, auth *
|
|||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
|
|
||||||
translatedReq := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
translatedReq := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
translatedReq, err := thinking.ApplyThinking(translatedReq, req.Model, from.String(), to.String(), e.Identifier())
|
translatedReq, err := thinking.ApplyThinking(translatedReq, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -87,12 +87,13 @@ func (e *IFlowExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, re
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("openai")
|
to := sdktranslator.FromString("openai")
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
body, _ = sjson.SetBytes(body, "model", baseModel)
|
body, _ = sjson.SetBytes(body, "model", baseModel)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), "iflow", e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), "iflow", e.Identifier())
|
||||||
@@ -163,7 +164,7 @@ func (e *IFlowExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, re
|
|||||||
var param any
|
var param any
|
||||||
// Note: TranslateNonStream uses req.Model (original with suffix) to preserve
|
// Note: TranslateNonStream uses req.Model (original with suffix) to preserve
|
||||||
// the original model name in the response for client compatibility.
|
// the original model name in the response for client compatibility.
|
||||||
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, data, ¶m)
|
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, opts.OriginalRequest, body, data, ¶m)
|
||||||
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
@@ -189,12 +190,13 @@ func (e *IFlowExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("openai")
|
to := sdktranslator.FromString("openai")
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), true)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, true)
|
||||||
body, _ = sjson.SetBytes(body, "model", baseModel)
|
body, _ = sjson.SetBytes(body, "model", baseModel)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), "iflow", e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), "iflow", e.Identifier())
|
||||||
@@ -274,7 +276,7 @@ func (e *IFlowExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au
|
|||||||
if detail, ok := parseOpenAIStreamUsage(line); ok {
|
if detail, ok := parseOpenAIStreamUsage(line); ok {
|
||||||
reporter.publish(ctx, detail)
|
reporter.publish(ctx, detail)
|
||||||
}
|
}
|
||||||
chunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, bytes.Clone(line), ¶m)
|
chunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, bytes.Clone(line), ¶m)
|
||||||
for i := range chunks {
|
for i := range chunks {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(chunks[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(chunks[i])}
|
||||||
}
|
}
|
||||||
@@ -296,7 +298,7 @@ func (e *IFlowExecutor) CountTokens(ctx context.Context, auth *cliproxyauth.Auth
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("openai")
|
to := sdktranslator.FromString("openai")
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
enc, err := tokenizerForModel(baseModel)
|
enc, err := tokenizerForModel(baseModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1681,6 +1681,7 @@ func (e *KiroExecutor) mapModelToKiro(model string) string {
|
|||||||
modelMap := map[string]string{
|
modelMap := map[string]string{
|
||||||
// Amazon Q format (amazonq- prefix) - same API as Kiro
|
// Amazon Q format (amazonq- prefix) - same API as Kiro
|
||||||
"amazonq-auto": "auto",
|
"amazonq-auto": "auto",
|
||||||
|
"amazonq-claude-opus-4-6": "claude-opus-4.6",
|
||||||
"amazonq-claude-opus-4-5": "claude-opus-4.5",
|
"amazonq-claude-opus-4-5": "claude-opus-4.5",
|
||||||
"amazonq-claude-sonnet-4-5": "claude-sonnet-4.5",
|
"amazonq-claude-sonnet-4-5": "claude-sonnet-4.5",
|
||||||
"amazonq-claude-sonnet-4-5-20250929": "claude-sonnet-4.5",
|
"amazonq-claude-sonnet-4-5-20250929": "claude-sonnet-4.5",
|
||||||
@@ -1688,6 +1689,7 @@ func (e *KiroExecutor) mapModelToKiro(model string) string {
|
|||||||
"amazonq-claude-sonnet-4-20250514": "claude-sonnet-4",
|
"amazonq-claude-sonnet-4-20250514": "claude-sonnet-4",
|
||||||
"amazonq-claude-haiku-4-5": "claude-haiku-4.5",
|
"amazonq-claude-haiku-4-5": "claude-haiku-4.5",
|
||||||
// Kiro format (kiro- prefix) - valid model names that should be preserved
|
// Kiro format (kiro- prefix) - valid model names that should be preserved
|
||||||
|
"kiro-claude-opus-4-6": "claude-opus-4.6",
|
||||||
"kiro-claude-opus-4-5": "claude-opus-4.5",
|
"kiro-claude-opus-4-5": "claude-opus-4.5",
|
||||||
"kiro-claude-sonnet-4-5": "claude-sonnet-4.5",
|
"kiro-claude-sonnet-4-5": "claude-sonnet-4.5",
|
||||||
"kiro-claude-sonnet-4-5-20250929": "claude-sonnet-4.5",
|
"kiro-claude-sonnet-4-5-20250929": "claude-sonnet-4.5",
|
||||||
@@ -1696,6 +1698,8 @@ func (e *KiroExecutor) mapModelToKiro(model string) string {
|
|||||||
"kiro-claude-haiku-4-5": "claude-haiku-4.5",
|
"kiro-claude-haiku-4-5": "claude-haiku-4.5",
|
||||||
"kiro-auto": "auto",
|
"kiro-auto": "auto",
|
||||||
// Native format (no prefix) - used by Kiro IDE directly
|
// Native format (no prefix) - used by Kiro IDE directly
|
||||||
|
"claude-opus-4-6": "claude-opus-4.6",
|
||||||
|
"claude-opus-4.6": "claude-opus-4.6",
|
||||||
"claude-opus-4-5": "claude-opus-4.5",
|
"claude-opus-4-5": "claude-opus-4.5",
|
||||||
"claude-opus-4.5": "claude-opus-4.5",
|
"claude-opus-4.5": "claude-opus-4.5",
|
||||||
"claude-haiku-4-5": "claude-haiku-4.5",
|
"claude-haiku-4-5": "claude-haiku-4.5",
|
||||||
@@ -1707,10 +1711,12 @@ func (e *KiroExecutor) mapModelToKiro(model string) string {
|
|||||||
"claude-sonnet-4-20250514": "claude-sonnet-4",
|
"claude-sonnet-4-20250514": "claude-sonnet-4",
|
||||||
"auto": "auto",
|
"auto": "auto",
|
||||||
// Agentic variants (same backend model IDs, but with special system prompt)
|
// Agentic variants (same backend model IDs, but with special system prompt)
|
||||||
|
"claude-opus-4.6-agentic": "claude-opus-4.6",
|
||||||
"claude-opus-4.5-agentic": "claude-opus-4.5",
|
"claude-opus-4.5-agentic": "claude-opus-4.5",
|
||||||
"claude-sonnet-4.5-agentic": "claude-sonnet-4.5",
|
"claude-sonnet-4.5-agentic": "claude-sonnet-4.5",
|
||||||
"claude-sonnet-4-agentic": "claude-sonnet-4",
|
"claude-sonnet-4-agentic": "claude-sonnet-4",
|
||||||
"claude-haiku-4.5-agentic": "claude-haiku-4.5",
|
"claude-haiku-4.5-agentic": "claude-haiku-4.5",
|
||||||
|
"kiro-claude-opus-4-6-agentic": "claude-opus-4.6",
|
||||||
"kiro-claude-opus-4-5-agentic": "claude-opus-4.5",
|
"kiro-claude-opus-4-5-agentic": "claude-opus-4.5",
|
||||||
"kiro-claude-sonnet-4-5-agentic": "claude-sonnet-4.5",
|
"kiro-claude-sonnet-4-5-agentic": "claude-sonnet-4.5",
|
||||||
"kiro-claude-sonnet-4-agentic": "claude-sonnet-4",
|
"kiro-claude-sonnet-4-agentic": "claude-sonnet-4",
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ func recordAPIRequest(ctx context.Context, cfg *config.Config, info upstreamRequ
|
|||||||
writeHeaders(builder, info.Headers)
|
writeHeaders(builder, info.Headers)
|
||||||
builder.WriteString("\nBody:\n")
|
builder.WriteString("\nBody:\n")
|
||||||
if len(info.Body) > 0 {
|
if len(info.Body) > 0 {
|
||||||
builder.WriteString(string(bytes.Clone(info.Body)))
|
builder.WriteString(string(info.Body))
|
||||||
} else {
|
} else {
|
||||||
builder.WriteString("<empty>")
|
builder.WriteString("<empty>")
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ func appendAPIResponseChunk(ctx context.Context, cfg *config.Config, chunk []byt
|
|||||||
if cfg == nil || !cfg.RequestLog {
|
if cfg == nil || !cfg.RequestLog {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data := bytes.TrimSpace(bytes.Clone(chunk))
|
data := bytes.TrimSpace(chunk)
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,12 +88,13 @@ func (e *OpenAICompatExecutor) Execute(ctx context.Context, auth *cliproxyauth.A
|
|||||||
to = sdktranslator.FromString("openai-response")
|
to = sdktranslator.FromString("openai-response")
|
||||||
endpoint = "/responses/compact"
|
endpoint = "/responses/compact"
|
||||||
}
|
}
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, opts.Stream)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, opts.Stream)
|
||||||
translated := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), opts.Stream)
|
translated := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, opts.Stream)
|
||||||
requestedModel := payloadRequestedModel(opts, req.Model)
|
requestedModel := payloadRequestedModel(opts, req.Model)
|
||||||
translated = applyPayloadConfigWithRoot(e.cfg, baseModel, to.String(), "", translated, originalTranslated, requestedModel)
|
translated = applyPayloadConfigWithRoot(e.cfg, baseModel, to.String(), "", translated, originalTranslated, requestedModel)
|
||||||
if opts.Alt == "responses/compact" {
|
if opts.Alt == "responses/compact" {
|
||||||
@@ -170,7 +171,7 @@ func (e *OpenAICompatExecutor) Execute(ctx context.Context, auth *cliproxyauth.A
|
|||||||
reporter.ensurePublished(ctx)
|
reporter.ensurePublished(ctx)
|
||||||
// Translate response back to source format when needed
|
// Translate response back to source format when needed
|
||||||
var param any
|
var param any
|
||||||
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), translated, body, ¶m)
|
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, opts.OriginalRequest, translated, body, ¶m)
|
||||||
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
@@ -189,12 +190,13 @@ func (e *OpenAICompatExecutor) ExecuteStream(ctx context.Context, auth *cliproxy
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("openai")
|
to := sdktranslator.FromString("openai")
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
||||||
translated := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), true)
|
translated := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, true)
|
||||||
requestedModel := payloadRequestedModel(opts, req.Model)
|
requestedModel := payloadRequestedModel(opts, req.Model)
|
||||||
translated = applyPayloadConfigWithRoot(e.cfg, baseModel, to.String(), "", translated, originalTranslated, requestedModel)
|
translated = applyPayloadConfigWithRoot(e.cfg, baseModel, to.String(), "", translated, originalTranslated, requestedModel)
|
||||||
|
|
||||||
@@ -283,7 +285,7 @@ func (e *OpenAICompatExecutor) ExecuteStream(ctx context.Context, auth *cliproxy
|
|||||||
|
|
||||||
// OpenAI-compatible streams are SSE: lines typically prefixed with "data: ".
|
// OpenAI-compatible streams are SSE: lines typically prefixed with "data: ".
|
||||||
// Pass through translator; it yields one or more chunks for the target schema.
|
// Pass through translator; it yields one or more chunks for the target schema.
|
||||||
chunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), translated, bytes.Clone(line), ¶m)
|
chunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, translated, bytes.Clone(line), ¶m)
|
||||||
for i := range chunks {
|
for i := range chunks {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(chunks[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(chunks[i])}
|
||||||
}
|
}
|
||||||
@@ -304,7 +306,7 @@ func (e *OpenAICompatExecutor) CountTokens(ctx context.Context, auth *cliproxyau
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("openai")
|
to := sdktranslator.FromString("openai")
|
||||||
translated := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
translated := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
modelForCounting := baseModel
|
modelForCounting := baseModel
|
||||||
|
|
||||||
|
|||||||
@@ -81,12 +81,13 @@ func (e *QwenExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, req
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("openai")
|
to := sdktranslator.FromString("openai")
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, false)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
body, _ = sjson.SetBytes(body, "model", baseModel)
|
body, _ = sjson.SetBytes(body, "model", baseModel)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
@@ -150,7 +151,7 @@ func (e *QwenExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, req
|
|||||||
var param any
|
var param any
|
||||||
// Note: TranslateNonStream uses req.Model (original with suffix) to preserve
|
// Note: TranslateNonStream uses req.Model (original with suffix) to preserve
|
||||||
// the original model name in the response for client compatibility.
|
// the original model name in the response for client compatibility.
|
||||||
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, data, ¶m)
|
out := sdktranslator.TranslateNonStream(ctx, to, from, req.Model, opts.OriginalRequest, body, data, ¶m)
|
||||||
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
resp = cliproxyexecutor.Response{Payload: []byte(out)}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
@@ -171,12 +172,13 @@ func (e *QwenExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Aut
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("openai")
|
to := sdktranslator.FromString("openai")
|
||||||
originalPayload := bytes.Clone(req.Payload)
|
originalPayloadSource := req.Payload
|
||||||
if len(opts.OriginalRequest) > 0 {
|
if len(opts.OriginalRequest) > 0 {
|
||||||
originalPayload = bytes.Clone(opts.OriginalRequest)
|
originalPayloadSource = opts.OriginalRequest
|
||||||
}
|
}
|
||||||
|
originalPayload := originalPayloadSource
|
||||||
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
originalTranslated := sdktranslator.TranslateRequest(from, to, baseModel, originalPayload, true)
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), true)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, true)
|
||||||
body, _ = sjson.SetBytes(body, "model", baseModel)
|
body, _ = sjson.SetBytes(body, "model", baseModel)
|
||||||
|
|
||||||
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
body, err = thinking.ApplyThinking(body, req.Model, from.String(), to.String(), e.Identifier())
|
||||||
@@ -253,12 +255,12 @@ func (e *QwenExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Aut
|
|||||||
if detail, ok := parseOpenAIStreamUsage(line); ok {
|
if detail, ok := parseOpenAIStreamUsage(line); ok {
|
||||||
reporter.publish(ctx, detail)
|
reporter.publish(ctx, detail)
|
||||||
}
|
}
|
||||||
chunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, bytes.Clone(line), ¶m)
|
chunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, bytes.Clone(line), ¶m)
|
||||||
for i := range chunks {
|
for i := range chunks {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(chunks[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(chunks[i])}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
doneChunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, bytes.Clone([]byte("[DONE]")), ¶m)
|
doneChunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, []byte("[DONE]"), ¶m)
|
||||||
for i := range doneChunks {
|
for i := range doneChunks {
|
||||||
out <- cliproxyexecutor.StreamChunk{Payload: []byte(doneChunks[i])}
|
out <- cliproxyexecutor.StreamChunk{Payload: []byte(doneChunks[i])}
|
||||||
}
|
}
|
||||||
@@ -276,7 +278,7 @@ func (e *QwenExecutor) CountTokens(ctx context.Context, auth *cliproxyauth.Auth,
|
|||||||
|
|
||||||
from := opts.SourceFormat
|
from := opts.SourceFormat
|
||||||
to := sdktranslator.FromString("openai")
|
to := sdktranslator.FromString("openai")
|
||||||
body := sdktranslator.TranslateRequest(from, to, baseModel, bytes.Clone(req.Payload), false)
|
body := sdktranslator.TranslateRequest(from, to, baseModel, req.Payload, false)
|
||||||
|
|
||||||
modelName := gjson.GetBytes(body, "model").String()
|
modelName := gjson.GetBytes(body, "model").String()
|
||||||
if strings.TrimSpace(modelName) == "" {
|
if strings.TrimSpace(modelName) == "" {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package claude
|
package claude
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/cache"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/cache"
|
||||||
@@ -37,7 +36,7 @@ import (
|
|||||||
// - []byte: The transformed request data in Gemini CLI API format
|
// - []byte: The transformed request data in Gemini CLI API format
|
||||||
func ConvertClaudeRequestToAntigravity(modelName string, inputRawJSON []byte, _ bool) []byte {
|
func ConvertClaudeRequestToAntigravity(modelName string, inputRawJSON []byte, _ bool) []byte {
|
||||||
enableThoughtTranslate := true
|
enableThoughtTranslate := true
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
|
|
||||||
// system instruction
|
// system instruction
|
||||||
systemInstructionJSON := ""
|
systemInstructionJSON := ""
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package gemini
|
package gemini
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -34,7 +33,7 @@ import (
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in Gemini API format
|
// - []byte: The transformed request data in Gemini API format
|
||||||
func ConvertGeminiRequestToAntigravity(modelName string, inputRawJSON []byte, _ bool) []byte {
|
func ConvertGeminiRequestToAntigravity(modelName string, inputRawJSON []byte, _ bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
template := ""
|
template := ""
|
||||||
template = `{"project":"","request":{},"model":""}`
|
template = `{"project":"","request":{},"model":""}`
|
||||||
template, _ = sjson.SetRaw(template, "request", string(rawJSON))
|
template, _ = sjson.SetRaw(template, "request", string(rawJSON))
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
package responses
|
package responses
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
|
|
||||||
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/antigravity/gemini"
|
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/antigravity/gemini"
|
||||||
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/openai/responses"
|
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/openai/responses"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ConvertOpenAIResponsesRequestToAntigravity(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertOpenAIResponsesRequestToAntigravity(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
rawJSON = ConvertOpenAIResponsesRequestToGemini(modelName, rawJSON, stream)
|
rawJSON = ConvertOpenAIResponsesRequestToGemini(modelName, rawJSON, stream)
|
||||||
return ConvertGeminiRequestToAntigravity(modelName, rawJSON, stream)
|
return ConvertGeminiRequestToAntigravity(modelName, rawJSON, stream)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
package geminiCLI
|
package geminiCLI
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
|
|
||||||
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/claude/gemini"
|
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/claude/gemini"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
"github.com/tidwall/sjson"
|
"github.com/tidwall/sjson"
|
||||||
@@ -30,7 +28,7 @@ import (
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in Claude Code API format
|
// - []byte: The transformed request data in Claude Code API format
|
||||||
func ConvertGeminiCLIRequestToClaude(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertGeminiCLIRequestToClaude(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
|
|
||||||
modelResult := gjson.GetBytes(rawJSON, "model")
|
modelResult := gjson.GetBytes(rawJSON, "model")
|
||||||
// Extract the inner request object and promote it to the top level
|
// Extract the inner request object and promote it to the top level
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package gemini
|
package gemini
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
@@ -46,7 +45,7 @@ var (
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in Claude Code API format
|
// - []byte: The transformed request data in Claude Code API format
|
||||||
func ConvertGeminiRequestToClaude(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertGeminiRequestToClaude(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
|
|
||||||
if account == "" {
|
if account == "" {
|
||||||
u, _ := uuid.NewRandom()
|
u, _ := uuid.NewRandom()
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package chat_completions
|
package chat_completions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
@@ -44,7 +43,7 @@ var (
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in Claude Code API format
|
// - []byte: The transformed request data in Claude Code API format
|
||||||
func ConvertOpenAIRequestToClaude(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertOpenAIRequestToClaude(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
|
|
||||||
if account == "" {
|
if account == "" {
|
||||||
u, _ := uuid.NewRandom()
|
u, _ := uuid.NewRandom()
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package responses
|
package responses
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
@@ -32,7 +31,7 @@ var (
|
|||||||
// - max_output_tokens -> max_tokens
|
// - max_output_tokens -> max_tokens
|
||||||
// - stream passthrough via parameter
|
// - stream passthrough via parameter
|
||||||
func ConvertOpenAIResponsesRequestToClaude(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertOpenAIResponsesRequestToClaude(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
|
|
||||||
if account == "" {
|
if account == "" {
|
||||||
u, _ := uuid.NewRandom()
|
u, _ := uuid.NewRandom()
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package claude
|
package claude
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -35,7 +34,7 @@ import (
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in internal client format
|
// - []byte: The transformed request data in internal client format
|
||||||
func ConvertClaudeRequestToCodex(modelName string, inputRawJSON []byte, _ bool) []byte {
|
func ConvertClaudeRequestToCodex(modelName string, inputRawJSON []byte, _ bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
|
|
||||||
template := `{"model":"","instructions":"","input":[]}`
|
template := `{"model":"","instructions":"","input":[]}`
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
package geminiCLI
|
package geminiCLI
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
|
|
||||||
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/codex/gemini"
|
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/codex/gemini"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
"github.com/tidwall/sjson"
|
"github.com/tidwall/sjson"
|
||||||
@@ -30,7 +28,7 @@ import (
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in Codex API format
|
// - []byte: The transformed request data in Codex API format
|
||||||
func ConvertGeminiCLIRequestToCodex(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertGeminiCLIRequestToCodex(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
|
|
||||||
rawJSON = []byte(gjson.GetBytes(rawJSON, "request").Raw)
|
rawJSON = []byte(gjson.GetBytes(rawJSON, "request").Raw)
|
||||||
rawJSON, _ = sjson.SetBytes(rawJSON, "model", modelName)
|
rawJSON, _ = sjson.SetBytes(rawJSON, "model", modelName)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package gemini
|
package gemini
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
@@ -37,7 +36,7 @@ import (
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in Codex API format
|
// - []byte: The transformed request data in Codex API format
|
||||||
func ConvertGeminiRequestToCodex(modelName string, inputRawJSON []byte, _ bool) []byte {
|
func ConvertGeminiRequestToCodex(modelName string, inputRawJSON []byte, _ bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
// Base template
|
// Base template
|
||||||
out := `{"model":"","instructions":"","input":[]}`
|
out := `{"model":"","instructions":"","input":[]}`
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,6 @@
|
|||||||
package chat_completions
|
package chat_completions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -29,7 +27,7 @@ import (
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in OpenAI Responses API format
|
// - []byte: The transformed request data in OpenAI Responses API format
|
||||||
func ConvertOpenAIRequestToCodex(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertOpenAIRequestToCodex(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
// Start with empty JSON object
|
// Start with empty JSON object
|
||||||
out := `{"instructions":""}`
|
out := `{"instructions":""}`
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package responses
|
package responses
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
@@ -9,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func ConvertOpenAIResponsesRequestToCodex(modelName string, inputRawJSON []byte, _ bool) []byte {
|
func ConvertOpenAIResponsesRequestToCodex(modelName string, inputRawJSON []byte, _ bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
|
|
||||||
inputResult := gjson.GetBytes(rawJSON, "input")
|
inputResult := gjson.GetBytes(rawJSON, "input")
|
||||||
if inputResult.Type == gjson.String {
|
if inputResult.Type == gjson.String {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const geminiCLIClaudeThoughtSignature = "skip_thought_signature_validator"
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in Gemini CLI API format
|
// - []byte: The transformed request data in Gemini CLI API format
|
||||||
func ConvertClaudeRequestToCLI(modelName string, inputRawJSON []byte, _ bool) []byte {
|
func ConvertClaudeRequestToCLI(modelName string, inputRawJSON []byte, _ bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
rawJSON = bytes.Replace(rawJSON, []byte(`"url":{"type":"string","format":"uri",`), []byte(`"url":{"type":"string",`), -1)
|
rawJSON = bytes.Replace(rawJSON, []byte(`"url":{"type":"string","format":"uri",`), []byte(`"url":{"type":"string",`), -1)
|
||||||
|
|
||||||
// Build output Gemini CLI request JSON
|
// Build output Gemini CLI request JSON
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package gemini
|
package gemini
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common"
|
||||||
@@ -33,7 +32,7 @@ import (
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in Gemini API format
|
// - []byte: The transformed request data in Gemini API format
|
||||||
func ConvertGeminiRequestToGeminiCLI(_ string, inputRawJSON []byte, _ bool) []byte {
|
func ConvertGeminiRequestToGeminiCLI(_ string, inputRawJSON []byte, _ bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
template := ""
|
template := ""
|
||||||
template = `{"project":"","request":{},"model":""}`
|
template = `{"project":"","request":{},"model":""}`
|
||||||
template, _ = sjson.SetRaw(template, "request", string(rawJSON))
|
template, _ = sjson.SetRaw(template, "request", string(rawJSON))
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
package chat_completions
|
package chat_completions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -28,7 +27,7 @@ const geminiCLIFunctionThoughtSignature = "skip_thought_signature_validator"
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in Gemini CLI API format
|
// - []byte: The transformed request data in Gemini CLI API format
|
||||||
func ConvertOpenAIRequestToGeminiCLI(modelName string, inputRawJSON []byte, _ bool) []byte {
|
func ConvertOpenAIRequestToGeminiCLI(modelName string, inputRawJSON []byte, _ bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
// Base envelope (no default thinkingConfig)
|
// Base envelope (no default thinkingConfig)
|
||||||
out := []byte(`{"project":"","request":{"contents":[]},"model":"gemini-2.5-pro"}`)
|
out := []byte(`{"project":"","request":{"contents":[]},"model":"gemini-2.5-pro"}`)
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
package responses
|
package responses
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
|
|
||||||
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini-cli/gemini"
|
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini-cli/gemini"
|
||||||
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/openai/responses"
|
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/openai/responses"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ConvertOpenAIResponsesRequestToGeminiCLI(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertOpenAIResponsesRequestToGeminiCLI(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
rawJSON = ConvertOpenAIResponsesRequestToGemini(modelName, rawJSON, stream)
|
rawJSON = ConvertOpenAIResponsesRequestToGemini(modelName, rawJSON, stream)
|
||||||
return ConvertGeminiRequestToGeminiCLI(modelName, rawJSON, stream)
|
return ConvertGeminiRequestToGeminiCLI(modelName, rawJSON, stream)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const geminiClaudeThoughtSignature = "skip_thought_signature_validator"
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request in Gemini CLI format.
|
// - []byte: The transformed request in Gemini CLI format.
|
||||||
func ConvertClaudeRequestToGemini(modelName string, inputRawJSON []byte, _ bool) []byte {
|
func ConvertClaudeRequestToGemini(modelName string, inputRawJSON []byte, _ bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
rawJSON = bytes.Replace(rawJSON, []byte(`"url":{"type":"string","format":"uri",`), []byte(`"url":{"type":"string",`), -1)
|
rawJSON = bytes.Replace(rawJSON, []byte(`"url":{"type":"string","format":"uri",`), []byte(`"url":{"type":"string",`), -1)
|
||||||
|
|
||||||
// Build output Gemini CLI request JSON
|
// Build output Gemini CLI request JSON
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package geminiCLI
|
package geminiCLI
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common"
|
||||||
@@ -19,7 +18,7 @@ import (
|
|||||||
// It extracts the model name, system instruction, message contents, and tool declarations
|
// It extracts the model name, system instruction, message contents, and tool declarations
|
||||||
// from the raw JSON request and returns them in the format expected by the internal client.
|
// from the raw JSON request and returns them in the format expected by the internal client.
|
||||||
func ConvertGeminiCLIRequestToGemini(_ string, inputRawJSON []byte, _ bool) []byte {
|
func ConvertGeminiCLIRequestToGemini(_ string, inputRawJSON []byte, _ bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
modelResult := gjson.GetBytes(rawJSON, "model")
|
modelResult := gjson.GetBytes(rawJSON, "model")
|
||||||
rawJSON = []byte(gjson.GetBytes(rawJSON, "request").Raw)
|
rawJSON = []byte(gjson.GetBytes(rawJSON, "request").Raw)
|
||||||
rawJSON, _ = sjson.SetBytes(rawJSON, "model", modelResult.String())
|
rawJSON, _ = sjson.SetBytes(rawJSON, "model", modelResult.String())
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
package gemini
|
package gemini
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common"
|
||||||
@@ -19,7 +18,7 @@ import (
|
|||||||
//
|
//
|
||||||
// It keeps the payload otherwise unchanged.
|
// It keeps the payload otherwise unchanged.
|
||||||
func ConvertGeminiRequestToGemini(_ string, inputRawJSON []byte, _ bool) []byte {
|
func ConvertGeminiRequestToGemini(_ string, inputRawJSON []byte, _ bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
// Fast path: if no contents field, only attach safety settings
|
// Fast path: if no contents field, only attach safety settings
|
||||||
contents := gjson.GetBytes(rawJSON, "contents")
|
contents := gjson.GetBytes(rawJSON, "contents")
|
||||||
if !contents.Exists() {
|
if !contents.Exists() {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
package chat_completions
|
package chat_completions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -28,7 +27,7 @@ const geminiFunctionThoughtSignature = "skip_thought_signature_validator"
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in Gemini API format
|
// - []byte: The transformed request data in Gemini API format
|
||||||
func ConvertOpenAIRequestToGemini(modelName string, inputRawJSON []byte, _ bool) []byte {
|
func ConvertOpenAIRequestToGemini(modelName string, inputRawJSON []byte, _ bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
// Base envelope (no default thinkingConfig)
|
// Base envelope (no default thinkingConfig)
|
||||||
out := []byte(`{"contents":[]}`)
|
out := []byte(`{"contents":[]}`)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package responses
|
package responses
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common"
|
||||||
@@ -12,7 +11,7 @@ import (
|
|||||||
const geminiResponsesThoughtSignature = "skip_thought_signature_validator"
|
const geminiResponsesThoughtSignature = "skip_thought_signature_validator"
|
||||||
|
|
||||||
func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
|
|
||||||
// Note: modelName and stream parameters are part of the fixed method signature
|
// Note: modelName and stream parameters are part of the fixed method signature
|
||||||
_ = modelName // Unused but required by interface
|
_ = modelName // Unused but required by interface
|
||||||
|
|||||||
@@ -659,13 +659,36 @@ func buildAssistantMessageFromOpenAI(msg gjson.Result) KiroAssistantResponseMess
|
|||||||
contentBuilder.WriteString(content.String())
|
contentBuilder.WriteString(content.String())
|
||||||
} else if content.IsArray() {
|
} else if content.IsArray() {
|
||||||
for _, part := range content.Array() {
|
for _, part := range content.Array() {
|
||||||
if part.Get("type").String() == "text" {
|
partType := part.Get("type").String()
|
||||||
|
switch partType {
|
||||||
|
case "text":
|
||||||
contentBuilder.WriteString(part.Get("text").String())
|
contentBuilder.WriteString(part.Get("text").String())
|
||||||
|
case "tool_use":
|
||||||
|
// Handle tool_use in content array (Anthropic/OpenCode format)
|
||||||
|
// This is different from OpenAI's tool_calls format
|
||||||
|
toolUseID := part.Get("id").String()
|
||||||
|
toolName := part.Get("name").String()
|
||||||
|
inputData := part.Get("input")
|
||||||
|
|
||||||
|
inputMap := make(map[string]interface{})
|
||||||
|
if inputData.Exists() && inputData.IsObject() {
|
||||||
|
inputData.ForEach(func(key, value gjson.Result) bool {
|
||||||
|
inputMap[key.String()] = value.Value()
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
toolUses = append(toolUses, KiroToolUse{
|
||||||
|
ToolUseID: toolUseID,
|
||||||
|
Name: toolName,
|
||||||
|
Input: inputMap,
|
||||||
|
})
|
||||||
|
log.Debugf("kiro-openai: extracted tool_use from content array: %s", toolName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle tool_calls
|
// Handle tool_calls (OpenAI format)
|
||||||
toolCalls := msg.Get("tool_calls")
|
toolCalls := msg.Get("tool_calls")
|
||||||
if toolCalls.IsArray() {
|
if toolCalls.IsArray() {
|
||||||
for _, tc := range toolCalls.Array() {
|
for _, tc := range toolCalls.Array() {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package claude
|
package claude
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/thinking"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/thinking"
|
||||||
@@ -18,7 +17,7 @@ import (
|
|||||||
// It extracts the model name, system instruction, message contents, and tool declarations
|
// It extracts the model name, system instruction, message contents, and tool declarations
|
||||||
// from the raw JSON request and returns them in the format expected by the OpenAI API.
|
// from the raw JSON request and returns them in the format expected by the OpenAI API.
|
||||||
func ConvertClaudeRequestToOpenAI(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertClaudeRequestToOpenAI(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
// Base OpenAI Chat Completions API template
|
// Base OpenAI Chat Completions API template
|
||||||
out := `{"model":"","messages":[]}`
|
out := `{"model":"","messages":[]}`
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
package geminiCLI
|
package geminiCLI
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
|
|
||||||
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/openai/gemini"
|
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/openai/gemini"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
"github.com/tidwall/sjson"
|
"github.com/tidwall/sjson"
|
||||||
@@ -17,7 +15,7 @@ import (
|
|||||||
// It extracts the model name, generation config, message contents, and tool declarations
|
// It extracts the model name, generation config, message contents, and tool declarations
|
||||||
// from the raw JSON request and returns them in the format expected by the OpenAI API.
|
// from the raw JSON request and returns them in the format expected by the OpenAI API.
|
||||||
func ConvertGeminiCLIRequestToOpenAI(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertGeminiCLIRequestToOpenAI(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
rawJSON = []byte(gjson.GetBytes(rawJSON, "request").Raw)
|
rawJSON = []byte(gjson.GetBytes(rawJSON, "request").Raw)
|
||||||
rawJSON, _ = sjson.SetBytes(rawJSON, "model", modelName)
|
rawJSON, _ = sjson.SetBytes(rawJSON, "model", modelName)
|
||||||
if gjson.GetBytes(rawJSON, "systemInstruction").Exists() {
|
if gjson.GetBytes(rawJSON, "systemInstruction").Exists() {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package gemini
|
package gemini
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
@@ -21,7 +20,7 @@ import (
|
|||||||
// It extracts the model name, generation config, message contents, and tool declarations
|
// It extracts the model name, generation config, message contents, and tool declarations
|
||||||
// from the raw JSON request and returns them in the format expected by the OpenAI API.
|
// from the raw JSON request and returns them in the format expected by the OpenAI API.
|
||||||
func ConvertGeminiRequestToOpenAI(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertGeminiRequestToOpenAI(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
// Base OpenAI Chat Completions API template
|
// Base OpenAI Chat Completions API template
|
||||||
out := `{"model":"","messages":[]}`
|
out := `{"model":"","messages":[]}`
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
package chat_completions
|
package chat_completions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"github.com/tidwall/sjson"
|
"github.com/tidwall/sjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,7 +24,7 @@ func ConvertOpenAIRequestToOpenAI(modelName string, inputRawJSON []byte, _ bool)
|
|||||||
// If there's an error, return the original JSON or handle the error appropriately.
|
// If there's an error, return the original JSON or handle the error appropriately.
|
||||||
// For now, we'll return the original, but in a real scenario, logging or a more robust error
|
// For now, we'll return the original, but in a real scenario, logging or a more robust error
|
||||||
// handling mechanism would be needed.
|
// handling mechanism would be needed.
|
||||||
return bytes.Clone(inputRawJSON)
|
return inputRawJSON
|
||||||
}
|
}
|
||||||
return updatedJSON
|
return updatedJSON
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package responses
|
package responses
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
@@ -28,7 +27,7 @@ import (
|
|||||||
// Returns:
|
// Returns:
|
||||||
// - []byte: The transformed request data in OpenAI chat completions format
|
// - []byte: The transformed request data in OpenAI chat completions format
|
||||||
func ConvertOpenAIResponsesRequestToOpenAIChatCompletions(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertOpenAIResponsesRequestToOpenAIChatCompletions(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := inputRawJSON
|
||||||
// Base OpenAI chat completions template with default values
|
// Base OpenAI chat completions template with default values
|
||||||
out := `{"model":"","messages":[],"stream":false}`
|
out := `{"model":"","messages":[],"stream":false}`
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ func TestIsClaudeThinkingModel(t *testing.T) {
|
|||||||
// Claude thinking models - should return true
|
// Claude thinking models - should return true
|
||||||
{"claude-sonnet-4-5-thinking", "claude-sonnet-4-5-thinking", true},
|
{"claude-sonnet-4-5-thinking", "claude-sonnet-4-5-thinking", true},
|
||||||
{"claude-opus-4-5-thinking", "claude-opus-4-5-thinking", true},
|
{"claude-opus-4-5-thinking", "claude-opus-4-5-thinking", true},
|
||||||
|
{"claude-opus-4-6-thinking", "claude-opus-4-6-thinking", true},
|
||||||
{"Claude-Sonnet-Thinking uppercase", "Claude-Sonnet-4-5-Thinking", true},
|
{"Claude-Sonnet-Thinking uppercase", "Claude-Sonnet-4-5-Thinking", true},
|
||||||
{"claude thinking mixed case", "Claude-THINKING-Model", true},
|
{"claude thinking mixed case", "Claude-THINKING-Model", true},
|
||||||
|
|
||||||
|
|||||||
@@ -61,14 +61,20 @@ func cleanJSONSchema(jsonStr string, addPlaceholder bool) string {
|
|||||||
|
|
||||||
// removeKeywords removes all occurrences of specified keywords from the JSON schema.
|
// removeKeywords removes all occurrences of specified keywords from the JSON schema.
|
||||||
func removeKeywords(jsonStr string, keywords []string) string {
|
func removeKeywords(jsonStr string, keywords []string) string {
|
||||||
|
deletePaths := make([]string, 0)
|
||||||
|
pathsByField := findPathsByFields(jsonStr, keywords)
|
||||||
for _, key := range keywords {
|
for _, key := range keywords {
|
||||||
for _, p := range findPaths(jsonStr, key) {
|
for _, p := range pathsByField[key] {
|
||||||
if isPropertyDefinition(trimSuffix(p, "."+key)) {
|
if isPropertyDefinition(trimSuffix(p, "."+key)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
jsonStr, _ = sjson.Delete(jsonStr, p)
|
deletePaths = append(deletePaths, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sortByDepth(deletePaths)
|
||||||
|
for _, p := range deletePaths {
|
||||||
|
jsonStr, _ = sjson.Delete(jsonStr, p)
|
||||||
|
}
|
||||||
return jsonStr
|
return jsonStr
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,8 +241,9 @@ var unsupportedConstraints = []string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func moveConstraintsToDescription(jsonStr string) string {
|
func moveConstraintsToDescription(jsonStr string) string {
|
||||||
|
pathsByField := findPathsByFields(jsonStr, unsupportedConstraints)
|
||||||
for _, key := range unsupportedConstraints {
|
for _, key := range unsupportedConstraints {
|
||||||
for _, p := range findPaths(jsonStr, key) {
|
for _, p := range pathsByField[key] {
|
||||||
val := gjson.Get(jsonStr, p)
|
val := gjson.Get(jsonStr, p)
|
||||||
if !val.Exists() || val.IsObject() || val.IsArray() {
|
if !val.Exists() || val.IsObject() || val.IsArray() {
|
||||||
continue
|
continue
|
||||||
@@ -424,14 +431,21 @@ func removeUnsupportedKeywords(jsonStr string) string {
|
|||||||
"$schema", "$defs", "definitions", "const", "$ref", "additionalProperties",
|
"$schema", "$defs", "definitions", "const", "$ref", "additionalProperties",
|
||||||
"propertyNames", // Gemini doesn't support property name validation
|
"propertyNames", // Gemini doesn't support property name validation
|
||||||
)
|
)
|
||||||
|
|
||||||
|
deletePaths := make([]string, 0)
|
||||||
|
pathsByField := findPathsByFields(jsonStr, keywords)
|
||||||
for _, key := range keywords {
|
for _, key := range keywords {
|
||||||
for _, p := range findPaths(jsonStr, key) {
|
for _, p := range pathsByField[key] {
|
||||||
if isPropertyDefinition(trimSuffix(p, "."+key)) {
|
if isPropertyDefinition(trimSuffix(p, "."+key)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
jsonStr, _ = sjson.Delete(jsonStr, p)
|
deletePaths = append(deletePaths, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sortByDepth(deletePaths)
|
||||||
|
for _, p := range deletePaths {
|
||||||
|
jsonStr, _ = sjson.Delete(jsonStr, p)
|
||||||
|
}
|
||||||
// Remove x-* extension fields (e.g., x-google-enum-descriptions) that are not supported by Gemini API
|
// Remove x-* extension fields (e.g., x-google-enum-descriptions) that are not supported by Gemini API
|
||||||
jsonStr = removeExtensionFields(jsonStr)
|
jsonStr = removeExtensionFields(jsonStr)
|
||||||
return jsonStr
|
return jsonStr
|
||||||
@@ -581,6 +595,42 @@ func findPaths(jsonStr, field string) []string {
|
|||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func findPathsByFields(jsonStr string, fields []string) map[string][]string {
|
||||||
|
set := make(map[string]struct{}, len(fields))
|
||||||
|
for _, field := range fields {
|
||||||
|
set[field] = struct{}{}
|
||||||
|
}
|
||||||
|
paths := make(map[string][]string, len(set))
|
||||||
|
walkForFields(gjson.Parse(jsonStr), "", set, paths)
|
||||||
|
return paths
|
||||||
|
}
|
||||||
|
|
||||||
|
func walkForFields(value gjson.Result, path string, fields map[string]struct{}, paths map[string][]string) {
|
||||||
|
switch value.Type {
|
||||||
|
case gjson.JSON:
|
||||||
|
value.ForEach(func(key, val gjson.Result) bool {
|
||||||
|
keyStr := key.String()
|
||||||
|
safeKey := escapeGJSONPathKey(keyStr)
|
||||||
|
|
||||||
|
var childPath string
|
||||||
|
if path == "" {
|
||||||
|
childPath = safeKey
|
||||||
|
} else {
|
||||||
|
childPath = path + "." + safeKey
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := fields[keyStr]; ok {
|
||||||
|
paths[keyStr] = append(paths[keyStr], childPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
walkForFields(val, childPath, fields, paths)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
case gjson.String, gjson.Number, gjson.True, gjson.False, gjson.Null:
|
||||||
|
// Terminal types - no further traversal needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func sortByDepth(paths []string) {
|
func sortByDepth(paths []string) {
|
||||||
sort.Slice(paths, func(i, j int) bool { return len(paths[i]) > len(paths[j]) })
|
sort.Slice(paths, func(i, j int) bool { return len(paths[i]) > len(paths[j]) })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -378,9 +378,13 @@ func (h *BaseAPIHandler) ExecuteWithAuthManager(ctx context.Context, handlerType
|
|||||||
}
|
}
|
||||||
reqMeta := requestExecutionMetadata(ctx)
|
reqMeta := requestExecutionMetadata(ctx)
|
||||||
reqMeta[coreexecutor.RequestedModelMetadataKey] = normalizedModel
|
reqMeta[coreexecutor.RequestedModelMetadataKey] = normalizedModel
|
||||||
|
payload := rawJSON
|
||||||
|
if len(payload) == 0 {
|
||||||
|
payload = nil
|
||||||
|
}
|
||||||
req := coreexecutor.Request{
|
req := coreexecutor.Request{
|
||||||
Model: normalizedModel,
|
Model: normalizedModel,
|
||||||
Payload: cloneBytes(rawJSON),
|
Payload: payload,
|
||||||
}
|
}
|
||||||
opts := coreexecutor.Options{
|
opts := coreexecutor.Options{
|
||||||
Stream: false,
|
Stream: false,
|
||||||
@@ -405,7 +409,7 @@ func (h *BaseAPIHandler) ExecuteWithAuthManager(ctx context.Context, handlerType
|
|||||||
}
|
}
|
||||||
return nil, &interfaces.ErrorMessage{StatusCode: status, Error: err, Addon: addon}
|
return nil, &interfaces.ErrorMessage{StatusCode: status, Error: err, Addon: addon}
|
||||||
}
|
}
|
||||||
return cloneBytes(resp.Payload), nil
|
return resp.Payload, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteCountWithAuthManager executes a non-streaming request via the core auth manager.
|
// ExecuteCountWithAuthManager executes a non-streaming request via the core auth manager.
|
||||||
@@ -417,9 +421,13 @@ func (h *BaseAPIHandler) ExecuteCountWithAuthManager(ctx context.Context, handle
|
|||||||
}
|
}
|
||||||
reqMeta := requestExecutionMetadata(ctx)
|
reqMeta := requestExecutionMetadata(ctx)
|
||||||
reqMeta[coreexecutor.RequestedModelMetadataKey] = normalizedModel
|
reqMeta[coreexecutor.RequestedModelMetadataKey] = normalizedModel
|
||||||
|
payload := rawJSON
|
||||||
|
if len(payload) == 0 {
|
||||||
|
payload = nil
|
||||||
|
}
|
||||||
req := coreexecutor.Request{
|
req := coreexecutor.Request{
|
||||||
Model: normalizedModel,
|
Model: normalizedModel,
|
||||||
Payload: cloneBytes(rawJSON),
|
Payload: payload,
|
||||||
}
|
}
|
||||||
opts := coreexecutor.Options{
|
opts := coreexecutor.Options{
|
||||||
Stream: false,
|
Stream: false,
|
||||||
@@ -444,7 +452,7 @@ func (h *BaseAPIHandler) ExecuteCountWithAuthManager(ctx context.Context, handle
|
|||||||
}
|
}
|
||||||
return nil, &interfaces.ErrorMessage{StatusCode: status, Error: err, Addon: addon}
|
return nil, &interfaces.ErrorMessage{StatusCode: status, Error: err, Addon: addon}
|
||||||
}
|
}
|
||||||
return cloneBytes(resp.Payload), nil
|
return resp.Payload, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteStreamWithAuthManager executes a streaming request via the core auth manager.
|
// ExecuteStreamWithAuthManager executes a streaming request via the core auth manager.
|
||||||
@@ -459,9 +467,13 @@ func (h *BaseAPIHandler) ExecuteStreamWithAuthManager(ctx context.Context, handl
|
|||||||
}
|
}
|
||||||
reqMeta := requestExecutionMetadata(ctx)
|
reqMeta := requestExecutionMetadata(ctx)
|
||||||
reqMeta[coreexecutor.RequestedModelMetadataKey] = normalizedModel
|
reqMeta[coreexecutor.RequestedModelMetadataKey] = normalizedModel
|
||||||
|
payload := rawJSON
|
||||||
|
if len(payload) == 0 {
|
||||||
|
payload = nil
|
||||||
|
}
|
||||||
req := coreexecutor.Request{
|
req := coreexecutor.Request{
|
||||||
Model: normalizedModel,
|
Model: normalizedModel,
|
||||||
Payload: cloneBytes(rawJSON),
|
Payload: payload,
|
||||||
}
|
}
|
||||||
opts := coreexecutor.Options{
|
opts := coreexecutor.Options{
|
||||||
Stream: true,
|
Stream: true,
|
||||||
@@ -685,7 +697,7 @@ func (h *BaseAPIHandler) WriteErrorResponse(c *gin.Context, msg *interfaces.Erro
|
|||||||
var previous []byte
|
var previous []byte
|
||||||
if existing, exists := c.Get("API_RESPONSE"); exists {
|
if existing, exists := c.Get("API_RESPONSE"); exists {
|
||||||
if existingBytes, ok := existing.([]byte); ok && len(existingBytes) > 0 {
|
if existingBytes, ok := existing.([]byte); ok && len(existingBytes) > 0 {
|
||||||
previous = bytes.Clone(existingBytes)
|
previous = existingBytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
appendAPIResponse(c, body)
|
appendAPIResponse(c, body)
|
||||||
|
|||||||
Reference in New Issue
Block a user