mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-09-28 03:40:32 +08:00
perf(antigravity): translate each upstream request once
Execute, executeClaudeNonStream and ExecuteStream all assign the validated original payload to the request and then translate both values. Since both translations saw the same bytes, every Antigravity request paid for a second full scan of the client payload. On a captured 24MB tool-history request that second pass cost roughly 0.9s of CPU and 651MB of allocations. Translate once when both inputs share a backing array and hand the caller an independent duplicate, because later stages edit the working copy in place. Payloads that genuinely differ still get two translations.
This commit is contained in:
@@ -66,8 +66,7 @@ func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Au
|
||||
auth = updatedAuth
|
||||
reporter.UpdateAccessTokenFingerprint(auth)
|
||||
}
|
||||
originalTranslated := helps.TranslateRequestWithCodexMultiAgentV2(ctx, opts.Headers, e.cfg, from, to, baseModel, originalPayload, false)
|
||||
translated := helps.TranslateRequestWithCodexMultiAgentV2(ctx, opts.Headers, e.cfg, from, to, baseModel, req.Payload, false)
|
||||
originalTranslated, translated := helps.TranslateRequestPairWithCodexMultiAgentV2(ctx, opts.Headers, e.cfg, from, to, baseModel, originalPayload, req.Payload, false)
|
||||
|
||||
translated, err = helps.ApplyThinkingWithSourcePayload(translated, req.Payload, originalPayloadSource, req.Model, from.String(), to.String(), e.Identifier())
|
||||
if err != nil {
|
||||
@@ -290,8 +289,7 @@ func (e *AntigravityExecutor) executeClaudeNonStream(ctx context.Context, auth *
|
||||
auth = updatedAuth
|
||||
reporter.UpdateAccessTokenFingerprint(auth)
|
||||
}
|
||||
originalTranslated := helps.TranslateRequestWithCodexMultiAgentV2(ctx, opts.Headers, e.cfg, from, to, baseModel, originalPayload, true)
|
||||
translated := helps.TranslateRequestWithCodexMultiAgentV2(ctx, opts.Headers, e.cfg, from, to, baseModel, req.Payload, true)
|
||||
originalTranslated, translated := helps.TranslateRequestPairWithCodexMultiAgentV2(ctx, opts.Headers, e.cfg, from, to, baseModel, originalPayload, req.Payload, true)
|
||||
|
||||
translated, err = helps.ApplyThinkingWithSourcePayload(translated, req.Payload, originalPayloadSource, req.Model, from.String(), to.String(), e.Identifier())
|
||||
if err != nil {
|
||||
|
||||
@@ -61,8 +61,7 @@ func (e *AntigravityExecutor) ExecuteStream(ctx context.Context, auth *cliproxya
|
||||
reporter.UpdateAccessTokenFingerprint(auth)
|
||||
}
|
||||
|
||||
originalTranslated := helps.TranslateRequestWithCodexMultiAgentV2(ctx, opts.Headers, e.cfg, from, to, baseModel, originalPayload, true)
|
||||
translated := helps.TranslateRequestWithCodexMultiAgentV2(ctx, opts.Headers, e.cfg, from, to, baseModel, req.Payload, true)
|
||||
originalTranslated, translated := helps.TranslateRequestPairWithCodexMultiAgentV2(ctx, opts.Headers, e.cfg, from, to, baseModel, originalPayload, req.Payload, true)
|
||||
|
||||
translated, err = helps.ApplyThinkingWithSourcePayload(translated, req.Payload, originalPayloadSource, req.Model, from.String(), to.String(), e.Identifier())
|
||||
if err != nil {
|
||||
|
||||
@@ -35,6 +35,35 @@ func TranslateRequestWithCodexMultiAgentV2(ctx context.Context, headers http.Hea
|
||||
return multiagentv2.TranslateRequestWithCodexMultiAgentV2(ctx, headers, cfg, from, to, model, payload, stream)
|
||||
}
|
||||
|
||||
// TranslateRequestPairWithCodexMultiAgentV2 translates the untouched baseline
|
||||
// payload and the working payload that later stages mutate in place. Executors
|
||||
// normally assign the original payload to the request before translating, so both
|
||||
// translations would rescan the same bytes and produce the same result. Request
|
||||
// translation is deterministic and never aliases its input, so that case is
|
||||
// translated once and duplicated, which removes a full extra pass over payloads
|
||||
// that can reach tens of megabytes.
|
||||
func TranslateRequestPairWithCodexMultiAgentV2(ctx context.Context, headers http.Header, cfg *config.Config, from, to sdktranslator.Format, model string, originalPayload, requestPayload []byte, stream bool) (original, working []byte) {
|
||||
original = TranslateRequestWithCodexMultiAgentV2(ctx, headers, cfg, from, to, model, originalPayload, stream)
|
||||
if sameByteSlice(originalPayload, requestPayload) {
|
||||
// The caller mutates the working copy, so it must not share the baseline array.
|
||||
return original, append([]byte(nil), original...)
|
||||
}
|
||||
return original, TranslateRequestWithCodexMultiAgentV2(ctx, headers, cfg, from, to, model, requestPayload, stream)
|
||||
}
|
||||
|
||||
// sameByteSlice reports whether both slices describe the same bytes of the same
|
||||
// backing array. It compares identity rather than content so the check stays
|
||||
// constant time on large payloads.
|
||||
func sameByteSlice(a, b []byte) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
if len(a) == 0 {
|
||||
return true
|
||||
}
|
||||
return &a[0] == &b[0]
|
||||
}
|
||||
|
||||
// TranslateRequestWithAPIKeyModelCompatibility applies compatibility-aware
|
||||
// request translators when a configured API-key model enables compatibility mode.
|
||||
func TranslateRequestWithAPIKeyModelCompatibility(ctx context.Context, headers http.Header, cfg *config.Config, from, to sdktranslator.Format, model string, payload []byte, stream, isCompat bool) []byte {
|
||||
|
||||
125
internal/runtime/executor/helps/codex_multi_agent_v2_test.go
Normal file
125
internal/runtime/executor/helps/codex_multi_agent_v2_test.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package helps
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/internal/config"
|
||||
_ "github.com/router-for-me/CLIProxyAPI/v7/internal/translator"
|
||||
sdktranslator "github.com/router-for-me/CLIProxyAPI/v7/sdk/translator"
|
||||
)
|
||||
|
||||
func geminiToolHistoryPayload(turns int) []byte {
|
||||
contents := []string{`{"role":"user","parts":[{"text":"start"}]}`}
|
||||
for i := 0; i < turns; i++ {
|
||||
contents = append(contents,
|
||||
fmt.Sprintf(`{"role":"user","parts":[{"text":"ask %d"}]}`, i),
|
||||
fmt.Sprintf(`{"role":"model","parts":[{"text":"think %d"},{"thoughtSignature":"sig-%d","functionCall":{"id":"c%d","name":"read_file","args":{"path":"a%d.go"}}}]}`, i, i, i, i),
|
||||
fmt.Sprintf(`{"role":"user","parts":[{"functionResponse":{"id":"c%d","name":"read_file","response":{"content":"data %d"}}}]}`, i, i),
|
||||
fmt.Sprintf(`{"role":"model","parts":[{"text":"answer %d"}]}`, i))
|
||||
}
|
||||
return []byte(fmt.Sprintf(
|
||||
`{"contents":[%s],"tools":[{"functionDeclarations":[{"name":"read_file","description":"read a file","parameters":{"type":"object","properties":{"path":{"type":"string"}},"required":["path"]}}]}],"generationConfig":{"temperature":1}}`,
|
||||
strings.Join(contents, ",")))
|
||||
}
|
||||
|
||||
// TestTranslateRequestPairMatchesSeparateTranslations pins the reuse fast path to
|
||||
// the behavior of translating both payloads independently.
|
||||
func TestTranslateRequestPairMatchesSeparateTranslations(t *testing.T) {
|
||||
from := sdktranslator.FormatGemini
|
||||
to := sdktranslator.FromString("antigravity")
|
||||
cfg := &config.Config{}
|
||||
const model = "gemini-3.6-flash-high"
|
||||
|
||||
for _, turns := range []int{0, 1, 5, 20} {
|
||||
payload := geminiToolHistoryPayload(turns)
|
||||
// Same bytes in a different backing array forces the translate-twice branch.
|
||||
detached := append([]byte(nil), payload...)
|
||||
|
||||
want := TranslateRequestWithCodexMultiAgentV2(context.Background(), http.Header{}, cfg, from, to, model, payload, true)
|
||||
|
||||
reuseBase, reuseWork := TranslateRequestPairWithCodexMultiAgentV2(
|
||||
context.Background(), http.Header{}, cfg, from, to, model, payload, payload, true)
|
||||
twiceBase, twiceWork := TranslateRequestPairWithCodexMultiAgentV2(
|
||||
context.Background(), http.Header{}, cfg, from, to, model, payload, detached, true)
|
||||
|
||||
for name, got := range map[string][]byte{
|
||||
"reuse baseline": reuseBase,
|
||||
"reuse working": reuseWork,
|
||||
"twice baseline": twiceBase,
|
||||
"twice working": twiceWork,
|
||||
} {
|
||||
if !bytes.Equal(want, got) {
|
||||
t.Fatalf("turns=%d: %s translation differs from a standalone translation", turns, name)
|
||||
}
|
||||
}
|
||||
|
||||
if len(reuseBase) > 0 && &reuseBase[0] == &reuseWork[0] {
|
||||
t.Fatalf("turns=%d: working copy aliases the baseline; later in-place edits would corrupt it", turns)
|
||||
}
|
||||
|
||||
// The caller mutates the working copy, so the baseline must stay intact.
|
||||
baselineBefore := append([]byte(nil), reuseBase...)
|
||||
reuseWork[0] = 'X'
|
||||
if !bytes.Equal(baselineBefore, reuseBase) {
|
||||
t.Fatalf("turns=%d: mutating the working copy changed the baseline", turns)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestTranslateRequestPairTranslatesDistinctPayloads guards the case where the
|
||||
// executor really does hand over two different requests.
|
||||
func TestTranslateRequestPairTranslatesDistinctPayloads(t *testing.T) {
|
||||
from := sdktranslator.FormatGemini
|
||||
to := sdktranslator.FromString("antigravity")
|
||||
cfg := &config.Config{}
|
||||
const model = "gemini-3.6-flash-high"
|
||||
|
||||
original := geminiToolHistoryPayload(2)
|
||||
request := geminiToolHistoryPayload(4)
|
||||
|
||||
base, work := TranslateRequestPairWithCodexMultiAgentV2(
|
||||
context.Background(), http.Header{}, cfg, from, to, model, original, request, true)
|
||||
|
||||
wantBase := TranslateRequestWithCodexMultiAgentV2(context.Background(), http.Header{}, cfg, from, to, model, original, true)
|
||||
wantWork := TranslateRequestWithCodexMultiAgentV2(context.Background(), http.Header{}, cfg, from, to, model, request, true)
|
||||
|
||||
if !bytes.Equal(wantBase, base) {
|
||||
t.Fatal("baseline translation differs for distinct payloads")
|
||||
}
|
||||
if !bytes.Equal(wantWork, work) {
|
||||
t.Fatal("working translation differs for distinct payloads")
|
||||
}
|
||||
if bytes.Equal(base, work) {
|
||||
t.Fatal("distinct payloads produced identical translations; the reuse path was taken by mistake")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSameByteSlice(t *testing.T) {
|
||||
buf := []byte("payload")
|
||||
cases := []struct {
|
||||
name string
|
||||
a, b []byte
|
||||
want bool
|
||||
}{
|
||||
{"identical slice", buf, buf, true},
|
||||
{"same array same length", buf[:3], buf[:3], true},
|
||||
{"equal bytes different array", buf, append([]byte(nil), buf...), false},
|
||||
{"different length", buf, buf[:3], false},
|
||||
{"both nil", nil, nil, true},
|
||||
{"nil and empty", nil, []byte{}, true},
|
||||
{"nil and non-empty", nil, buf, false},
|
||||
{"offset alias", buf, buf[1:], false},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if got := sameByteSlice(tc.a, tc.b); got != tc.want {
|
||||
t.Fatalf("sameByteSlice() = %v, want %v", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user