Skip to content

Commit 344043b

Browse files
authored
Merge pull request router-for-me#506 from router-for-me/plus
v6.9.22
2 parents 938af75 + 26c298c commit 344043b

18 files changed

Lines changed: 2887 additions & 356 deletions

config.example.yaml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,21 @@ enable-gemini-cli-endpoint: false
114114

115115
# When > 0, emit blank lines every N seconds for non-streaming responses to prevent idle timeouts.
116116
nonstream-keepalive-interval: 0
117-
118117
# Streaming behavior (SSE keep-alives + safe bootstrap retries).
119118
# streaming:
120119
# keepalive-seconds: 15 # Default: 0 (disabled). <= 0 disables keep-alives.
121120
# bootstrap-retries: 1 # Default: 0 (disabled). Retries before first byte is sent.
122121

122+
# Signature cache validation for thinking blocks (Antigravity/Claude).
123+
# When true (default), cached signatures are preferred and validated.
124+
# When false, client signatures are used directly after normalization (bypass mode for testing).
125+
# antigravity-signature-cache-enabled: true
126+
127+
# Bypass mode signature validation strictness (only applies when signature cache is disabled).
128+
# When true, validates full Claude protobuf tree (Field 2 -> Field 1 structure).
129+
# When false (default), only checks R/E prefix + base64 + first byte 0x12.
130+
# antigravity-signature-bypass-strict: false
131+
123132
# Gemini API keys
124133
# gemini-api-key:
125134
# - api-key: "AIzaSy...01"

internal/api/handlers/management/auth_files.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ func startCallbackForwarder(port int, provider, targetBase string) (*callbackFor
152152
stopForwarderInstance(port, prev)
153153
}
154154

