Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
69b950d
fix(executor): fix OAuth extra usage detection by Anthropic API
wykk-12138 Apr 8, 2026
613fe67
fix(executor): inject full Claude Code system prompt blocks with prop…
wykk-12138 Apr 9, 2026
f6f4640
fix: use sjson to build system blocks, avoid raw newlines in JSON
wykk-12138 Apr 9, 2026
8783caf
fix: buildTextBlock cache_control sjson path issue
wykk-12138 Apr 9, 2026
9e0ab4d
fix: build cache_control JSON manually to avoid sjson map marshaling
wykk-12138 Apr 9, 2026
e2e3c7d
fix: remove invalid org scope and match Claude Code block layout
wykk-12138 Apr 9, 2026
7cdf8e9
fix(claude): sanitize forwarded third-party prompts for OAuth cloaking
wykk-12138 Apr 9, 2026
f0c20e8
fix(claude): remove invalid cache_control scope from static system block
wykk-12138 Apr 9, 2026
7e8e222
fix(claude): reduce forwarded OAuth prompt to minimal tool reminder
wykk-12138 Apr 9, 2026
e8d1b79
fix(claude): remap OAuth tool names to Claude Code style to avoid thi…
wykk-12138 Apr 9, 2026
cf24958
feat(antigravity): configurable signature cache with bypass-mode vali…
sususu98 Mar 31, 2026
38f0ae5
docs(antigravity): document signature validation spec alignment
sususu98 Mar 31, 2026
30e94b6
fix(antigravity): refine 429 handling and credits fallback
ZTXBOSS666 Apr 9, 2026
39dc455
Merge pull request #2412 from sususu98/feat/signature-cache-toggle
luispater Apr 9, 2026
ac36119
fix(claude): preserve OAuth tool renames when filtering tools
wykk-12138 Apr 9, 2026
f780c28
fix(claude): map question/skill to TitleCase instead of removing them
wykk-12138 Apr 9, 2026
96056d0
Merge remote-tracking branch 'upstream/main' into fix/oauth-extra-usa…
wykk-12138 Apr 9, 2026
0f45d89
fix(claude): address PR review feedback for OAuth cloaking
wykk-12138 Apr 9, 2026
f32c8c9
fix(handlers): update listener to bind on all interfaces instead of l…
luispater Apr 9, 2026
b2c0cdf
Merge pull request #2621 from wykk-12138/fix/oauth-extra-usage-detection
luispater Apr 10, 2026
d801393
feat(antigravity): prefer prod URL as first priority
sususu98 Apr 10, 2026
2a97037
Merge pull request #2670 from sususu98/feat/antigravity-prefer-prod-url
hkfires Apr 10, 2026
65ce863
fix(executor): implement immediate retry with token refresh on 429 fo…
luispater Apr 10, 2026
5ab9afa
fix(executor): handle OAuth tool name remapping with rename detection…
luispater Apr 10, 2026
26c298c
Merge branch 'main' into plus
luispater Apr 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,21 @@ enable-gemini-cli-endpoint: false

# When > 0, emit blank lines every N seconds for non-streaming responses to prevent idle timeouts.
nonstream-keepalive-interval: 0

# Streaming behavior (SSE keep-alives + safe bootstrap retries).
# streaming:
# keepalive-seconds: 15 # Default: 0 (disabled). <= 0 disables keep-alives.
# bootstrap-retries: 1 # Default: 0 (disabled). Retries before first byte is sent.

# Signature cache validation for thinking blocks (Antigravity/Claude).
# When true (default), cached signatures are preferred and validated.
# When false, client signatures are used directly after normalization (bypass mode for testing).
# antigravity-signature-cache-enabled: true

# Bypass mode signature validation strictness (only applies when signature cache is disabled).
# When true, validates full Claude protobuf tree (Field 2 -> Field 1 structure).
# When false (default), only checks R/E prefix + base64 + first byte 0x12.
# antigravity-signature-bypass-strict: false

# Gemini API keys
# gemini-api-key:
# - api-key: "AIzaSy...01"
Expand Down
2 changes: 1 addition & 1 deletion internal/api/handlers/management/auth_files.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func startCallbackForwarder(port int, provider, targetBase string) (*callbackFor
stopForwarderInstance(port, prev)
}

