@expiren/opencode-antigravity-auth 1.6.20 → 1.6.21

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.
package/dist/index.js CHANGED
@@ -27,17 +27,14 @@ var ANTIGRAVITY_SCOPES = [
27
27
  ];
28
28
  var ANTIGRAVITY_REDIRECT_URI = "http://localhost:51121/oauth-callback";
29
29
  var ANTIGRAVITY_ENDPOINT_DAILY = "https://daily-cloudcode-pa.sandbox.googleapis.com";
30
- var ANTIGRAVITY_ENDPOINT_AUTOPUSH = "https://autopush-cloudcode-pa.sandbox.googleapis.com";
31
30
  var ANTIGRAVITY_ENDPOINT_PROD = "https://cloudcode-pa.googleapis.com";
32
31
  var ANTIGRAVITY_ENDPOINT_FALLBACKS = [
33
32
  ANTIGRAVITY_ENDPOINT_DAILY,
34
- ANTIGRAVITY_ENDPOINT_AUTOPUSH,
35
33
  ANTIGRAVITY_ENDPOINT_PROD
36
34
  ];
37
35
  var ANTIGRAVITY_LOAD_ENDPOINTS = [
38
36
  ANTIGRAVITY_ENDPOINT_PROD,
39
- ANTIGRAVITY_ENDPOINT_DAILY,
40
- ANTIGRAVITY_ENDPOINT_AUTOPUSH
37
+ ANTIGRAVITY_ENDPOINT_DAILY
41
38
  ];
42
39
  var ANTIGRAVITY_ENDPOINT = ANTIGRAVITY_ENDPOINT_DAILY;
43
40
  var GEMINI_CLI_ENDPOINT = ANTIGRAVITY_ENDPOINT_PROD;