155-
addr := fmt.Sprintf("127.0.0.1:%d", port)
155+
addr := fmt.Sprintf("0.0.0.0:%d", port)
156156
ln, err := net.Listen("tcp", addr)
157157
if err != nil {
158158
return nil, fmt.Errorf("failed to listen on %s: %w", addr, err)

internal/api/server.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/router-for-me/CLIProxyAPI/v6/internal/api/middleware"
2525
"github.com/router-for-me/CLIProxyAPI/v6/internal/api/modules"
2626
ampmodule "github.com/router-for-me/CLIProxyAPI/v6/internal/api/modules/amp"
27+
"github.com/router-for-me/CLIProxyAPI/v6/internal/cache"
2728
"github.com/router-for-me/CLIProxyAPI/v6/internal/auth/kiro"
2829
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
2930
"github.com/router-for-me/CLIProxyAPI/v6/internal/logging"
@@ -262,6 +263,7 @@ func NewServer(cfg *config.Config, authManager *auth.Manager, accessManager *sdk
262263
}
263264
managementasset.SetCurrentConfig(cfg)
264265
auth.SetQuotaCooldownDisabled(cfg.DisableCooling)
266+
applySignatureCacheConfig(nil, cfg)
265267
// Initialize management handler
266268
s.mgmt = managementHandlers.NewHandler(cfg, configFilePath, authManager)
267269
if optionState.localPassword != "" {
@@ -966,6 +968,8 @@ func (s *Server) UpdateClients(cfg *config.Config) {
966968
auth.SetQuotaCooldownDisabled(cfg.DisableCooling)
967969
}
968970

971+
applySignatureCacheConfig(oldCfg, cfg)
972+
969973
if s.handlers != nil && s.handlers.AuthManager != nil {
970974
s.handlers.AuthManager.SetRetryConfig(cfg.RequestRetry, time.Duration(cfg.MaxRetryInterval)*time.Second, cfg.MaxRetryCredentials)
971975
}
@@ -1104,3 +1108,40 @@ func AuthMiddleware(manager *sdkaccess.Manager) gin.HandlerFunc {
11041108
c.AbortWithStatusJSON(statusCode, gin.H{"error": err.Message})
11051109
}
11061110
}
1111+
1112+
func configuredSignatureCacheEnabled(cfg *config.Config) bool {
1113+
if cfg != nil && cfg.AntigravitySignatureCacheEnabled != nil {
1114+
return *cfg.AntigravitySignatureCacheEnabled
1115+
}
1116+
return true
1117+
}
1118+
1119+
func applySignatureCacheConfig(oldCfg, cfg *config.Config) {
1120+
newVal := configuredSignatureCacheEnabled(cfg)
1121+
newStrict := configuredSignatureBypassStrict(cfg)
1122+
if oldCfg == nil {
1123+
cache.SetSignatureCacheEnabled(newVal)
1124+
cache.SetSignatureBypassStrictMode(newStrict)
1125+
log.Debugf("antigravity_signature_cache_enabled toggled to %t", newVal)
1126+
return
1127+
}
1128+
1129+
oldVal := configuredSignatureCacheEnabled(oldCfg)
1130+
if oldVal != newVal {
1131+
cache.SetSignatureCacheEnabled(newVal)
1132+
log.Debugf("antigravity_signature_cache_enabled updated from %t to %t", oldVal, newVal)
1133+
}
1134+
1135+
oldStrict := configuredSignatureBypassStrict(oldCfg)
1136+
if oldStrict != newStrict {
1137+
cache.SetSignatureBypassStrictMode(newStrict)
1138+
log.Debugf("antigravity_signature_bypass_strict updated from %t to %t", oldStrict, newStrict)
1139+
}
1140+
}
1141+
1142+
func configuredSignatureBypassStrict(cfg *config.Config) bool {
1143+
if cfg != nil && cfg.AntigravitySignatureBypassStrict != nil {
1144+
return *cfg.AntigravitySignatureBypassStrict
1145+
}
1146+
return false
1147+
}

internal/cache/signature_cache.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import (
55
"encoding/hex"
66
"strings"
77
"sync"
8+
"sync/atomic"
89
"time"
10+
11+
log "github.com/sirupsen/logrus"
912
)
1013

1114
// SignatureEntry holds a cached thinking signature with timestamp
@@ -193,3 +196,39 @@ func GetModelGroup(modelName string) string {
193196
}
194197
return modelName
195198
}
199+
200+
var signatureCacheEnabled atomic.Bool
201+
var signatureBypassStrictMode atomic.Bool
202+
203+
func init() {
204+
signatureCacheEnabled.Store(true)
205+
signatureBypassStrictMode.Store(false)
206+
}
207+
208+
// SetSignatureCacheEnabled switches Antigravity signature handling between cache mode and bypass mode.
209+
func SetSignatureCacheEnabled(enabled bool) {
210+
signatureCacheEnabled.Store(enabled)
211+
if !enabled {
212+
log.Warn("antigravity signature cache DISABLED - bypass mode active, cached signatures will not be used for request translation")
213+
}
214+
}
215+
216+
// SignatureCacheEnabled returns whether signature cache validation is enabled.
217+
func SignatureCacheEnabled() bool {
218+
return signatureCacheEnabled.Load()
219+
}
220+
221+
// SetSignatureBypassStrictMode controls whether bypass mode uses strict protobuf-tree validation.
222+
func SetSignatureBypassStrictMode(strict bool) {
223+
signatureBypassStrictMode.Store(strict)
224+
if strict {
225+
log.Info("antigravity bypass signature validation: strict mode (protobuf tree)")
226+
} else {
227+
log.Info("antigravity bypass signature validation: basic mode (R/E + 0x12)")
228+
}
229+
}
230+
231+
// SignatureBypassStrictMode returns whether bypass mode uses strict protobuf-tree validation.
232+
func SignatureBypassStrictMode() bool {
233+
return signatureBypassStrictMode.Load()
234+
}

internal/config/config.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ type Config struct {
8585
// WebsocketAuth enables or disables authentication for the WebSocket API.
8686
WebsocketAuth bool `yaml:"ws-auth" json:"ws-auth"`
8787

88+
// AntigravitySignatureCacheEnabled controls whether signature cache validation is enabled for thinking blocks.
89+
// When true (default), cached signatures are preferred and validated.
90+
// When false, client signatures are used directly after normalization (bypass mode).
91+
AntigravitySignatureCacheEnabled *bool `yaml:"antigravity-signature-cache-enabled,omitempty" json:"antigravity-signature-cache-enabled,omitempty"`
92+
93+
AntigravitySignatureBypassStrict *bool `yaml:"antigravity-signature-bypass-strict,omitempty" json:"antigravity-signature-bypass-strict,omitempty"`
94+
8895
// GeminiKey defines Gemini API key configurations with optional routing overrides.
8996
GeminiKey []GeminiKey `yaml:"gemini-api-key" json:"gemini-api-key"`
9097

0 commit comments

Comments
 (0)