History

Merge branch 'router-for-me:main' into main

Luis Pater committed 10 months agov6.6.59-0

Commit d35152b2 parents 60936b5 c281f4c3 files · +23 −20Browse files

Unified · Split

3 files
  1. internal/runtime/executor/usage_helpers.go +6 −2
  2. internal/translator/antigravity/claude/antigravity_claude_response.go +8 −0
  3. sdk/cliproxy/auth/conductor.go +9 −18
internal/runtime/executor/usage_helpers.go+6−2
@@ -482,12 +482,16 @@ func StripUsageMetadataFromJSON(rawJSON []byte) ([]byte, bool) { · 481 unmodified lines
482482 cleaned := jsonBytes
483483 var changed bool
484484
485− if gjson.GetBytes(cleaned, "usageMetadata").Exists() {
485+ if usageMetadata = gjson.GetBytes(cleaned, "usageMetadata"); usageMetadata.Exists() {
486+ // Rename usageMetadata to cpaUsageMetadata in the message_start event of Claude
487+ cleaned, _ = sjson.SetRawBytes(cleaned, "cpaUsageMetadata", []byte(usageMetadata.Raw))
486488 cleaned, _ = sjson.DeleteBytes(cleaned, "usageMetadata")
487489 changed = true
488490 }
489491
490− if gjson.GetBytes(cleaned, "response.usageMetadata").Exists() {
492+ if usageMetadata = gjson.GetBytes(cleaned, "response.usageMetadata"); usageMetadata.Exists() {
493+ // Rename usageMetadata to cpaUsageMetadata in the message_start event of Claude
494+ cleaned, _ = sjson.SetRawBytes(cleaned, "response.cpaUsageMetadata", []byte(usageMetadata.Raw))
491495 cleaned, _ = sjson.DeleteBytes(cleaned, "response.usageMetadata")
492496 changed = true
493497 }
internal/translator/antigravity/claude/antigravity_claude_response.go+8−0
@@ -99,6 +99,14 @@ func ConvertAntigravityResponseToClaude(_ context.Context, _ string, originalReq · 98 unmodified lines
9999 // This follows the Claude Code API specification for streaming message initialization
100100 messageStartTemplate := `{"type": "message_start", "message": {"id": "msg_1nZdL29xx5MUA1yADyHTEsnR8uuvGzszyY", "type": "message", "role": "assistant", "content": [], "model": "claude-3-5-sonnet-20241022", "stop_reason": null, "stop_sequence": null, "usage": {"input_tokens": 0, "output_tokens": 0}}}`
101101
102+ // Use cpaUsageMetadata within the message_start event for Claude.
103+ if promptTokenCount := gjson.GetBytes(rawJSON, "response.cpaUsageMetadata.promptTokenCount"); promptTokenCount.Exists() {
104+ messageStartTemplate, _ = sjson.Set(messageStartTemplate, "message.usage.input_tokens", promptTokenCount.Int())
105+ }
106+ if candidatesTokenCount := gjson.GetBytes(rawJSON, "response.cpaUsageMetadata.candidatesTokenCount"); candidatesTokenCount.Exists() {
107+ messageStartTemplate, _ = sjson.Set(messageStartTemplate, "message.usage.output_tokens", candidatesTokenCount.Int())
108+ }
109+
102110 // Override default values with actual response metadata if available from the Gemini CLI response
103111 if modelVersionResult := gjson.GetBytes(rawJSON, "response.modelVersion"); modelVersionResult.Exists() {
104112 messageStartTemplate, _ = sjson.Set(messageStartTemplate, "message.model", modelVersionResult.String())
sdk/cliproxy/auth/conductor.go+9−18
@@ -263,7 +263,6 @@ func (m *Manager) Execute(ctx context.Context, providers []string, req cliproxye · 262 unmodified lines
263263 return cliproxyexecutor.Response{}, &Error{Code: "provider_not_found", Message: "no provider supplied"}
264264 }
265265 rotated := m.rotateProviders(req.Model, normalized)
266− defer m.advanceProviderCursor(req.Model, normalized)
267266
268267 retryTimes, maxWait := m.retrySettings()
269268 attempts := retryTimes + 1
@@ -302,7 +301,6 @@ func (m *Manager) ExecuteCount(ctx context.Context, providers []string, req clip · 32 unmodified lines
302301 return cliproxyexecutor.Response{}, &Error{Code: "provider_not_found", Message: "no provider supplied"}
303302 }
304303 rotated := m.rotateProviders(req.Model, normalized)
305− defer m.advanceProviderCursor(req.Model, normalized)
306304
307305 retryTimes, maxWait := m.retrySettings()
308306 attempts := retryTimes + 1
@@ -341,7 +339,6 @@ func (m *Manager) ExecuteStream(ctx context.Context, providers []string, req cli · 32 unmodified lines
341339 return nil, &Error{Code: "provider_not_found", Message: "no provider supplied"}
342340 }
343341 rotated := m.rotateProviders(req.Model, normalized)
344− defer m.advanceProviderCursor(req.Model, normalized)
345342
346343 retryTimes, maxWait := m.retrySettings()
347344 attempts := retryTimes + 1
@@ -640,13 +637,20 @@ func (m *Manager) normalizeProviders(providers []string) []string { · 292 unmodified lines
640637 return result
641638 }
642639
640+// rotateProviders returns a rotated view of the providers list starting from the
641+// current offset for the model, and atomically increments the offset for the next call.
642+// This ensures concurrent requests get different starting providers.
643643 func (m *Manager) rotateProviders(model string, providers []string) []string {
644644 if len(providers) == 0 {
645645 return nil
646646 }
647− m.mu.RLock()
647+
648+ // Atomic read-and-increment: get current offset and advance cursor in one lock
649+ m.mu.Lock()
648650 offset := m.providerOffsets[model]
649− m.mu.RUnlock()
651+ m.providerOffsets[model] = (offset + 1) % len(providers)
652+ m.mu.Unlock()
653+
650654 if len(providers) > 0 {
651655 offset %= len(providers)
652656 }
@@ -662,19 +666,6 @@ func (m *Manager) rotateProviders(model string, providers []string) []string { · 9 unmodified lines
662666 return rotated
663667 }
664668
665−func (m *Manager) advanceProviderCursor(model string, providers []string) {
666− if len(providers) == 0 {
667− m.mu.Lock()
668− delete(m.providerOffsets, model)
669− m.mu.Unlock()
670− return
671− }
672− m.mu.Lock()
673− current := m.providerOffsets[model]
674− m.providerOffsets[model] = (current + 1) % len(providers)
675− m.mu.Unlock()
676−}
677−
678669 func (m *Manager) retrySettings() (int, time.Duration) {
679670 if m == nil {
680671 return 0, 0