refactor(translator, executor): remove redundant bytes.Clone calls for improved performance

- Replaced all instances of `bytes.Clone` with direct references to enhance efficiency.
- Simplified payload handling across executors and translators by eliminating unnecessary data duplication.
This commit is contained in:
Luis Pater
2026-02-06 03:26:29 +08:00
parent c71905e5e8
commit a5a25dec57
38 changed files with 104 additions and 134 deletions

View File

@@ -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, opts.OriginalRequest, bytes.Clone(translatedReq), bytes.Clone(wsResp.Body), &param) out := sdktranslator.TranslateNonStream(ctx, body.toFormat, opts.SourceFormat, req.Model, opts.OriginalRequest, translatedReq, wsResp.Body, &param)
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, opts.OriginalRequest, translatedReq, bytes.Clone(filtered), &param) lines := sdktranslator.TranslateStream(ctx, body.toFormat, opts.SourceFormat, req.Model, opts.OriginalRequest, translatedReq, filtered, &param)
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, opts.OriginalRequest, translatedReq, bytes.Clone(event.Payload), &param) lines := sdktranslator.TranslateStream(ctx, body.toFormat, opts.SourceFormat, req.Model, opts.OriginalRequest, translatedReq, event.Payload, &param)
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
} }
@@ -397,9 +397,9 @@ func (e *AIStudioExecutor) translateRequest(req cliproxyexecutor.Request, opts c
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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

View File

@@ -137,9 +137,9 @@ func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Au
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -279,9 +279,9 @@ func (e *AntigravityExecutor) executeClaudeNonStream(ctx context.Context, auth *
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -671,9 +671,9 @@ func (e *AntigravityExecutor) ExecuteStream(ctx context.Context, auth *cliproxya
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -875,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 {

View File

@@ -104,9 +104,9 @@ func (e *ClaudeExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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())
@@ -245,9 +245,9 @@ func (e *ClaudeExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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())
@@ -413,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") {

View File

@@ -92,9 +92,9 @@ func (e *CodexExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, re
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -202,9 +202,9 @@ func (e *CodexExecutor) executeCompact(ctx context.Context, auth *cliproxyauth.A
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -292,9 +292,9 @@ func (e *CodexExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -400,7 +400,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 {

View File

@@ -123,9 +123,9 @@ func (e *GeminiCLIExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -277,9 +277,9 @@ func (e *GeminiCLIExecutor) ExecuteStream(ctx context.Context, auth *cliproxyaut
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -408,7 +408,7 @@ func (e *GeminiCLIExecutor) ExecuteStream(ctx context.Context, auth *cliproxyaut
} }
} }
segments := sdktranslator.TranslateStream(respCtx, to, from, attemptModel, opts.OriginalRequest, reqBody, bytes.Clone([]byte("[DONE]")), &param) segments := sdktranslator.TranslateStream(respCtx, to, from, attemptModel, opts.OriginalRequest, reqBody, []byte("[DONE]"), &param)
for i := range segments { for i := range segments {
out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])} out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])}
} }
@@ -435,7 +435,7 @@ func (e *GeminiCLIExecutor) ExecuteStream(ctx context.Context, auth *cliproxyaut
out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])} out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])}
} }
segments = sdktranslator.TranslateStream(respCtx, to, from, attemptModel, opts.OriginalRequest, reqBody, bytes.Clone([]byte("[DONE]")), &param) segments = sdktranslator.TranslateStream(respCtx, to, from, attemptModel, opts.OriginalRequest, reqBody, []byte("[DONE]"), &param)
for i := range segments { for i := range segments {
out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])} out <- cliproxyexecutor.StreamChunk{Payload: []byte(segments[i])}
} }
@@ -487,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 {

View File

@@ -120,9 +120,9 @@ func (e *GeminiExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -227,9 +227,9 @@ func (e *GeminiExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -325,7 +325,7 @@ func (e *GeminiExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])} out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
} }
} }
lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, bytes.Clone([]byte("[DONE]")), &param) lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, []byte("[DONE]"), &param)
for i := range lines { for i := range lines {
out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])} out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])}
} }
@@ -346,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 {

View File

@@ -322,9 +322,9 @@ func (e *GeminiVertexExecutor) executeWithServiceAccount(ctx context.Context, au
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -437,9 +437,9 @@ func (e *GeminiVertexExecutor) executeWithAPIKey(ctx context.Context, auth *clip
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -542,9 +542,9 @@ func (e *GeminiVertexExecutor) executeStreamWithServiceAccount(ctx context.Conte
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -667,9 +667,9 @@ func (e *GeminiVertexExecutor) executeStreamWithAPIKey(ctx context.Context, auth
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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 {
@@ -785,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 {
@@ -869,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 {

View File

@@ -91,9 +91,9 @@ func (e *IFlowExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, re
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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())
@@ -194,9 +194,9 @@ func (e *IFlowExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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())
@@ -298,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 {

View File

@@ -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
} }

View File

@@ -92,9 +92,9 @@ func (e *OpenAICompatExecutor) Execute(ctx context.Context, auth *cliproxyauth.A
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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" {
@@ -194,9 +194,9 @@ func (e *OpenAICompatExecutor) ExecuteStream(ctx context.Context, auth *cliproxy
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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)
@@ -306,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

View File

@@ -85,9 +85,9 @@ func (e *QwenExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, req
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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())
@@ -176,9 +176,9 @@ func (e *QwenExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Aut
if len(opts.OriginalRequest) > 0 { if len(opts.OriginalRequest) > 0 {
originalPayloadSource = opts.OriginalRequest originalPayloadSource = opts.OriginalRequest
} }
originalPayload := bytes.Clone(originalPayloadSource) 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())
@@ -260,7 +260,7 @@ func (e *QwenExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Aut
out <- cliproxyexecutor.StreamChunk{Payload: []byte(chunks[i])} out <- cliproxyexecutor.StreamChunk{Payload: []byte(chunks[i])}
} }
} }
doneChunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, bytes.Clone([]byte("[DONE]")), &param) doneChunks := sdktranslator.TranslateStream(ctx, to, from, req.Model, opts.OriginalRequest, body, []byte("[DONE]"), &param)
for i := range doneChunks { for i := range doneChunks {
out <- cliproxyexecutor.StreamChunk{Payload: []byte(doneChunks[i])} out <- cliproxyexecutor.StreamChunk{Payload: []byte(doneChunks[i])}
} }
@@ -278,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) == "" {

View File

@@ -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 := ""

View File

@@ -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))

View File

@@ -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)
} }

View File

@@ -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

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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":[]}`

View File

@@ -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)

View File

@@ -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":[]}`

View File

@@ -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":""}`

View File

@@ -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 {

View File

@@ -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

View File

@@ -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))

View File

@@ -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"}`)

View File

@@ -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)
} }

View File

@@ -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

View File

@@ -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())

View File

@@ -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() {

View File

@@ -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":[]}`)

View File

@@ -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

View File

@@ -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":[]}`

View File

@@ -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() {

View File

@@ -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":[]}`

View File

@@ -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
} }

View File

@@ -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}`

View File

@@ -408,7 +408,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.
@@ -451,7 +451,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.
@@ -696,7 +696,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)