antigravity-auth 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/README.md +79 -41
  2. package/dist/cli.js +2868 -0
  3. package/dist/handler.js +25119 -0
  4. package/dist/index.js +25110 -5
  5. package/package.json +66 -54
  6. package/dist/antigravity/oauth.d.ts +0 -30
  7. package/dist/antigravity/oauth.js +0 -170
  8. package/dist/claude/login.d.ts +0 -7
  9. package/dist/claude/login.js +0 -480
  10. package/dist/claude/menu-helpers.d.ts +0 -22
  11. package/dist/claude/menu-helpers.js +0 -281
  12. package/dist/claude/proxy-manager.d.ts +0 -11
  13. package/dist/claude/proxy-manager.js +0 -129
  14. package/dist/claude/proxy.d.ts +0 -1
  15. package/dist/claude/proxy.js +0 -733
  16. package/dist/constants.d.ts +0 -138
  17. package/dist/constants.js +0 -216
  18. package/dist/hooks/auto-update-checker/cache.d.ts +0 -2
  19. package/dist/hooks/auto-update-checker/cache.js +0 -70
  20. package/dist/hooks/auto-update-checker/checker.d.ts +0 -15
  21. package/dist/hooks/auto-update-checker/checker.js +0 -233
  22. package/dist/hooks/auto-update-checker/constants.d.ts +0 -8
  23. package/dist/hooks/auto-update-checker/constants.js +0 -22
  24. package/dist/hooks/auto-update-checker/index.d.ts +0 -33
  25. package/dist/hooks/auto-update-checker/index.js +0 -121
  26. package/dist/hooks/auto-update-checker/logging.d.ts +0 -2
  27. package/dist/hooks/auto-update-checker/logging.js +0 -8
  28. package/dist/hooks/auto-update-checker/types.d.ts +0 -24
  29. package/dist/hooks/auto-update-checker/types.js +0 -1
  30. package/dist/index.d.ts +0 -6
  31. package/dist/opencode/hooks/auto-update-checker/cache.d.ts +0 -2
  32. package/dist/opencode/hooks/auto-update-checker/cache.js +0 -70
  33. package/dist/opencode/hooks/auto-update-checker/checker.d.ts +0 -15
  34. package/dist/opencode/hooks/auto-update-checker/checker.js +0 -233
  35. package/dist/opencode/hooks/auto-update-checker/constants.d.ts +0 -8
  36. package/dist/opencode/hooks/auto-update-checker/constants.js +0 -22
  37. package/dist/opencode/hooks/auto-update-checker/index.d.ts +0 -33
  38. package/dist/opencode/hooks/auto-update-checker/index.js +0 -121
  39. package/dist/opencode/hooks/auto-update-checker/logging.d.ts +0 -2
  40. package/dist/opencode/hooks/auto-update-checker/logging.js +0 -8
  41. package/dist/opencode/hooks/auto-update-checker/types.d.ts +0 -24
  42. package/dist/opencode/hooks/auto-update-checker/types.js +0 -1
  43. package/dist/opencode/plugin.d.ts +0 -29
  44. package/dist/opencode/plugin.js +0 -2954
  45. package/dist/plugin/accounts.d.ts +0 -173
  46. package/dist/plugin/accounts.js +0 -966
  47. package/dist/plugin/auth.d.ts +0 -20
  48. package/dist/plugin/auth.js +0 -44
  49. package/dist/plugin/cache/index.d.ts +0 -4
  50. package/dist/plugin/cache/index.js +0 -4
  51. package/dist/plugin/cache/signature-cache.d.ts +0 -110
  52. package/dist/plugin/cache/signature-cache.js +0 -347
  53. package/dist/plugin/cache.d.ts +0 -43
  54. package/dist/plugin/cache.js +0 -180
  55. package/dist/plugin/cli.d.ts +0 -26
  56. package/dist/plugin/cli.js +0 -126
  57. package/dist/plugin/config/index.d.ts +0 -15
  58. package/dist/plugin/config/index.js +0 -15
  59. package/dist/plugin/config/loader.d.ts +0 -38
  60. package/dist/plugin/config/loader.js +0 -150
  61. package/dist/plugin/config/models.d.ts +0 -26
  62. package/dist/plugin/config/models.js +0 -95
  63. package/dist/plugin/config/schema.d.ts +0 -144
  64. package/dist/plugin/config/schema.js +0 -458
  65. package/dist/plugin/config/updater.d.ts +0 -76
  66. package/dist/plugin/config/updater.js +0 -205
  67. package/dist/plugin/core/streaming/index.d.ts +0 -2
  68. package/dist/plugin/core/streaming/index.js +0 -2
  69. package/dist/plugin/core/streaming/transformer.d.ts +0 -9
  70. package/dist/plugin/core/streaming/transformer.js +0 -301
  71. package/dist/plugin/core/streaming/types.d.ts +0 -28
  72. package/dist/plugin/core/streaming/types.js +0 -1
  73. package/dist/plugin/debug.d.ts +0 -93
  74. package/dist/plugin/debug.js +0 -375
  75. package/dist/plugin/errors.d.ts +0 -27
  76. package/dist/plugin/errors.js +0 -41
  77. package/dist/plugin/fingerprint.d.ts +0 -69
  78. package/dist/plugin/fingerprint.js +0 -137
  79. package/dist/plugin/image-saver.d.ts +0 -24
  80. package/dist/plugin/image-saver.js +0 -78
  81. package/dist/plugin/logger.d.ts +0 -35
  82. package/dist/plugin/logger.js +0 -67
  83. package/dist/plugin/logging-utils.d.ts +0 -22
  84. package/dist/plugin/logging-utils.js +0 -91
  85. package/dist/plugin/project.d.ts +0 -32
  86. package/dist/plugin/project.js +0 -229
  87. package/dist/plugin/quota.d.ts +0 -34
  88. package/dist/plugin/quota.js +0 -261
  89. package/dist/plugin/recovery/constants.d.ts +0 -21
  90. package/dist/plugin/recovery/constants.js +0 -42
  91. package/dist/plugin/recovery/index.d.ts +0 -11
  92. package/dist/plugin/recovery/index.js +0 -11
  93. package/dist/plugin/recovery/storage.d.ts +0 -23
  94. package/dist/plugin/recovery/storage.js +0 -340
  95. package/dist/plugin/recovery/types.d.ts +0 -115
  96. package/dist/plugin/recovery/types.js +0 -6
  97. package/dist/plugin/recovery.d.ts +0 -60
  98. package/dist/plugin/recovery.js +0 -360
  99. package/dist/plugin/refresh-queue.d.ts +0 -99
  100. package/dist/plugin/refresh-queue.js +0 -235
  101. package/dist/plugin/request-helpers.d.ts +0 -281
  102. package/dist/plugin/request-helpers.js +0 -2200
  103. package/dist/plugin/request.d.ts +0 -110
  104. package/dist/plugin/request.js +0 -1489
  105. package/dist/plugin/rotation.d.ts +0 -182
  106. package/dist/plugin/rotation.js +0 -364
  107. package/dist/plugin/search.d.ts +0 -31
  108. package/dist/plugin/search.js +0 -185
  109. package/dist/plugin/server.d.ts +0 -22
  110. package/dist/plugin/server.js +0 -306
  111. package/dist/plugin/storage.d.ts +0 -136
  112. package/dist/plugin/storage.js +0 -599
  113. package/dist/plugin/stores/signature-store.d.ts +0 -4
  114. package/dist/plugin/stores/signature-store.js +0 -24
  115. package/dist/plugin/thinking-recovery.d.ts +0 -89
  116. package/dist/plugin/thinking-recovery.js +0 -289
  117. package/dist/plugin/token.d.ts +0 -18
  118. package/dist/plugin/token.js +0 -127
  119. package/dist/plugin/transform/claude.d.ts +0 -79
  120. package/dist/plugin/transform/claude.js +0 -256
  121. package/dist/plugin/transform/cross-model-sanitizer.d.ts +0 -34
  122. package/dist/plugin/transform/cross-model-sanitizer.js +0 -224
  123. package/dist/plugin/transform/gemini.d.ts +0 -132
  124. package/dist/plugin/transform/gemini.js +0 -659
  125. package/dist/plugin/transform/index.d.ts +0 -14
  126. package/dist/plugin/transform/index.js +0 -9
  127. package/dist/plugin/transform/model-resolver.d.ts +0 -98
  128. package/dist/plugin/transform/model-resolver.js +0 -320
  129. package/dist/plugin/transform/types.d.ts +0 -110
  130. package/dist/plugin/transform/types.js +0 -1
  131. package/dist/plugin/types.d.ts +0 -95
  132. package/dist/plugin/types.js +0 -1
  133. package/dist/plugin/ui/ansi.d.ts +0 -31
  134. package/dist/plugin/ui/ansi.js +0 -45
  135. package/dist/plugin/ui/auth-menu.d.ts +0 -47
  136. package/dist/plugin/ui/auth-menu.js +0 -199
  137. package/dist/plugin/ui/confirm.d.ts +0 -1
  138. package/dist/plugin/ui/confirm.js +0 -14
  139. package/dist/plugin/ui/select.d.ts +0 -22
  140. package/dist/plugin/ui/select.js +0 -243
  141. package/dist/plugin/version.d.ts +0 -18
  142. package/dist/plugin/version.js +0 -79
  143. package/dist/src/antigravity/oauth.d.ts +0 -30
  144. package/dist/src/antigravity/oauth.js +0 -170
  145. package/dist/src/constants.d.ts +0 -138
  146. package/dist/src/constants.js +0 -216
  147. package/dist/src/hooks/auto-update-checker/cache.d.ts +0 -2
  148. package/dist/src/hooks/auto-update-checker/cache.js +0 -70
  149. package/dist/src/hooks/auto-update-checker/checker.d.ts +0 -15
  150. package/dist/src/hooks/auto-update-checker/checker.js +0 -233
  151. package/dist/src/hooks/auto-update-checker/constants.d.ts +0 -8
  152. package/dist/src/hooks/auto-update-checker/constants.js +0 -22
  153. package/dist/src/hooks/auto-update-checker/index.d.ts +0 -33
  154. package/dist/src/hooks/auto-update-checker/index.js +0 -121
  155. package/dist/src/hooks/auto-update-checker/logging.d.ts +0 -2
  156. package/dist/src/hooks/auto-update-checker/logging.js +0 -8
  157. package/dist/src/hooks/auto-update-checker/types.d.ts +0 -24
  158. package/dist/src/hooks/auto-update-checker/types.js +0 -1
  159. package/dist/src/index.d.ts +0 -6
  160. package/dist/src/index.js +0 -5
  161. package/dist/src/plugin/accounts.d.ts +0 -173
  162. package/dist/src/plugin/accounts.js +0 -966
  163. package/dist/src/plugin/auth.d.ts +0 -20
  164. package/dist/src/plugin/auth.js +0 -44
  165. package/dist/src/plugin/cache/index.d.ts +0 -4
  166. package/dist/src/plugin/cache/index.js +0 -4
  167. package/dist/src/plugin/cache/signature-cache.d.ts +0 -110
  168. package/dist/src/plugin/cache/signature-cache.js +0 -347
  169. package/dist/src/plugin/cache.d.ts +0 -43
  170. package/dist/src/plugin/cache.js +0 -180
  171. package/dist/src/plugin/cli.d.ts +0 -26
  172. package/dist/src/plugin/cli.js +0 -126
  173. package/dist/src/plugin/config/index.d.ts +0 -15
  174. package/dist/src/plugin/config/index.js +0 -15
  175. package/dist/src/plugin/config/loader.d.ts +0 -38
  176. package/dist/src/plugin/config/loader.js +0 -150
  177. package/dist/src/plugin/config/models.d.ts +0 -26
  178. package/dist/src/plugin/config/models.js +0 -95
  179. package/dist/src/plugin/config/schema.d.ts +0 -144
  180. package/dist/src/plugin/config/schema.js +0 -458
  181. package/dist/src/plugin/config/updater.d.ts +0 -76
  182. package/dist/src/plugin/config/updater.js +0 -205
  183. package/dist/src/plugin/core/streaming/index.d.ts +0 -2
  184. package/dist/src/plugin/core/streaming/index.js +0 -2
  185. package/dist/src/plugin/core/streaming/transformer.d.ts +0 -9
  186. package/dist/src/plugin/core/streaming/transformer.js +0 -301
  187. package/dist/src/plugin/core/streaming/types.d.ts +0 -28
  188. package/dist/src/plugin/core/streaming/types.js +0 -1
  189. package/dist/src/plugin/debug.d.ts +0 -93
  190. package/dist/src/plugin/debug.js +0 -375
  191. package/dist/src/plugin/errors.d.ts +0 -27
  192. package/dist/src/plugin/errors.js +0 -41
  193. package/dist/src/plugin/fingerprint.d.ts +0 -69
  194. package/dist/src/plugin/fingerprint.js +0 -137
  195. package/dist/src/plugin/image-saver.d.ts +0 -24
  196. package/dist/src/plugin/image-saver.js +0 -78
  197. package/dist/src/plugin/logger.d.ts +0 -35
  198. package/dist/src/plugin/logger.js +0 -67
  199. package/dist/src/plugin/logging-utils.d.ts +0 -22
  200. package/dist/src/plugin/logging-utils.js +0 -91
  201. package/dist/src/plugin/project.d.ts +0 -32
  202. package/dist/src/plugin/project.js +0 -229
  203. package/dist/src/plugin/quota.d.ts +0 -34
  204. package/dist/src/plugin/quota.js +0 -261
  205. package/dist/src/plugin/recovery/constants.d.ts +0 -21
  206. package/dist/src/plugin/recovery/constants.js +0 -42
  207. package/dist/src/plugin/recovery/index.d.ts +0 -11
  208. package/dist/src/plugin/recovery/index.js +0 -11
  209. package/dist/src/plugin/recovery/storage.d.ts +0 -23
  210. package/dist/src/plugin/recovery/storage.js +0 -340
  211. package/dist/src/plugin/recovery/types.d.ts +0 -115
  212. package/dist/src/plugin/recovery/types.js +0 -6
  213. package/dist/src/plugin/recovery.d.ts +0 -60
  214. package/dist/src/plugin/recovery.js +0 -360
  215. package/dist/src/plugin/refresh-queue.d.ts +0 -99
  216. package/dist/src/plugin/refresh-queue.js +0 -235
  217. package/dist/src/plugin/request-helpers.d.ts +0 -281
  218. package/dist/src/plugin/request-helpers.js +0 -2200
  219. package/dist/src/plugin/request.d.ts +0 -110
  220. package/dist/src/plugin/request.js +0 -1489
  221. package/dist/src/plugin/rotation.d.ts +0 -182
  222. package/dist/src/plugin/rotation.js +0 -364
  223. package/dist/src/plugin/search.d.ts +0 -31
  224. package/dist/src/plugin/search.js +0 -185
  225. package/dist/src/plugin/server.d.ts +0 -22
  226. package/dist/src/plugin/server.js +0 -306
  227. package/dist/src/plugin/storage.d.ts +0 -136
  228. package/dist/src/plugin/storage.js +0 -599
  229. package/dist/src/plugin/stores/signature-store.d.ts +0 -4
  230. package/dist/src/plugin/stores/signature-store.js +0 -24
  231. package/dist/src/plugin/thinking-recovery.d.ts +0 -89
  232. package/dist/src/plugin/thinking-recovery.js +0 -289
  233. package/dist/src/plugin/token.d.ts +0 -18
  234. package/dist/src/plugin/token.js +0 -127
  235. package/dist/src/plugin/transform/claude.d.ts +0 -79
  236. package/dist/src/plugin/transform/claude.js +0 -256
  237. package/dist/src/plugin/transform/cross-model-sanitizer.d.ts +0 -34
  238. package/dist/src/plugin/transform/cross-model-sanitizer.js +0 -224
  239. package/dist/src/plugin/transform/gemini.d.ts +0 -132
  240. package/dist/src/plugin/transform/gemini.js +0 -659
  241. package/dist/src/plugin/transform/index.d.ts +0 -14
  242. package/dist/src/plugin/transform/index.js +0 -9
  243. package/dist/src/plugin/transform/model-resolver.d.ts +0 -98
  244. package/dist/src/plugin/transform/model-resolver.js +0 -320
  245. package/dist/src/plugin/transform/types.d.ts +0 -110
  246. package/dist/src/plugin/transform/types.js +0 -1
  247. package/dist/src/plugin/types.d.ts +0 -95
  248. package/dist/src/plugin/types.js +0 -1
  249. package/dist/src/plugin/ui/ansi.d.ts +0 -31
  250. package/dist/src/plugin/ui/ansi.js +0 -45
  251. package/dist/src/plugin/ui/auth-menu.d.ts +0 -47
  252. package/dist/src/plugin/ui/auth-menu.js +0 -199
  253. package/dist/src/plugin/ui/confirm.d.ts +0 -1
  254. package/dist/src/plugin/ui/confirm.js +0 -14
  255. package/dist/src/plugin/ui/select.d.ts +0 -22
  256. package/dist/src/plugin/ui/select.js +0 -243
  257. package/dist/src/plugin/version.d.ts +0 -18
  258. package/dist/src/plugin/version.js +0 -79