addr := fmt.Sprintf("127.0.0.1:%d", port)
addr := fmt.Sprintf("0.0.0.0:%d", port)
ln, err := net.Listen("tcp", addr)
if err != nil {
return nil, fmt.Errorf("failed to listen on %s: %w", addr, err)
Expand Down
41 changes: 41 additions & 0 deletions internal/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/router-for-me/CLIProxyAPI/v6/internal/api/middleware"
"github.com/router-for-me/CLIProxyAPI/v6/internal/api/modules"
ampmodule "github.com/router-for-me/CLIProxyAPI/v6/internal/api/modules/amp"
"github.com/router-for-me/CLIProxyAPI/v6/internal/cache"
"github.com/router-for-me/CLIProxyAPI/v6/internal/auth/kiro"
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
"github.com/router-for-me/CLIProxyAPI/v6/internal/logging"
Expand Down Expand Up @@ -262,6 +263,7 @@ func NewServer(cfg *config.Config, authManager *auth.Manager, accessManager *sdk
}
managementasset.SetCurrentConfig(cfg)
auth.SetQuotaCooldownDisabled(cfg.DisableCooling)
applySignatureCacheConfig(nil, cfg)
// Initialize management handler
s.mgmt = managementHandlers.NewHandler(cfg, configFilePath, authManager)
if optionState.localPassword != "" {
Expand Down Expand Up @@ -966,6 +968,8 @@ func (s *Server) UpdateClients(cfg *config.Config) {
auth.SetQuotaCooldownDisabled(cfg.DisableCooling)
}

applySignatureCacheConfig(oldCfg, cfg)

if s.handlers != nil && s.handlers.AuthManager != nil {
s.handlers.AuthManager.SetRetryConfig(cfg.RequestRetry, time.Duration(cfg.MaxRetryInterval)*time.Second, cfg.MaxRetryCredentials)
}
Expand Down Expand Up @@ -1104,3 +1108,40 @@ func AuthMiddleware(manager *sdkaccess.Manager) gin.HandlerFunc {
c.AbortWithStatusJSON(statusCode, gin.H{"error": err.Message})
}
}

func configuredSignatureCacheEnabled(cfg *config.Config) bool {
if cfg != nil && cfg.AntigravitySignatureCacheEnabled != nil {
return *cfg.AntigravitySignatureCacheEnabled
}
return true
}

func applySignatureCacheConfig(oldCfg, cfg *config.Config) {
newVal := configuredSignatureCacheEnabled(cfg)
newStrict := configuredSignatureBypassStrict(cfg)
if oldCfg == nil {
cache.SetSignatureCacheEnabled(newVal)
cache.SetSignatureBypassStrictMode(newStrict)
log.Debugf("antigravity_signature_cache_enabled toggled to %t", newVal)
return
}

oldVal := configuredSignatureCacheEnabled(oldCfg)
if oldVal != newVal {
cache.SetSignatureCacheEnabled(newVal)
log.Debugf("antigravity_signature_cache_enabled updated from %t to %t", oldVal, newVal)
}

oldStrict := configuredSignatureBypassStrict(oldCfg)
if oldStrict != newStrict {
cache.SetSignatureBypassStrictMode(newStrict)
log.Debugf("antigravity_signature_bypass_strict updated from %t to %t", oldStrict, newStrict)
}
}

func configuredSignatureBypassStrict(cfg *config.Config) bool {
if cfg != nil && cfg.AntigravitySignatureBypassStrict != nil {
return *cfg.AntigravitySignatureBypassStrict
}
return false
}
39 changes: 39 additions & 0 deletions internal/cache/signature_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import (
"encoding/hex"
"strings"
"sync"
"sync/atomic"
"time"

log "github.com/sirupsen/logrus"
)

// SignatureEntry holds a cached thinking signature with timestamp
Expand Down Expand Up @@ -193,3 +196,39 @@ func GetModelGroup(modelName string) string {
}
return modelName
}

var signatureCacheEnabled atomic.Bool
var signatureBypassStrictMode atomic.Bool

func init() {
signatureCacheEnabled.Store(true)
signatureBypassStrictMode.Store(false)
}

// SetSignatureCacheEnabled switches Antigravity signature handling between cache mode and bypass mode.
func SetSignatureCacheEnabled(enabled bool) {
signatureCacheEnabled.Store(enabled)
if !enabled {
log.Warn("antigravity signature cache DISABLED - bypass mode active, cached signatures will not be used for request translation")
}
}

// SignatureCacheEnabled returns whether signature cache validation is enabled.
func SignatureCacheEnabled() bool {
return signatureCacheEnabled.Load()
}

// SetSignatureBypassStrictMode controls whether bypass mode uses strict protobuf-tree validation.
func SetSignatureBypassStrictMode(strict bool) {
signatureBypassStrictMode.Store(strict)
if strict {
log.Info("antigravity bypass signature validation: strict mode (protobuf tree)")
} else {
log.Info("antigravity bypass signature validation: basic mode (R/E + 0x12)")
}
}

// SignatureBypassStrictMode returns whether bypass mode uses strict protobuf-tree validation.
func SignatureBypassStrictMode() bool {
return signatureBypassStrictMode.Load()
}
7 changes: 7 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ type Config struct {
// WebsocketAuth enables or disables authentication for the WebSocket API.
WebsocketAuth bool `yaml:"ws-auth" json:"ws-auth"`

// AntigravitySignatureCacheEnabled controls whether signature cache validation is enabled for thinking blocks.
// When true (default), cached signatures are preferred and validated.
// When false, client signatures are used directly after normalization (bypass mode).
AntigravitySignatureCacheEnabled *bool `yaml:"antigravity-signature-cache-enabled,omitempty" json:"antigravity-signature-cache-enabled,omitempty"`

AntigravitySignatureBypassStrict *bool `yaml:"antigravity-signature-bypass-strict,omitempty" json:"antigravity-signature-bypass-strict,omitempty"`

// GeminiKey defines Gemini API key configurations with optional routing overrides.
GeminiKey []GeminiKey `yaml:"gemini-api-key" json:"gemini-api-key"`

Expand Down
Loading
Loading