@@ -3023,9 +3020,21 @@ var AntigravityConfigSchema = z2.object({
3023
3020
  * @default false
3024
3021
  */
3025
3022
  keep_thinking: z2.boolean().default(false),
3023
+ /**
3024
+ * Enable thinking warmup requests for Claude thinking models.
3025
+ * When enabled, sends a separate API call at session start to warm up
3026
+ * thinking signature validation. Costs 1 full API call per session.
3027
+ *
3028
+ * Disable to save quota — most users don't need this unless using
3029
+ * keep_thinking with signature caching.
3030
+ *
3031
+ * Env override: OPENCODE_ANTIGRAVITY_THINKING_WARMUP=1
3032
+ * @default false
3033
+ */
3034
+ thinking_warmup: z2.boolean().default(false),
3026
3035
  // =========================================================================
3027
3036
  // Session Recovery
3028
- // =========================================================================
3037
+ // =========================================================================
3029
3038
  /**
3030
3039
  * Enable automatic session recovery from tool_result_missing errors.
3031
3040
  * When enabled, shows a toast notification when recoverable errors occur.
@@ -3065,9 +3074,9 @@ var AntigravityConfigSchema = z2.object({
3065
3074
  * Maximum retry attempts when Antigravity returns an empty response.
3066
3075
  * Empty responses occur when no candidates/choices are returned.
3067
3076
  *
3068
- * @default 4
3077
+ * @default 2
3069
3078
  */
3070
- empty_response_max_attempts: z2.number().min(1).max(10).default(4),
3079
+ empty_response_max_attempts: z2.number().min(1).max(10).default(2),
3071
3080
  /**
3072
3081
  * Delay in milliseconds between empty response retries.
3073
3082
  *
@@ -3188,8 +3197,28 @@ var AntigravityConfigSchema = z2.object({
3188
3197
  */
3189
3198
  switch_on_first_rate_limit: z2.boolean().default(true),
3190
3199
  /**
3191
- * Scheduling mode for rate limit behavior.
3200
+ * Maximum number of account switches per request before giving up.
3201
+ * Each switch re-sends the full request payload, consuming quota on the new account.
3202
+ * Lower values reduce quota waste from cascading rate limits across accounts.
3203
+ *
3204
+ * Env override: OPENCODE_ANTIGRAVITY_MAX_ACCOUNT_SWITCHES
3205
+ * @default 2
3206
+ */
3207
+ max_account_switches: z2.number().min(0).max(50).default(2),
3208
+ /**
3209
+ * Allow falling back between quota pools (antigravity ↔ gemini-cli) when rate-limited.
3210
+ * When enabled, if one quota pool is exhausted the plugin re-sends the SAME request
3211
+ * using the alternate header style, consuming tokens from BOTH pools.
3212
+ * Disable to prevent double-spending quota across pools — the plugin will only
3213
+ * rotate accounts instead.
3214
+ * Only applies to Gemini models (Claude always uses antigravity).
3192
3215
  *
3216
+ * Env override: OPENCODE_ANTIGRAVITY_QUOTA_STYLE_FALLBACK
3217
+ * @default false
3218
+ */
3219
+ quota_style_fallback: z2.boolean().default(false),
3220
+ /**
3221
+ * Scheduling mode for rate limit behavior. *
3193
3222
  * - `cache_first`: Wait for same account to recover (preserves prompt cache). Default.
3194
3223
  * - `balance`: Switch account immediately on rate limit. Maximum availability.
3195
3224
  * - `performance_first`: Round-robin distribution for maximum throughput.
@@ -3253,7 +3282,7 @@ var AntigravityConfigSchema = z2.object({
3253
3282
  *
3254
3283
  * @default 15
3255
3284
  */
3256
- quota_refresh_interval_minutes: z2.number().min(0).max(60).default(15),
3285
+ quota_refresh_interval_minutes: z2.number().min(0).max(120).default(30),
3257
3286
  /**
3258
3287
  * How long quota cache is considered fresh for threshold checks (in minutes).
3259
3288
  * After this time, cache is stale and account is allowed (fail-open).
@@ -3301,10 +3330,11 @@ var DEFAULT_CONFIG = {
3301
3330
  debug: false,
3302
3331
  debug_tui: false,
3303
3332
  keep_thinking: false,
3333
+ thinking_warmup: false,
3304
3334
  session_recovery: true,
3305
3335
  auto_resume: true,
3306
3336
  resume_text: "continue",
3307
- empty_response_max_attempts: 4,
3337
+ empty_response_max_attempts: 2,
3308
3338
  empty_response_retry_delay_ms: 2e3,
3309
3339
  tool_id_recovery: true,
3310
3340
  claude_tool_hardening: true,
@@ -3318,6 +3348,8 @@ var DEFAULT_CONFIG = {
3318
3348
  account_selection_strategy: "hybrid",
3319
3349
  pid_offset_enabled: false,
3320
3350
  switch_on_first_rate_limit: true,
3351
+ max_account_switches: 2,
3352
+ quota_style_fallback: false,
3321
3353
  scheduling_mode: "cache_first",
3322
3354
  max_cache_first_wait_seconds: 60,
3323
3355
  failure_ttl_seconds: 3600,
@@ -3325,7 +3357,7 @@ var DEFAULT_CONFIG = {
3325
3357
  max_backoff_seconds: 60,
3326
3358
  request_jitter_max_ms: 0,
3327
3359
  soft_quota_threshold_percent: 90,
3328
- quota_refresh_interval_minutes: 15,
3360
+ quota_refresh_interval_minutes: 30,
3329
3361
  soft_quota_cache_ttl_minutes: "auto",
3330
3362
  auto_update: true,
3331
3363
  signature_cache: {
@@ -5606,6 +5638,12 @@ function needsThinkingRecovery(state) {
5606
5638
 
5607
5639
  // src/plugin/transform/claude.ts
5608
5640
  var CLAUDE_THINKING_MAX_OUTPUT_TOKENS = 64e3;
5641
+ function computeClaudeMaxOutputTokens(thinkingBudget) {
5642
+ if (typeof thinkingBudget !== "number" || thinkingBudget <= 0) {
5643
+ return CLAUDE_THINKING_MAX_OUTPUT_TOKENS;
5644
+ }
5645
+ return Math.min(Math.max(thinkingBudget * 2, 32e3), CLAUDE_THINKING_MAX_OUTPUT_TOKENS);
5646
+ }
5609
5647
  function isClaudeModel(model) {
5610
5648
  return model.toLowerCase().includes("claude");
5611
5649
  }
@@ -6138,7 +6176,7 @@ function resolveModelWithTier(requestedModel, options = {}) {
6138
6176
  if (isClaudeThinking) {
6139
6177
  return {
6140
6178
  actualModel: resolvedModel,
6141
- thinkingBudget: THINKING_TIER_BUDGETS.claude.high,
6179
+ thinkingBudget: THINKING_TIER_BUDGETS.claude.medium,
6142
6180
  isThinkingModel: true,
6143
6181
  quotaPreference,
6144
6182
  explicitQuota
@@ -7510,7 +7548,7 @@ function prepareAntigravityRequest(input2, init, accessToken, projectId, endpoin
7510
7548
  if (isClaudeThinking && typeof thinkingBudget === "number" && thinkingBudget > 0) {
7511
7549
  const currentMax = rawGenerationConfig.maxOutputTokens ?? rawGenerationConfig.max_output_tokens;
7512
7550
  if (!currentMax || currentMax <= thinkingBudget) {
7513
- rawGenerationConfig.maxOutputTokens = CLAUDE_THINKING_MAX_OUTPUT_TOKENS;
7551
+ rawGenerationConfig.maxOutputTokens = computeClaudeMaxOutputTokens(thinkingBudget);
7514
7552
  if (rawGenerationConfig.max_output_tokens !== void 0) {
7515
7553
  delete rawGenerationConfig.max_output_tokens;
7516
7554
  }
@@ -7520,7 +7558,7 @@ function prepareAntigravityRequest(input2, init, accessToken, projectId, endpoin
7520
7558
  } else {
7521
7559
  const generationConfig = { thinkingConfig };
7522
7560
  if (isClaudeThinking && typeof thinkingBudget === "number" && thinkingBudget > 0) {
7523
- generationConfig.maxOutputTokens = CLAUDE_THINKING_MAX_OUTPUT_TOKENS;
7561
+ generationConfig.maxOutputTokens = computeClaudeMaxOutputTokens(thinkingBudget);
7524
7562
  }
7525
7563
  requestPayload.generationConfig = generationConfig;
7526
7564
  }
@@ -7830,7 +7868,7 @@ function buildThinkingWarmupBody(bodyText, isClaudeThinking) {
7830
7868
  include_thoughts: true,
7831
7869
  thinking_budget: DEFAULT_THINKING_BUDGET
7832
7870
  };
7833
- generationConfig.maxOutputTokens = CLAUDE_THINKING_MAX_OUTPUT_TOKENS;
7871
+ generationConfig.maxOutputTokens = computeClaudeMaxOutputTokens(DEFAULT_THINKING_BUDGET);
7834
7872
  req.generationConfig = generationConfig;
7835
7873
  };
7836
7874
  if (parsed.request && typeof parsed.request === "object") {
@@ -11917,6 +11955,8 @@ var createAntigravityPlugin = (providerId) => async ({ client, directory }) => {
11917
11955
  if (family !== "gemini") return false;
11918
11956
  return accountManager.hasOtherAccountWithAntigravityAvailable(currentAccount.index, family, model);
11919
11957
  };
11958
+ let accountSwitchCount = 0;
11959
+ const maxAccountSwitches = config.max_account_switches ?? 2;
11920
11960
  while (true) {
11921
11961
  checkAborted();
11922
11962
  const accountCount = accountManager.getAccountCount();
@@ -12137,6 +12177,9 @@ var createAntigravityPlugin = (providerId) => async ({ client, directory }) => {
12137
12177
  }
12138
12178
  }
12139
12179
  const runThinkingWarmup = async (prepared, projectId) => {
12180
+ if (!config.thinking_warmup) {
12181
+ return;
12182
+ }
12140
12183
  if (!prepared.needsSignedThinkingWarmup || !prepared.sessionId) {
12141
12184
  return;
12142
12185
  }
@@ -12248,6 +12291,7 @@ var createAntigravityPlugin = (providerId) => async ({ client, directory }) => {
12248
12291
  let tokenConsumed = false;
12249
12292
  let capacityRetryCount = 0;
12250
12293
  let lastEndpointIndex = -1;
12294
+ let apiRequestCount = 0;
12251
12295
  for (let i = 0; i < ANTIGRAVITY_ENDPOINT_FALLBACKS.length; i++) {
12252
12296
  if (i !== lastEndpointIndex) {
12253
12297
  capacityRetryCount = 0;
@@ -12310,7 +12354,8 @@ var createAntigravityPlugin = (providerId) => async ({ client, directory }) => {
12310
12354
  tokenConsumed = getTokenTracker().consume(account.index);
12311
12355
  }
12312
12356
  const response = await fetch(prepared.request, prepared.init);
12313
- pushDebug(`status=${response.status} ${response.statusText}`);
12357
+ apiRequestCount++;
12358
+ pushDebug(`status=${response.status} ${response.statusText} (api_request #${apiRequestCount})`);
12314
12359
  if (response.status === 429 || response.status === 503 || response.status === 529) {
12315
12360
  if (tokenConsumed) {
12316
12361
  getTokenTracker().refund(account.index);
@@ -12335,12 +12380,12 @@ var createAntigravityPlugin = (providerId) => async ({ client, directory }) => {
12335
12380
  "warning"
12336
12381
  );
12337
12382
  await sleep(waitMs, abortSignal);
12338
- if (capacityRetryCount < 3) {
12383
+ if (capacityRetryCount < 1) {
12339
12384
  capacityRetryCount++;
12340
12385
  i -= 1;
12341
12386
  continue;
12342
12387
  } else {
12343
- pushDebug(`Max capacity retries (3) exhausted for endpoint ${currentEndpoint}, regenerating fingerprint...`);
12388
+ pushDebug(`Max capacity retries (1) exhausted for endpoint ${currentEndpoint}, regenerating fingerprint...`);
12344
12389
  const newFingerprint = accountManager.regenerateAccountFingerprint(account.index);
12345
12390
  if (newFingerprint) {
12346
12391
  pushDebug(`Fingerprint regenerated for account ${account.index}`);
@@ -12592,6 +12637,9 @@ Alternatively, you can:
12592
12637
  );
12593
12638
  }
12594
12639
  }
12640
+ if (apiRequestCount > 1) {
12641
+ pushDebug(`[Quota] Total API requests for this user message: ${apiRequestCount} (${apiRequestCount - 1} retries)`);
12642
+ }
12595
12643
  return transformedResponse;
12596
12644
  } catch (error) {
12597
12645
  if (tokenConsumed) {
@@ -12638,6 +12686,27 @@ Alternatively, you can:
12638
12686
  }
12639
12687
  }
12640
12688
  if (shouldSwitchAccount) {
12689
+ accountSwitchCount++;
12690
+ if (accountSwitchCount > maxAccountSwitches) {
12691
+ pushDebug(`account-switch-cap: exceeded max_account_switches=${maxAccountSwitches}, giving up`);
12692
+ if (lastFailure) {
12693
+ return transformAntigravityResponse(
12694
+ lastFailure.response,
12695
+ lastFailure.streaming,
12696
+ lastFailure.debugContext,
12697
+ lastFailure.requestedModel,
12698
+ lastFailure.projectId,
12699
+ lastFailure.endpoint,
12700
+ lastFailure.effectiveModel,
12701
+ lastFailure.sessionId,
12702
+ lastFailure.toolDebugMissing,
12703
+ lastFailure.toolDebugSummary,
12704
+ lastFailure.toolDebugPayload,
12705
+ debugLines
12706
+ );
12707
+ }
12708
+ throw lastError || new Error(`Exceeded max account switches (${maxAccountSwitches}). All accounts rate-limited.`);
12709
+ }
12641
12710
  if (accountCount <= 1) {
12642
12711
  if (lastFailure) {
12643
12712
  return transformAntigravityResponse(
@@ -13481,7 +13550,7 @@ function resolveHeaderRoutingDecision(urlString, family, config) {
13481
13550
  cliFirst,
13482
13551
  preferredHeaderStyle,
13483
13552
  explicitQuota,
13484
- allowQuotaFallback: family === "gemini"
13553
+ allowQuotaFallback: family === "gemini" && !!(config.quota_style_fallback ?? false)
13485
13554
  };
13486
13555
  }
13487
13556
  function getCliFirst(config) {