@@ -1,182 +0,0 @@
1
- /**
2
- * Account Rotation System
3
- *
4
- * Implements advanced account selection algorithms:
5
- * - Health Score: Track account wellness based on success/failure
6
- * - LRU Selection: Prefer accounts with longest rest periods
7
- * - Jitter: Add random variance to break predictable patterns
8
- *
9
- * Used by 'hybrid' strategy for improved ban prevention and load distribution.
10
- */
11
- export interface HealthScoreConfig {
12
- /** Initial score for new accounts (default: 70) */
13
- initial: number;
14
- /** Points added on successful request (default: 1) */
15
- successReward: number;
16
- /** Points removed on rate limit (default: -10) */
17
- rateLimitPenalty: number;
18
- /** Points removed on failure (auth, network, etc.) (default: -20) */
19
- failurePenalty: number;
20
- /** Points recovered per hour of rest (default: 2) */
21
- recoveryRatePerHour: number;
22
- /** Minimum score to be considered usable (default: 50) */
23
- minUsable: number;
24
- /** Maximum score cap (default: 100) */
25
- maxScore: number;
26
- }
27
- export declare const DEFAULT_HEALTH_SCORE_CONFIG: HealthScoreConfig;
28
- /**
29
- * Tracks health scores for accounts.
30
- * Higher score = healthier account = preferred for selection.
31
- */
32
- export declare class HealthScoreTracker {
33
- private readonly scores;
34
- private readonly config;
35
- constructor(config?: Partial<HealthScoreConfig>);
36
- /**
37
- * Get current health score for an account, applying time-based recovery.
38
- */
39
- getScore(accountIndex: number): number;
40
- /**
41
- * Record a successful request - improves health score.
42
- */
43
- recordSuccess(accountIndex: number): void;
44
- /**
45
- * Record a rate limit hit - moderate penalty.
46
- */
47
- recordRateLimit(accountIndex: number): void;
48
- /**
49
- * Record a failure (auth, network, etc.) - larger penalty.
50
- */
51
- recordFailure(accountIndex: number): void;
52
- /**
53
- * Check if account is healthy enough to use.
54
- */
55
- isUsable(accountIndex: number): boolean;
56
- /**
57
- * Get consecutive failure count for an account.
58
- */
59
- getConsecutiveFailures(accountIndex: number): number;
60
- /**
61
- * Reset health state for an account (e.g., after removal).
62
- */
63
- reset(accountIndex: number): void;
64
- /**
65
- * Get all scores for debugging/logging.
66
- */
67
- getSnapshot(): Map<number, {
68
- score: number;
69
- consecutiveFailures: number;
70
- }>;
71
- }
72
- /**
73
- * Add random jitter to a delay value.
74
- * Helps break predictable timing patterns.
75
- *
76
- * @param baseMs - Base delay in milliseconds
77
- * @param jitterFactor - Fraction of base to vary (default: 0.3 = ±30%)
78
- * @returns Jittered delay in milliseconds
79
- */
80
- export declare function addJitter(baseMs: number, jitterFactor?: number): number;
81
- /**
82
- * Generate a random delay within a range.
83
- *
84
- * @param minMs - Minimum delay in milliseconds
85
- * @param maxMs - Maximum delay in milliseconds
86
- * @returns Random delay between min and max
87
- */
88
- export declare function randomDelay(minMs: number, maxMs: number): number;
89
- export interface AccountWithMetrics {
90
- index: number;
91
- lastUsed: number;
92
- healthScore: number;
93
- isRateLimited: boolean;
94
- isCoolingDown: boolean;
95
- }
96
- /**
97
- * Sort accounts by LRU (least recently used first) with health score tiebreaker.
98
- *
99
- * Priority:
100
- * 1. Filter out rate-limited and cooling-down accounts
101
- * 2. Filter out unhealthy accounts (score < minUsable)
102
- * 3. Sort by lastUsed ascending (oldest first = most rested)
103
- * 4. Tiebreaker: higher health score wins
104
- */
105
- export declare function sortByLruWithHealth(accounts: AccountWithMetrics[], minHealthScore?: number): AccountWithMetrics[];
106
- /**
107
- * Select account using hybrid strategy with stickiness:
108
- * 1. Filter available accounts (not rate-limited, not cooling down, healthy, has tokens)
109
- * 2. Calculate priority score: health (2x) + tokens (5x) + freshness (0.1x)
110
- * 3. Apply stickiness bonus to current account
111
- * 4. Only switch if another account beats current by SWITCH_THRESHOLD
112
- *
113
- * @param accounts - All accounts with their metrics
114
- * @param tokenTracker - Token bucket tracker for token balances
115
- * @param currentAccountIndex - Currently active account index (for stickiness)
116
- * @param minHealthScore - Minimum health score to be considered
117
- * @returns Best account index, or null if none available
118
- */
119
- export declare function selectHybridAccount(accounts: AccountWithMetrics[], tokenTracker: TokenBucketTracker, currentAccountIndex?: number | null, minHealthScore?: number): number | null;
120
- export interface TokenBucketConfig {
121
- /** Maximum tokens per account (default: 50) */
122
- maxTokens: number;
123
- /** Tokens regenerated per minute (default: 6) */
124
- regenerationRatePerMinute: number;
125
- /** Initial tokens for new accounts (default: 50) */
126
- initialTokens: number;
127
- }
128
- export declare const DEFAULT_TOKEN_BUCKET_CONFIG: TokenBucketConfig;
129
- /**
130
- * Client-side rate limiting using Token Bucket algorithm.
131
- * Helps prevent hitting server 429s by tracking "cost" of requests.
132
- */
133
- export declare class TokenBucketTracker {
134
- private readonly buckets;
135
- private readonly config;
136
- constructor(config?: Partial<TokenBucketConfig>);
137
- /**
138
- * Get current token balance for an account, applying regeneration.
139
- */
140
- getTokens(accountIndex: number): number;
141
- /**
142
- * Check if account has enough tokens for a request.
143
- * @param cost Cost of the request (default: 1)
144
- */
145
- hasTokens(accountIndex: number, cost?: number): boolean;
146
- /**
147
- * Consume tokens for a request.
148
- * @returns true if tokens were consumed, false if insufficient
149
- */
150
- consume(accountIndex: number, cost?: number): boolean;
151
- /**
152
- * Refund tokens (e.g., if request wasn't actually sent).
153
- */
154
- refund(accountIndex: number, amount?: number): void;
155
- getMaxTokens(): number;
156
- }
157
- export declare function getTokenTracker(): TokenBucketTracker;
158
- export declare function initTokenTracker(config: Partial<TokenBucketConfig>): TokenBucketTracker;
159
- /**
160
- * Get the global health score tracker instance.
161
- * Creates one with default config if not initialized.
162
- */
163
- export declare function getHealthTracker(): HealthScoreTracker;
164
- /**
165
- * Initialize the global health tracker with custom config.
166
- * Call this at plugin startup if custom config is needed.
167
- */
168
- export declare function initHealthTracker(config: Partial<HealthScoreConfig>): HealthScoreTracker;
169
- export declare class LeaseTracker {
170
- private leasedAccounts;
171
- lease(accountIndex: number): void;
172
- release(accountIndex: number): void;
173
- isLeased(accountIndex: number): boolean;
174
- }
175
- export declare class ProxyManager {
176
- private proxyCooldowns;
177
- markCooldown(proxy: string, cooldownMs?: number): void;
178
- isCoolingDown(proxy: string): boolean;
179
- selectBestProxy(proxies?: string[]): string | undefined;
180
- }
181
- export declare function getLeaseTracker(): LeaseTracker;
182
- export declare function getProxyManager(): ProxyManager;
@@ -1,364 +0,0 @@
1
- /**
2
- * Account Rotation System
3
- *
4
- * Implements advanced account selection algorithms:
5
- * - Health Score: Track account wellness based on success/failure
6
- * - LRU Selection: Prefer accounts with longest rest periods
7
- * - Jitter: Add random variance to break predictable patterns
8
- *
9
- * Used by 'hybrid' strategy for improved ban prevention and load distribution.
10
- */
11
- export const DEFAULT_HEALTH_SCORE_CONFIG = {
12
- initial: 70,
13
- successReward: 1,
14
- rateLimitPenalty: -10,
15
- failurePenalty: -20,
16
- recoveryRatePerHour: 2,
17
- minUsable: 50,
18
- maxScore: 100,
19
- };
20
- /**
21
- * Tracks health scores for accounts.
22
- * Higher score = healthier account = preferred for selection.
23
- */
24
- export class HealthScoreTracker {
25
- scores = new Map();
26
- config;
27
- constructor(config = {}) {
28
- this.config = { ...DEFAULT_HEALTH_SCORE_CONFIG, ...config };
29
- }
30
- /**
31
- * Get current health score for an account, applying time-based recovery.
32
- */
33
- getScore(accountIndex) {
34
- const state = this.scores.get(accountIndex);
35
- if (!state) {
36
- return this.config.initial;
37
- }
38
- const now = Date.now();
39
- const hoursSinceUpdate = (now - state.lastUpdated) / (1000 * 60 * 60);
40
- const recoveredPoints = Math.floor(hoursSinceUpdate * this.config.recoveryRatePerHour);
41
- return Math.min(this.config.maxScore, state.score + recoveredPoints);
42
- }
43
- /**
44
- * Record a successful request - improves health score.
45
- */
46
- recordSuccess(accountIndex) {
47
- const now = Date.now();
48
- const current = this.getScore(accountIndex);
49
- this.scores.set(accountIndex, {
50
- score: Math.min(this.config.maxScore, current + this.config.successReward),
51
- lastUpdated: now,
52
- lastSuccess: now,
53
- consecutiveFailures: 0,
54
- });
55
- }
56
- /**
57
- * Record a rate limit hit - moderate penalty.
58
- */
59
- recordRateLimit(accountIndex) {
60
- const now = Date.now();
61
- const state = this.scores.get(accountIndex);
62
- const current = this.getScore(accountIndex);
63
- this.scores.set(accountIndex, {
64
- score: Math.max(0, current + this.config.rateLimitPenalty),
65
- lastUpdated: now,
66
- lastSuccess: state?.lastSuccess ?? 0,
67
- consecutiveFailures: (state?.consecutiveFailures ?? 0) + 1,
68
- });
69
- }
70
- /**
71
- * Record a failure (auth, network, etc.) - larger penalty.
72
- */
73
- recordFailure(accountIndex) {
74
- const now = Date.now();
75
- const state = this.scores.get(accountIndex);
76
- const current = this.getScore(accountIndex);
77
- this.scores.set(accountIndex, {
78
- score: Math.max(0, current + this.config.failurePenalty),
79
- lastUpdated: now,
80
- lastSuccess: state?.lastSuccess ?? 0,
81
- consecutiveFailures: (state?.consecutiveFailures ?? 0) + 1,
82
- });
83
- }
84
- /**
85
- * Check if account is healthy enough to use.
86
- */
87
- isUsable(accountIndex) {
88
- return this.getScore(accountIndex) >= this.config.minUsable;
89
- }
90
- /**
91
- * Get consecutive failure count for an account.
92
- */
93
- getConsecutiveFailures(accountIndex) {
94
- return this.scores.get(accountIndex)?.consecutiveFailures ?? 0;
95
- }
96
- /**
97
- * Reset health state for an account (e.g., after removal).
98
- */
99
- reset(accountIndex) {
100
- this.scores.delete(accountIndex);
101
- }
102
- /**
103
- * Get all scores for debugging/logging.
104
- */
105
- getSnapshot() {
106
- const result = new Map();
107
- for (const [index] of this.scores) {
108
- result.set(index, {
109
- score: this.getScore(index),
110
- consecutiveFailures: this.getConsecutiveFailures(index),
111
- });
112
- }
113
- return result;
114
- }
115
- }
116
- // ============================================================================
117
- // ============================================================================
118
- /**
119
- * Add random jitter to a delay value.
120
- * Helps break predictable timing patterns.
121
- *
122
- * @param baseMs - Base delay in milliseconds
123
- * @param jitterFactor - Fraction of base to vary (default: 0.3 = ±30%)
124
- * @returns Jittered delay in milliseconds
125
- */
126
- export function addJitter(baseMs, jitterFactor = 0.3) {
127
- const jitterRange = baseMs * jitterFactor;
128
- const jitter = (Math.random() * 2 - 1) * jitterRange; // -jitterRange to +jitterRange
129
- return Math.max(0, Math.round(baseMs + jitter));
130
- }
131
- /**
132
- * Generate a random delay within a range.
133
- *
134
- * @param minMs - Minimum delay in milliseconds
135
- * @param maxMs - Maximum delay in milliseconds
136
- * @returns Random delay between min and max
137
- */
138
- export function randomDelay(minMs, maxMs) {
139
- return Math.round(minMs + Math.random() * (maxMs - minMs));
140
- }
141
- /**
142
- * Sort accounts by LRU (least recently used first) with health score tiebreaker.
143
- *
144
- * Priority:
145
- * 1. Filter out rate-limited and cooling-down accounts
146
- * 2. Filter out unhealthy accounts (score < minUsable)
147
- * 3. Sort by lastUsed ascending (oldest first = most rested)
148
- * 4. Tiebreaker: higher health score wins
149
- */
150
- export function sortByLruWithHealth(accounts, minHealthScore = 50) {
151
- return accounts
152
- .filter(acc => !acc.isRateLimited && !acc.isCoolingDown && acc.healthScore >= minHealthScore)
153
- .sort((a, b) => {
154
- const lruDiff = a.lastUsed - b.lastUsed;
155
- if (lruDiff !== 0)
156
- return lruDiff;
157
- return b.healthScore - a.healthScore;
158
- });
159
- }
160
- /** Stickiness bonus added to current account's score to prevent unnecessary switching */
161
- const STICKINESS_BONUS = 150;
162
- /** Minimum score advantage required to switch away from current account */
163
- const SWITCH_THRESHOLD = 100;
164
- /**
165
- * Select account using hybrid strategy with stickiness:
166
- * 1. Filter available accounts (not rate-limited, not cooling down, healthy, has tokens)
167
- * 2. Calculate priority score: health (2x) + tokens (5x) + freshness (0.1x)
168
- * 3. Apply stickiness bonus to current account
169
- * 4. Only switch if another account beats current by SWITCH_THRESHOLD
170
- *
171
- * @param accounts - All accounts with their metrics
172
- * @param tokenTracker - Token bucket tracker for token balances
173
- * @param currentAccountIndex - Currently active account index (for stickiness)
174
- * @param minHealthScore - Minimum health score to be considered
175
- * @returns Best account index, or null if none available
176
- */
177
- export function selectHybridAccount(accounts, tokenTracker, currentAccountIndex = null, minHealthScore = 50) {
178
- const candidates = accounts
179
- .filter(acc => !getLeaseTracker().isLeased(acc.index) &&
180
- !acc.isRateLimited &&
181
- !acc.isCoolingDown &&
182
- acc.healthScore >= minHealthScore &&
183
- tokenTracker.hasTokens(acc.index))
184
- .map(acc => ({
185
- ...acc,
186
- tokens: tokenTracker.getTokens(acc.index)
187
- }));
188
- if (candidates.length === 0) {
189
- return null;
190
- }
191
- const maxTokens = tokenTracker.getMaxTokens();
192
- const scored = candidates
193
- .map(acc => {
194
- const baseScore = calculateHybridScore(acc, maxTokens);
195
- const stickinessBonus = acc.index === currentAccountIndex ? STICKINESS_BONUS : 0;
196
- return {
197
- index: acc.index,
198
- baseScore,
199
- score: baseScore + stickinessBonus,
200
- isCurrent: acc.index === currentAccountIndex
201
- };
202
- })
203
- .sort((a, b) => b.score - a.score);
204
- const best = scored[0];
205
- if (!best) {
206
- return null;
207
- }
208
- const currentCandidate = scored.find(s => s.isCurrent);
209
- if (currentCandidate && !best.isCurrent) {
210
- // (compare base scores to avoid circular stickiness bonus comparison)
211
- const advantage = best.baseScore - currentCandidate.baseScore;
212
- if (advantage < SWITCH_THRESHOLD) {
213
- return currentCandidate.index;
214
- }
215
- }
216
- return best.index;
217
- }
218
- function calculateHybridScore(account, maxTokens) {
219
- const healthComponent = account.healthScore * 2; // 0-200
220
- const tokenComponent = (account.tokens / maxTokens) * 100 * 5; // 0-500
221
- const secondsSinceUsed = (Date.now() - account.lastUsed) / 1000;
222
- const freshnessComponent = Math.min(secondsSinceUsed, 3600) * 0.1; // 0-360
223
- return Math.max(0, healthComponent + tokenComponent + freshnessComponent);
224
- }
225
- export const DEFAULT_TOKEN_BUCKET_CONFIG = {
226
- maxTokens: 50,
227
- regenerationRatePerMinute: 6,
228
- initialTokens: 50,
229
- };
230
- /**
231
- * Client-side rate limiting using Token Bucket algorithm.
232
- * Helps prevent hitting server 429s by tracking "cost" of requests.
233
- */
234
- export class TokenBucketTracker {
235
- buckets = new Map();
236
- config;
237
- constructor(config = {}) {
238
- this.config = { ...DEFAULT_TOKEN_BUCKET_CONFIG, ...config };
239
- }
240
- /**
241
- * Get current token balance for an account, applying regeneration.
242
- */
243
- getTokens(accountIndex) {
244
- const state = this.buckets.get(accountIndex);
245
- if (!state) {
246
- return this.config.initialTokens;
247
- }
248
- const now = Date.now();
249
- const minutesSinceUpdate = (now - state.lastUpdated) / (1000 * 60);
250
- const recoveredTokens = minutesSinceUpdate * this.config.regenerationRatePerMinute;
251
- return Math.min(this.config.maxTokens, state.tokens + recoveredTokens);
252
- }
253
- /**
254
- * Check if account has enough tokens for a request.
255
- * @param cost Cost of the request (default: 1)
256
- */
257
- hasTokens(accountIndex, cost = 1) {
258
- return this.getTokens(accountIndex) >= cost;
259
- }
260
- /**
261
- * Consume tokens for a request.
262
- * @returns true if tokens were consumed, false if insufficient
263
- */
264
- consume(accountIndex, cost = 1) {
265
- const current = this.getTokens(accountIndex);
266
- if (current < cost) {
267
- return false;
268
- }
269
- this.buckets.set(accountIndex, {
270
- tokens: current - cost,
271
- lastUpdated: Date.now(),
272
- });
273
- return true;
274
- }
275
- /**
276
- * Refund tokens (e.g., if request wasn't actually sent).
277
- */
278
- refund(accountIndex, amount = 1) {
279
- const current = this.getTokens(accountIndex);
280
- this.buckets.set(accountIndex, {
281
- tokens: Math.min(this.config.maxTokens, current + amount),
282
- lastUpdated: Date.now(),
283
- });
284
- }
285
- getMaxTokens() {
286
- return this.config.maxTokens;
287
- }
288
- }
289
- // ============================================================================
290
- // ============================================================================
291
- let globalTokenTracker = null;
292
- export function getTokenTracker() {
293
- if (!globalTokenTracker) {
294
- globalTokenTracker = new TokenBucketTracker();
295
- }
296
- return globalTokenTracker;
297
- }
298
- export function initTokenTracker(config) {
299
- globalTokenTracker = new TokenBucketTracker(config);
300
- return globalTokenTracker;
301
- }
302
- let globalHealthTracker = null;
303
- /**
304
- * Get the global health score tracker instance.
305
- * Creates one with default config if not initialized.
306
- */
307
- export function getHealthTracker() {
308
- if (!globalHealthTracker) {
309
- globalHealthTracker = new HealthScoreTracker();
310
- }
311
- return globalHealthTracker;
312
- }
313
- /**
314
- * Initialize the global health tracker with custom config.
315
- * Call this at plugin startup if custom config is needed.
316
- */
317
- export function initHealthTracker(config) {
318
- globalHealthTracker = new HealthScoreTracker(config);
319
- return globalHealthTracker;
320
- }
321
- // ============================================================================
322
- // ============================================================================
323
- export class LeaseTracker {
324
- leasedAccounts = new Set();
325
- lease(accountIndex) { this.leasedAccounts.add(accountIndex); }
326
- release(accountIndex) { this.leasedAccounts.delete(accountIndex); }
327
- isLeased(accountIndex) { return this.leasedAccounts.has(accountIndex); }
328
- }
329
- export class ProxyManager {
330
- proxyCooldowns = new Map();
331
- markCooldown(proxy, cooldownMs = 60000) {
332
- this.proxyCooldowns.set(proxy, Date.now() + cooldownMs);
333
- }
334
- isCoolingDown(proxy) {
335
- const expiresAt = this.proxyCooldowns.get(proxy);
336
- if (!expiresAt)
337
- return false;
338
- if (Date.now() > expiresAt) {
339
- this.proxyCooldowns.delete(proxy);
340
- return false;
341
- }
342
- return true;
343
- }
344
- selectBestProxy(proxies) {
345
- if (!proxies || proxies.length === 0)
346
- return undefined;
347
- const available = proxies.filter(p => !this.isCoolingDown(p));
348
- if (available.length === 0)
349
- return proxies[Math.floor(Math.random() * proxies.length)]; // fallback
350
- return available[Math.floor(Math.random() * available.length)];
351
- }
352
- }
353
- let globalLeaseTracker = null;
354
- export function getLeaseTracker() {
355
- if (!globalLeaseTracker)
356
- globalLeaseTracker = new LeaseTracker();
357
- return globalLeaseTracker;
358
- }
359
- let globalProxyManager = null;
360
- export function getProxyManager() {
361
- if (!globalProxyManager)
362
- globalProxyManager = new ProxyManager();
363
- return globalProxyManager;
364
- }
@@ -1,31 +0,0 @@
1
- /**
2
- * Google Search Tool Implementation
3
- *
4
- * Due to Gemini API limitations, native search tools (googleSearch, urlContext)
5
- * cannot be combined with function declarations. This module implements a
6
- * wrapper that makes separate API calls with only the grounding tools enabled.
7
- */
8
- export interface SearchArgs {
9
- query: string;
10
- urls?: string[];
11
- thinking?: boolean;
12
- }
13
- export interface SearchResult {
14
- text: string;
15
- sources: Array<{
16
- title: string;
17
- url: string;
18
- }>;
19
- searchQueries: string[];
20
- urlsRetrieved: Array<{
21
- url: string;
22
- status: string;
23
- }>;
24
- }
25
- /**
26
- * Execute a Google Search using the Gemini grounding API.
27
- *
28
- * This makes a SEPARATE API call with only googleSearch/urlContext tools,
29
- * which is required because these tools cannot be combined with function declarations.
30
- */
31
- export declare function executeSearch(args: SearchArgs, accessToken: string, projectId: string, abortSignal?: AbortSignal): Promise<string>;