claudish 7.29.1 → 7.30.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 (2) hide show
  1. package/dist/index.js +1741 -921
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -651,7 +651,7 @@ var init_onepassword_config = __esm(() => {
651
651
  });
652
652
 
653
653
  // src/version.ts
654
- var VERSION = "7.29.1";
654
+ var VERSION = "7.30.0";
655
655
 
656
656
  // src/logger.ts
657
657
  var exports_logger = {};
@@ -27704,6 +27704,26 @@ var init_provider_definitions = __esm(() => {
27704
27704
  isDirectApi: true,
27705
27705
  description: "Direct Gemini API (g@, google@)"
27706
27706
  },
27707
+ {
27708
+ name: "antigravity",
27709
+ displayName: "Antigravity",
27710
+ transport: "antigravity",
27711
+ baseUrl: "https://cloudcode-pa.googleapis.com",
27712
+ apiPath: "/v1internal:streamGenerateContent?alt=sse",
27713
+ apiKeyEnvVar: "",
27714
+ apiKeyDescription: "Antigravity (shared OAuth token)",
27715
+ apiKeyUrl: "https://antigravity.google/",
27716
+ oauthLoginSlug: "gemini",
27717
+ shortcuts: ["ag", "antigravity", "go"],
27718
+ shortestPrefix: "ag",
27719
+ legacyPrefixes: [
27720
+ { prefix: "ag/", stripPrefix: true },
27721
+ { prefix: "antigravity/", stripPrefix: true },
27722
+ { prefix: "go/", stripPrefix: true }
27723
+ ],
27724
+ isDirectApi: true,
27725
+ description: "Antigravity subscription (ag@; go@ deprecated)"
27726
+ },
27707
27727
  {
27708
27728
  name: "gemini-codeassist",
27709
27729
  displayName: "Gemini Code Assist",
@@ -27714,11 +27734,11 @@ var init_provider_definitions = __esm(() => {
27714
27734
  apiKeyDescription: "Gemini Code Assist (OAuth)",
27715
27735
  apiKeyUrl: "https://cloud.google.com/code-assist",
27716
27736
  oauthLoginSlug: "gemini",
27717
- shortcuts: ["go"],
27718
- shortestPrefix: "go",
27719
- legacyPrefixes: [{ prefix: "go/", stripPrefix: true }],
27737
+ shortcuts: [],
27738
+ shortestPrefix: "gemini-codeassist",
27739
+ legacyPrefixes: [],
27720
27740
  isDirectApi: true,
27721
- description: "Gemini Code Assist OAuth (go@)"
27741
+ description: "Gemini Code Assist OAuth (routing fallback for gemini-*)"
27722
27742
  },
27723
27743
  {
27724
27744
  name: "openai",
@@ -28231,125 +28251,191 @@ var init_provider_definitions = __esm(() => {
28231
28251
  ];
28232
28252
  });
28233
28253
 
28234
- // src/auth/credentials/api-key-credential.ts
28254
+ // src/auth/antigravity-token.ts
28255
+ import { execFileSync } from "child_process";
28235
28256
  import { existsSync as existsSync6 } from "fs";
28236
28257
  import { homedir as homedir8 } from "os";
28237
28258
  import { join as join8 } from "path";
28238
- function realValue(v) {
28239
- if (!v)
28240
- return;
28241
- return UNEXPANDED_PLACEHOLDER.test(v.trim()) ? undefined : v;
28259
+ function defaultReadStore() {
28260
+ if (process.platform !== "darwin") {
28261
+ logStderr("[Antigravity] Shared token store is macOS-only for now (other keyring backends are a follow-up).");
28262
+ return null;
28263
+ }
28264
+ try {
28265
+ const out = execFileSync("security", ["find-generic-password", "-s", KC_SERVICE, "-a", KC_ACCOUNT, "-w"], { encoding: "utf8" });
28266
+ const trimmed = out.trim();
28267
+ return trimmed.length > 0 ? trimmed : null;
28268
+ } catch {
28269
+ return null;
28270
+ }
28242
28271
  }
28243
-
28244
- class ApiKeyCredentialProvider {
28245
- catalogName;
28246
- envVar;
28247
- aliases;
28248
- authScheme;
28249
- staticHeaders;
28250
- publicKeyFallback;
28251
- oauthFallback;
28252
- declaredKey;
28253
- cachedKey;
28254
- resolving;
28255
- constructor(descriptor) {
28256
- this.catalogName = descriptor.catalogName;
28257
- this.envVar = descriptor.envVar;
28258
- this.aliases = descriptor.aliases ?? [];
28259
- this.authScheme = descriptor.authScheme ?? "bearer";
28260
- this.staticHeaders = descriptor.staticHeaders ?? {};
28261
- this.publicKeyFallback = descriptor.publicKeyFallback;
28262
- this.oauthFallback = descriptor.oauthFallback;
28263
- this.declaredKey = descriptor.declaredKey;
28272
+ function defaultWriteStore(rawValue) {
28273
+ if (process.platform !== "darwin") {
28274
+ throw new Error("[Antigravity] Cannot write the shared token store on a non-macOS platform.");
28264
28275
  }
28265
- resolveFromEnvConfig() {
28266
- return realValue(process.env[this.envVar]) || this.aliases.map((a) => realValue(process.env[a])).find((v) => !!v) || realValue(getApiKey(this.envVar)) || realValue(this.resolveDeclared());
28276
+ execFileSync("security", ["add-generic-password", "-U", "-s", KC_SERVICE, "-a", KC_ACCOUNT, "-w", rawValue], { stdio: ["ignore", "ignore", "ignore"] });
28277
+ }
28278
+ function locateAgyBinary() {
28279
+ try {
28280
+ const p = execFileSync("which", ["agy"], { encoding: "utf8" }).trim();
28281
+ if (p.length > 0)
28282
+ return p;
28283
+ } catch {}
28284
+ const fallback = join8(homedir8(), ".local", "bin", "agy");
28285
+ return existsSync6(fallback) ? fallback : null;
28286
+ }
28287
+ function defaultExtractCreds() {
28288
+ const agy = locateAgyBinary();
28289
+ if (!agy) {
28290
+ logStderr("[Antigravity] Could not locate the `agy` binary \u2014 self-refresh is unavailable.");
28291
+ return [];
28267
28292
  }
28268
- resolveDeclared() {
28269
- try {
28270
- return this.declaredKey?.() || undefined;
28271
- } catch {
28272
- return;
28273
- }
28293
+ let dump;
28294
+ try {
28295
+ dump = execFileSync("strings", [agy], {
28296
+ encoding: "utf8",
28297
+ maxBuffer: 128 * 1024 * 1024
28298
+ });
28299
+ } catch {
28300
+ logStderr("[Antigravity] `strings` failed on the agy binary \u2014 self-refresh is unavailable.");
28301
+ return [];
28274
28302
  }
28275
- hasOauthFallbackFile() {
28276
- if (!this.oauthFallback)
28277
- return false;
28278
- try {
28279
- return existsSync6(join8(homedir8(), ".claudish", this.oauthFallback));
28280
- } catch {
28281
- return false;
28303
+ const clientIds = Array.from(new Set(dump.match(/[0-9]{6,}-[a-z0-9]+\.apps\.googleusercontent\.com/g) ?? []));
28304
+ const secrets = Array.from(new Set(dump.match(/GOCSPX-[A-Za-z0-9_-]{20,}/g) ?? []));
28305
+ const combos = [];
28306
+ for (const clientId of clientIds) {
28307
+ for (const clientSecret of secrets) {
28308
+ combos.push({ clientId, clientSecret });
28282
28309
  }
28283
28310
  }
28284
- async resolveKey(opts) {
28285
- if (this.cachedKey !== undefined)
28286
- return this.cachedKey;
28287
- if (this.resolving)
28288
- return this.resolving;
28289
- this.resolving = (async () => {
28290
- const local = this.resolveFromEnvConfig();
28291
- if (local) {
28292
- this.cachedKey = local;
28293
- return local;
28294
- }
28295
- if (hasOpSources()) {
28296
- const wanted = new Set([this.envVar, ...this.aliases]);
28297
- const resolved = await resolveOpKeyForEnvVars(wanted, {
28298
- onAuthFailure: "skip",
28299
- allowPrompt: opts?.allowOpPrompt ?? false
28300
- });
28301
- const value = resolved[this.envVar] ?? this.aliases.map((a) => resolved[a]).find((v) => !!v);
28302
- if (value) {
28303
- process.env[this.envVar] = value;
28304
- this.cachedKey = value;
28305
- return value;
28306
- }
28307
- return "";
28308
- }
28309
- this.cachedKey = "";
28310
- return "";
28311
- })();
28312
- try {
28313
- return await this.resolving;
28314
- } finally {
28315
- this.resolving = undefined;
28316
- }
28311
+ return combos;
28312
+ }
28313
+ function parseRecord(raw) {
28314
+ if (!raw)
28315
+ return null;
28316
+ if (!raw.startsWith(PREFIX)) {
28317
+ logStderr("[Antigravity] Shared token is in an unsupported keyring format (not go-keyring-base64) \u2014 skipping.");
28318
+ return null;
28317
28319
  }
28318
- async isAvailable(opts) {
28319
- if (this.publicKeyFallback)
28320
- return true;
28321
- if (this.resolveFromEnvConfig())
28322
- return true;
28323
- if (this.hasOauthFallbackFile())
28324
- return true;
28325
- const key = await this.resolveKey(opts);
28326
- return !!key;
28320
+ try {
28321
+ const json2 = Buffer.from(raw.slice(PREFIX.length), "base64").toString("utf8");
28322
+ const rec = JSON.parse(json2);
28323
+ if (!rec?.token?.access_token)
28324
+ return null;
28325
+ return rec;
28326
+ } catch (err) {
28327
+ log(`[Antigravity] Failed to decode shared token: ${err}`);
28328
+ return null;
28327
28329
  }
28328
- invalidate() {
28329
- this.cachedKey = undefined;
28330
- this.resolving = undefined;
28330
+ }
28331
+ function encodeRecord(rec) {
28332
+ return PREFIX + Buffer.from(JSON.stringify(rec), "utf8").toString("base64");
28333
+ }
28334
+ function readSharedAntigravityToken(deps = defaultDeps) {
28335
+ const rec = parseRecord(deps.readStore());
28336
+ return rec ? rec.token : null;
28337
+ }
28338
+ function hasSharedAntigravityToken(deps = defaultDeps) {
28339
+ const now = Date.now();
28340
+ if (cachedHasToken && now - cachedHasToken.at < HAS_TOKEN_TTL_MS)
28341
+ return cachedHasToken.value;
28342
+ let value = false;
28343
+ try {
28344
+ value = readSharedAntigravityToken(deps) != null;
28345
+ } catch {
28346
+ value = false;
28331
28347
  }
28332
- async getRequestAuth(ctx) {
28333
- const key = await this.resolveKey({ allowOpPrompt: ctx.allowOpPrompt }) || this.publicKeyFallback || "";
28334
- let headers;
28335
- if (this.authScheme === "x-api-key") {
28336
- headers = { "x-api-key": key, ...this.staticHeaders };
28337
- } else if (key) {
28338
- headers = { Authorization: `Bearer ${key}`, ...this.staticHeaders };
28339
- } else {
28340
- headers = { ...this.staticHeaders };
28348
+ cachedHasToken = { at: now, value };
28349
+ return value;
28350
+ }
28351
+ function writeSharedAntigravityToken(tok, deps = defaultDeps) {
28352
+ const existing = parseRecord(deps.readStore());
28353
+ const base = existing ?? { token: tok };
28354
+ const merged = {
28355
+ ...base,
28356
+ token: { ...base.token, ...tok }
28357
+ };
28358
+ deps.writeStore(encodeRecord(merged));
28359
+ }
28360
+ function needsRefresh(tok, now) {
28361
+ const expMs = Date.parse(tok.expiry);
28362
+ if (Number.isNaN(expMs))
28363
+ return true;
28364
+ return now >= expMs - EXPIRY_SKEW_MS;
28365
+ }
28366
+ async function refreshToken(tok, deps) {
28367
+ const combos = cachedCred ? [cachedCred] : deps.extractCreds();
28368
+ if (combos.length === 0) {
28369
+ throw new Error("[Antigravity] Access token expired and no OAuth client credentials could be extracted " + "from the `agy` binary to refresh it. Re-run the Antigravity CLI to refresh your session, " + "or use g@<model> with GEMINI_API_KEY.");
28370
+ }
28371
+ let lastStatus = 0;
28372
+ let lastBody = "";
28373
+ for (const cred of combos) {
28374
+ const res = await deps.fetch(REFRESH_ENDPOINT, {
28375
+ method: "POST",
28376
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
28377
+ body: new URLSearchParams({
28378
+ client_id: cred.clientId,
28379
+ client_secret: cred.clientSecret,
28380
+ refresh_token: tok.refresh_token,
28381
+ grant_type: "refresh_token"
28382
+ })
28383
+ });
28384
+ if (res.ok) {
28385
+ cachedCred = cred;
28386
+ const j = await res.json();
28387
+ const expiry = new Date(deps.now() + j.expires_in * 1000).toISOString();
28388
+ return {
28389
+ access_token: j.access_token,
28390
+ token_type: tok.token_type || "Bearer",
28391
+ refresh_token: j.refresh_token || tok.refresh_token,
28392
+ expiry
28393
+ };
28341
28394
  }
28342
- return { headers };
28395
+ lastStatus = res.status;
28396
+ lastBody = await res.text().catch(() => "");
28343
28397
  }
28398
+ throw new Error(`[Antigravity] Token refresh failed for all ${combos.length} client-cred combo(s) ` + `(last HTTP ${lastStatus}${lastBody ? `: ${lastBody.slice(0, 200)}` : ""}). ` + "Re-run the Antigravity CLI to refresh your session, or use g@<model> with GEMINI_API_KEY.");
28344
28399
  }
28345
- var UNEXPANDED_PLACEHOLDER;
28346
- var init_api_key_credential = __esm(() => {
28347
- init_profile_config();
28348
- init_op_source();
28349
- UNEXPANDED_PLACEHOLDER = /^\$\{[^}]*\}$/;
28400
+ async function resolveValidToken(deps) {
28401
+ if (process.platform !== "darwin") {
28402
+ throw new Error("[Antigravity] The shared Antigravity token store is macOS-only for now. " + "Use g@<model> with GEMINI_API_KEY on this platform.");
28403
+ }
28404
+ const rec = parseRecord(deps.readStore());
28405
+ if (!rec) {
28406
+ throw new Error("[Antigravity] No Antigravity session found. Install Antigravity and sign in " + "(the `agy` CLI), or use g@<model> with GEMINI_API_KEY " + "(get one at https://aistudio.google.com/app/apikey).");
28407
+ }
28408
+ const tok = rec.token;
28409
+ if (!needsRefresh(tok, deps.now())) {
28410
+ return tok.access_token;
28411
+ }
28412
+ log("[Antigravity] Access token expired/near-expiry \u2014 refreshing.");
28413
+ const refreshed = await refreshToken(tok, deps);
28414
+ writeSharedAntigravityToken(refreshed, deps);
28415
+ log("[Antigravity] Token refreshed and written back to the shared store.");
28416
+ return refreshed.access_token;
28417
+ }
28418
+ function getValidAntigravityAccessToken(deps = defaultDeps) {
28419
+ if (inFlight)
28420
+ return inFlight;
28421
+ inFlight = resolveValidToken(deps).finally(() => {
28422
+ inFlight = null;
28423
+ });
28424
+ return inFlight;
28425
+ }
28426
+ var KC_SERVICE = "gemini", KC_ACCOUNT = "antigravity", PREFIX = "go-keyring-base64:", REFRESH_ENDPOINT = "https://oauth2.googleapis.com/token", EXPIRY_SKEW_MS = 120000, defaultDeps, cachedHasToken = null, HAS_TOKEN_TTL_MS = 5000, cachedCred = null, inFlight = null;
28427
+ var init_antigravity_token = __esm(() => {
28428
+ init_logger();
28429
+ defaultDeps = {
28430
+ readStore: defaultReadStore,
28431
+ writeStore: defaultWriteStore,
28432
+ extractCreds: defaultExtractCreds,
28433
+ fetch: (input, init) => fetch(input, init),
28434
+ now: () => Date.now()
28435
+ };
28350
28436
  });
28351
28437
 
28352
- // src/auth/codex-oauth.ts
28438
+ // src/auth/gemini-oauth.ts
28353
28439
  import { exec } from "child_process";
28354
28440
  import { createHash as createHash2, randomBytes } from "crypto";
28355
28441
  import { closeSync as closeSync2, existsSync as existsSync7, openSync as openSync2, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeSync as writeSync2 } from "fs";
@@ -28357,18 +28443,25 @@ import { createServer } from "http";
28357
28443
  import { homedir as homedir9 } from "os";
28358
28444
  import { join as join9 } from "path";
28359
28445
  import { promisify } from "util";
28446
+ function buildCodeAssistUserAgent(model) {
28447
+ if (USE_LEGACY_GEMINI_IDENTITY) {
28448
+ const modelSegment = model || "gemini-code-assist";
28449
+ return `GeminiCLI/0.5.6/${modelSegment} (${process.platform}; ${process.arch})`;
28450
+ }
28451
+ return `antigravity/cli/1.1.9 (aidev_client; os_type=${process.platform}; arch=${process.arch}; auth_method=consumer)`;
28452
+ }
28360
28453
 
28361
- class CodexOAuth {
28454
+ class GeminiOAuth {
28362
28455
  static instance = null;
28363
28456
  credentials = null;
28364
28457
  refreshPromise = null;
28365
28458
  tokenRefreshMargin = 5 * 60 * 1000;
28366
28459
  oauthState = null;
28367
28460
  static getInstance() {
28368
- if (!CodexOAuth.instance) {
28369
- CodexOAuth.instance = new CodexOAuth;
28461
+ if (!GeminiOAuth.instance) {
28462
+ GeminiOAuth.instance = new GeminiOAuth;
28370
28463
  }
28371
- return CodexOAuth.instance;
28464
+ return GeminiOAuth.instance;
28372
28465
  }
28373
28466
  constructor() {
28374
28467
  this.credentials = this.loadCredentials();
@@ -28382,60 +28475,55 @@ class CodexOAuth {
28382
28475
  }
28383
28476
  getCredentialsPath() {
28384
28477
  const claudishDir = join9(homedir9(), ".claudish");
28385
- return join9(claudishDir, "codex-oauth.json");
28478
+ return join9(claudishDir, "gemini-oauth.json");
28386
28479
  }
28387
28480
  async login() {
28388
- log("[CodexOAuth] Starting OAuth login flow");
28481
+ log("[GeminiOAuth] Starting OAuth login flow");
28389
28482
  const codeVerifier = this.generateCodeVerifier();
28390
28483
  const codeChallenge = await this.generateCodeChallenge(codeVerifier);
28391
28484
  this.oauthState = randomBytes(32).toString("base64url");
28392
28485
  const { authCode, redirectUri } = await this.startCallbackServer(codeChallenge, this.oauthState);
28393
28486
  const tokens = await this.exchangeCodeForTokens(authCode, codeVerifier, redirectUri);
28394
- const accountId = tokens.id_token ? this.extractAccountId(tokens.id_token) : undefined;
28395
28487
  const credentials = {
28396
28488
  access_token: tokens.access_token,
28397
28489
  refresh_token: tokens.refresh_token,
28398
- expires_at: Date.now() + tokens.expires_in * 1000,
28399
- account_id: accountId
28490
+ expires_at: Date.now() + tokens.expires_in * 1000
28400
28491
  };
28401
28492
  this.saveCredentials(credentials);
28402
28493
  this.credentials = credentials;
28403
28494
  this.oauthState = null;
28404
- log("[CodexOAuth] Login successful");
28405
- if (accountId) {
28406
- log(`[CodexOAuth] Account ID: ${accountId}`);
28407
- }
28495
+ log("[GeminiOAuth] Login successful");
28408
28496
  }
28409
28497
  async logout() {
28410
28498
  const credPath = this.getCredentialsPath();
28411
28499
  if (existsSync7(credPath)) {
28412
28500
  unlinkSync2(credPath);
28413
- log("[CodexOAuth] Credentials deleted");
28501
+ log("[GeminiOAuth] Credentials deleted");
28414
28502
  }
28415
28503
  this.credentials = null;
28416
28504
  }
28417
28505
  async getAccessToken() {
28418
28506
  if (this.refreshPromise) {
28419
- log("[CodexOAuth] Waiting for in-progress refresh");
28507
+ log("[GeminiOAuth] Waiting for in-progress refresh");
28420
28508
  return this.refreshPromise;
28421
28509
  }
28422
28510
  if (!this.credentials) {
28423
- throw new Error("No OpenAI Codex OAuth credentials found. Please run `claudish login codex` first.");
28511
+ throw new Error("No Gemini OAuth credentials found. Please run `claudish login gemini` first.");
28424
28512
  }
28425
28513
  if (this.isTokenValid()) {
28426
28514
  return this.credentials.access_token;
28427
28515
  }
28428
- this.refreshPromise = this.doRefreshToken().finally(() => {
28516
+ this.refreshPromise = this.doRefreshToken();
28517
+ try {
28518
+ const token = await this.refreshPromise;
28519
+ return token;
28520
+ } finally {
28429
28521
  this.refreshPromise = null;
28430
- });
28431
- return this.refreshPromise;
28432
- }
28433
- getAccountId() {
28434
- return this.credentials?.account_id;
28522
+ }
28435
28523
  }
28436
28524
  async refreshToken() {
28437
28525
  if (!this.credentials) {
28438
- throw new Error("No OpenAI Codex OAuth credentials found. Please run `claudish login codex` first.");
28526
+ throw new Error("No Gemini OAuth credentials found. Please run `claudish login gemini` first.");
28439
28527
  }
28440
28528
  await this.doRefreshToken();
28441
28529
  }
@@ -28446,19 +28534,20 @@ class CodexOAuth {
28446
28534
  }
28447
28535
  async doRefreshToken() {
28448
28536
  if (!this.credentials) {
28449
- throw new Error("No OpenAI Codex OAuth credentials found. Please run `claudish login codex` first.");
28537
+ throw new Error("No Gemini OAuth credentials found. Please run `claudish login gemini` first.");
28450
28538
  }
28451
- log("[CodexOAuth] Refreshing access token");
28539
+ log("[GeminiOAuth] Refreshing access token");
28452
28540
  try {
28453
28541
  const response = await fetch(OAUTH_CONFIG.tokenUrl, {
28454
28542
  method: "POST",
28455
28543
  headers: {
28456
- "Content-Type": "application/json"
28544
+ "Content-Type": "application/x-www-form-urlencoded"
28457
28545
  },
28458
- body: JSON.stringify({
28546
+ body: new URLSearchParams({
28459
28547
  grant_type: "refresh_token",
28460
28548
  refresh_token: this.credentials.refresh_token,
28461
- client_id: OAUTH_CONFIG.clientId
28549
+ client_id: OAUTH_CONFIG.clientId,
28550
+ client_secret: OAUTH_CONFIG.clientSecret
28462
28551
  })
28463
28552
  });
28464
28553
  if (!response.ok) {
@@ -28466,20 +28555,18 @@ class CodexOAuth {
28466
28555
  throw new Error(`Token refresh failed: ${response.status} - ${errorText}`);
28467
28556
  }
28468
28557
  const tokens = await response.json();
28469
- const accountId = tokens.id_token ? this.extractAccountId(tokens.id_token) : this.credentials.account_id;
28470
28558
  const updatedCredentials = {
28471
28559
  access_token: tokens.access_token,
28472
28560
  refresh_token: tokens.refresh_token || this.credentials.refresh_token,
28473
- expires_at: Date.now() + tokens.expires_in * 1000,
28474
- account_id: accountId
28561
+ expires_at: Date.now() + tokens.expires_in * 1000
28475
28562
  };
28476
28563
  this.saveCredentials(updatedCredentials);
28477
28564
  this.credentials = updatedCredentials;
28478
- log(`[CodexOAuth] Token refreshed, valid until ${new Date(updatedCredentials.expires_at).toISOString()}`);
28565
+ log(`[GeminiOAuth] Token refreshed, valid until ${new Date(updatedCredentials.expires_at).toISOString()}`);
28479
28566
  return updatedCredentials.access_token;
28480
28567
  } catch (e) {
28481
- log(`[CodexOAuth] Refresh failed: ${e.message}`);
28482
- throw new Error(`OAuth credentials invalid. Please run \`claudish login codex\` again.
28568
+ log(`[GeminiOAuth] Refresh failed: ${e.message}`);
28569
+ throw new Error(`OAuth credentials invalid. Please run \`claudish login gemini\` again.
28483
28570
 
28484
28571
  Details: ${e.message}`);
28485
28572
  }
@@ -28493,13 +28580,13 @@ Details: ${e.message}`);
28493
28580
  const data = readFileSync6(credPath, "utf-8");
28494
28581
  const credentials = JSON.parse(data);
28495
28582
  if (!credentials.access_token || !credentials.refresh_token || !credentials.expires_at) {
28496
- log("[CodexOAuth] Invalid credentials file structure");
28583
+ log("[GeminiOAuth] Invalid credentials file structure");
28497
28584
  return null;
28498
28585
  }
28499
- log("[CodexOAuth] Loaded credentials from file");
28586
+ log("[GeminiOAuth] Loaded credentials from file");
28500
28587
  return credentials;
28501
28588
  } catch (e) {
28502
- log(`[CodexOAuth] Failed to load credentials: ${e.message}`);
28589
+ log(`[GeminiOAuth] Failed to load credentials: ${e.message}`);
28503
28590
  return null;
28504
28591
  }
28505
28592
  }
@@ -28517,7 +28604,7 @@ Details: ${e.message}`);
28517
28604
  } finally {
28518
28605
  closeSync2(fd);
28519
28606
  }
28520
- log(`[CodexOAuth] Credentials saved to ${credPath}`);
28607
+ log(`[GeminiOAuth] Credentials saved to ${credPath}`);
28521
28608
  }
28522
28609
  generateCodeVerifier() {
28523
28610
  return randomBytes(64).toString("base64url");
@@ -28526,46 +28613,26 @@ Details: ${e.message}`);
28526
28613
  const hash2 = createHash2("sha256").update(verifier).digest("base64url");
28527
28614
  return hash2;
28528
28615
  }
28529
- extractAccountId(idToken) {
28530
- try {
28531
- const parts = idToken.split(".");
28532
- if (parts.length !== 3)
28533
- return;
28534
- const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
28535
- const authClaim = payload["https://api.openai.com/auth"];
28536
- const accountId = authClaim?.chatgpt_account_id || payload.chatgpt_account_id || authClaim?.user_id;
28537
- if (accountId) {
28538
- log(`[CodexOAuth] Extracted account ID from id_token: ${accountId}`);
28539
- return accountId;
28540
- }
28541
- return;
28542
- } catch (e) {
28543
- log(`[CodexOAuth] Failed to extract account ID from id_token: ${e.message}`);
28544
- return;
28545
- }
28546
- }
28547
28616
  buildAuthUrl(codeChallenge, state, redirectUri) {
28548
- const scope = OAUTH_CONFIG.scopes.join("+");
28549
- const params = [
28550
- "response_type=code",
28551
- `client_id=${encodeURIComponent(OAUTH_CONFIG.clientId)}`,
28552
- `redirect_uri=${encodeURIComponent(redirectUri)}`,
28553
- `scope=${scope}`,
28554
- `code_challenge=${encodeURIComponent(codeChallenge)}`,
28555
- "code_challenge_method=S256",
28556
- "id_token_add_organizations=true",
28557
- "codex_cli_simplified_flow=true",
28558
- `state=${encodeURIComponent(state)}`,
28559
- "originator=opencode"
28560
- ].join("&");
28561
- return `${OAUTH_CONFIG.authUrl}?${params}`;
28617
+ const params = new URLSearchParams({
28618
+ client_id: OAUTH_CONFIG.clientId,
28619
+ redirect_uri: redirectUri,
28620
+ response_type: "code",
28621
+ scope: OAUTH_CONFIG.scopes.join(" "),
28622
+ code_challenge: codeChallenge,
28623
+ code_challenge_method: "S256",
28624
+ access_type: "offline",
28625
+ prompt: "consent",
28626
+ state
28627
+ });
28628
+ return `${OAUTH_CONFIG.authUrl}?${params.toString()}`;
28562
28629
  }
28563
28630
  async startCallbackServer(codeChallenge, state) {
28564
28631
  return new Promise((resolve, reject) => {
28565
28632
  let redirectUri = "";
28566
28633
  const server = createServer((req, res) => {
28567
- const url2 = new URL(req.url, redirectUri.replace("/auth/callback", ""));
28568
- if (url2.pathname === "/auth/callback") {
28634
+ const url2 = new URL(req.url, redirectUri.replace("/callback", ""));
28635
+ if (url2.pathname === "/callback") {
28569
28636
  const code = url2.searchParams.get("code");
28570
28637
  const callbackState = url2.searchParams.get("state");
28571
28638
  const error46 = url2.searchParams.get("error");
@@ -28630,15 +28697,15 @@ Details: ${e.message}`);
28630
28697
  res.end("Not found");
28631
28698
  }
28632
28699
  });
28633
- server.listen(1455, () => {
28700
+ server.listen(0, () => {
28634
28701
  const address = server.address();
28635
28702
  if (!address || typeof address === "string") {
28636
28703
  reject(new Error("Failed to get server port"));
28637
28704
  return;
28638
28705
  }
28639
28706
  const port = address.port;
28640
- redirectUri = `http://localhost:${port}/auth/callback`;
28641
- log(`[CodexOAuth] Callback server started on http://localhost:${port}`);
28707
+ redirectUri = `http://localhost:${port}/callback`;
28708
+ log(`[GeminiOAuth] Callback server started on http://localhost:${port}`);
28642
28709
  const authUrl = this.buildAuthUrl(codeChallenge, state, redirectUri);
28643
28710
  this.openBrowser(authUrl);
28644
28711
  });
@@ -28652,7 +28719,7 @@ Details: ${e.message}`);
28652
28719
  });
28653
28720
  }
28654
28721
  async exchangeCodeForTokens(code, verifier, redirectUri) {
28655
- log("[CodexOAuth] Exchanging auth code for tokens");
28722
+ log("[GeminiOAuth] Exchanging auth code for tokens");
28656
28723
  try {
28657
28724
  const response = await fetch(OAUTH_CONFIG.tokenUrl, {
28658
28725
  method: "POST",
@@ -28664,6 +28731,7 @@ Details: ${e.message}`);
28664
28731
  code,
28665
28732
  redirect_uri: redirectUri,
28666
28733
  client_id: OAUTH_CONFIG.clientId,
28734
+ client_secret: OAUTH_CONFIG.clientSecret,
28667
28735
  code_verifier: verifier
28668
28736
  })
28669
28737
  });
@@ -28677,7 +28745,7 @@ Details: ${e.message}`);
28677
28745
  }
28678
28746
  return tokens;
28679
28747
  } catch (e) {
28680
- throw new Error(`Failed to authenticate with OpenAI OAuth: ${e.message}`);
28748
+ throw new Error(`Failed to authenticate with Google OAuth: ${e.message}`);
28681
28749
  }
28682
28750
  }
28683
28751
  async openBrowser(url2) {
@@ -28691,7 +28759,7 @@ Details: ${e.message}`);
28691
28759
  await execAsync(`xdg-open "${url2}"`);
28692
28760
  }
28693
28761
  console.log(`
28694
- Opening browser for OpenAI authentication...`);
28762
+ Opening browser for authentication...`);
28695
28763
  console.log(`If the browser doesn't open, visit this URL:
28696
28764
  ${url2}
28697
28765
  `);
@@ -28703,136 +28771,1006 @@ Please open this URL in your browser to authenticate:`);
28703
28771
  }
28704
28772
  }
28705
28773
  }
28706
- function getCodexOAuth() {
28707
- return CodexOAuth.getInstance();
28774
+ function reloadGeminiCredentials() {
28775
+ GeminiOAuth.getInstance().reloadCredentials();
28776
+ resetGeminiUserCache();
28708
28777
  }
28709
- var execAsync, OAUTH_CONFIG;
28710
- var init_codex_oauth = __esm(() => {
28778
+ function rankCodeAssistModel(model) {
28779
+ const lower = model.toLowerCase();
28780
+ let tier;
28781
+ if (lower.includes("pro"))
28782
+ tier = 0;
28783
+ else if (lower.includes("lite"))
28784
+ tier = 2;
28785
+ else if (lower.includes("flash"))
28786
+ tier = 1;
28787
+ else
28788
+ tier = 3;
28789
+ const vMatch = lower.match(/^gemini-(\d+(?:\.\d+)?)(?![\d.])/);
28790
+ const version2 = vMatch ? Number.parseFloat(vMatch[1]) : 0;
28791
+ return tier * 1000 - version2;
28792
+ }
28793
+ async function getServedCodeAssistModels(accessToken, projectId, opts) {
28794
+ const now = Date.now();
28795
+ if (!opts?.force && servedModelsCache && now - servedModelsCacheAt < SERVED_MODELS_TTL_MS) {
28796
+ return servedModelsCache;
28797
+ }
28798
+ try {
28799
+ const data = await retrieveUserQuota(accessToken, projectId);
28800
+ const ids = (data?.buckets ?? []).map((b) => b.modelId).filter((m) => typeof m === "string" && m.length > 0);
28801
+ if (ids.length > 0) {
28802
+ const sorted = ids.slice().sort((a, b) => rankCodeAssistModel(a) - rankCodeAssistModel(b));
28803
+ servedModelsCache = sorted;
28804
+ servedModelsCacheAt = now;
28805
+ return sorted;
28806
+ }
28807
+ } catch (err) {
28808
+ log(`[GeminiOAuth] getServedCodeAssistModels error: ${err}`);
28809
+ }
28810
+ if (servedModelsCache)
28811
+ return servedModelsCache;
28812
+ return CODE_ASSIST_FALLBACK_CHAIN.slice().sort((a, b) => rankCodeAssistModel(a) - rankCodeAssistModel(b));
28813
+ }
28814
+ async function getValidAccessToken() {
28815
+ const oauth = GeminiOAuth.getInstance();
28816
+ return oauth.getAccessToken();
28817
+ }
28818
+ function resetGeminiUserCache() {
28819
+ cachedProjectId = null;
28820
+ cachedTierId = null;
28821
+ cachedTierName = null;
28822
+ cachedSetupError = null;
28823
+ }
28824
+ function getGeminiTierDisplayName() {
28825
+ if (!cachedTierId)
28826
+ return "GeminiCA";
28827
+ return TIER_SHORT_NAMES[cachedTierId] || cachedTierId.replace(/-tier$/, "");
28828
+ }
28829
+ function getGeminiTierFullName() {
28830
+ if (cachedTierName)
28831
+ return cachedTierName;
28832
+ return getGeminiTierDisplayName();
28833
+ }
28834
+ function makeTerminalSetupError(message) {
28835
+ const err = new Error(message);
28836
+ err.terminal = true;
28837
+ return err;
28838
+ }
28839
+ function buildProjectRequiredError(tierId, chosenTier, loadRes) {
28840
+ const tierLabel = chosenTier?.name || chosenTier?.displayName || tierId;
28841
+ const lines = [
28842
+ `Gemini Code Assist requires a Google Cloud project for the "${tierLabel}" tier (${tierId}), and none is configured.`,
28843
+ "",
28844
+ "Set the project that holds your Code Assist license:",
28845
+ " export GOOGLE_CLOUD_PROJECT='your-project-id'"
28846
+ ];
28847
+ const refused = loadRes.ineligibleTiers ?? [];
28848
+ if (refused.length > 0) {
28849
+ lines.push("", "Google refused the other tier(s) on this account:");
28850
+ for (const t of refused) {
28851
+ const name = t.tierName || t.tierId || "unknown tier";
28852
+ const code = t.reasonCode ? ` [${t.reasonCode}]` : "";
28853
+ lines.push(` \u2022 ${name}${code}`);
28854
+ if (t.reasonMessage)
28855
+ lines.push(` ${t.reasonMessage}`);
28856
+ }
28857
+ }
28858
+ lines.push("", "No project / no Code Assist seat? Use the direct Gemini API instead:", " export GEMINI_API_KEY='your-key' # https://aistudio.google.com/app/apikey", ' claudish --model google@gemini-2.5-pro "..."');
28859
+ return lines.join(`
28860
+ `);
28861
+ }
28862
+ async function setupGeminiUser(accessToken) {
28863
+ if (cachedProjectId && cachedTierId) {
28864
+ log(`[GeminiOAuth] Using cached project ID: ${cachedProjectId}, tier: ${cachedTierId}`);
28865
+ return { projectId: cachedProjectId, tierId: cachedTierId };
28866
+ }
28867
+ if (cachedSetupError) {
28868
+ log("[GeminiOAuth] Re-raising cached setup failure (no network retry)");
28869
+ throw makeTerminalSetupError(cachedSetupError);
28870
+ }
28871
+ const envProject = process.env.GOOGLE_CLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT_ID;
28872
+ log("[GeminiOAuth] Calling loadCodeAssist...");
28873
+ const loadRes = await callLoadCodeAssist(accessToken, envProject);
28874
+ log(`[GeminiOAuth] loadCodeAssist response: ${JSON.stringify(loadRes)}`);
28875
+ const resolvedTier = loadRes.paidTier?.id || (typeof loadRes.currentTier === "object" ? loadRes.currentTier?.id : loadRes.currentTier) || null;
28876
+ if ((loadRes.currentTier || loadRes.paidTier) && loadRes.cloudaicompanionProject) {
28877
+ const projectId2 = envProject || loadRes.cloudaicompanionProject;
28878
+ if (projectId2) {
28879
+ cachedProjectId = projectId2;
28880
+ cachedTierId = resolvedTier || "free-tier";
28881
+ cachedTierName = loadRes.paidTier?.name || null;
28882
+ log(`[GeminiOAuth] User already set up, project: ${projectId2}, tier: ${cachedTierId}`);
28883
+ return { projectId: projectId2, tierId: cachedTierId };
28884
+ }
28885
+ }
28886
+ const tierId = resolvedTier || loadRes.allowedTiers?.[0]?.id || "free-tier";
28887
+ const isFree = tierId === "free-tier";
28888
+ const onboardProject = isFree ? undefined : envProject;
28889
+ const chosenTier = loadRes.allowedTiers?.find((t) => t.id === tierId);
28890
+ if (!isFree && chosenTier?.userDefinedCloudaicompanionProject && !onboardProject) {
28891
+ cachedSetupError = buildProjectRequiredError(tierId, chosenTier, loadRes);
28892
+ throw makeTerminalSetupError(cachedSetupError);
28893
+ }
28894
+ const MAX_POLL_ATTEMPTS = 30;
28895
+ log(`[GeminiOAuth] Onboarding user to ${tierId}...`);
28896
+ let lro = await callOnboardUser(accessToken, tierId, onboardProject);
28897
+ log(`[GeminiOAuth] Initial onboardUser response: done=${lro.done}`);
28898
+ let attempts = 0;
28899
+ while (!lro.done && attempts < MAX_POLL_ATTEMPTS) {
28900
+ attempts++;
28901
+ log(`[GeminiOAuth] Polling onboardUser (attempt ${attempts}/${MAX_POLL_ATTEMPTS})...`);
28902
+ await new Promise((r) => setTimeout(r, 2000));
28903
+ lro = await callOnboardUser(accessToken, tierId, onboardProject);
28904
+ }
28905
+ if (!lro.done) {
28906
+ throw new Error(`Gemini onboarding timed out after ${MAX_POLL_ATTEMPTS * 2} seconds`);
28907
+ }
28908
+ if (lro.error) {
28909
+ throw new Error(`Gemini onboarding failed: ${JSON.stringify(lro.error)}`);
28910
+ }
28911
+ const projectId = lro.response?.cloudaicompanionProject?.id;
28912
+ if (!projectId) {
28913
+ if (envProject) {
28914
+ cachedProjectId = envProject;
28915
+ cachedTierId = tierId;
28916
+ return { projectId: envProject, tierId };
28917
+ }
28918
+ cachedSetupError = buildProjectRequiredError(tierId, chosenTier, loadRes);
28919
+ throw makeTerminalSetupError(cachedSetupError);
28920
+ }
28921
+ cachedProjectId = projectId;
28922
+ cachedTierId = tierId;
28923
+ log(`[GeminiOAuth] Onboarding complete, project: ${projectId}, tier: ${tierId}`);
28924
+ return { projectId, tierId };
28925
+ }
28926
+ async function callLoadCodeAssist(accessToken, projectId) {
28927
+ const metadata = GEMINI_IDENTITY_IS_ANTIGRAVITY ? { ideType: GEMINI_IDE_TYPE } : {
28928
+ pluginType: "GEMINI",
28929
+ ideType: GEMINI_IDE_TYPE,
28930
+ platform: "PLATFORM_UNSPECIFIED",
28931
+ duetProject: projectId
28932
+ };
28933
+ const res = await fetch(`${CODE_ASSIST_API_BASE}:loadCodeAssist`, {
28934
+ method: "POST",
28935
+ headers: {
28936
+ Authorization: `Bearer ${accessToken}`,
28937
+ "Content-Type": "application/json",
28938
+ "User-Agent": buildCodeAssistUserAgent()
28939
+ },
28940
+ body: JSON.stringify({ metadata, cloudaicompanionProject: projectId })
28941
+ });
28942
+ if (!res.ok) {
28943
+ throw new Error(`loadCodeAssist failed: ${res.status} ${await res.text()}`);
28944
+ }
28945
+ return await res.json();
28946
+ }
28947
+ async function callOnboardUser(accessToken, tierId, projectId) {
28948
+ const metadata = {
28949
+ pluginType: "GEMINI",
28950
+ ideType: GEMINI_IDE_TYPE,
28951
+ platform: "PLATFORM_UNSPECIFIED",
28952
+ duetProject: projectId
28953
+ };
28954
+ const res = await fetch(`${CODE_ASSIST_API_BASE}:onboardUser`, {
28955
+ method: "POST",
28956
+ headers: {
28957
+ Authorization: `Bearer ${accessToken}`,
28958
+ "Content-Type": "application/json",
28959
+ "User-Agent": buildCodeAssistUserAgent()
28960
+ },
28961
+ body: JSON.stringify({
28962
+ tierId,
28963
+ metadata,
28964
+ cloudaicompanionProject: projectId
28965
+ })
28966
+ });
28967
+ if (!res.ok) {
28968
+ throw new Error(`onboardUser failed: ${res.status} ${await res.text()}`);
28969
+ }
28970
+ return await res.json();
28971
+ }
28972
+ async function retrieveUserQuota(accessToken, projectId) {
28973
+ try {
28974
+ const res = await fetch(`${CODE_ASSIST_API_BASE}:retrieveUserQuota`, {
28975
+ method: "POST",
28976
+ headers: {
28977
+ Authorization: `Bearer ${accessToken}`,
28978
+ "Content-Type": "application/json",
28979
+ "User-Agent": `GeminiCLI/0.5.6/gemini-code-assist (${process.platform}; ${process.arch})`
28980
+ },
28981
+ body: JSON.stringify({ project: projectId })
28982
+ });
28983
+ if (!res.ok) {
28984
+ log(`[GeminiOAuth] retrieveUserQuota failed: ${res.status}`);
28985
+ return null;
28986
+ }
28987
+ return await res.json();
28988
+ } catch (err) {
28989
+ log(`[GeminiOAuth] retrieveUserQuota error: ${err}`);
28990
+ return null;
28991
+ }
28992
+ }
28993
+ function buildAntigravityUserAgent() {
28994
+ return `antigravity/cli/1.1.9 (aidev_client; os_type=${process.platform}; arch=${process.arch}; auth_method=consumer)`;
28995
+ }
28996
+ async function callLoadCodeAssistAntigravity(accessToken) {
28997
+ const res = await fetch(`${CODE_ASSIST_API_BASE}:loadCodeAssist`, {
28998
+ method: "POST",
28999
+ headers: {
29000
+ Authorization: `Bearer ${accessToken}`,
29001
+ "Content-Type": "application/json",
29002
+ "User-Agent": buildAntigravityUserAgent()
29003
+ },
29004
+ body: JSON.stringify({ metadata: { ideType: ANTIGRAVITY_IDE_TYPE } })
29005
+ });
29006
+ if (!res.ok) {
29007
+ throw new Error(`loadCodeAssist (antigravity) failed: ${res.status} ${await res.text()}`);
29008
+ }
29009
+ return await res.json();
29010
+ }
29011
+ async function setupAntigravityUser(accessToken) {
29012
+ if (cachedAgProjectId && cachedAgTierId) {
29013
+ return { projectId: cachedAgProjectId, tierId: cachedAgTierId };
29014
+ }
29015
+ const loadRes = await callLoadCodeAssistAntigravity(accessToken);
29016
+ log(`[Antigravity] loadCodeAssist response: ${JSON.stringify(loadRes)}`);
29017
+ const resolvedTier = loadRes.paidTier?.id || (typeof loadRes.currentTier === "object" ? loadRes.currentTier?.id : loadRes.currentTier) || "free-tier";
29018
+ const projectId = loadRes.cloudaicompanionProject;
29019
+ if (!projectId) {
29020
+ throw makeTerminalSetupError("Antigravity did not return a project for this account. Sign in to Antigravity " + "(the `agy` CLI) and try again, or use g@<model> with GEMINI_API_KEY " + "(get one at https://aistudio.google.com/app/apikey).");
29021
+ }
29022
+ cachedAgProjectId = projectId;
29023
+ cachedAgTierId = resolvedTier;
29024
+ cachedAgTierName = loadRes.paidTier?.name || null;
29025
+ log(`[Antigravity] User set up, project: ${projectId}, tier: ${resolvedTier}`);
29026
+ return { projectId, tierId: resolvedTier };
29027
+ }
29028
+ function getAntigravityTierDisplayName() {
29029
+ if (!cachedAgTierName && !cachedAgTierId)
29030
+ return "Antigravity";
29031
+ const id = cachedAgTierId || "";
29032
+ if (id.includes("ultra"))
29033
+ return "Antigravity Ultra";
29034
+ if (id.includes("pro"))
29035
+ return "Antigravity Pro";
29036
+ if (id === "free-tier")
29037
+ return "Antigravity Free";
29038
+ return cachedAgTierName || "Antigravity";
29039
+ }
29040
+ async function getServedAntigravityModels(accessToken, projectId, opts) {
29041
+ const now = Date.now();
29042
+ if (!opts?.force && agServedCache && now - agServedCacheAt < SERVED_MODELS_TTL_MS) {
29043
+ return agServedCache;
29044
+ }
29045
+ try {
29046
+ const res = await fetch(`${CODE_ASSIST_API_BASE}:fetchAvailableModels`, {
29047
+ method: "POST",
29048
+ headers: {
29049
+ Authorization: `Bearer ${accessToken}`,
29050
+ "Content-Type": "application/json",
29051
+ "User-Agent": buildAntigravityUserAgent()
29052
+ },
29053
+ body: JSON.stringify({ project: projectId })
29054
+ });
29055
+ if (res.ok) {
29056
+ const data = await res.json();
29057
+ const servedIds = data.models ? Object.keys(data.models) : [];
29058
+ const defaultId = typeof data.defaultAgentModelId === "string" ? data.defaultAgentModelId : null;
29059
+ if (servedIds.length > 0) {
29060
+ agServedCache = { servedIds, defaultId };
29061
+ agServedCacheAt = now;
29062
+ return agServedCache;
29063
+ }
29064
+ } else {
29065
+ log(`[Antigravity] fetchAvailableModels failed: ${res.status}`);
29066
+ }
29067
+ } catch (err) {
29068
+ log(`[Antigravity] fetchAvailableModels error: ${err}`);
29069
+ }
29070
+ if (agServedCache)
29071
+ return agServedCache;
29072
+ return { servedIds: [], defaultId: null };
29073
+ }
29074
+ var execAsync, getDefaultClientId = () => {
29075
+ const parts = [
29076
+ "681255809395",
29077
+ "oo8ft2oprdrnp9e3aqf6av3hmdib135j",
29078
+ "apps",
29079
+ "googleusercontent",
29080
+ "com"
29081
+ ];
29082
+ return `${parts[0]}-${parts[1]}.${parts[2]}.${parts[3]}.${parts[4]}`;
29083
+ }, getDefaultClientSecret = () => {
29084
+ const p = ["GOCSPX", "4uHgMPm", "1o7Sk", "geV6Cu5clXFsxl"];
29085
+ return `${p[0]}-${p[1]}-${p[2]}-${p[3]}`;
29086
+ }, OAUTH_CONFIG, USE_ANTIGRAVITY_GEMINI_IDENTITY, USE_LEGACY_GEMINI_IDENTITY, GEMINI_IDE_TYPE, GEMINI_IDENTITY_IS_ANTIGRAVITY, CODE_ASSIST_API_BASE = "https://cloudcode-pa.googleapis.com/v1internal", CODE_ASSIST_FALLBACK_CHAIN, servedModelsCache = null, servedModelsCacheAt = 0, SERVED_MODELS_TTL_MS, cachedProjectId = null, cachedTierId = null, cachedTierName = null, cachedSetupError = null, TIER_SHORT_NAMES, ANTIGRAVITY_IDE_TYPE = "ANTIGRAVITY", cachedAgProjectId = null, cachedAgTierId = null, cachedAgTierName = null, agServedCache = null, agServedCacheAt = 0;
29087
+ var init_gemini_oauth = __esm(() => {
28711
29088
  init_logger();
28712
29089
  execAsync = promisify(exec);
28713
29090
  OAUTH_CONFIG = {
28714
- clientId: "app_EMoamEEZ73f0CkXaXp7hrann",
28715
- authUrl: "https://auth.openai.com/oauth/authorize",
28716
- tokenUrl: "https://auth.openai.com/oauth/token",
28717
- scopes: ["openid", "profile", "email", "offline_access"]
29091
+ clientId: process.env.GEMINI_CLIENT_ID || getDefaultClientId(),
29092
+ clientSecret: process.env.GEMINI_CLIENT_SECRET || getDefaultClientSecret(),
29093
+ authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
29094
+ tokenUrl: "https://oauth2.googleapis.com/token",
29095
+ scopes: [
29096
+ "https://www.googleapis.com/auth/cloud-platform",
29097
+ "https://www.googleapis.com/auth/userinfo.email",
29098
+ "https://www.googleapis.com/auth/userinfo.profile"
29099
+ ]
29100
+ };
29101
+ USE_ANTIGRAVITY_GEMINI_IDENTITY = process.env.CLAUDISH_GEMINI_ANTIGRAVITY === "1";
29102
+ USE_LEGACY_GEMINI_IDENTITY = !USE_ANTIGRAVITY_GEMINI_IDENTITY;
29103
+ GEMINI_IDE_TYPE = USE_LEGACY_GEMINI_IDENTITY ? "GEMINI_CLI" : "ANTIGRAVITY";
29104
+ GEMINI_IDENTITY_IS_ANTIGRAVITY = !USE_LEGACY_GEMINI_IDENTITY;
29105
+ CODE_ASSIST_FALLBACK_CHAIN = [
29106
+ "gemini-2.5-pro",
29107
+ "gemini-2.5-flash",
29108
+ "gemini-2.5-flash-lite",
29109
+ "gemini-3.1-flash-lite"
29110
+ ];
29111
+ SERVED_MODELS_TTL_MS = 10 * 60 * 1000;
29112
+ TIER_SHORT_NAMES = {
29113
+ "free-tier": "GeminiCA Free",
29114
+ "standard-tier": "GeminiCA Std",
29115
+ "g1-pro-tier": "GeminiCA Pro",
29116
+ "legacy-tier": "GeminiCA Legacy"
28718
29117
  };
28719
29118
  });
28720
29119
 
28721
- // src/auth/credentials/composite-credential.ts
28722
- class CompositeCredentialProvider {
28723
- catalogName;
28724
- primary;
28725
- fallback;
28726
- opts;
28727
- constructor(catalogName, primary, fallback, opts = {}) {
28728
- this.catalogName = catalogName;
28729
- this.primary = primary;
28730
- this.fallback = fallback;
28731
- this.opts = opts;
29120
+ // src/handlers/shared/gemini-queue.ts
29121
+ class GeminiRequestQueue {
29122
+ static instance = null;
29123
+ queue = [];
29124
+ processing = false;
29125
+ minDelayMs = 1000;
29126
+ lastRequestTime = 0;
29127
+ consecutiveErrors = 0;
29128
+ totalProcessed = 0;
29129
+ totalErrors = 0;
29130
+ baseDelayMs = 1000;
29131
+ maxDelayMs = 1e4;
29132
+ maxQueueSize = 100;
29133
+ constructor() {
29134
+ log("[GeminiQueue] Queue initialized with minDelay=1000ms, maxQueueSize=100");
28732
29135
  }
28733
- async isAvailable(opts) {
28734
- return await this.primary.isAvailable(opts) || await this.fallback.isAvailable(opts);
29136
+ static getInstance() {
29137
+ if (!GeminiRequestQueue.instance) {
29138
+ GeminiRequestQueue.instance = new GeminiRequestQueue;
29139
+ }
29140
+ return GeminiRequestQueue.instance;
28735
29141
  }
28736
- invalidate() {
28737
- this.primary.invalidate?.();
28738
- this.fallback.invalidate?.();
29142
+ async enqueue(fetchFn) {
29143
+ if (this.queue.length >= this.maxQueueSize) {
29144
+ log(`[GeminiQueue] Queue full (${this.queue.length}/${this.maxQueueSize}), rejecting request`);
29145
+ throw new Error("Gemini request queue full. Please retry later.");
29146
+ }
29147
+ return new Promise((resolve, reject) => {
29148
+ const queuedRequest = {
29149
+ fetchFn,
29150
+ resolve,
29151
+ reject
29152
+ };
29153
+ this.queue.push(queuedRequest);
29154
+ log(`[GeminiQueue] Request enqueued (queue length: ${this.queue.length})`);
29155
+ if (!this.processing) {
29156
+ this.processQueue();
29157
+ }
29158
+ });
28739
29159
  }
28740
- async getRequestAuth(ctx) {
28741
- if (await this.primary.isAvailable({ allowOpPrompt: ctx.allowOpPrompt })) {
29160
+ async processQueue() {
29161
+ if (this.processing) {
29162
+ return;
29163
+ }
29164
+ this.processing = true;
29165
+ log("[GeminiQueue] Worker started");
29166
+ while (this.queue.length > 0) {
29167
+ const request = this.queue.shift();
29168
+ if (!request)
29169
+ break;
29170
+ log(`[GeminiQueue] Processing request (${this.queue.length} remaining in queue)`);
28742
29171
  try {
28743
- return await this.primary.getRequestAuth(ctx);
28744
- } catch (e) {
28745
- const signal = this.opts.fallbackSignal;
28746
- if (signal && String(e?.message) === signal) {
28747
- return this.fallback.getRequestAuth(ctx);
29172
+ await this.waitForNextSlot();
29173
+ const response = await request.fetchFn();
29174
+ this.lastRequestTime = Date.now();
29175
+ if (response.status === 429) {
29176
+ this.totalErrors++;
29177
+ const errorText = await response.clone().text();
29178
+ this.handleRateLimitResponse(errorText);
29179
+ log(`[GeminiQueue] Rate limit hit (429), adjusted delay to ${this.minDelayMs}ms`);
29180
+ } else {
29181
+ this.handleSuccessResponse();
28748
29182
  }
28749
- throw e;
29183
+ this.totalProcessed++;
29184
+ request.resolve(response);
29185
+ } catch (error46) {
29186
+ this.totalErrors++;
29187
+ log(`[GeminiQueue] Request failed with error: ${error46}`);
29188
+ request.reject(error46 instanceof Error ? error46 : new Error(String(error46)));
28750
29189
  }
28751
29190
  }
28752
- return this.fallback.getRequestAuth(ctx);
29191
+ this.processing = false;
29192
+ log("[GeminiQueue] Worker stopped (queue empty)");
28753
29193
  }
28754
- async login() {
28755
- await this.primary.login?.();
29194
+ async waitForNextSlot() {
29195
+ const now = Date.now();
29196
+ const timeSinceLastRequest = now - this.lastRequestTime;
29197
+ let delayMs = this.minDelayMs;
29198
+ if (this.consecutiveErrors > 0) {
29199
+ const backoffMultiplier = 1 + this.consecutiveErrors * 0.5;
29200
+ delayMs = Math.min(this.minDelayMs * backoffMultiplier, this.maxDelayMs);
29201
+ log(`[GeminiQueue] Applying backoff (${this.consecutiveErrors} errors): ${delayMs}ms`);
29202
+ }
29203
+ if (timeSinceLastRequest < delayMs) {
29204
+ const waitMs = delayMs - timeSinceLastRequest;
29205
+ log(`[GeminiQueue] Waiting ${waitMs}ms before next request`);
29206
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
29207
+ }
28756
29208
  }
28757
- async logout() {
28758
- await this.primary.logout?.();
29209
+ handleRateLimitResponse(errorText) {
29210
+ this.consecutiveErrors++;
29211
+ try {
29212
+ const errorData = JSON.parse(errorText);
29213
+ const quotaDetail = errorData?.error?.details?.find((d) => d.quotaResetDelay);
29214
+ if (quotaDetail?.quotaResetDelay) {
29215
+ const delayStr = quotaDetail.quotaResetDelay;
29216
+ const match = delayStr.match(/(\d+(?:\.\d+)?)/);
29217
+ if (match) {
29218
+ const delaySeconds = Number.parseFloat(match[1]);
29219
+ const suggestedDelayMs = Math.ceil(delaySeconds * 1000);
29220
+ this.minDelayMs = Math.max(suggestedDelayMs, this.minDelayMs, this.baseDelayMs);
29221
+ this.minDelayMs = Math.min(this.minDelayMs, this.maxDelayMs);
29222
+ log(`[GeminiQueue] Parsed quotaResetDelay: ${delayStr} (${suggestedDelayMs}ms), ` + `new minDelay: ${this.minDelayMs}ms`);
29223
+ }
29224
+ }
29225
+ } catch {
29226
+ log("[GeminiQueue] Failed to parse rate limit response, using backoff");
29227
+ }
29228
+ const backoffMultiplier = 1 + this.consecutiveErrors * 0.5;
29229
+ this.minDelayMs = Math.min(this.baseDelayMs * backoffMultiplier, this.maxDelayMs);
29230
+ }
29231
+ handleSuccessResponse() {
29232
+ if (this.consecutiveErrors > 0) {
29233
+ log(`[GeminiQueue] Success after ${this.consecutiveErrors} errors, resetting counter`);
29234
+ this.consecutiveErrors = 0;
29235
+ }
29236
+ if (this.minDelayMs > this.baseDelayMs) {
29237
+ this.minDelayMs = Math.max(this.baseDelayMs, this.minDelayMs * 0.9);
29238
+ log(`[GeminiQueue] Reducing delay to ${this.minDelayMs}ms`);
29239
+ }
29240
+ }
29241
+ getStats() {
29242
+ return {
29243
+ queueLength: this.queue.length,
29244
+ processing: this.processing,
29245
+ consecutiveErrors: this.consecutiveErrors,
29246
+ currentDelayMs: this.minDelayMs,
29247
+ totalProcessed: this.totalProcessed,
29248
+ totalErrors: this.totalErrors
29249
+ };
28759
29250
  }
28760
29251
  }
29252
+ var init_gemini_queue = __esm(() => {
29253
+ init_logger();
29254
+ });
28761
29255
 
28762
- // src/auth/credentials/codex-credential.ts
28763
- function buildOAuthHeaders(token, accountId) {
28764
- const headers = {
28765
- Authorization: `Bearer ${token}`,
28766
- "OpenAI-Beta": "responses=experimental",
28767
- originator: "codex_cli_rs",
28768
- accept: "text/event-stream"
28769
- };
28770
- if (accountId) {
28771
- headers["chatgpt-account-id"] = accountId;
28772
- headers["x-conversation-id"] = "claudish-session";
28773
- headers["x-session-id"] = "claudish-session";
29256
+ // src/providers/transport/antigravity.ts
29257
+ import { randomUUID } from "crypto";
29258
+ function rankReasoningSuffix(suffix) {
29259
+ const rank = REASONING_TIER_RANK[suffix.toLowerCase()];
29260
+ return rank === undefined ? Number.MAX_SAFE_INTEGER : rank;
29261
+ }
29262
+ function resolveAntigravityModelId(requested, servedIds, defaultId) {
29263
+ const req = requested.trim();
29264
+ if (servedIds.includes(req))
29265
+ return req;
29266
+ const familyPrefix = `${req}-`;
29267
+ const variants = servedIds.filter((id) => id.startsWith(familyPrefix));
29268
+ if (variants.length > 0) {
29269
+ if (defaultId && variants.includes(defaultId))
29270
+ return defaultId;
29271
+ let best = variants[0];
29272
+ let bestRank = rankReasoningSuffix(best.slice(familyPrefix.length));
29273
+ for (const variant of variants.slice(1)) {
29274
+ const rank = rankReasoningSuffix(variant.slice(familyPrefix.length));
29275
+ if (rank < bestRank) {
29276
+ best = variant;
29277
+ bestRank = rank;
29278
+ }
29279
+ }
29280
+ return best;
29281
+ }
29282
+ return req;
29283
+ }
29284
+ function createActivityRequestId() {
29285
+ return Math.random().toString(36).substring(7);
29286
+ }
29287
+ function classify429(responseBody) {
29288
+ try {
29289
+ const raw = JSON.parse(responseBody);
29290
+ const error46 = Array.isArray(raw) ? raw[0]?.error : raw?.error;
29291
+ const details = Array.isArray(error46?.details) ? error46.details : [];
29292
+ const retryInfo = details.find((d) => d["@type"] === "type.googleapis.com/google.rpc.RetryInfo");
29293
+ let retryDelayMs = parseRetryDelay(retryInfo?.retryDelay);
29294
+ if (retryDelayMs === undefined && typeof error46?.message === "string") {
29295
+ const match = error46.message.match(/retry in ([\d.]+)(ms|s)/i);
29296
+ if (match) {
29297
+ const val = Number.parseFloat(match[1]);
29298
+ retryDelayMs = match[2] === "ms" ? Math.round(val) : Math.round(val * 1000);
29299
+ }
29300
+ }
29301
+ const errorInfo = details.find((d) => d["@type"] === "type.googleapis.com/google.rpc.ErrorInfo");
29302
+ const reason = errorInfo?.reason;
29303
+ if (reason === "QUOTA_EXHAUSTED") {
29304
+ return { terminal: true, retryDelayMs, reason };
29305
+ }
29306
+ if (reason === "RATE_LIMIT_EXCEEDED") {
29307
+ return { terminal: false, retryDelayMs: retryDelayMs ?? DEFAULT_RATE_LIMIT_DELAY_MS, reason };
29308
+ }
29309
+ if (reason === "MODEL_CAPACITY_EXHAUSTED") {
29310
+ return { terminal: true, retryDelayMs, reason };
29311
+ }
29312
+ const quotaFailure = details.find((d) => d["@type"] === "type.googleapis.com/google.rpc.QuotaFailure");
29313
+ if (quotaFailure?.violations?.length) {
29314
+ const text = quotaFailure.violations.map((v) => `${v.quotaId || ""} ${v.description || ""}`).join(" ").toLowerCase();
29315
+ if (text.includes("perday") || text.includes("daily") || text.includes("per day")) {
29316
+ return { terminal: true, retryDelayMs, reason };
29317
+ }
29318
+ if (text.includes("perminute") || text.includes("per minute")) {
29319
+ return { terminal: false, retryDelayMs: retryDelayMs ?? 60000, reason };
29320
+ }
29321
+ }
29322
+ return { terminal: false, retryDelayMs, reason };
29323
+ } catch {
29324
+ return null;
28774
29325
  }
28775
- return headers;
29326
+ }
29327
+ function parseRetryDelay(value) {
29328
+ if (!value)
29329
+ return;
29330
+ if (typeof value === "string") {
29331
+ const match = value.match(/([\d.]+)s/);
29332
+ return match ? Math.round(Number.parseFloat(match[1]) * 1000) : undefined;
29333
+ }
29334
+ if (typeof value === "object") {
29335
+ const seconds = typeof value.seconds === "number" ? value.seconds : 0;
29336
+ const nanos = typeof value.nanos === "number" ? value.nanos : 0;
29337
+ const ms = Math.round(seconds * 1000 + nanos / 1e6);
29338
+ return ms > 0 ? ms : undefined;
29339
+ }
29340
+ return;
28776
29341
  }
28777
29342
 
28778
- class CodexOAuthHalf {
28779
- catalogName = "openai-codex";
28780
- oauth = CodexOAuth.getInstance();
28781
- async isAvailable() {
28782
- return this.oauth.hasCredentials();
29343
+ class AntigravityProviderTransport {
29344
+ name = "antigravity";
29345
+ _displayName = "Antigravity";
29346
+ get displayName() {
29347
+ return this._displayName;
28783
29348
  }
28784
- async getRequestAuth(_ctx) {
28785
- const token = await this.oauth.getAccessToken();
28786
- const accountId = this.oauth.getAccountId();
29349
+ streamFormat = "gemini-sse";
29350
+ modelName;
29351
+ servedModelName;
29352
+ accessToken = null;
29353
+ projectId = null;
29354
+ tierId = null;
29355
+ cachedAuth = null;
29356
+ lastEnvelope = null;
29357
+ _activeModelName;
29358
+ servedModels = [];
29359
+ defaultServedModel = null;
29360
+ constructor(modelName) {
29361
+ this.modelName = modelName;
29362
+ this.servedModelName = modelName;
29363
+ }
29364
+ getActiveModelName() {
29365
+ return this._activeModelName;
29366
+ }
29367
+ getEndpoint() {
29368
+ return CODE_ASSIST_ENDPOINT;
29369
+ }
29370
+ async getHeaders() {
29371
+ if (this.cachedAuth)
29372
+ return { ...this.cachedAuth.headers };
29373
+ return this.buildLocalHeaders();
29374
+ }
29375
+ buildLocalHeaders() {
28787
29376
  return {
28788
- headers: buildOAuthHeaders(token, accountId),
28789
- endpoint: CODEX_RESPONSES_ENDPOINT,
28790
- transformPayload: (p) => ({
28791
- ...p,
28792
- store: false,
28793
- include: ["reasoning.encrypted_content"]
28794
- })
29377
+ Authorization: `Bearer ${this.accessToken}`,
29378
+ "User-Agent": buildAntigravityUserAgent(),
29379
+ "x-activity-request-id": createActivityRequestId()
28795
29380
  };
28796
29381
  }
28797
- async login() {
28798
- await this.oauth.login();
29382
+ async refreshAuth() {
29383
+ this.cachedAuth = await credentials.getRequestAuth("antigravity", {
29384
+ model: this.modelName
29385
+ });
29386
+ this.accessToken = await getValidAntigravityAccessToken();
29387
+ const { projectId, tierId } = await setupAntigravityUser(this.accessToken);
29388
+ this.projectId = projectId;
29389
+ this.tierId = tierId;
29390
+ this._displayName = getAntigravityTierDisplayName();
29391
+ const served = await getServedAntigravityModels(this.accessToken, this.projectId);
29392
+ this.servedModels = served.servedIds;
29393
+ this.defaultServedModel = served.defaultId;
29394
+ this.servedModelName = resolveAntigravityModelId(this.modelName, this.servedModels, this.defaultServedModel);
29395
+ log(`[Antigravity] Auth refreshed, project: ${this.projectId}, tier: ${this._displayName}, ` + `model: ${this.modelName} -> ${this.servedModelName}, served: ${this.servedModels.join(",") || "(none)"}`);
28799
29396
  }
28800
- async logout() {
28801
- await this.oauth.logout();
29397
+ transformPayload(payload) {
29398
+ const envelope = this.cachedAuth?.transformPayload ? this.cachedAuth.transformPayload(payload) : this.buildEnvelope(payload, this.servedModelName);
29399
+ this.lastEnvelope = envelope;
29400
+ return envelope;
29401
+ }
29402
+ buildEnvelope(innerPayload, model) {
29403
+ const envelope = {
29404
+ model,
29405
+ project: this.projectId,
29406
+ user_prompt_id: randomUUID(),
29407
+ request: innerPayload
29408
+ };
29409
+ if (this.tierId && this.tierId !== "free-tier") {
29410
+ envelope.enabled_credit_types = ["GOOGLE_ONE_AI"];
29411
+ }
29412
+ return envelope;
29413
+ }
29414
+ async enqueueRequest(fetchFn) {
29415
+ const queue = GeminiRequestQueue.getInstance();
29416
+ let lastResponse = null;
29417
+ for (let attempt = 1;attempt <= MAX_RETRY_ATTEMPTS; attempt++) {
29418
+ const response = attempt === 1 ? await queue.enqueue(fetchFn) : await queue.enqueue(fetchFn);
29419
+ if (response.status !== 429) {
29420
+ if (response.status === 404) {
29421
+ return this.rewriteModelNotFound(response);
29422
+ }
29423
+ return response;
29424
+ }
29425
+ const bodyText = await response.clone().text();
29426
+ const classification = classify429(bodyText);
29427
+ lastResponse = response;
29428
+ if (!classification) {
29429
+ log("[Antigravity] 429 response could not be classified, returning to caller");
29430
+ return response;
29431
+ }
29432
+ log(`[Antigravity] 429 classified: reason=${classification.reason}, terminal=${classification.terminal}, delay=${classification.retryDelayMs}ms`);
29433
+ if (classification.reason === "MODEL_CAPACITY_EXHAUSTED") {
29434
+ return this.handleCapacityExhausted(response, queue);
29435
+ }
29436
+ if (classification.terminal) {
29437
+ logStderr(`[Antigravity] Quota exhausted (${classification.reason || "daily limit"}). Check plan limits.`);
29438
+ return response;
29439
+ }
29440
+ if (attempt < MAX_RETRY_ATTEMPTS) {
29441
+ const delay = classification.retryDelayMs ?? DEFAULT_RATE_LIMIT_DELAY_MS;
29442
+ logStderr(`[Antigravity] Rate limited (${classification.reason || "unknown"}), retrying in ${(delay / 1000).toFixed(1)}s (attempt ${attempt}/${MAX_RETRY_ATTEMPTS})`);
29443
+ if (attempt === 1) {
29444
+ await this.logQuotaInfo();
29445
+ }
29446
+ await new Promise((r) => setTimeout(r, delay));
29447
+ }
29448
+ }
29449
+ logStderr(`[Antigravity] Rate limit persisted after ${MAX_RETRY_ATTEMPTS} retries`);
29450
+ return lastResponse;
29451
+ }
29452
+ async handleCapacityExhausted(originalResponse, queue) {
29453
+ const candidates = this.servedModels.filter((m) => m !== this.servedModelName);
29454
+ if (candidates.length === 0) {
29455
+ log(`[Antigravity] ${this.servedModelName} capacity exhausted, no fallback models available`);
29456
+ return originalResponse;
29457
+ }
29458
+ if (!this.lastEnvelope) {
29459
+ log(`[Antigravity] ${this.servedModelName} capacity exhausted but no stored envelope for retry`);
29460
+ return originalResponse;
29461
+ }
29462
+ log(`[Antigravity] Model ${this.servedModelName} capacity exhausted, starting fallback chain`);
29463
+ logStderr(`[Antigravity] ${this.servedModelName} capacity exhausted, trying fallback models...`);
29464
+ let lastResponse = originalResponse;
29465
+ const innerPayload = this.lastEnvelope.request;
29466
+ const endpoint = this.getEndpoint();
29467
+ const tried = [this.servedModelName];
29468
+ for (const fallbackModel of candidates) {
29469
+ log(`[Antigravity] Trying fallback model: ${fallbackModel}`);
29470
+ tried.push(fallbackModel);
29471
+ const fallbackEnvelope = this.buildEnvelope(innerPayload, fallbackModel);
29472
+ const headers = this.buildLocalHeaders();
29473
+ headers["Content-Type"] = "application/json";
29474
+ const fallbackResponse = await queue.enqueue(() => fetch(endpoint, {
29475
+ method: "POST",
29476
+ headers,
29477
+ body: JSON.stringify(fallbackEnvelope)
29478
+ }));
29479
+ if (fallbackResponse.status === 200) {
29480
+ this._activeModelName = fallbackModel;
29481
+ logStderr(`[Antigravity] Using fallback model: ${fallbackModel} (${this.servedModelName} had no capacity)`);
29482
+ return fallbackResponse;
29483
+ }
29484
+ if (fallbackResponse.status === 404) {
29485
+ log(`[Antigravity] ${fallbackModel} returned 404, skipping to next fallback`);
29486
+ lastResponse = fallbackResponse;
29487
+ continue;
29488
+ }
29489
+ if (fallbackResponse.status === 429) {
29490
+ const fallbackBodyText = await fallbackResponse.clone().text();
29491
+ const classification = classify429(fallbackBodyText);
29492
+ if (classification?.reason === "MODEL_CAPACITY_EXHAUSTED") {
29493
+ log(`[Antigravity] ${fallbackModel} also capacity exhausted, trying next...`);
29494
+ lastResponse = fallbackResponse;
29495
+ continue;
29496
+ }
29497
+ return fallbackResponse;
29498
+ }
29499
+ return fallbackResponse;
29500
+ }
29501
+ log("[Antigravity] All fallback models exhausted");
29502
+ logStderr(`[Antigravity] All models capacity exhausted (tried: ${tried.join(" -> ")})`);
29503
+ if (lastResponse.status === 404) {
29504
+ return this.rewriteModelNotFound(lastResponse, true);
29505
+ }
29506
+ return lastResponse;
29507
+ }
29508
+ rewriteModelNotFound(response, capacityFallbacksExhausted = false) {
29509
+ const served = this.servedModels;
29510
+ if (!capacityFallbacksExhausted && served.includes(this.servedModelName)) {
29511
+ log(`[Antigravity] 404 for ${this.servedModelName}, which IS in the served set \u2014 passing through unmodified`);
29512
+ return response;
29513
+ }
29514
+ response.text().catch(() => {});
29515
+ const servesClause = served.length > 0 ? `That tier currently serves: ${served.join(", ")}. ` : "";
29516
+ const tier = this._displayName || "Antigravity";
29517
+ const reason = capacityFallbacksExhausted ? `${this.modelName} could not be served after every Antigravity capacity fallback failed (${tier}, via ag@). ` + servesClause : `${this.modelName} is not served by your Antigravity tier (${tier}, via ag@). ` + servesClause;
29518
+ const message = reason + `To use ${this.modelName}, go through the direct Gemini API instead \u2014 ` + `set GEMINI_API_KEY (get one at https://aistudio.google.com/app/apikey) and run ` + `google@${this.modelName}.`;
29519
+ const list = served.join(", ");
29520
+ const body = JSON.stringify({
29521
+ error: { code: 404, status: "NOT_FOUND", message }
29522
+ });
29523
+ if (capacityFallbacksExhausted) {
29524
+ logStderr(`[Antigravity] ${this.modelName} capacity fallbacks exhausted (404). Reported models: ${list}`);
29525
+ } else {
29526
+ logStderr(`[Antigravity] ${this.modelName} not served by ${tier} (404). Serves: ${list}`);
29527
+ }
29528
+ return new Response(body, {
29529
+ status: 404,
29530
+ headers: { "Content-Type": "application/json" }
29531
+ });
29532
+ }
29533
+ async logQuotaInfo() {
29534
+ if (!this.accessToken || !this.projectId)
29535
+ return;
29536
+ try {
29537
+ const data = await retrieveUserQuota(this.accessToken, this.projectId);
29538
+ if (!data?.buckets?.length)
29539
+ return;
29540
+ const lines = [];
29541
+ for (const bucket of data.buckets) {
29542
+ if (!bucket.modelId)
29543
+ continue;
29544
+ const pct = typeof bucket.remainingFraction === "number" ? `${(bucket.remainingFraction * 100).toFixed(1)}%` : "?";
29545
+ const reset = bucket.resetTime ? new Date(bucket.resetTime).toLocaleTimeString([], {
29546
+ hour: "2-digit",
29547
+ minute: "2-digit"
29548
+ }) : "?";
29549
+ lines.push(` ${bucket.modelId}: ${pct} remaining (resets ${reset})`);
29550
+ }
29551
+ if (lines.length > 0) {
29552
+ logStderr(`[Antigravity] Quota status:
29553
+ ${lines.join(`
29554
+ `)}`);
29555
+ }
29556
+ } catch {}
29557
+ }
29558
+ async getQuotaRemaining(modelName) {
29559
+ if (!this.accessToken || !this.projectId)
29560
+ return;
29561
+ try {
29562
+ const data = await retrieveUserQuota(this.accessToken, this.projectId);
29563
+ if (!data?.buckets?.length)
29564
+ return;
29565
+ const bucket = data.buckets.find((b) => b.modelId === modelName);
29566
+ return typeof bucket?.remainingFraction === "number" ? bucket.remainingFraction : undefined;
29567
+ } catch {
29568
+ return;
29569
+ }
28802
29570
  }
28803
29571
  }
28804
- function makeCodexCredential() {
28805
- return new CompositeCredentialProvider("openai-codex", new CodexOAuthHalf, new ApiKeyCredentialProvider({
28806
- catalogName: "openai-codex",
28807
- envVar: "OPENAI_CODEX_API_KEY"
28808
- }));
29572
+ var CODE_ASSIST_BASE = "https://cloudcode-pa.googleapis.com", CODE_ASSIST_ENDPOINT, MAX_RETRY_ATTEMPTS = 3, DEFAULT_RATE_LIMIT_DELAY_MS = 1e4, REASONING_TIER_RANK;
29573
+ var init_antigravity = __esm(() => {
29574
+ init_authority();
29575
+ init_antigravity_token();
29576
+ init_gemini_oauth();
29577
+ init_gemini_queue();
29578
+ init_logger();
29579
+ CODE_ASSIST_ENDPOINT = `${CODE_ASSIST_BASE}/v1internal:streamGenerateContent?alt=sse`;
29580
+ REASONING_TIER_RANK = {
29581
+ high: 0,
29582
+ medium: 1,
29583
+ low: 2,
29584
+ "extra-low": 3,
29585
+ tiered: 4
29586
+ };
29587
+ });
29588
+
29589
+ // src/auth/credentials/antigravity-credential.ts
29590
+ import { randomUUID as randomUUID2 } from "crypto";
29591
+ function createActivityRequestId2() {
29592
+ return Math.random().toString(36).substring(7);
28809
29593
  }
28810
- var CODEX_RESPONSES_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
28811
- var init_codex_credential = __esm(() => {
28812
- init_codex_oauth();
28813
- init_api_key_credential();
29594
+
29595
+ class AntigravityCredentialProvider {
29596
+ catalogName = "antigravity";
29597
+ async isAvailable() {
29598
+ try {
29599
+ return readSharedAntigravityToken() !== null;
29600
+ } catch {
29601
+ return false;
29602
+ }
29603
+ }
29604
+ async getRequestAuth(ctx) {
29605
+ const token = await getValidAntigravityAccessToken();
29606
+ const { projectId, tierId } = await setupAntigravityUser(token);
29607
+ const { servedIds, defaultId } = await getServedAntigravityModels(token, projectId);
29608
+ const servedModel = resolveAntigravityModelId(ctx.model, servedIds, defaultId);
29609
+ return {
29610
+ headers: {
29611
+ Authorization: `Bearer ${token}`,
29612
+ "User-Agent": buildAntigravityUserAgent(),
29613
+ "x-activity-request-id": createActivityRequestId2()
29614
+ },
29615
+ transformPayload: (inner) => {
29616
+ const env = {
29617
+ model: servedModel,
29618
+ project: projectId,
29619
+ user_prompt_id: randomUUID2(),
29620
+ request: inner
29621
+ };
29622
+ if (tierId && tierId !== "free-tier") {
29623
+ env.enabled_credit_types = ["GOOGLE_ONE_AI"];
29624
+ }
29625
+ return env;
29626
+ }
29627
+ };
29628
+ }
29629
+ }
29630
+ var init_antigravity_credential = __esm(() => {
29631
+ init_antigravity();
29632
+ init_antigravity_token();
29633
+ init_gemini_oauth();
28814
29634
  });
28815
29635
 
28816
- // src/auth/gemini-oauth.ts
29636
+ // src/auth/credentials/api-key-credential.ts
29637
+ import { existsSync as existsSync8 } from "fs";
29638
+ import { homedir as homedir10 } from "os";
29639
+ import { join as join10 } from "path";
29640
+ function realValue(v) {
29641
+ if (!v)
29642
+ return;
29643
+ return UNEXPANDED_PLACEHOLDER.test(v.trim()) ? undefined : v;
29644
+ }
29645
+
29646
+ class ApiKeyCredentialProvider {
29647
+ catalogName;
29648
+ envVar;
29649
+ aliases;
29650
+ authScheme;
29651
+ staticHeaders;
29652
+ publicKeyFallback;
29653
+ oauthFallback;
29654
+ declaredKey;
29655
+ cachedKey;
29656
+ resolving;
29657
+ constructor(descriptor) {
29658
+ this.catalogName = descriptor.catalogName;
29659
+ this.envVar = descriptor.envVar;
29660
+ this.aliases = descriptor.aliases ?? [];
29661
+ this.authScheme = descriptor.authScheme ?? "bearer";
29662
+ this.staticHeaders = descriptor.staticHeaders ?? {};
29663
+ this.publicKeyFallback = descriptor.publicKeyFallback;
29664
+ this.oauthFallback = descriptor.oauthFallback;
29665
+ this.declaredKey = descriptor.declaredKey;
29666
+ }
29667
+ resolveFromEnvConfig() {
29668
+ return realValue(process.env[this.envVar]) || this.aliases.map((a) => realValue(process.env[a])).find((v) => !!v) || realValue(getApiKey(this.envVar)) || realValue(this.resolveDeclared());
29669
+ }
29670
+ resolveDeclared() {
29671
+ try {
29672
+ return this.declaredKey?.() || undefined;
29673
+ } catch {
29674
+ return;
29675
+ }
29676
+ }
29677
+ hasOauthFallbackFile() {
29678
+ if (!this.oauthFallback)
29679
+ return false;
29680
+ try {
29681
+ return existsSync8(join10(homedir10(), ".claudish", this.oauthFallback));
29682
+ } catch {
29683
+ return false;
29684
+ }
29685
+ }
29686
+ async resolveKey(opts) {
29687
+ if (this.cachedKey !== undefined)
29688
+ return this.cachedKey;
29689
+ if (this.resolving)
29690
+ return this.resolving;
29691
+ this.resolving = (async () => {
29692
+ const local = this.resolveFromEnvConfig();
29693
+ if (local) {
29694
+ this.cachedKey = local;
29695
+ return local;
29696
+ }
29697
+ if (hasOpSources()) {
29698
+ const wanted = new Set([this.envVar, ...this.aliases]);
29699
+ const resolved = await resolveOpKeyForEnvVars(wanted, {
29700
+ onAuthFailure: "skip",
29701
+ allowPrompt: opts?.allowOpPrompt ?? false
29702
+ });
29703
+ const value = resolved[this.envVar] ?? this.aliases.map((a) => resolved[a]).find((v) => !!v);
29704
+ if (value) {
29705
+ process.env[this.envVar] = value;
29706
+ this.cachedKey = value;
29707
+ return value;
29708
+ }
29709
+ return "";
29710
+ }
29711
+ this.cachedKey = "";
29712
+ return "";
29713
+ })();
29714
+ try {
29715
+ return await this.resolving;
29716
+ } finally {
29717
+ this.resolving = undefined;
29718
+ }
29719
+ }
29720
+ async isAvailable(opts) {
29721
+ if (this.publicKeyFallback)
29722
+ return true;
29723
+ if (this.resolveFromEnvConfig())
29724
+ return true;
29725
+ if (this.hasOauthFallbackFile())
29726
+ return true;
29727
+ const key = await this.resolveKey(opts);
29728
+ return !!key;
29729
+ }
29730
+ invalidate() {
29731
+ this.cachedKey = undefined;
29732
+ this.resolving = undefined;
29733
+ }
29734
+ async getRequestAuth(ctx) {
29735
+ const key = await this.resolveKey({ allowOpPrompt: ctx.allowOpPrompt }) || this.publicKeyFallback || "";
29736
+ let headers;
29737
+ if (this.authScheme === "x-api-key") {
29738
+ headers = { "x-api-key": key, ...this.staticHeaders };
29739
+ } else if (key) {
29740
+ headers = { Authorization: `Bearer ${key}`, ...this.staticHeaders };
29741
+ } else {
29742
+ headers = { ...this.staticHeaders };
29743
+ }
29744
+ return { headers };
29745
+ }
29746
+ }
29747
+ var UNEXPANDED_PLACEHOLDER;
29748
+ var init_api_key_credential = __esm(() => {
29749
+ init_profile_config();
29750
+ init_op_source();
29751
+ UNEXPANDED_PLACEHOLDER = /^\$\{[^}]*\}$/;
29752
+ });
29753
+
29754
+ // src/auth/codex-oauth.ts
28817
29755
  import { exec as exec2 } from "child_process";
28818
29756
  import { createHash as createHash3, randomBytes as randomBytes2 } from "crypto";
28819
- import { closeSync as closeSync3, existsSync as existsSync8, openSync as openSync3, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeSync as writeSync3 } from "fs";
29757
+ import { closeSync as closeSync3, existsSync as existsSync9, openSync as openSync3, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeSync as writeSync3 } from "fs";
28820
29758
  import { createServer as createServer2 } from "http";
28821
- import { homedir as homedir10 } from "os";
28822
- import { join as join10 } from "path";
29759
+ import { homedir as homedir11 } from "os";
29760
+ import { join as join11 } from "path";
28823
29761
  import { promisify as promisify2 } from "util";
28824
29762
 
28825
- class GeminiOAuth {
29763
+ class CodexOAuth {
28826
29764
  static instance = null;
28827
29765
  credentials = null;
28828
29766
  refreshPromise = null;
28829
29767
  tokenRefreshMargin = 5 * 60 * 1000;
28830
29768
  oauthState = null;
28831
29769
  static getInstance() {
28832
- if (!GeminiOAuth.instance) {
28833
- GeminiOAuth.instance = new GeminiOAuth;
29770
+ if (!CodexOAuth.instance) {
29771
+ CodexOAuth.instance = new CodexOAuth;
28834
29772
  }
28835
- return GeminiOAuth.instance;
29773
+ return CodexOAuth.instance;
28836
29774
  }
28837
29775
  constructor() {
28838
29776
  this.credentials = this.loadCredentials();
@@ -28845,56 +29783,61 @@ class GeminiOAuth {
28845
29783
  return this.credentials !== null && !!this.credentials.refresh_token;
28846
29784
  }
28847
29785
  getCredentialsPath() {
28848
- const claudishDir = join10(homedir10(), ".claudish");
28849
- return join10(claudishDir, "gemini-oauth.json");
29786
+ const claudishDir = join11(homedir11(), ".claudish");
29787
+ return join11(claudishDir, "codex-oauth.json");
28850
29788
  }
28851
29789
  async login() {
28852
- log("[GeminiOAuth] Starting OAuth login flow");
29790
+ log("[CodexOAuth] Starting OAuth login flow");
28853
29791
  const codeVerifier = this.generateCodeVerifier();
28854
29792
  const codeChallenge = await this.generateCodeChallenge(codeVerifier);
28855
29793
  this.oauthState = randomBytes2(32).toString("base64url");
28856
29794
  const { authCode, redirectUri } = await this.startCallbackServer(codeChallenge, this.oauthState);
28857
29795
  const tokens = await this.exchangeCodeForTokens(authCode, codeVerifier, redirectUri);
28858
- const credentials = {
29796
+ const accountId = tokens.id_token ? this.extractAccountId(tokens.id_token) : undefined;
29797
+ const credentials2 = {
28859
29798
  access_token: tokens.access_token,
28860
29799
  refresh_token: tokens.refresh_token,
28861
- expires_at: Date.now() + tokens.expires_in * 1000
29800
+ expires_at: Date.now() + tokens.expires_in * 1000,
29801
+ account_id: accountId
28862
29802
  };
28863
- this.saveCredentials(credentials);
28864
- this.credentials = credentials;
29803
+ this.saveCredentials(credentials2);
29804
+ this.credentials = credentials2;
28865
29805
  this.oauthState = null;
28866
- log("[GeminiOAuth] Login successful");
29806
+ log("[CodexOAuth] Login successful");
29807
+ if (accountId) {
29808
+ log(`[CodexOAuth] Account ID: ${accountId}`);
29809
+ }
28867
29810
  }
28868
29811
  async logout() {
28869
29812
  const credPath = this.getCredentialsPath();
28870
- if (existsSync8(credPath)) {
29813
+ if (existsSync9(credPath)) {
28871
29814
  unlinkSync3(credPath);
28872
- log("[GeminiOAuth] Credentials deleted");
29815
+ log("[CodexOAuth] Credentials deleted");
28873
29816
  }
28874
29817
  this.credentials = null;
28875
29818
  }
28876
29819
  async getAccessToken() {
28877
29820
  if (this.refreshPromise) {
28878
- log("[GeminiOAuth] Waiting for in-progress refresh");
29821
+ log("[CodexOAuth] Waiting for in-progress refresh");
28879
29822
  return this.refreshPromise;
28880
29823
  }
28881
29824
  if (!this.credentials) {
28882
- throw new Error("No Gemini OAuth credentials found. Please run `claudish login gemini` first.");
29825
+ throw new Error("No OpenAI Codex OAuth credentials found. Please run `claudish login codex` first.");
28883
29826
  }
28884
29827
  if (this.isTokenValid()) {
28885
29828
  return this.credentials.access_token;
28886
29829
  }
28887
- this.refreshPromise = this.doRefreshToken();
28888
- try {
28889
- const token = await this.refreshPromise;
28890
- return token;
28891
- } finally {
29830
+ this.refreshPromise = this.doRefreshToken().finally(() => {
28892
29831
  this.refreshPromise = null;
28893
- }
29832
+ });
29833
+ return this.refreshPromise;
29834
+ }
29835
+ getAccountId() {
29836
+ return this.credentials?.account_id;
28894
29837
  }
28895
29838
  async refreshToken() {
28896
29839
  if (!this.credentials) {
28897
- throw new Error("No Gemini OAuth credentials found. Please run `claudish login gemini` first.");
29840
+ throw new Error("No OpenAI Codex OAuth credentials found. Please run `claudish login codex` first.");
28898
29841
  }
28899
29842
  await this.doRefreshToken();
28900
29843
  }
@@ -28905,20 +29848,19 @@ class GeminiOAuth {
28905
29848
  }
28906
29849
  async doRefreshToken() {
28907
29850
  if (!this.credentials) {
28908
- throw new Error("No Gemini OAuth credentials found. Please run `claudish login gemini` first.");
29851
+ throw new Error("No OpenAI Codex OAuth credentials found. Please run `claudish login codex` first.");
28909
29852
  }
28910
- log("[GeminiOAuth] Refreshing access token");
29853
+ log("[CodexOAuth] Refreshing access token");
28911
29854
  try {
28912
29855
  const response = await fetch(OAUTH_CONFIG2.tokenUrl, {
28913
29856
  method: "POST",
28914
29857
  headers: {
28915
- "Content-Type": "application/x-www-form-urlencoded"
29858
+ "Content-Type": "application/json"
28916
29859
  },
28917
- body: new URLSearchParams({
29860
+ body: JSON.stringify({
28918
29861
  grant_type: "refresh_token",
28919
29862
  refresh_token: this.credentials.refresh_token,
28920
- client_id: OAUTH_CONFIG2.clientId,
28921
- client_secret: OAUTH_CONFIG2.clientSecret
29863
+ client_id: OAUTH_CONFIG2.clientId
28922
29864
  })
28923
29865
  });
28924
29866
  if (!response.ok) {
@@ -28926,56 +29868,58 @@ class GeminiOAuth {
28926
29868
  throw new Error(`Token refresh failed: ${response.status} - ${errorText}`);
28927
29869
  }
28928
29870
  const tokens = await response.json();
29871
+ const accountId = tokens.id_token ? this.extractAccountId(tokens.id_token) : this.credentials.account_id;
28929
29872
  const updatedCredentials = {
28930
29873
  access_token: tokens.access_token,
28931
29874
  refresh_token: tokens.refresh_token || this.credentials.refresh_token,
28932
- expires_at: Date.now() + tokens.expires_in * 1000
29875
+ expires_at: Date.now() + tokens.expires_in * 1000,
29876
+ account_id: accountId
28933
29877
  };
28934
29878
  this.saveCredentials(updatedCredentials);
28935
29879
  this.credentials = updatedCredentials;
28936
- log(`[GeminiOAuth] Token refreshed, valid until ${new Date(updatedCredentials.expires_at).toISOString()}`);
29880
+ log(`[CodexOAuth] Token refreshed, valid until ${new Date(updatedCredentials.expires_at).toISOString()}`);
28937
29881
  return updatedCredentials.access_token;
28938
29882
  } catch (e) {
28939
- log(`[GeminiOAuth] Refresh failed: ${e.message}`);
28940
- throw new Error(`OAuth credentials invalid. Please run \`claudish login gemini\` again.
29883
+ log(`[CodexOAuth] Refresh failed: ${e.message}`);
29884
+ throw new Error(`OAuth credentials invalid. Please run \`claudish login codex\` again.
28941
29885
 
28942
29886
  Details: ${e.message}`);
28943
29887
  }
28944
29888
  }
28945
29889
  loadCredentials() {
28946
29890
  const credPath = this.getCredentialsPath();
28947
- if (!existsSync8(credPath)) {
29891
+ if (!existsSync9(credPath)) {
28948
29892
  return null;
28949
29893
  }
28950
29894
  try {
28951
29895
  const data = readFileSync7(credPath, "utf-8");
28952
- const credentials = JSON.parse(data);
28953
- if (!credentials.access_token || !credentials.refresh_token || !credentials.expires_at) {
28954
- log("[GeminiOAuth] Invalid credentials file structure");
29896
+ const credentials2 = JSON.parse(data);
29897
+ if (!credentials2.access_token || !credentials2.refresh_token || !credentials2.expires_at) {
29898
+ log("[CodexOAuth] Invalid credentials file structure");
28955
29899
  return null;
28956
29900
  }
28957
- log("[GeminiOAuth] Loaded credentials from file");
28958
- return credentials;
29901
+ log("[CodexOAuth] Loaded credentials from file");
29902
+ return credentials2;
28959
29903
  } catch (e) {
28960
- log(`[GeminiOAuth] Failed to load credentials: ${e.message}`);
29904
+ log(`[CodexOAuth] Failed to load credentials: ${e.message}`);
28961
29905
  return null;
28962
29906
  }
28963
29907
  }
28964
- saveCredentials(credentials) {
29908
+ saveCredentials(credentials2) {
28965
29909
  const credPath = this.getCredentialsPath();
28966
- const claudishDir = join10(homedir10(), ".claudish");
28967
- if (!existsSync8(claudishDir)) {
29910
+ const claudishDir = join11(homedir11(), ".claudish");
29911
+ if (!existsSync9(claudishDir)) {
28968
29912
  const { mkdirSync: mkdirSync6 } = __require("fs");
28969
29913
  mkdirSync6(claudishDir, { recursive: true });
28970
29914
  }
28971
29915
  const fd = openSync3(credPath, "w", 384);
28972
29916
  try {
28973
- const data = JSON.stringify(credentials, null, 2);
29917
+ const data = JSON.stringify(credentials2, null, 2);
28974
29918
  writeSync3(fd, data, 0, "utf-8");
28975
29919
  } finally {
28976
29920
  closeSync3(fd);
28977
29921
  }
28978
- log(`[GeminiOAuth] Credentials saved to ${credPath}`);
29922
+ log(`[CodexOAuth] Credentials saved to ${credPath}`);
28979
29923
  }
28980
29924
  generateCodeVerifier() {
28981
29925
  return randomBytes2(64).toString("base64url");
@@ -28984,26 +29928,46 @@ Details: ${e.message}`);
28984
29928
  const hash2 = createHash3("sha256").update(verifier).digest("base64url");
28985
29929
  return hash2;
28986
29930
  }
29931
+ extractAccountId(idToken) {
29932
+ try {
29933
+ const parts = idToken.split(".");
29934
+ if (parts.length !== 3)
29935
+ return;
29936
+ const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
29937
+ const authClaim = payload["https://api.openai.com/auth"];
29938
+ const accountId = authClaim?.chatgpt_account_id || payload.chatgpt_account_id || authClaim?.user_id;
29939
+ if (accountId) {
29940
+ log(`[CodexOAuth] Extracted account ID from id_token: ${accountId}`);
29941
+ return accountId;
29942
+ }
29943
+ return;
29944
+ } catch (e) {
29945
+ log(`[CodexOAuth] Failed to extract account ID from id_token: ${e.message}`);
29946
+ return;
29947
+ }
29948
+ }
28987
29949
  buildAuthUrl(codeChallenge, state, redirectUri) {
28988
- const params = new URLSearchParams({
28989
- client_id: OAUTH_CONFIG2.clientId,
28990
- redirect_uri: redirectUri,
28991
- response_type: "code",
28992
- scope: OAUTH_CONFIG2.scopes.join(" "),
28993
- code_challenge: codeChallenge,
28994
- code_challenge_method: "S256",
28995
- access_type: "offline",
28996
- prompt: "consent",
28997
- state
28998
- });
28999
- return `${OAUTH_CONFIG2.authUrl}?${params.toString()}`;
29950
+ const scope = OAUTH_CONFIG2.scopes.join("+");
29951
+ const params = [
29952
+ "response_type=code",
29953
+ `client_id=${encodeURIComponent(OAUTH_CONFIG2.clientId)}`,
29954
+ `redirect_uri=${encodeURIComponent(redirectUri)}`,
29955
+ `scope=${scope}`,
29956
+ `code_challenge=${encodeURIComponent(codeChallenge)}`,
29957
+ "code_challenge_method=S256",
29958
+ "id_token_add_organizations=true",
29959
+ "codex_cli_simplified_flow=true",
29960
+ `state=${encodeURIComponent(state)}`,
29961
+ "originator=opencode"
29962
+ ].join("&");
29963
+ return `${OAUTH_CONFIG2.authUrl}?${params}`;
29000
29964
  }
29001
29965
  async startCallbackServer(codeChallenge, state) {
29002
29966
  return new Promise((resolve, reject) => {
29003
29967
  let redirectUri = "";
29004
29968
  const server = createServer2((req, res) => {
29005
- const url2 = new URL(req.url, redirectUri.replace("/callback", ""));
29006
- if (url2.pathname === "/callback") {
29969
+ const url2 = new URL(req.url, redirectUri.replace("/auth/callback", ""));
29970
+ if (url2.pathname === "/auth/callback") {
29007
29971
  const code = url2.searchParams.get("code");
29008
29972
  const callbackState = url2.searchParams.get("state");
29009
29973
  const error46 = url2.searchParams.get("error");
@@ -29068,15 +30032,15 @@ Details: ${e.message}`);
29068
30032
  res.end("Not found");
29069
30033
  }
29070
30034
  });
29071
- server.listen(0, () => {
30035
+ server.listen(1455, () => {
29072
30036
  const address = server.address();
29073
30037
  if (!address || typeof address === "string") {
29074
30038
  reject(new Error("Failed to get server port"));
29075
30039
  return;
29076
30040
  }
29077
30041
  const port = address.port;
29078
- redirectUri = `http://localhost:${port}/callback`;
29079
- log(`[GeminiOAuth] Callback server started on http://localhost:${port}`);
30042
+ redirectUri = `http://localhost:${port}/auth/callback`;
30043
+ log(`[CodexOAuth] Callback server started on http://localhost:${port}`);
29080
30044
  const authUrl = this.buildAuthUrl(codeChallenge, state, redirectUri);
29081
30045
  this.openBrowser(authUrl);
29082
30046
  });
@@ -29090,7 +30054,7 @@ Details: ${e.message}`);
29090
30054
  });
29091
30055
  }
29092
30056
  async exchangeCodeForTokens(code, verifier, redirectUri) {
29093
- log("[GeminiOAuth] Exchanging auth code for tokens");
30057
+ log("[CodexOAuth] Exchanging auth code for tokens");
29094
30058
  try {
29095
30059
  const response = await fetch(OAUTH_CONFIG2.tokenUrl, {
29096
30060
  method: "POST",
@@ -29102,7 +30066,6 @@ Details: ${e.message}`);
29102
30066
  code,
29103
30067
  redirect_uri: redirectUri,
29104
30068
  client_id: OAUTH_CONFIG2.clientId,
29105
- client_secret: OAUTH_CONFIG2.clientSecret,
29106
30069
  code_verifier: verifier
29107
30070
  })
29108
30071
  });
@@ -29116,7 +30079,7 @@ Details: ${e.message}`);
29116
30079
  }
29117
30080
  return tokens;
29118
30081
  } catch (e) {
29119
- throw new Error(`Failed to authenticate with Google OAuth: ${e.message}`);
30082
+ throw new Error(`Failed to authenticate with OpenAI OAuth: ${e.message}`);
29120
30083
  }
29121
30084
  }
29122
30085
  async openBrowser(url2) {
@@ -29130,7 +30093,7 @@ Details: ${e.message}`);
29130
30093
  await execAsync2(`xdg-open "${url2}"`);
29131
30094
  }
29132
30095
  console.log(`
29133
- Opening browser for authentication...`);
30096
+ Opening browser for OpenAI authentication...`);
29134
30097
  console.log(`If the browser doesn't open, visit this URL:
29135
30098
  ${url2}
29136
30099
  `);
@@ -29142,197 +30105,123 @@ Please open this URL in your browser to authenticate:`);
29142
30105
  }
29143
30106
  }
29144
30107
  }
29145
- function reloadGeminiCredentials() {
29146
- GeminiOAuth.getInstance().reloadCredentials();
29147
- resetGeminiUserCache();
29148
- }
29149
- async function getValidAccessToken() {
29150
- const oauth = GeminiOAuth.getInstance();
29151
- return oauth.getAccessToken();
29152
- }
29153
- function resetGeminiUserCache() {
29154
- cachedProjectId = null;
29155
- cachedTierId = null;
29156
- cachedTierName = null;
29157
- }
29158
- function getGeminiTierDisplayName() {
29159
- if (!cachedTierId)
29160
- return "Gemini Free";
29161
- return TIER_SHORT_NAMES[cachedTierId] || cachedTierId.replace(/-tier$/, "");
29162
- }
29163
- function getGeminiTierFullName() {
29164
- if (cachedTierName)
29165
- return cachedTierName;
29166
- return getGeminiTierDisplayName();
30108
+ function getCodexOAuth() {
30109
+ return CodexOAuth.getInstance();
29167
30110
  }
29168
- async function setupGeminiUser(accessToken) {
29169
- if (cachedProjectId && cachedTierId) {
29170
- log(`[GeminiOAuth] Using cached project ID: ${cachedProjectId}, tier: ${cachedTierId}`);
29171
- return { projectId: cachedProjectId, tierId: cachedTierId };
30111
+ var execAsync2, OAUTH_CONFIG2;
30112
+ var init_codex_oauth = __esm(() => {
30113
+ init_logger();
30114
+ execAsync2 = promisify2(exec2);
30115
+ OAUTH_CONFIG2 = {
30116
+ clientId: "app_EMoamEEZ73f0CkXaXp7hrann",
30117
+ authUrl: "https://auth.openai.com/oauth/authorize",
30118
+ tokenUrl: "https://auth.openai.com/oauth/token",
30119
+ scopes: ["openid", "profile", "email", "offline_access"]
30120
+ };
30121
+ });
30122
+
30123
+ // src/auth/credentials/composite-credential.ts
30124
+ class CompositeCredentialProvider {
30125
+ catalogName;
30126
+ primary;
30127
+ fallback;
30128
+ opts;
30129
+ constructor(catalogName, primary, fallback, opts = {}) {
30130
+ this.catalogName = catalogName;
30131
+ this.primary = primary;
30132
+ this.fallback = fallback;
30133
+ this.opts = opts;
29172
30134
  }
29173
- const envProject = process.env.GOOGLE_CLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT_ID;
29174
- log("[GeminiOAuth] Calling loadCodeAssist...");
29175
- const loadRes = await callLoadCodeAssist(accessToken, envProject);
29176
- log(`[GeminiOAuth] loadCodeAssist response: ${JSON.stringify(loadRes)}`);
29177
- const resolvedTier = loadRes.paidTier?.id || (typeof loadRes.currentTier === "object" ? loadRes.currentTier?.id : loadRes.currentTier) || null;
29178
- if ((loadRes.currentTier || loadRes.paidTier) && loadRes.cloudaicompanionProject) {
29179
- const projectId2 = envProject || loadRes.cloudaicompanionProject;
29180
- if (projectId2) {
29181
- cachedProjectId = projectId2;
29182
- cachedTierId = resolvedTier || "free-tier";
29183
- cachedTierName = loadRes.paidTier?.name || null;
29184
- log(`[GeminiOAuth] User already set up, project: ${projectId2}, tier: ${cachedTierId}`);
29185
- return { projectId: projectId2, tierId: cachedTierId };
29186
- }
30135
+ async isAvailable(opts) {
30136
+ return await this.primary.isAvailable(opts) || await this.fallback.isAvailable(opts);
29187
30137
  }
29188
- const tierId = resolvedTier || loadRes.allowedTiers?.[0]?.id || "free-tier";
29189
- const isFree = tierId === "free-tier";
29190
- const onboardProject = isFree ? undefined : envProject;
29191
- const MAX_POLL_ATTEMPTS = 30;
29192
- log(`[GeminiOAuth] Onboarding user to ${tierId}...`);
29193
- let lro = await callOnboardUser(accessToken, tierId, onboardProject);
29194
- log(`[GeminiOAuth] Initial onboardUser response: done=${lro.done}`);
29195
- let attempts = 0;
29196
- while (!lro.done && attempts < MAX_POLL_ATTEMPTS) {
29197
- attempts++;
29198
- log(`[GeminiOAuth] Polling onboardUser (attempt ${attempts}/${MAX_POLL_ATTEMPTS})...`);
29199
- await new Promise((r) => setTimeout(r, 2000));
29200
- lro = await callOnboardUser(accessToken, tierId, onboardProject);
30138
+ invalidate() {
30139
+ this.primary.invalidate?.();
30140
+ this.fallback.invalidate?.();
29201
30141
  }
29202
- if (!lro.done) {
29203
- throw new Error(`Gemini onboarding timed out after ${MAX_POLL_ATTEMPTS * 2} seconds`);
30142
+ async getRequestAuth(ctx) {
30143
+ if (await this.primary.isAvailable({ allowOpPrompt: ctx.allowOpPrompt })) {
30144
+ try {
30145
+ return await this.primary.getRequestAuth(ctx);
30146
+ } catch (e) {
30147
+ const signal = this.opts.fallbackSignal;
30148
+ if (signal && String(e?.message) === signal) {
30149
+ return this.fallback.getRequestAuth(ctx);
30150
+ }
30151
+ throw e;
30152
+ }
30153
+ }
30154
+ return this.fallback.getRequestAuth(ctx);
29204
30155
  }
29205
- if (lro.error) {
29206
- throw new Error(`Gemini onboarding failed: ${JSON.stringify(lro.error)}`);
30156
+ async login() {
30157
+ await this.primary.login?.();
29207
30158
  }
29208
- const projectId = lro.response?.cloudaicompanionProject?.id;
29209
- if (!projectId) {
29210
- if (envProject) {
29211
- cachedProjectId = envProject;
29212
- cachedTierId = tierId;
29213
- return { projectId: envProject, tierId };
29214
- }
29215
- throw new Error("Gemini onboarding completed but no project ID returned.");
30159
+ async logout() {
30160
+ await this.primary.logout?.();
29216
30161
  }
29217
- cachedProjectId = projectId;
29218
- cachedTierId = tierId;
29219
- log(`[GeminiOAuth] Onboarding complete, project: ${projectId}, tier: ${tierId}`);
29220
- return { projectId, tierId };
29221
30162
  }
29222
- async function callLoadCodeAssist(accessToken, projectId) {
29223
- const metadata = {
29224
- pluginType: "GEMINI",
29225
- ideType: "GEMINI_CLI",
29226
- platform: "PLATFORM_UNSPECIFIED",
29227
- duetProject: projectId
30163
+
30164
+ // src/auth/credentials/codex-credential.ts
30165
+ function buildOAuthHeaders(token, accountId) {
30166
+ const headers = {
30167
+ Authorization: `Bearer ${token}`,
30168
+ "OpenAI-Beta": "responses=experimental",
30169
+ originator: "codex_cli_rs",
30170
+ accept: "text/event-stream"
29228
30171
  };
29229
- const res = await fetch(`${CODE_ASSIST_API_BASE}:loadCodeAssist`, {
29230
- method: "POST",
29231
- headers: {
29232
- Authorization: `Bearer ${accessToken}`,
29233
- "Content-Type": "application/json"
29234
- },
29235
- body: JSON.stringify({ metadata, cloudaicompanionProject: projectId })
29236
- });
29237
- if (!res.ok) {
29238
- throw new Error(`loadCodeAssist failed: ${res.status} ${await res.text()}`);
30172
+ if (accountId) {
30173
+ headers["chatgpt-account-id"] = accountId;
30174
+ headers["x-conversation-id"] = "claudish-session";
30175
+ headers["x-session-id"] = "claudish-session";
29239
30176
  }
29240
- return await res.json();
30177
+ return headers;
29241
30178
  }
29242
- async function callOnboardUser(accessToken, tierId, projectId) {
29243
- const metadata = {
29244
- pluginType: "GEMINI",
29245
- ideType: "GEMINI_CLI",
29246
- platform: "PLATFORM_UNSPECIFIED",
29247
- duetProject: projectId
29248
- };
29249
- const res = await fetch(`${CODE_ASSIST_API_BASE}:onboardUser`, {
29250
- method: "POST",
29251
- headers: {
29252
- Authorization: `Bearer ${accessToken}`,
29253
- "Content-Type": "application/json"
29254
- },
29255
- body: JSON.stringify({
29256
- tierId,
29257
- metadata,
29258
- cloudaicompanionProject: projectId
29259
- })
29260
- });
29261
- if (!res.ok) {
29262
- throw new Error(`onboardUser failed: ${res.status} ${await res.text()}`);
30179
+
30180
+ class CodexOAuthHalf {
30181
+ catalogName = "openai-codex";
30182
+ oauth = CodexOAuth.getInstance();
30183
+ async isAvailable() {
30184
+ return this.oauth.hasCredentials();
29263
30185
  }
29264
- return await res.json();
29265
- }
29266
- async function retrieveUserQuota(accessToken, projectId) {
29267
- try {
29268
- const res = await fetch(`${CODE_ASSIST_API_BASE}:retrieveUserQuota`, {
29269
- method: "POST",
29270
- headers: {
29271
- Authorization: `Bearer ${accessToken}`,
29272
- "Content-Type": "application/json",
29273
- "User-Agent": `GeminiCLI/0.5.6/gemini-code-assist (${process.platform}; ${process.arch})`
29274
- },
29275
- body: JSON.stringify({ project: projectId })
29276
- });
29277
- if (!res.ok) {
29278
- log(`[GeminiOAuth] retrieveUserQuota failed: ${res.status}`);
29279
- return null;
29280
- }
29281
- return await res.json();
29282
- } catch (err) {
29283
- log(`[GeminiOAuth] retrieveUserQuota error: ${err}`);
29284
- return null;
30186
+ async getRequestAuth(_ctx) {
30187
+ const token = await this.oauth.getAccessToken();
30188
+ const accountId = this.oauth.getAccountId();
30189
+ return {
30190
+ headers: buildOAuthHeaders(token, accountId),
30191
+ endpoint: CODEX_RESPONSES_ENDPOINT,
30192
+ transformPayload: (p) => ({
30193
+ ...p,
30194
+ store: false,
30195
+ include: ["reasoning.encrypted_content"]
30196
+ })
30197
+ };
30198
+ }
30199
+ async login() {
30200
+ await this.oauth.login();
30201
+ }
30202
+ async logout() {
30203
+ await this.oauth.logout();
29285
30204
  }
29286
30205
  }
29287
- var execAsync2, getDefaultClientId = () => {
29288
- const parts = [
29289
- "681255809395",
29290
- "oo8ft2oprdrnp9e3aqf6av3hmdib135j",
29291
- "apps",
29292
- "googleusercontent",
29293
- "com"
29294
- ];
29295
- return `${parts[0]}-${parts[1]}.${parts[2]}.${parts[3]}.${parts[4]}`;
29296
- }, getDefaultClientSecret = () => {
29297
- const p = ["GOCSPX", "4uHgMPm", "1o7Sk", "geV6Cu5clXFsxl"];
29298
- return `${p[0]}-${p[1]}-${p[2]}-${p[3]}`;
29299
- }, OAUTH_CONFIG2, CODE_ASSIST_API_BASE = "https://cloudcode-pa.googleapis.com/v1internal", CODE_ASSIST_FALLBACK_CHAIN, cachedProjectId = null, cachedTierId = null, cachedTierName = null, TIER_SHORT_NAMES;
29300
- var init_gemini_oauth = __esm(() => {
29301
- init_logger();
29302
- execAsync2 = promisify2(exec2);
29303
- OAUTH_CONFIG2 = {
29304
- clientId: process.env.GEMINI_CLIENT_ID || getDefaultClientId(),
29305
- clientSecret: process.env.GEMINI_CLIENT_SECRET || getDefaultClientSecret(),
29306
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
29307
- tokenUrl: "https://oauth2.googleapis.com/token",
29308
- scopes: [
29309
- "https://www.googleapis.com/auth/cloud-platform",
29310
- "https://www.googleapis.com/auth/userinfo.email",
29311
- "https://www.googleapis.com/auth/userinfo.profile"
29312
- ]
29313
- };
29314
- CODE_ASSIST_FALLBACK_CHAIN = [
29315
- "gemini-3.1-pro-preview",
29316
- "gemini-3-pro-preview",
29317
- "gemini-3-flash-preview",
29318
- "gemini-2.5-pro",
29319
- "gemini-2.5-flash"
29320
- ];
29321
- TIER_SHORT_NAMES = {
29322
- "free-tier": "GeminiCA Free",
29323
- "standard-tier": "GeminiCA Std",
29324
- "g1-pro-tier": "GeminiCA Pro",
29325
- "legacy-tier": "GeminiCA Legacy"
29326
- };
30206
+ function makeCodexCredential() {
30207
+ return new CompositeCredentialProvider("openai-codex", new CodexOAuthHalf, new ApiKeyCredentialProvider({
30208
+ catalogName: "openai-codex",
30209
+ envVar: "OPENAI_CODEX_API_KEY"
30210
+ }));
30211
+ }
30212
+ var CODEX_RESPONSES_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
30213
+ var init_codex_credential = __esm(() => {
30214
+ init_codex_oauth();
30215
+ init_api_key_credential();
29327
30216
  });
29328
30217
 
29329
30218
  // src/auth/oauth-registry.ts
29330
- import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
29331
- import { homedir as homedir11 } from "os";
29332
- import { join as join11 } from "path";
30219
+ import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
30220
+ import { homedir as homedir12 } from "os";
30221
+ import { join as join12 } from "path";
29333
30222
  function hasValidOAuthCredentials(descriptor) {
29334
- const credPath = join11(homedir11(), ".claudish", descriptor.credentialFile);
29335
- if (!existsSync9(credPath))
30223
+ const credPath = join12(homedir12(), ".claudish", descriptor.credentialFile);
30224
+ if (!existsSync10(credPath))
29336
30225
  return false;
29337
30226
  if (descriptor.validationMode === "file-exists") {
29338
30227
  return true;
@@ -29395,13 +30284,8 @@ var init_oauth_registry = __esm(() => {
29395
30284
  });
29396
30285
 
29397
30286
  // src/auth/credentials/gemini-credential.ts
29398
- import { randomUUID } from "crypto";
29399
- function buildGeminiCliUserAgent(model) {
29400
- const version2 = "0.5.6";
29401
- const modelSegment = model || "gemini-code-assist";
29402
- return `GeminiCLI/${version2}/${modelSegment} (${process.platform}; ${process.arch})`;
29403
- }
29404
- function createActivityRequestId() {
30287
+ import { randomUUID as randomUUID3 } from "crypto";
30288
+ function createActivityRequestId3() {
29405
30289
  return Math.random().toString(36).substring(7);
29406
30290
  }
29407
30291
 
@@ -29416,14 +30300,14 @@ class GeminiCodeAssistCredentialProvider {
29416
30300
  return {
29417
30301
  headers: {
29418
30302
  Authorization: `Bearer ${token}`,
29419
- "User-Agent": buildGeminiCliUserAgent(ctx.model),
29420
- "x-activity-request-id": createActivityRequestId()
30303
+ "User-Agent": buildCodeAssistUserAgent(ctx.model),
30304
+ "x-activity-request-id": createActivityRequestId3()
29421
30305
  },
29422
30306
  transformPayload: (inner) => {
29423
30307
  const env = {
29424
30308
  model: ctx.model,
29425
30309
  project: projectId,
29426
- user_prompt_id: randomUUID(),
30310
+ user_prompt_id: randomUUID3(),
29427
30311
  request: inner
29428
30312
  };
29429
30313
  if (tierId && tierId !== "free-tier") {
@@ -29448,9 +30332,9 @@ var init_gemini_credential = __esm(() => {
29448
30332
  // src/auth/kimi-oauth.ts
29449
30333
  import { exec as exec3 } from "child_process";
29450
30334
  import { randomBytes as randomBytes3 } from "crypto";
29451
- import { closeSync as closeSync4, existsSync as existsSync10, openSync as openSync4, readFileSync as readFileSync9, unlinkSync as unlinkSync4, writeSync as writeSync4 } from "fs";
29452
- import { homedir as homedir12, hostname as hostname3, platform, release as release2 } from "os";
29453
- import { join as join12 } from "path";
30335
+ import { closeSync as closeSync4, existsSync as existsSync11, openSync as openSync4, readFileSync as readFileSync9, unlinkSync as unlinkSync4, writeSync as writeSync4 } from "fs";
30336
+ import { homedir as homedir13, hostname as hostname3, platform, release as release2 } from "os";
30337
+ import { join as join13 } from "path";
29454
30338
  import { promisify as promisify3 } from "util";
29455
30339
 
29456
30340
  class KimiOAuth {
@@ -29478,21 +30362,21 @@ class KimiOAuth {
29478
30362
  return this.credentials !== null && !!this.credentials.refresh_token;
29479
30363
  }
29480
30364
  getCredentialsPath() {
29481
- const claudishDir = join12(homedir12(), ".claudish");
29482
- return join12(claudishDir, "kimi-oauth.json");
30365
+ const claudishDir = join13(homedir13(), ".claudish");
30366
+ return join13(claudishDir, "kimi-oauth.json");
29483
30367
  }
29484
30368
  getDeviceIdPath() {
29485
- const claudishDir = join12(homedir12(), ".claudish");
29486
- return join12(claudishDir, "kimi-device-id");
30369
+ const claudishDir = join13(homedir13(), ".claudish");
30370
+ return join13(claudishDir, "kimi-device-id");
29487
30371
  }
29488
30372
  loadOrCreateDeviceId() {
29489
30373
  const deviceIdPath = this.getDeviceIdPath();
29490
- const claudishDir = join12(homedir12(), ".claudish");
29491
- if (!existsSync10(claudishDir)) {
30374
+ const claudishDir = join13(homedir13(), ".claudish");
30375
+ if (!existsSync11(claudishDir)) {
29492
30376
  const { mkdirSync: mkdirSync6 } = __require("fs");
29493
30377
  mkdirSync6(claudishDir, { recursive: true });
29494
30378
  }
29495
- if (existsSync10(deviceIdPath)) {
30379
+ if (existsSync11(deviceIdPath)) {
29496
30380
  try {
29497
30381
  const deviceId2 = readFileSync9(deviceIdPath, "utf-8").trim();
29498
30382
  if (deviceId2) {
@@ -29544,15 +30428,15 @@ Please authorize this device:`);
29544
30428
  Waiting for authorization...`);
29545
30429
  await this.openBrowser(deviceAuth.verification_uri_complete);
29546
30430
  const tokens = await this.pollForToken(deviceAuth.device_code, deviceAuth.interval, deviceAuth.expires_in);
29547
- const credentials = {
30431
+ const credentials2 = {
29548
30432
  access_token: tokens.access_token,
29549
30433
  refresh_token: tokens.refresh_token,
29550
30434
  expires_at: Date.now() + tokens.expires_in * 1000,
29551
30435
  scope: tokens.scope,
29552
30436
  token_type: tokens.token_type
29553
30437
  };
29554
- this.saveCredentials(credentials);
29555
- this.credentials = credentials;
30438
+ this.saveCredentials(credentials2);
30439
+ this.credentials = credentials2;
29556
30440
  log("[KimiOAuth] Login successful");
29557
30441
  }
29558
30442
  async requestDeviceAuthorization() {
@@ -29665,7 +30549,7 @@ Waiting for authorization...`);
29665
30549
  }
29666
30550
  async logout() {
29667
30551
  const credPath = this.getCredentialsPath();
29668
- if (existsSync10(credPath)) {
30552
+ if (existsSync11(credPath)) {
29669
30553
  unlinkSync4(credPath);
29670
30554
  log("[KimiOAuth] Credentials deleted");
29671
30555
  }
@@ -29732,7 +30616,7 @@ Waiting for authorization...`);
29732
30616
  } catch (e) {
29733
30617
  log(`[KimiOAuth] Refresh failed: ${e.message}`);
29734
30618
  const credPath = this.getCredentialsPath();
29735
- if (existsSync10(credPath)) {
30619
+ if (existsSync11(credPath)) {
29736
30620
  unlinkSync4(credPath);
29737
30621
  }
29738
30622
  this.credentials = null;
@@ -29749,33 +30633,33 @@ Details: ${e.message}`);
29749
30633
  }
29750
30634
  loadCredentials() {
29751
30635
  const credPath = this.getCredentialsPath();
29752
- if (!existsSync10(credPath)) {
30636
+ if (!existsSync11(credPath)) {
29753
30637
  return null;
29754
30638
  }
29755
30639
  try {
29756
30640
  const data = readFileSync9(credPath, "utf-8");
29757
- const credentials = JSON.parse(data);
29758
- if (!credentials.access_token || !credentials.refresh_token || !credentials.expires_at || !credentials.scope || !credentials.token_type) {
30641
+ const credentials2 = JSON.parse(data);
30642
+ if (!credentials2.access_token || !credentials2.refresh_token || !credentials2.expires_at || !credentials2.scope || !credentials2.token_type) {
29759
30643
  log("[KimiOAuth] Invalid credentials file structure");
29760
30644
  return null;
29761
30645
  }
29762
30646
  log("[KimiOAuth] Loaded credentials from file");
29763
- return credentials;
30647
+ return credentials2;
29764
30648
  } catch (e) {
29765
30649
  log(`[KimiOAuth] Failed to load credentials: ${e.message}`);
29766
30650
  return null;
29767
30651
  }
29768
30652
  }
29769
- saveCredentials(credentials) {
30653
+ saveCredentials(credentials2) {
29770
30654
  const credPath = this.getCredentialsPath();
29771
- const claudishDir = join12(homedir12(), ".claudish");
29772
- if (!existsSync10(claudishDir)) {
30655
+ const claudishDir = join13(homedir13(), ".claudish");
30656
+ if (!existsSync11(claudishDir)) {
29773
30657
  const { mkdirSync: mkdirSync6 } = __require("fs");
29774
30658
  mkdirSync6(claudishDir, { recursive: true });
29775
30659
  }
29776
30660
  const fd = openSync4(credPath, "w", 384);
29777
30661
  try {
29778
- const data = JSON.stringify(credentials, null, 2);
30662
+ const data = JSON.stringify(credentials2, null, 2);
29779
30663
  writeSync4(fd, data, 0, "utf-8");
29780
30664
  } finally {
29781
30665
  closeSync4(fd);
@@ -29943,9 +30827,9 @@ var init_native_anthropic_credential = __esm(() => {
29943
30827
 
29944
30828
  // src/auth/vertex-auth.ts
29945
30829
  import { exec as exec4 } from "child_process";
29946
- import { existsSync as existsSync11 } from "fs";
29947
- import { homedir as homedir13 } from "os";
29948
- import { join as join13 } from "path";
30830
+ import { existsSync as existsSync12 } from "fs";
30831
+ import { homedir as homedir14 } from "os";
30832
+ import { join as join14 } from "path";
29949
30833
  import { promisify as promisify4 } from "util";
29950
30834
 
29951
30835
  class VertexAuthManager {
@@ -30000,8 +30884,8 @@ class VertexAuthManager {
30000
30884
  }
30001
30885
  async tryADC() {
30002
30886
  try {
30003
- const adcPath = join13(homedir13(), ".config/gcloud/application_default_credentials.json");
30004
- if (!existsSync11(adcPath)) {
30887
+ const adcPath = join14(homedir14(), ".config/gcloud/application_default_credentials.json");
30888
+ if (!existsSync12(adcPath)) {
30005
30889
  log("[VertexAuth] ADC credentials file not found");
30006
30890
  return null;
30007
30891
  }
@@ -30025,7 +30909,7 @@ class VertexAuthManager {
30025
30909
  if (!credPath) {
30026
30910
  return null;
30027
30911
  }
30028
- if (!existsSync11(credPath)) {
30912
+ if (!existsSync12(credPath)) {
30029
30913
  throw new Error(`Service account file not found: ${credPath}
30030
30914
 
30031
30915
  Check GOOGLE_APPLICATION_CREDENTIALS path.`);
@@ -30064,8 +30948,8 @@ function validateVertexOAuthConfig() {
30064
30948
  ` + ` export VERTEX_PROJECT='your-gcp-project-id'
30065
30949
  ` + " export VERTEX_LOCATION='us-central1' # optional";
30066
30950
  }
30067
- const adcPath = join13(homedir13(), ".config/gcloud/application_default_credentials.json");
30068
- const hasADC = existsSync11(adcPath);
30951
+ const adcPath = join14(homedir14(), ".config/gcloud/application_default_credentials.json");
30952
+ const hasADC = existsSync12(adcPath);
30069
30953
  const hasServiceAccount = !!process.env.GOOGLE_APPLICATION_CREDENTIALS;
30070
30954
  if (!hasADC && !hasServiceAccount) {
30071
30955
  return `No Vertex AI credentials found.
@@ -30184,6 +31068,7 @@ class CredentialAuthority {
30184
31068
  const authority = new CredentialAuthority;
30185
31069
  authority.register(makeCodexCredential(), ["openai-codex"]);
30186
31070
  authority.register(new GeminiCodeAssistCredentialProvider, ["gemini-codeassist"]);
31071
+ authority.register(new AntigravityCredentialProvider, ["antigravity"]);
30187
31072
  authority.register(makeKimiCredential(), ["kimi"]);
30188
31073
  authority.register(makeKimiCodingCredential(), ["kimi-coding"]);
30189
31074
  authority.register(new VertexCredentialProvider, ["vertex"]);
@@ -30194,6 +31079,7 @@ class CredentialAuthority {
30194
31079
  const alreadyRegistered = new Set([
30195
31080
  "openai-codex",
30196
31081
  "gemini-codeassist",
31082
+ "antigravity",
30197
31083
  "kimi",
30198
31084
  "kimi-coding",
30199
31085
  "vertex",
@@ -30222,6 +31108,7 @@ class CredentialAuthority {
30222
31108
  var LOCAL_PROVIDER_NAMES, RUNTIME_NAME_ALIASES, credentials;
30223
31109
  var init_authority = __esm(() => {
30224
31110
  init_provider_definitions();
31111
+ init_antigravity_credential();
30225
31112
  init_api_key_credential();
30226
31113
  init_codex_credential();
30227
31114
  init_gemini_credential();
@@ -30237,6 +31124,13 @@ var init_authority = __esm(() => {
30237
31124
  });
30238
31125
 
30239
31126
  // src/providers/model-parser.ts
31127
+ function warnGoAliasDeprecatedOnce() {
31128
+ if (_goDeprecationWarned)
31129
+ return;
31130
+ _goDeprecationWarned = true;
31131
+ process.stderr.write(`[claudish] go@ is deprecated \u2014 use ag@<model> (Antigravity). Routing there.
31132
+ `);
31133
+ }
30240
31134
  function parseModelSpec(modelSpec) {
30241
31135
  const original = modelSpec;
30242
31136
  if (modelSpec.startsWith("http://") || modelSpec.startsWith("https://")) {
@@ -30259,6 +31153,8 @@ function parseModelSpec(modelSpec) {
30259
31153
  concurrency = Number.parseInt(concurrencyMatch[2], 10);
30260
31154
  }
30261
31155
  const provider = PROVIDER_SHORTCUTS[providerPart] || providerPart;
31156
+ if (providerPart === "go")
31157
+ warnGoAliasDeprecatedOnce();
30262
31158
  return {
30263
31159
  provider,
30264
31160
  model: modelPart,
@@ -30272,6 +31168,8 @@ function parseModelSpec(modelSpec) {
30272
31168
  for (const { prefix, provider, stripPrefix } of LEGACY_PREFIX_PATTERNS) {
30273
31169
  if (lowerSpec.startsWith(prefix)) {
30274
31170
  const model = stripPrefix ? modelSpec.slice(prefix.length) : modelSpec;
31171
+ if (prefix === "go/")
31172
+ warnGoAliasDeprecatedOnce();
30275
31173
  let concurrency;
30276
31174
  let modelName = model;
30277
31175
  if (LOCAL_PROVIDERS.has(provider)) {
@@ -30332,7 +31230,7 @@ function getLegacySyntaxWarning(parsed) {
30332
31230
  return `Deprecation warning: "${parsed.original}" uses legacy prefix syntax.
30333
31231
  ` + ` Consider using: ${newSyntax}`;
30334
31232
  }
30335
- var PROVIDER_SHORTCUTS, LOCAL_PROVIDERS, NATIVE_MODEL_PATTERNS, LEGACY_PREFIX_PATTERNS;
31233
+ var PROVIDER_SHORTCUTS, _goDeprecationWarned = false, LOCAL_PROVIDERS, NATIVE_MODEL_PATTERNS, LEGACY_PREFIX_PATTERNS;
30336
31234
  var init_model_parser = __esm(() => {
30337
31235
  init_provider_definitions();
30338
31236
  PROVIDER_SHORTCUTS = getShortcuts();
@@ -30612,11 +31510,11 @@ var init_routing_hints = __esm(() => {
30612
31510
  });
30613
31511
 
30614
31512
  // src/providers/all-models-cache.ts
30615
- import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
30616
- import { homedir as homedir14 } from "os";
30617
- import { dirname as dirname5, join as join14 } from "path";
31513
+ import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
31514
+ import { homedir as homedir15 } from "os";
31515
+ import { dirname as dirname5, join as join15 } from "path";
30618
31516
  function readAllModelsCache(path = ALL_MODELS_CACHE_PATH) {
30619
- if (!existsSync12(path))
31517
+ if (!existsSync13(path))
30620
31518
  return null;
30621
31519
  let raw;
30622
31520
  try {
@@ -30650,7 +31548,7 @@ function writeAllModelsCache(data, path = ALL_MODELS_CACHE_PATH) {
30650
31548
  }
30651
31549
  var ALL_MODELS_CACHE_PATH;
30652
31550
  var init_all_models_cache = __esm(() => {
30653
- ALL_MODELS_CACHE_PATH = join14(homedir14(), ".claudish", "all-models.json");
31551
+ ALL_MODELS_CACHE_PATH = join15(homedir15(), ".claudish", "all-models.json");
30654
31552
  });
30655
31553
 
30656
31554
  // src/adapters/model-catalog.ts
@@ -31745,10 +32643,10 @@ var init_signal_watcher = __esm(() => {
31745
32643
 
31746
32644
  // src/channel/session-manager.ts
31747
32645
  import { spawn } from "child_process";
31748
- import { randomUUID as randomUUID2 } from "crypto";
32646
+ import { randomUUID as randomUUID4 } from "crypto";
31749
32647
  import { createWriteStream, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7 } from "fs";
31750
- import { homedir as homedir15 } from "os";
31751
- import { join as join15 } from "path";
32648
+ import { homedir as homedir16 } from "os";
32649
+ import { join as join16 } from "path";
31752
32650
 
31753
32651
  class SessionManager {
31754
32652
  sessions = new Map;
@@ -31765,13 +32663,13 @@ class SessionManager {
31765
32663
  if (this.activeSessions >= this.maxSessions) {
31766
32664
  throw new Error(`Max sessions (${this.maxSessions}) reached`);
31767
32665
  }
31768
- const sessionId = randomUUID2().slice(0, 8);
32666
+ const sessionId = randomUUID4().slice(0, 8);
31769
32667
  const timeout = Math.min(opts.timeoutSeconds ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);
31770
32668
  const startedAt = new Date().toISOString();
31771
- const sessionDir = join15(homedir15(), ".claudish", "sessions", sessionId);
32669
+ const sessionDir = join16(homedir16(), ".claudish", "sessions", sessionId);
31772
32670
  mkdirSync7(sessionDir, { recursive: true });
31773
32671
  if (opts.prompt) {
31774
- writeFileSync7(join15(sessionDir, "prompt.md"), opts.prompt, "utf-8");
32672
+ writeFileSync7(join16(sessionDir, "prompt.md"), opts.prompt, "utf-8");
31775
32673
  }
31776
32674
  const args = ["--model", opts.model, "-y", "--stdin", "--quiet", ...opts.claudishFlags ?? []];
31777
32675
  const proc = spawn("claudish", args, {
@@ -31798,7 +32696,7 @@ class SessionManager {
31798
32696
  });
31799
32697
  }
31800
32698
  });
31801
- const outputLogStream = createWriteStream(join15(sessionDir, "output.log"));
32699
+ const outputLogStream = createWriteStream(join16(sessionDir, "output.log"));
31802
32700
  const entry = {
31803
32701
  info: {
31804
32702
  sessionId,
@@ -31845,9 +32743,9 @@ class SessionManager {
31845
32743
  watcher.processExited(code);
31846
32744
  outputLogStream.end();
31847
32745
  if (entry.stderr) {
31848
- writeFileSync7(join15(sessionDir, "stderr.log"), entry.stderr, "utf-8");
32746
+ writeFileSync7(join16(sessionDir, "stderr.log"), entry.stderr, "utf-8");
31849
32747
  }
31850
- writeFileSync7(join15(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
32748
+ writeFileSync7(join16(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
31851
32749
  this.cleanupSigint();
31852
32750
  });
31853
32751
  proc.on("error", (err) => {
@@ -32020,9 +32918,9 @@ var init_cache_ttl = __esm(() => {
32020
32918
  });
32021
32919
 
32022
32920
  // src/model-loader.ts
32023
- import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
32024
- import { homedir as homedir16 } from "os";
32025
- import { join as join16 } from "path";
32921
+ import { existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
32922
+ import { homedir as homedir17 } from "os";
32923
+ import { join as join17 } from "path";
32026
32924
  function groupRecommendedModels(entries) {
32027
32925
  const byId = new Map;
32028
32926
  for (const entry of entries) {
@@ -32118,7 +33016,7 @@ async function getRecommendedModels(opts = {}) {
32118
33016
  if (!forceRefresh && _cachedRecommendedModels) {
32119
33017
  return _cachedRecommendedModels;
32120
33018
  }
32121
- if (!forceRefresh && existsSync13(RECOMMENDED_MODELS_CACHE_PATH)) {
33019
+ if (!forceRefresh && existsSync14(RECOMMENDED_MODELS_CACHE_PATH)) {
32122
33020
  try {
32123
33021
  const cacheData = JSON.parse(readFileSync11(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
32124
33022
  if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
@@ -32136,7 +33034,7 @@ async function getRecommendedModels(opts = {}) {
32136
33034
  if (data.models && data.models.length > 0) {
32137
33035
  _cachedRecommendedModels = data;
32138
33036
  try {
32139
- const cacheDir = join16(homedir16(), ".claudish");
33037
+ const cacheDir = join17(homedir17(), ".claudish");
32140
33038
  mkdirSync8(cacheDir, { recursive: true });
32141
33039
  writeFileSync8(RECOMMENDED_MODELS_CACHE_PATH, JSON.stringify(data), "utf-8");
32142
33040
  } catch {}
@@ -32149,7 +33047,7 @@ async function getRecommendedModels(opts = {}) {
32149
33047
  function getRecommendedModelsSync() {
32150
33048
  if (_cachedRecommendedModels)
32151
33049
  return _cachedRecommendedModels;
32152
- if (existsSync13(RECOMMENDED_MODELS_CACHE_PATH)) {
33050
+ if (existsSync14(RECOMMENDED_MODELS_CACHE_PATH)) {
32153
33051
  try {
32154
33052
  const cacheData = JSON.parse(readFileSync11(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
32155
33053
  if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
@@ -32275,7 +33173,7 @@ var _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels =
32275
33173
  var init_model_loader = __esm(() => {
32276
33174
  init_cache_ttl();
32277
33175
  FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
32278
- RECOMMENDED_MODELS_CACHE_PATH = join16(homedir16(), ".claudish", "recommended-models-cache.json");
33176
+ RECOMMENDED_MODELS_CACHE_PATH = join17(homedir17(), ".claudish", "recommended-models-cache.json");
32279
33177
  FIREBASE_SLUG_TO_PROVIDER_NAME = {
32280
33178
  openai: "openai",
32281
33179
  google: "google",
@@ -37176,8 +38074,8 @@ var init_harness = __esm(() => {
37176
38074
 
37177
38075
  // src/behavior/journal.ts
37178
38076
  import { appendFile as appendFile2, mkdir, stat } from "fs/promises";
37179
- import { homedir as homedir17 } from "os";
37180
- import { dirname as dirname6, join as join17 } from "path";
38077
+ import { homedir as homedir18 } from "os";
38078
+ import { dirname as dirname6, join as join18 } from "path";
37181
38079
  function classifyPath(observed, expected) {
37182
38080
  if (!observed)
37183
38081
  return "not_applicable";
@@ -37189,7 +38087,7 @@ function classifyPath(observed, expected) {
37189
38087
  return dirOf(observed) === dirOf(expected) ? "same_dir_wrong_name" : "outside_expected_dir";
37190
38088
  }
37191
38089
  function journalPath() {
37192
- return join17(homedir17(), ".claudish", "behavior-journal.jsonl");
38090
+ return join18(homedir18(), ".claudish", "behavior-journal.jsonl");
37193
38091
  }
37194
38092
  async function recordDecision(entry, path = journalPath()) {
37195
38093
  try {
@@ -37406,10 +38304,10 @@ __export(exports_live_log, {
37406
38304
  recordLiveDivergence: () => recordLiveDivergence
37407
38305
  });
37408
38306
  import { appendFile as appendFile3 } from "fs/promises";
37409
- import { homedir as homedir18 } from "os";
37410
- import { join as join18 } from "path";
38307
+ import { homedir as homedir19 } from "os";
38308
+ import { join as join19 } from "path";
37411
38309
  function defaultPath() {
37412
- return join18(homedir18(), ".claudish", "behavior-divergences.jsonl");
38310
+ return join19(homedir19(), ".claudish", "behavior-divergences.jsonl");
37413
38311
  }
37414
38312
  async function recordLiveDivergence(entry, path = defaultPath()) {
37415
38313
  try {
@@ -37830,8 +38728,8 @@ var init_hooks = __esm(() => {
37830
38728
 
37831
38729
  // src/behavior/observer/corpus.ts
37832
38730
  import { appendFileSync as appendFileSync3, readFileSync as readFileSync12, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
37833
- import { homedir as homedir19 } from "os";
37834
- import { join as join19 } from "path";
38731
+ import { homedir as homedir20 } from "os";
38732
+ import { join as join20 } from "path";
37835
38733
  function directoryOf2(filePath) {
37836
38734
  const slash = filePath.lastIndexOf("/");
37837
38735
  return slash > 0 ? filePath.slice(0, slash) : undefined;
@@ -37910,26 +38808,26 @@ function listTranscripts(root) {
37910
38808
  return files;
37911
38809
  }
37912
38810
  for (const project of projects) {
37913
- const dir = join19(root, project);
38811
+ const dir = join20(root, project);
37914
38812
  try {
37915
38813
  if (!statSync2(dir).isDirectory())
37916
38814
  continue;
37917
38815
  for (const f of readdirSync2(dir)) {
37918
38816
  if (f.endsWith(".jsonl"))
37919
- files.push(join19(dir, f));
38817
+ files.push(join20(dir, f));
37920
38818
  }
37921
38819
  } catch {}
37922
38820
  }
37923
38821
  return files;
37924
38822
  }
37925
38823
  function buildCorpus(options = {}) {
37926
- const root = options.projectsRoot ?? join19(homedir19(), ".claude", "projects");
38824
+ const root = options.projectsRoot ?? join20(homedir20(), ".claude", "projects");
37927
38825
  const files = listTranscripts(root);
37928
38826
  const records = [];
37929
38827
  for (const f of files)
37930
38828
  records.push(...replayTranscript(f));
37931
38829
  if (options.write && records.length > 0) {
37932
- const outputPath = options.outputPath ?? join19(homedir19(), ".claudish", "behavior-divergences.jsonl");
38830
+ const outputPath = options.outputPath ?? join20(homedir20(), ".claudish", "behavior-divergences.jsonl");
37933
38831
  try {
37934
38832
  appendFileSync3(outputPath, `${records.map((r) => JSON.stringify(r)).join(`
37935
38833
  `)}
@@ -38540,23 +39438,23 @@ var init_vision_proxy = __esm(() => {
38540
39438
 
38541
39439
  // src/stats-buffer.ts
38542
39440
  import {
38543
- existsSync as existsSync14,
39441
+ existsSync as existsSync15,
38544
39442
  mkdirSync as mkdirSync9,
38545
39443
  readFileSync as readFileSync13,
38546
39444
  renameSync,
38547
39445
  unlinkSync as unlinkSync5,
38548
39446
  writeFileSync as writeFileSync9
38549
39447
  } from "fs";
38550
- import { homedir as homedir20 } from "os";
38551
- import { join as join20 } from "path";
39448
+ import { homedir as homedir21 } from "os";
39449
+ import { join as join21 } from "path";
38552
39450
  function ensureDir() {
38553
- if (!existsSync14(CLAUDISH_DIR)) {
39451
+ if (!existsSync15(CLAUDISH_DIR)) {
38554
39452
  mkdirSync9(CLAUDISH_DIR, { recursive: true });
38555
39453
  }
38556
39454
  }
38557
39455
  function readFromDisk() {
38558
39456
  try {
38559
- if (!existsSync14(BUFFER_FILE))
39457
+ if (!existsSync15(BUFFER_FILE))
38560
39458
  return [];
38561
39459
  const raw2 = readFileSync13(BUFFER_FILE, "utf-8");
38562
39460
  const parsed = JSON.parse(raw2);
@@ -38583,7 +39481,7 @@ function writeToDisk(events) {
38583
39481
  ensureDir();
38584
39482
  const trimmed = enforceSizeCap([...events]);
38585
39483
  const payload = { version: 1, events: trimmed };
38586
- const tmpFile = join20(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
39484
+ const tmpFile = join21(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
38587
39485
  writeFileSync9(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
38588
39486
  renameSync(tmpFile, BUFFER_FILE);
38589
39487
  memoryCache = trimmed;
@@ -38627,7 +39525,7 @@ function clearBuffer() {
38627
39525
  try {
38628
39526
  memoryCache = [];
38629
39527
  eventsSinceLastFlush = 0;
38630
- if (existsSync14(BUFFER_FILE)) {
39528
+ if (existsSync15(BUFFER_FILE)) {
38631
39529
  unlinkSync5(BUFFER_FILE);
38632
39530
  }
38633
39531
  } catch {}
@@ -38656,8 +39554,8 @@ function syncFlushOnExit() {
38656
39554
  var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, flushScheduled = false;
38657
39555
  var init_stats_buffer = __esm(() => {
38658
39556
  BUFFER_MAX_BYTES = 64 * 1024;
38659
- CLAUDISH_DIR = join20(homedir20(), ".claudish");
38660
- BUFFER_FILE = join20(CLAUDISH_DIR, "stats-buffer.json");
39557
+ CLAUDISH_DIR = join21(homedir21(), ".claudish");
39558
+ BUFFER_FILE = join21(CLAUDISH_DIR, "stats-buffer.json");
38661
39559
  process.on("exit", syncFlushOnExit);
38662
39560
  process.on("SIGTERM", () => {
38663
39561
  try {
@@ -40938,8 +41836,8 @@ var init_openai_responses_sse = __esm(() => {
40938
41836
 
40939
41837
  // src/handlers/shared/token-tracker.ts
40940
41838
  import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
40941
- import { homedir as homedir21 } from "os";
40942
- import { dirname as dirname7, join as join21 } from "path";
41839
+ import { homedir as homedir22 } from "os";
41840
+ import { dirname as dirname7, join as join22 } from "path";
40943
41841
 
40944
41842
  class TokenTracker {
40945
41843
  port;
@@ -41083,7 +41981,7 @@ class TokenTracker {
41083
41981
  data.quota_remaining = this.quotaRemaining;
41084
41982
  }
41085
41983
  const override = process.env.CLAUDISH_TOKEN_FILE;
41086
- const outPath = override || join21(homedir21(), ".claudish", `tokens-${this.port}.json`);
41984
+ const outPath = override || join22(homedir22(), ".claudish", `tokens-${this.port}.json`);
41087
41985
  mkdirSync10(dirname7(outPath), { recursive: true });
41088
41986
  writeFileSync10(outPath, JSON.stringify(data), "utf-8");
41089
41987
  } catch (e) {
@@ -41304,6 +42202,9 @@ class ComposedHandler {
41304
42202
  isInteractive: this.isInteractive,
41305
42203
  authType: "oauth"
41306
42204
  });
42205
+ if (err?.terminal) {
42206
+ return c.json(wrapAnthropicError(400, err.message, "invalid_request_error"), 400);
42207
+ }
41307
42208
  return c.json(wrapAnthropicError(401, err.message, "authentication_error"), 401);
41308
42209
  }
41309
42210
  }
@@ -41898,7 +42799,7 @@ function isRetryableError(status, errorBody) {
41898
42799
  }
41899
42800
  }
41900
42801
  if (status === 400) {
41901
- if (lower.includes("model not found") || lower.includes("not registered") || lower.includes("does not exist") || lower.includes("unknown model") || lower.includes("unsupported model") || lower.includes("no healthy deployment")) {
42802
+ if (lower.includes("model not found") || lower.includes("not registered") || lower.includes("does not exist") || lower.includes("unknown model") || lower.includes("unsupported model") || lower.includes("no healthy deployment") || lower.includes("requires a google cloud project") || lower.includes("unsupported_client")) {
41902
42803
  return true;
41903
42804
  }
41904
42805
  }
@@ -43582,11 +44483,11 @@ var init_ollama_api_format = __esm(() => {
43582
44483
  });
43583
44484
 
43584
44485
  // src/providers/api-key-provenance.ts
43585
- import { existsSync as existsSync15, readFileSync as readFileSync14 } from "fs";
43586
- import { homedir as homedir22 } from "os";
43587
- import { join as join22, resolve as resolve2 } from "path";
44486
+ import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
44487
+ import { homedir as homedir23 } from "os";
44488
+ import { join as join23, resolve as resolve2 } from "path";
43588
44489
  function activeConfigPath() {
43589
- return activeGlobalConfigFile(join22(homedir22(), ".claudish", "config.json"));
44490
+ return activeGlobalConfigFile(join23(homedir23(), ".claudish", "config.json"));
43590
44491
  }
43591
44492
  function configLayerLabel() {
43592
44493
  return getConfigFileOverride() ? activeConfigPath() : "~/.claudish/config.json";
@@ -43663,7 +44564,7 @@ function formatProvenanceLog(p) {
43663
44564
  function readDotenvKey(envVars) {
43664
44565
  try {
43665
44566
  const dotenvPath = resolve2(".env");
43666
- if (!existsSync15(dotenvPath))
44567
+ if (!existsSync16(dotenvPath))
43667
44568
  return null;
43668
44569
  const parsed = import_dotenv.parse(readFileSync14(dotenvPath, "utf-8"));
43669
44570
  for (const v of envVars) {
@@ -43678,7 +44579,7 @@ function readDotenvKey(envVars) {
43678
44579
  function readConfigKey(envVar) {
43679
44580
  try {
43680
44581
  const configPath = activeConfigPath();
43681
- if (!existsSync15(configPath))
44582
+ if (!existsSync16(configPath))
43682
44583
  return null;
43683
44584
  const cfg = JSON.parse(readFileSync14(configPath, "utf-8"));
43684
44585
  return cfg.apiKeys?.[envVar] || null;
@@ -43692,142 +44593,6 @@ var init_api_key_provenance = __esm(() => {
43692
44593
  import_dotenv = __toESM(require_main(), 1);
43693
44594
  });
43694
44595
 
43695
- // src/handlers/shared/gemini-queue.ts
43696
- class GeminiRequestQueue {
43697
- static instance = null;
43698
- queue = [];
43699
- processing = false;
43700
- minDelayMs = 1000;
43701
- lastRequestTime = 0;
43702
- consecutiveErrors = 0;
43703
- totalProcessed = 0;
43704
- totalErrors = 0;
43705
- baseDelayMs = 1000;
43706
- maxDelayMs = 1e4;
43707
- maxQueueSize = 100;
43708
- constructor() {
43709
- log("[GeminiQueue] Queue initialized with minDelay=1000ms, maxQueueSize=100");
43710
- }
43711
- static getInstance() {
43712
- if (!GeminiRequestQueue.instance) {
43713
- GeminiRequestQueue.instance = new GeminiRequestQueue;
43714
- }
43715
- return GeminiRequestQueue.instance;
43716
- }
43717
- async enqueue(fetchFn) {
43718
- if (this.queue.length >= this.maxQueueSize) {
43719
- log(`[GeminiQueue] Queue full (${this.queue.length}/${this.maxQueueSize}), rejecting request`);
43720
- throw new Error("Gemini request queue full. Please retry later.");
43721
- }
43722
- return new Promise((resolve3, reject) => {
43723
- const queuedRequest = {
43724
- fetchFn,
43725
- resolve: resolve3,
43726
- reject
43727
- };
43728
- this.queue.push(queuedRequest);
43729
- log(`[GeminiQueue] Request enqueued (queue length: ${this.queue.length})`);
43730
- if (!this.processing) {
43731
- this.processQueue();
43732
- }
43733
- });
43734
- }
43735
- async processQueue() {
43736
- if (this.processing) {
43737
- return;
43738
- }
43739
- this.processing = true;
43740
- log("[GeminiQueue] Worker started");
43741
- while (this.queue.length > 0) {
43742
- const request = this.queue.shift();
43743
- if (!request)
43744
- break;
43745
- log(`[GeminiQueue] Processing request (${this.queue.length} remaining in queue)`);
43746
- try {
43747
- await this.waitForNextSlot();
43748
- const response = await request.fetchFn();
43749
- this.lastRequestTime = Date.now();
43750
- if (response.status === 429) {
43751
- this.totalErrors++;
43752
- const errorText = await response.clone().text();
43753
- this.handleRateLimitResponse(errorText);
43754
- log(`[GeminiQueue] Rate limit hit (429), adjusted delay to ${this.minDelayMs}ms`);
43755
- } else {
43756
- this.handleSuccessResponse();
43757
- }
43758
- this.totalProcessed++;
43759
- request.resolve(response);
43760
- } catch (error46) {
43761
- this.totalErrors++;
43762
- log(`[GeminiQueue] Request failed with error: ${error46}`);
43763
- request.reject(error46 instanceof Error ? error46 : new Error(String(error46)));
43764
- }
43765
- }
43766
- this.processing = false;
43767
- log("[GeminiQueue] Worker stopped (queue empty)");
43768
- }
43769
- async waitForNextSlot() {
43770
- const now = Date.now();
43771
- const timeSinceLastRequest = now - this.lastRequestTime;
43772
- let delayMs = this.minDelayMs;
43773
- if (this.consecutiveErrors > 0) {
43774
- const backoffMultiplier = 1 + this.consecutiveErrors * 0.5;
43775
- delayMs = Math.min(this.minDelayMs * backoffMultiplier, this.maxDelayMs);
43776
- log(`[GeminiQueue] Applying backoff (${this.consecutiveErrors} errors): ${delayMs}ms`);
43777
- }
43778
- if (timeSinceLastRequest < delayMs) {
43779
- const waitMs = delayMs - timeSinceLastRequest;
43780
- log(`[GeminiQueue] Waiting ${waitMs}ms before next request`);
43781
- await new Promise((resolve3) => setTimeout(resolve3, waitMs));
43782
- }
43783
- }
43784
- handleRateLimitResponse(errorText) {
43785
- this.consecutiveErrors++;
43786
- try {
43787
- const errorData = JSON.parse(errorText);
43788
- const quotaDetail = errorData?.error?.details?.find((d) => d.quotaResetDelay);
43789
- if (quotaDetail?.quotaResetDelay) {
43790
- const delayStr = quotaDetail.quotaResetDelay;
43791
- const match2 = delayStr.match(/(\d+(?:\.\d+)?)/);
43792
- if (match2) {
43793
- const delaySeconds = Number.parseFloat(match2[1]);
43794
- const suggestedDelayMs = Math.ceil(delaySeconds * 1000);
43795
- this.minDelayMs = Math.max(suggestedDelayMs, this.minDelayMs, this.baseDelayMs);
43796
- this.minDelayMs = Math.min(this.minDelayMs, this.maxDelayMs);
43797
- log(`[GeminiQueue] Parsed quotaResetDelay: ${delayStr} (${suggestedDelayMs}ms), ` + `new minDelay: ${this.minDelayMs}ms`);
43798
- }
43799
- }
43800
- } catch {
43801
- log("[GeminiQueue] Failed to parse rate limit response, using backoff");
43802
- }
43803
- const backoffMultiplier = 1 + this.consecutiveErrors * 0.5;
43804
- this.minDelayMs = Math.min(this.baseDelayMs * backoffMultiplier, this.maxDelayMs);
43805
- }
43806
- handleSuccessResponse() {
43807
- if (this.consecutiveErrors > 0) {
43808
- log(`[GeminiQueue] Success after ${this.consecutiveErrors} errors, resetting counter`);
43809
- this.consecutiveErrors = 0;
43810
- }
43811
- if (this.minDelayMs > this.baseDelayMs) {
43812
- this.minDelayMs = Math.max(this.baseDelayMs, this.minDelayMs * 0.9);
43813
- log(`[GeminiQueue] Reducing delay to ${this.minDelayMs}ms`);
43814
- }
43815
- }
43816
- getStats() {
43817
- return {
43818
- queueLength: this.queue.length,
43819
- processing: this.processing,
43820
- consecutiveErrors: this.consecutiveErrors,
43821
- currentDelayMs: this.minDelayMs,
43822
- totalProcessed: this.totalProcessed,
43823
- totalErrors: this.totalErrors
43824
- };
43825
- }
43826
- }
43827
- var init_gemini_queue = __esm(() => {
43828
- init_logger();
43829
- });
43830
-
43831
44596
  // src/providers/transport/gemini-apikey.ts
43832
44597
  class GeminiProviderTransport {
43833
44598
  name = "gemini";
@@ -43860,22 +44625,17 @@ var init_gemini_apikey = __esm(() => {
43860
44625
  });
43861
44626
 
43862
44627
  // src/providers/transport/gemini-codeassist.ts
43863
- import { randomUUID as randomUUID3 } from "crypto";
43864
- function buildGeminiCliUserAgent2(model) {
43865
- const version2 = "0.5.6";
43866
- const modelSegment = model || "gemini-code-assist";
43867
- return `GeminiCLI/${version2}/${modelSegment} (${process.platform}; ${process.arch})`;
43868
- }
43869
- function createActivityRequestId2() {
44628
+ import { randomUUID as randomUUID5 } from "crypto";
44629
+ function createActivityRequestId4() {
43870
44630
  return Math.random().toString(36).substring(7);
43871
44631
  }
43872
- function classify429(responseBody) {
44632
+ function classify4292(responseBody) {
43873
44633
  try {
43874
44634
  const raw2 = JSON.parse(responseBody);
43875
44635
  const error46 = Array.isArray(raw2) ? raw2[0]?.error : raw2?.error;
43876
44636
  const details = Array.isArray(error46?.details) ? error46.details : [];
43877
44637
  const retryInfo = details.find((d) => d["@type"] === "type.googleapis.com/google.rpc.RetryInfo");
43878
- let retryDelayMs = parseRetryDelay(retryInfo?.retryDelay);
44638
+ let retryDelayMs = parseRetryDelay2(retryInfo?.retryDelay);
43879
44639
  if (retryDelayMs === undefined && typeof error46?.message === "string") {
43880
44640
  const match2 = error46.message.match(/retry in ([\d.]+)(ms|s)/i);
43881
44641
  if (match2) {
@@ -43889,7 +44649,7 @@ function classify429(responseBody) {
43889
44649
  return { terminal: true, retryDelayMs, reason };
43890
44650
  }
43891
44651
  if (reason === "RATE_LIMIT_EXCEEDED") {
43892
- return { terminal: false, retryDelayMs: retryDelayMs ?? DEFAULT_RATE_LIMIT_DELAY_MS, reason };
44652
+ return { terminal: false, retryDelayMs: retryDelayMs ?? DEFAULT_RATE_LIMIT_DELAY_MS2, reason };
43893
44653
  }
43894
44654
  if (reason === "MODEL_CAPACITY_EXHAUSTED") {
43895
44655
  return { terminal: true, retryDelayMs, reason };
@@ -43909,7 +44669,7 @@ function classify429(responseBody) {
43909
44669
  return null;
43910
44670
  }
43911
44671
  }
43912
- function parseRetryDelay(value) {
44672
+ function parseRetryDelay2(value) {
43913
44673
  if (!value)
43914
44674
  return;
43915
44675
  if (typeof value === "string") {
@@ -43927,7 +44687,7 @@ function parseRetryDelay(value) {
43927
44687
 
43928
44688
  class GeminiCodeAssistProviderTransport {
43929
44689
  name = "gemini-codeassist";
43930
- _displayName = "Gemini Free";
44690
+ _displayName = "GeminiCA";
43931
44691
  get displayName() {
43932
44692
  return this._displayName;
43933
44693
  }
@@ -43937,19 +44697,17 @@ class GeminiCodeAssistProviderTransport {
43937
44697
  projectId = null;
43938
44698
  tierId = null;
43939
44699
  cachedAuth = null;
43940
- fallbackStartIndex;
43941
44700
  lastEnvelope = null;
43942
44701
  _activeModelName;
44702
+ servedModels = [];
43943
44703
  constructor(modelName) {
43944
44704
  this.modelName = modelName;
43945
- const idx = CODE_ASSIST_FALLBACK_CHAIN.indexOf(modelName);
43946
- this.fallbackStartIndex = idx >= 0 ? idx : CODE_ASSIST_FALLBACK_CHAIN.length;
43947
44705
  }
43948
44706
  getActiveModelName() {
43949
44707
  return this._activeModelName;
43950
44708
  }
43951
44709
  getEndpoint() {
43952
- return CODE_ASSIST_ENDPOINT;
44710
+ return CODE_ASSIST_ENDPOINT2;
43953
44711
  }
43954
44712
  async getHeaders() {
43955
44713
  if (this.cachedAuth)
@@ -43959,8 +44717,8 @@ class GeminiCodeAssistProviderTransport {
43959
44717
  buildLocalHeaders() {
43960
44718
  return {
43961
44719
  Authorization: `Bearer ${this.accessToken}`,
43962
- "User-Agent": buildGeminiCliUserAgent2(this.modelName),
43963
- "x-activity-request-id": createActivityRequestId2()
44720
+ "User-Agent": buildCodeAssistUserAgent(this.modelName),
44721
+ "x-activity-request-id": createActivityRequestId4()
43964
44722
  };
43965
44723
  }
43966
44724
  async refreshAuth() {
@@ -43972,7 +44730,8 @@ class GeminiCodeAssistProviderTransport {
43972
44730
  this.projectId = projectId;
43973
44731
  this.tierId = tierId;
43974
44732
  this._displayName = getGeminiTierDisplayName();
43975
- log(`[GeminiCodeAssist] Auth refreshed, project: ${this.projectId}, tier: ${this._displayName}`);
44733
+ this.servedModels = await getServedCodeAssistModels(this.accessToken, this.projectId);
44734
+ log(`[GeminiCodeAssist] Auth refreshed, project: ${this.projectId}, tier: ${this._displayName}, served: ${this.servedModels.join(",") || "(none)"}`);
43976
44735
  }
43977
44736
  transformPayload(payload) {
43978
44737
  const envelope = this.cachedAuth?.transformPayload ? this.cachedAuth.transformPayload(payload) : this.buildEnvelope(payload, this.modelName);
@@ -43983,7 +44742,7 @@ class GeminiCodeAssistProviderTransport {
43983
44742
  const envelope = {
43984
44743
  model,
43985
44744
  project: this.projectId,
43986
- user_prompt_id: randomUUID3(),
44745
+ user_prompt_id: randomUUID5(),
43987
44746
  request: innerPayload
43988
44747
  };
43989
44748
  if (this.tierId && this.tierId !== "free-tier") {
@@ -43994,13 +44753,16 @@ class GeminiCodeAssistProviderTransport {
43994
44753
  async enqueueRequest(fetchFn) {
43995
44754
  const queue = GeminiRequestQueue.getInstance();
43996
44755
  let lastResponse = null;
43997
- for (let attempt = 1;attempt <= MAX_RETRY_ATTEMPTS; attempt++) {
44756
+ for (let attempt = 1;attempt <= MAX_RETRY_ATTEMPTS2; attempt++) {
43998
44757
  const response = attempt === 1 ? await queue.enqueue(fetchFn) : await queue.enqueue(fetchFn);
43999
44758
  if (response.status !== 429) {
44759
+ if (response.status === 404) {
44760
+ return this.rewriteModelNotFound(response);
44761
+ }
44000
44762
  return response;
44001
44763
  }
44002
44764
  const bodyText = await response.clone().text();
44003
- const classification = classify429(bodyText);
44765
+ const classification = classify4292(bodyText);
44004
44766
  lastResponse = response;
44005
44767
  if (!classification) {
44006
44768
  log("[GeminiCodeAssist] 429 response could not be classified, returning to caller");
@@ -44014,20 +44776,21 @@ class GeminiCodeAssistProviderTransport {
44014
44776
  logStderr(`[GeminiCodeAssist] Quota exhausted (${classification.reason || "daily limit"}). Check plan limits.`);
44015
44777
  return response;
44016
44778
  }
44017
- if (attempt < MAX_RETRY_ATTEMPTS) {
44018
- const delay = classification.retryDelayMs ?? DEFAULT_RATE_LIMIT_DELAY_MS;
44019
- logStderr(`[GeminiCodeAssist] Rate limited (${classification.reason || "unknown"}), retrying in ${(delay / 1000).toFixed(1)}s (attempt ${attempt}/${MAX_RETRY_ATTEMPTS})`);
44779
+ if (attempt < MAX_RETRY_ATTEMPTS2) {
44780
+ const delay = classification.retryDelayMs ?? DEFAULT_RATE_LIMIT_DELAY_MS2;
44781
+ logStderr(`[GeminiCodeAssist] Rate limited (${classification.reason || "unknown"}), retrying in ${(delay / 1000).toFixed(1)}s (attempt ${attempt}/${MAX_RETRY_ATTEMPTS2})`);
44020
44782
  if (attempt === 1) {
44021
44783
  await this.logQuotaInfo();
44022
44784
  }
44023
44785
  await new Promise((r) => setTimeout(r, delay));
44024
44786
  }
44025
44787
  }
44026
- logStderr(`[GeminiCodeAssist] Rate limit persisted after ${MAX_RETRY_ATTEMPTS} retries`);
44788
+ logStderr(`[GeminiCodeAssist] Rate limit persisted after ${MAX_RETRY_ATTEMPTS2} retries`);
44027
44789
  return lastResponse;
44028
44790
  }
44029
44791
  async handleCapacityExhausted(originalResponse, queue) {
44030
- if (this.fallbackStartIndex >= CODE_ASSIST_FALLBACK_CHAIN.length - 1) {
44792
+ const candidates = this.servedModels.filter((m) => m !== this.modelName);
44793
+ if (candidates.length === 0) {
44031
44794
  log(`[GeminiCodeAssist] ${this.modelName} capacity exhausted, no fallback models available`);
44032
44795
  return originalResponse;
44033
44796
  }
@@ -44039,11 +44802,12 @@ class GeminiCodeAssistProviderTransport {
44039
44802
  logStderr(`[GeminiCodeAssist] ${this.modelName} capacity exhausted, trying fallback models...`);
44040
44803
  let lastResponse = originalResponse;
44041
44804
  const innerPayload = this.lastEnvelope.request;
44042
- for (let i = this.fallbackStartIndex + 1;i < CODE_ASSIST_FALLBACK_CHAIN.length; i++) {
44043
- const fallbackModel = CODE_ASSIST_FALLBACK_CHAIN[i];
44805
+ const endpoint = this.getEndpoint();
44806
+ const tried = [this.modelName];
44807
+ for (const fallbackModel of candidates) {
44044
44808
  log(`[GeminiCodeAssist] Trying fallback model: ${fallbackModel}`);
44809
+ tried.push(fallbackModel);
44045
44810
  const fallbackEnvelope = this.buildEnvelope(innerPayload, fallbackModel);
44046
- const endpoint = this.getEndpoint();
44047
44811
  const headers = this.buildLocalHeaders();
44048
44812
  headers["Content-Type"] = "application/json";
44049
44813
  const fallbackResponse = await queue.enqueue(() => fetch(endpoint, {
@@ -44051,23 +44815,59 @@ class GeminiCodeAssistProviderTransport {
44051
44815
  headers,
44052
44816
  body: JSON.stringify(fallbackEnvelope)
44053
44817
  }));
44054
- if (fallbackResponse.status !== 429) {
44818
+ if (fallbackResponse.status === 200) {
44055
44819
  this._activeModelName = fallbackModel;
44056
44820
  logStderr(`[GeminiCodeAssist] Using fallback model: ${fallbackModel} (${this.modelName} had no capacity)`);
44057
44821
  return fallbackResponse;
44058
44822
  }
44059
- const fallbackBodyText = await fallbackResponse.clone().text();
44060
- const classification = classify429(fallbackBodyText);
44061
- if (classification?.reason !== "MODEL_CAPACITY_EXHAUSTED") {
44823
+ if (fallbackResponse.status === 404) {
44824
+ log(`[GeminiCodeAssist] ${fallbackModel} returned 404, skipping to next fallback`);
44825
+ lastResponse = fallbackResponse;
44826
+ continue;
44827
+ }
44828
+ if (fallbackResponse.status === 429) {
44829
+ const fallbackBodyText = await fallbackResponse.clone().text();
44830
+ const classification = classify4292(fallbackBodyText);
44831
+ if (classification?.reason === "MODEL_CAPACITY_EXHAUSTED") {
44832
+ log(`[GeminiCodeAssist] ${fallbackModel} also capacity exhausted, trying next...`);
44833
+ lastResponse = fallbackResponse;
44834
+ continue;
44835
+ }
44062
44836
  return fallbackResponse;
44063
44837
  }
44064
- log(`[GeminiCodeAssist] ${fallbackModel} also capacity exhausted, trying next...`);
44065
- lastResponse = fallbackResponse;
44838
+ return fallbackResponse;
44066
44839
  }
44067
44840
  log("[GeminiCodeAssist] All fallback models exhausted");
44068
- logStderr(`[GeminiCodeAssist] All models capacity exhausted (tried: ${CODE_ASSIST_FALLBACK_CHAIN.slice(this.fallbackStartIndex).join(" -> ")})`);
44841
+ logStderr(`[GeminiCodeAssist] All models capacity exhausted (tried: ${tried.join(" -> ")})`);
44842
+ if (lastResponse.status === 404) {
44843
+ return this.rewriteModelNotFound(lastResponse, true);
44844
+ }
44069
44845
  return lastResponse;
44070
44846
  }
44847
+ rewriteModelNotFound(response, capacityFallbacksExhausted = false) {
44848
+ const served = this.servedModels.length > 0 ? this.servedModels : CODE_ASSIST_FALLBACK_CHAIN.slice();
44849
+ if (!capacityFallbacksExhausted && served.includes(this.modelName)) {
44850
+ log(`[GeminiCodeAssist] 404 for ${this.modelName}, which IS in the served set \u2014 passing through unmodified`);
44851
+ return response;
44852
+ }
44853
+ response.text().catch(() => {});
44854
+ const list = served.join(", ");
44855
+ const tier = this._displayName || "Gemini Code Assist";
44856
+ const reason = capacityFallbacksExhausted ? `${this.modelName} could not be served after every Gemini Code Assist capacity fallback failed (${tier}, via go@). ` + `That tier currently reports: ${list}. ` : `${this.modelName} is not served by your Gemini Code Assist tier (${tier}, via go@). ` + `That tier currently serves: ${list}. `;
44857
+ const message = reason + `To use ${this.modelName}, go through the direct Gemini API instead \u2014 ` + `set GEMINI_API_KEY (get one at https://aistudio.google.com/app/apikey) and run ` + `google@${this.modelName}.`;
44858
+ const body = JSON.stringify({
44859
+ error: { code: 404, status: "NOT_FOUND", message }
44860
+ });
44861
+ if (capacityFallbacksExhausted) {
44862
+ logStderr(`[GeminiCodeAssist] ${this.modelName} capacity fallbacks exhausted (404). Reported models: ${list}`);
44863
+ } else {
44864
+ logStderr(`[GeminiCodeAssist] ${this.modelName} not served by ${tier} (404). Serves: ${list}`);
44865
+ }
44866
+ return new Response(body, {
44867
+ status: 404,
44868
+ headers: { "Content-Type": "application/json" }
44869
+ });
44870
+ }
44071
44871
  async logQuotaInfo() {
44072
44872
  if (!this.accessToken || !this.projectId)
44073
44873
  return;
@@ -44107,13 +44907,13 @@ ${lines.join(`
44107
44907
  }
44108
44908
  }
44109
44909
  }
44110
- var CODE_ASSIST_BASE = "https://cloudcode-pa.googleapis.com", CODE_ASSIST_ENDPOINT, MAX_RETRY_ATTEMPTS = 3, DEFAULT_RATE_LIMIT_DELAY_MS = 1e4;
44910
+ var CODE_ASSIST_BASE2 = "https://cloudcode-pa.googleapis.com", CODE_ASSIST_ENDPOINT2, MAX_RETRY_ATTEMPTS2 = 3, DEFAULT_RATE_LIMIT_DELAY_MS2 = 1e4;
44111
44911
  var init_gemini_codeassist = __esm(() => {
44112
44912
  init_authority();
44113
44913
  init_gemini_oauth();
44114
44914
  init_gemini_queue();
44115
44915
  init_logger();
44116
- CODE_ASSIST_ENDPOINT = `${CODE_ASSIST_BASE}/v1internal:streamGenerateContent?alt=sse`;
44916
+ CODE_ASSIST_ENDPOINT2 = `${CODE_ASSIST_BASE2}/v1internal:streamGenerateContent?alt=sse`;
44117
44917
  });
44118
44918
 
44119
44919
  // src/providers/transport/ollamacloud.ts
@@ -44275,7 +45075,7 @@ function createHandlerForProvider(ctx) {
44275
45075
  log(`[Proxy] Handler: provider=${ctx.provider.name}, model=${ctx.modelName}`);
44276
45076
  return profile.createHandler(ctx);
44277
45077
  }
44278
- var geminiProfile, geminiCodeAssistProfile, openaiProfile, openaiCodexProfile, anthropicCompatProfile, glmProfile, openCodeZenProfile, ollamaCloudProfile, litellmProfile, vertexProfile, PROVIDER_PROFILES;
45078
+ var geminiProfile, geminiCodeAssistProfile, antigravityProfile, openaiProfile, openaiCodexProfile, anthropicCompatProfile, glmProfile, openCodeZenProfile, ollamaCloudProfile, litellmProfile, vertexProfile, PROVIDER_PROFILES;
44279
45079
  var init_provider_profiles = __esm(() => {
44280
45080
  init_anthropic_api_format();
44281
45081
  init_base_api_format();
@@ -44291,6 +45091,7 @@ var init_provider_profiles = __esm(() => {
44291
45091
  init_remote_provider_registry();
44292
45092
  init_runtime_providers();
44293
45093
  init_anthropic_compat();
45094
+ init_antigravity();
44294
45095
  init_gemini_apikey();
44295
45096
  init_gemini_codeassist();
44296
45097
  init_litellm();
@@ -44323,6 +45124,19 @@ var init_provider_profiles = __esm(() => {
44323
45124
  return handler;
44324
45125
  }
44325
45126
  };
45127
+ antigravityProfile = {
45128
+ createHandler(ctx) {
45129
+ const transport = new AntigravityProviderTransport(ctx.modelName);
45130
+ const adapter = new GeminiAPIFormat(ctx.modelName);
45131
+ const handler = new ComposedHandler(transport, ctx.targetModel, ctx.modelName, ctx.port, {
45132
+ adapter,
45133
+ unwrapGeminiResponse: true,
45134
+ ...ctx.sharedOpts
45135
+ });
45136
+ log(`[Proxy] Created Antigravity handler (composed): ${ctx.modelName}`);
45137
+ return handler;
45138
+ }
45139
+ };
44326
45140
  openaiProfile = {
44327
45141
  createHandler(ctx) {
44328
45142
  if (requiresResponsesApi(ctx.modelName)) {
@@ -44501,6 +45315,7 @@ var init_provider_profiles = __esm(() => {
44501
45315
  PROVIDER_PROFILES = {
44502
45316
  gemini: geminiProfile,
44503
45317
  "gemini-codeassist": geminiCodeAssistProfile,
45318
+ antigravity: antigravityProfile,
44504
45319
  openai: openaiProfile,
44505
45320
  "openai-codex": openaiCodexProfile,
44506
45321
  "x-ai": openaiProfile,
@@ -45238,9 +46053,9 @@ var init_poe = __esm(() => {
45238
46053
  });
45239
46054
 
45240
46055
  // src/services/pricing-cache.ts
45241
- import { existsSync as existsSync16, readFileSync as readFileSync15, statSync as statSync4 } from "fs";
45242
- import { homedir as homedir23 } from "os";
45243
- import { join as join23 } from "path";
46056
+ import { existsSync as existsSync17, readFileSync as readFileSync15, statSync as statSync4 } from "fs";
46057
+ import { homedir as homedir24 } from "os";
46058
+ import { join as join24 } from "path";
45244
46059
  function prefixMatch(modelName) {
45245
46060
  for (const [key, pricing] of pricingMap) {
45246
46061
  if (modelName.startsWith(key))
@@ -45278,7 +46093,7 @@ async function warmPricingCache() {
45278
46093
  }
45279
46094
  function loadDiskCache() {
45280
46095
  try {
45281
- if (!existsSync16(CACHE_FILE))
46096
+ if (!existsSync17(CACHE_FILE))
45282
46097
  return false;
45283
46098
  const stat2 = statSync4(CACHE_FILE);
45284
46099
  const age = Date.now() - stat2.mtimeMs;
@@ -45299,8 +46114,8 @@ var init_pricing_cache = __esm(() => {
45299
46114
  init_logger();
45300
46115
  init_catalog_query();
45301
46116
  pricingMap = new Map;
45302
- CACHE_DIR = join23(homedir23(), ".claudish");
45303
- CACHE_FILE = join23(CACHE_DIR, "pricing-cache.json");
46117
+ CACHE_DIR = join24(homedir24(), ".claudish");
46118
+ CACHE_FILE = join24(CACHE_DIR, "pricing-cache.json");
45304
46119
  CACHE_TTL_MS2 = 24 * 60 * 60 * 1000;
45305
46120
  });
45306
46121
 
@@ -45757,17 +46572,17 @@ var init_proxy_server = __esm(() => {
45757
46572
  });
45758
46573
 
45759
46574
  // src/team-stats.ts
45760
- import { existsSync as existsSync17, readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
45761
- import { join as join24 } from "path";
46575
+ import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
46576
+ import { join as join25 } from "path";
45762
46577
  function statsDir(sessionPath) {
45763
- return join24(sessionPath, "stats");
46578
+ return join25(sessionPath, "stats");
45764
46579
  }
45765
46580
  function tokenFileFor(sessionPath, anonId) {
45766
- return join24(statsDir(sessionPath), `${anonId}.json`);
46581
+ return join25(statsDir(sessionPath), `${anonId}.json`);
45767
46582
  }
45768
46583
  function readTokenStats(sessionPath, anonId) {
45769
46584
  const path = tokenFileFor(sessionPath, anonId);
45770
- if (!existsSync17(path))
46585
+ if (!existsSync18(path))
45771
46586
  return null;
45772
46587
  try {
45773
46588
  return JSON.parse(readFileSync16(path, "utf-8"));
@@ -45918,7 +46733,7 @@ ${segs.join(" \xB7 ")}`;
45918
46733
  }
45919
46734
  function writeStatusFile(sessionPath, manifest, status, opts) {
45920
46735
  try {
45921
- writeFileSync11(join24(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
46736
+ writeFileSync11(join25(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
45922
46737
  `, "utf-8");
45923
46738
  } catch {}
45924
46739
  }
@@ -45944,13 +46759,13 @@ __export(exports_team_orchestrator, {
45944
46759
  import { spawn as spawn2 } from "child_process";
45945
46760
  import {
45946
46761
  createWriteStream as createWriteStream2,
45947
- existsSync as existsSync18,
46762
+ existsSync as existsSync19,
45948
46763
  mkdirSync as mkdirSync11,
45949
46764
  readFileSync as readFileSync17,
45950
46765
  readdirSync as readdirSync3,
45951
46766
  writeFileSync as writeFileSync12
45952
46767
  } from "fs";
45953
- import { join as join25, resolve as resolve3 } from "path";
46768
+ import { join as join26, resolve as resolve3 } from "path";
45954
46769
  function classifyRunOutput(opts) {
45955
46770
  const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
45956
46771
  const apiError = API_ERROR_RE.exec(stdoutTail);
@@ -46011,18 +46826,18 @@ function setupSession(sessionPath, models, input) {
46011
46826
  if (models.length === 0) {
46012
46827
  throw new Error("At least one model is required");
46013
46828
  }
46014
- if (existsSync18(join25(sessionPath, "manifest.json"))) {
46829
+ if (existsSync19(join26(sessionPath, "manifest.json"))) {
46015
46830
  throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
46016
46831
  }
46017
46832
  const sentinels = models.filter(isSentinelModel);
46018
46833
  if (sentinels.length > 0) {
46019
46834
  throw new Error(`Invalid model(s) for team run: ${sentinels.join(", ")}. These are Claude Code agent selectors, not external model IDs. Use real external models (e.g., "gemini-2.0-flash", "gpt-4o", "or@deepseek/deepseek-r1"). For Claude models, use a Task agent instead of the team tool.`);
46020
46835
  }
46021
- mkdirSync11(join25(sessionPath, "work"), { recursive: true });
46022
- mkdirSync11(join25(sessionPath, "errors"), { recursive: true });
46836
+ mkdirSync11(join26(sessionPath, "work"), { recursive: true });
46837
+ mkdirSync11(join26(sessionPath, "errors"), { recursive: true });
46023
46838
  if (input !== undefined) {
46024
- writeFileSync12(join25(sessionPath, "input.md"), input, "utf-8");
46025
- } else if (!existsSync18(join25(sessionPath, "input.md"))) {
46839
+ writeFileSync12(join26(sessionPath, "input.md"), input, "utf-8");
46840
+ } else if (!existsSync19(join26(sessionPath, "input.md"))) {
46026
46841
  throw new Error(`No input.md found at ${sessionPath} and no input provided`);
46027
46842
  }
46028
46843
  const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
@@ -46039,9 +46854,9 @@ function setupSession(sessionPath, models, input) {
46039
46854
  model: models[i],
46040
46855
  assignedAt: now
46041
46856
  };
46042
- mkdirSync11(join25(sessionPath, "work", anonId), { recursive: true });
46857
+ mkdirSync11(join26(sessionPath, "work", anonId), { recursive: true });
46043
46858
  }
46044
- writeFileSync12(join25(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
46859
+ writeFileSync12(join26(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
46045
46860
  const status = {
46046
46861
  startedAt: now,
46047
46862
  models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
@@ -46055,14 +46870,14 @@ function setupSession(sessionPath, models, input) {
46055
46870
  }
46056
46871
  ]))
46057
46872
  };
46058
- writeFileSync12(join25(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
46873
+ writeFileSync12(join26(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
46059
46874
  return manifest;
46060
46875
  }
46061
46876
  async function runModels(sessionPath, opts = {}) {
46062
46877
  const timeoutMs = (opts.timeout ?? 300) * 1000;
46063
- const manifest = JSON.parse(readFileSync17(join25(sessionPath, "manifest.json"), "utf-8"));
46064
- const statusPath = join25(sessionPath, "status.json");
46065
- const inputPath = join25(sessionPath, "input.md");
46878
+ const manifest = JSON.parse(readFileSync17(join26(sessionPath, "manifest.json"), "utf-8"));
46879
+ const statusPath = join26(sessionPath, "status.json");
46880
+ const inputPath = join26(sessionPath, "input.md");
46066
46881
  const inputContent = readFileSync17(inputPath, "utf-8");
46067
46882
  await prehydrateCredentialsForSpawn(Object.values(manifest.models).map((m) => m.model));
46068
46883
  const statusCache = JSON.parse(readFileSync17(statusPath, "utf-8"));
@@ -46084,8 +46899,8 @@ async function runModels(sessionPath, opts = {}) {
46084
46899
  process.on("SIGINT", sigintHandler);
46085
46900
  const completionPromises = [];
46086
46901
  for (const [anonId, entry] of Object.entries(manifest.models)) {
46087
- const outputPath = join25(sessionPath, `response-${anonId}.md`);
46088
- const errorLogPath = join25(sessionPath, "errors", `${anonId}.log`);
46902
+ const outputPath = join26(sessionPath, `response-${anonId}.md`);
46903
+ const errorLogPath = join26(sessionPath, "errors", `${anonId}.log`);
46089
46904
  const args = ["--model", entry.model, "-y", "--stdin", "--quiet", ...opts.claudeFlags ?? []];
46090
46905
  updateModelStatus(anonId, {
46091
46906
  state: "RUNNING",
@@ -46274,23 +47089,23 @@ async function judgeResponses(sessionPath, opts = {}) {
46274
47089
  const responses = {};
46275
47090
  for (const file2 of responseFiles) {
46276
47091
  const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
46277
- responses[id] = readFileSync17(join25(sessionPath, file2), "utf-8");
47092
+ responses[id] = readFileSync17(join26(sessionPath, file2), "utf-8");
46278
47093
  }
46279
- const input = readFileSync17(join25(sessionPath, "input.md"), "utf-8");
47094
+ const input = readFileSync17(join26(sessionPath, "input.md"), "utf-8");
46280
47095
  const judgePrompt = buildJudgePrompt(input, responses);
46281
- writeFileSync12(join25(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
47096
+ writeFileSync12(join26(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
46282
47097
  const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
46283
- const judgePath = join25(sessionPath, "judging");
47098
+ const judgePath = join26(sessionPath, "judging");
46284
47099
  mkdirSync11(judgePath, { recursive: true });
46285
47100
  setupSession(judgePath, judgeModels, judgePrompt);
46286
47101
  await runModels(judgePath, { claudeFlags: opts.claudeFlags });
46287
47102
  const votes = parseJudgeVotes(judgePath, Object.keys(responses));
46288
47103
  const verdict = aggregateVerdict(votes, Object.keys(responses));
46289
- writeFileSync12(join25(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
47104
+ writeFileSync12(join26(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
46290
47105
  return verdict;
46291
47106
  }
46292
47107
  function getStatus(sessionPath) {
46293
- return JSON.parse(readFileSync17(join25(sessionPath, "status.json"), "utf-8"));
47108
+ return JSON.parse(readFileSync17(join26(sessionPath, "status.json"), "utf-8"));
46294
47109
  }
46295
47110
  function fisherYatesShuffle(arr) {
46296
47111
  for (let i = arr.length - 1;i > 0; i--) {
@@ -46300,7 +47115,7 @@ function fisherYatesShuffle(arr) {
46300
47115
  return arr;
46301
47116
  }
46302
47117
  function getDefaultJudgeModels(sessionPath) {
46303
- const manifest = JSON.parse(readFileSync17(join25(sessionPath, "manifest.json"), "utf-8"));
47118
+ const manifest = JSON.parse(readFileSync17(join26(sessionPath, "manifest.json"), "utf-8"));
46304
47119
  return Object.values(manifest.models).map((e) => e.model);
46305
47120
  }
46306
47121
  function buildJudgePrompt(input, responses) {
@@ -46363,7 +47178,7 @@ function parseJudgeVotes(judgePath, responseIds) {
46363
47178
  const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
46364
47179
  let content;
46365
47180
  try {
46366
- content = readFileSync17(join25(judgePath, file2), "utf-8");
47181
+ content = readFileSync17(join26(judgePath, file2), "utf-8");
46367
47182
  } catch {
46368
47183
  continue;
46369
47184
  }
@@ -46415,7 +47230,7 @@ function aggregateVerdict(votes, responseIds) {
46415
47230
  function formatVerdict(verdict, sessionPath) {
46416
47231
  let manifest = null;
46417
47232
  try {
46418
- manifest = JSON.parse(readFileSync17(join25(sessionPath, "manifest.json"), "utf-8"));
47233
+ manifest = JSON.parse(readFileSync17(join26(sessionPath, "manifest.json"), "utf-8"));
46419
47234
  } catch {}
46420
47235
  let output = `# Team Verdict
46421
47236
 
@@ -46470,12 +47285,12 @@ __export(exports_mcp_server, {
46470
47285
  parseAnthropicSse: () => parseAnthropicSse,
46471
47286
  formatTeamResult: () => formatTeamResult
46472
47287
  });
46473
- import { existsSync as existsSync19, mkdirSync as mkdirSync12, readFileSync as readFileSync18, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
46474
- import { homedir as homedir24 } from "os";
46475
- import { dirname as dirname8, join as join26 } from "path";
47288
+ import { existsSync as existsSync20, mkdirSync as mkdirSync12, readFileSync as readFileSync18, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
47289
+ import { homedir as homedir25 } from "os";
47290
+ import { dirname as dirname8, join as join27 } from "path";
46476
47291
  import { fileURLToPath } from "url";
46477
47292
  async function loadAllModels(forceRefresh = false) {
46478
- if (!forceRefresh && existsSync19(ALL_MODELS_CACHE_PATH2)) {
47293
+ if (!forceRefresh && existsSync20(ALL_MODELS_CACHE_PATH2)) {
46479
47294
  try {
46480
47295
  const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH2, "utf-8"));
46481
47296
  const lastUpdated = new Date(cacheData.lastUpdated);
@@ -46495,7 +47310,7 @@ async function loadAllModels(forceRefresh = false) {
46495
47310
  writeFileSync13(ALL_MODELS_CACHE_PATH2, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
46496
47311
  return models;
46497
47312
  } catch {
46498
- if (existsSync19(ALL_MODELS_CACHE_PATH2)) {
47313
+ if (existsSync20(ALL_MODELS_CACHE_PATH2)) {
46499
47314
  const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH2, "utf-8"));
46500
47315
  return cacheData.models || [];
46501
47316
  }
@@ -47071,16 +47886,16 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
47071
47886
  const sp = session_path;
47072
47887
  for (const file2 of ["status.json", "manifest.json", "input.md"]) {
47073
47888
  try {
47074
- sessionData[file2] = readFileSync18(join26(sp, file2), "utf-8");
47889
+ sessionData[file2] = readFileSync18(join27(sp, file2), "utf-8");
47075
47890
  } catch {}
47076
47891
  }
47077
47892
  try {
47078
- const errorDir = join26(sp, "errors");
47079
- if (existsSync19(errorDir)) {
47893
+ const errorDir = join27(sp, "errors");
47894
+ if (existsSync20(errorDir)) {
47080
47895
  for (const f of readdirSync4(errorDir)) {
47081
47896
  if (f.endsWith(".log")) {
47082
47897
  try {
47083
- sessionData[`errors/${f}`] = readFileSync18(join26(errorDir, f), "utf-8");
47898
+ sessionData[`errors/${f}`] = readFileSync18(join27(errorDir, f), "utf-8");
47084
47899
  } catch {}
47085
47900
  }
47086
47901
  }
@@ -47090,7 +47905,7 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
47090
47905
  for (const f of readdirSync4(sp)) {
47091
47906
  if (f.startsWith("response-") && f.endsWith(".md")) {
47092
47907
  try {
47093
- const content = readFileSync18(join26(sp, f), "utf-8");
47908
+ const content = readFileSync18(join27(sp, f), "utf-8");
47094
47909
  sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
47095
47910
  } catch {}
47096
47911
  }
@@ -47099,8 +47914,8 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
47099
47914
  }
47100
47915
  let version2 = "unknown";
47101
47916
  try {
47102
- const pkgPath = join26(__dirname2, "../package.json");
47103
- if (existsSync19(pkgPath)) {
47917
+ const pkgPath = join27(__dirname2, "../package.json");
47918
+ if (existsSync20(pkgPath)) {
47104
47919
  version2 = JSON.parse(readFileSync18(pkgPath, "utf-8")).version;
47105
47920
  }
47106
47921
  } catch {}
@@ -47499,8 +48314,8 @@ var init_mcp_server = __esm(() => {
47499
48314
  import_dotenv2.config({ quiet: true });
47500
48315
  __filename2 = fileURLToPath(import.meta.url);
47501
48316
  __dirname2 = dirname8(__filename2);
47502
- CLAUDISH_CACHE_DIR = join26(homedir24(), ".claudish");
47503
- ALL_MODELS_CACHE_PATH2 = join26(CLAUDISH_CACHE_DIR, "all-models.json");
48317
+ CLAUDISH_CACHE_DIR = join27(homedir25(), ".claudish");
48318
+ ALL_MODELS_CACHE_PATH2 = join27(CLAUDISH_CACHE_DIR, "all-models.json");
47504
48319
  NEXT_STEP = {
47505
48320
  nonzero_exit: "read the evidence log, then retry or drop the model",
47506
48321
  timeout: "raise `timeout`, or pick a faster model",
@@ -47525,7 +48340,7 @@ var exports_serve_command = {};
47525
48340
  __export(exports_serve_command, {
47526
48341
  serveCommand: () => serveCommand
47527
48342
  });
47528
- import { existsSync as existsSync20, readFileSync as readFileSync19 } from "fs";
48343
+ import { existsSync as existsSync21, readFileSync as readFileSync19 } from "fs";
47529
48344
  function parseServeArgs(args) {
47530
48345
  const out = {};
47531
48346
  for (let i = 0;i < args.length; i++) {
@@ -47544,7 +48359,7 @@ function parseServeArgs(args) {
47544
48359
  return out;
47545
48360
  }
47546
48361
  function loadModelMap(path) {
47547
- if (!existsSync20(path)) {
48362
+ if (!existsSync21(path)) {
47548
48363
  throw new Error(`--models file not found: ${path}`);
47549
48364
  }
47550
48365
  let raw2;
@@ -47748,6 +48563,8 @@ function describeSourceSync(p, config3) {
47748
48563
  return isLocalProviderEnabled(p.catalogName, config3) ? "local" : null;
47749
48564
  if (p.oauthSlug && hasOAuthCredentials(p.catalogName))
47750
48565
  return "oauth";
48566
+ if (p.catalogName === "antigravity" && hasSharedAntigravityToken())
48567
+ return "oauth";
47751
48568
  const hasCfg = !!p.apiKeyEnvVar && !!realValue(config3.apiKeys?.[p.apiKeyEnvVar]);
47752
48569
  const hasEnv = !!p.apiKeyEnvVar && !!realValue(process.env[p.apiKeyEnvVar]);
47753
48570
  if (hasEnv && hasCfg)
@@ -47768,6 +48585,7 @@ async function describeSource(p, config3) {
47768
48585
  }
47769
48586
  var init_source = __esm(() => {
47770
48587
  init_profile_config();
48588
+ init_antigravity_token();
47771
48589
  init_oauth_registry();
47772
48590
  init_api_key_credential();
47773
48591
  init_authority();
@@ -47815,7 +48633,7 @@ function providerAuthCapabilities(p, config3) {
47815
48633
  const apiKeySupported = !!p.apiKeyEnvVar;
47816
48634
  const apiKeySet = apiKeySupported && (!!process.env[p.apiKeyEnvVar] || !!config3.apiKeys?.[p.apiKeyEnvVar]);
47817
48635
  const oauthSupported = !!p.oauthSlug;
47818
- const oauthSet = oauthSupported && hasOAuthCredentials(p.catalogName);
48636
+ const oauthSet = oauthSupported && (hasOAuthCredentials(p.catalogName) || p.catalogName === "antigravity" && hasSharedAntigravityToken());
47819
48637
  return {
47820
48638
  apiKey: { supported: apiKeySupported, set: apiKeySet },
47821
48639
  oauth: { supported: oauthSupported, set: oauthSet }
@@ -47831,6 +48649,7 @@ function maskKey2(key) {
47831
48649
  var SKIP, PROVIDERS;
47832
48650
  var init_providers = __esm(() => {
47833
48651
  init_source();
48652
+ init_antigravity_token();
47834
48653
  init_oauth_registry();
47835
48654
  init_provider_definitions();
47836
48655
  SKIP = new Set(["qwen", "native-anthropic"]);
@@ -59145,7 +59964,7 @@ import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
59145
59964
  import { readFileSync as readFileSync20, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
59146
59965
  import path from "path";
59147
59966
  import os from "os";
59148
- import { randomUUID as randomUUID4 } from "crypto";
59967
+ import { randomUUID as randomUUID6 } from "crypto";
59149
59968
  function editAsync(text = "", callback, fileOptions) {
59150
59969
  const editor = new ExternalEditor(text, fileOptions);
59151
59970
  editor.runAsync((err, result) => {
@@ -59237,7 +60056,7 @@ class ExternalEditor {
59237
60056
  createTemporaryFile() {
59238
60057
  try {
59239
60058
  const baseDir = this.fileOptions.dir ?? os.tmpdir();
59240
- const id = randomUUID4();
60059
+ const id = randomUUID6();
59241
60060
  const prefix = sanitizeAffix(this.fileOptions.prefix);
59242
60061
  const postfix = sanitizeAffix(this.fileOptions.postfix);
59243
60062
  const filename = `${prefix}${id}${postfix}`;
@@ -60413,13 +61232,14 @@ async function geminiQuotaHandler() {
60413
61232
  }
60414
61233
  console.log("");
60415
61234
  }
61235
+ const fallbackChain = quota.buckets.map((b) => b.modelId).filter((m) => typeof m === "string" && m.length > 0).sort((a, b) => rankCodeAssistModel(a) - rankCodeAssistModel(b));
60416
61236
  console.log(` ${B}${CYN}Fallback Chain${R} ${D}(on capacity exhaustion)${R}`);
60417
- for (let i = 0;i < CODE_ASSIST_FALLBACK_CHAIN.length; i++) {
60418
- const model = CODE_ASSIST_FALLBACK_CHAIN[i];
61237
+ for (let i = 0;i < fallbackChain.length; i++) {
61238
+ const model = fallbackChain[i];
60419
61239
  const rem = remainingByModel.get(model);
60420
61240
  const pct = rem !== undefined ? `${((1 - rem) * 100).toFixed(0)}%` : "?";
60421
61241
  const color = rem === undefined ? GRY : rem > 0.5 ? GRN : rem > 0.2 ? YEL : RED;
60422
- const arrow = i < CODE_ASSIST_FALLBACK_CHAIN.length - 1 ? ` ${GRY}\u2192${R}` : "";
61242
+ const arrow = i < fallbackChain.length - 1 ? ` ${GRY}\u2192${R}` : "";
60423
61243
  const marker = i === 0 ? `${CYN}\u25B8${R} ` : " ";
60424
61244
  console.log(` ${marker}${WHT}${model}${R} ${color}${pct}${R}${arrow}`);
60425
61245
  }
@@ -60453,11 +61273,11 @@ async function geminiQuotaHandler() {
60453
61273
  }
60454
61274
  }
60455
61275
  async function codexQuotaHandler() {
60456
- const { readFileSync: readFileSync21, existsSync: existsSync21 } = await import("fs");
60457
- const { join: join27 } = await import("path");
60458
- const { homedir: homedir25 } = await import("os");
60459
- const credPath = join27(homedir25(), ".claudish", "codex-oauth.json");
60460
- if (!existsSync21(credPath)) {
61276
+ const { readFileSync: readFileSync21, existsSync: existsSync22 } = await import("fs");
61277
+ const { join: join28 } = await import("path");
61278
+ const { homedir: homedir26 } = await import("os");
61279
+ const credPath = join28(homedir26(), ".claudish", "codex-oauth.json");
61280
+ if (!existsSync22(credPath)) {
60461
61281
  console.error(`${RED}No Codex credentials found.${R} Run: ${B}claudish login codex${R}`);
60462
61282
  process.exit(1);
60463
61283
  }
@@ -60513,8 +61333,8 @@ async function codexQuotaHandler() {
60513
61333
  }
60514
61334
  let modelSlugs = [];
60515
61335
  try {
60516
- const modelsPath = join27(homedir25(), ".codex", "models_cache.json");
60517
- if (existsSync21(modelsPath)) {
61336
+ const modelsPath = join28(homedir26(), ".codex", "models_cache.json");
61337
+ if (existsSync22(modelsPath)) {
60518
61338
  const cache2 = JSON.parse(readFileSync21(modelsPath, "utf-8"));
60519
61339
  modelSlugs = (cache2.models || []).map((m) => m.slug || m.id).filter(Boolean);
60520
61340
  }
@@ -64485,22 +65305,22 @@ __export(exports_cli, {
64485
65305
  });
64486
65306
  import {
64487
65307
  copyFileSync as copyFileSync2,
64488
- existsSync as existsSync21,
65308
+ existsSync as existsSync22,
64489
65309
  mkdirSync as mkdirSync13,
64490
65310
  readFileSync as readFileSync21,
64491
65311
  readdirSync as readdirSync5,
64492
65312
  unlinkSync as unlinkSync7,
64493
65313
  writeFileSync as writeFileSync15
64494
65314
  } from "fs";
64495
- import { homedir as homedir25 } from "os";
64496
- import { dirname as dirname9, join as join27 } from "path";
65315
+ import { homedir as homedir26 } from "os";
65316
+ import { dirname as dirname9, join as join28 } from "path";
64497
65317
  import { fileURLToPath as fileURLToPath2 } from "url";
64498
65318
  function getVersion3() {
64499
65319
  return VERSION;
64500
65320
  }
64501
65321
  function clearAllModelCaches() {
64502
- const cacheDir = join27(homedir25(), ".claudish");
64503
- if (!existsSync21(cacheDir))
65322
+ const cacheDir = join28(homedir26(), ".claudish");
65323
+ if (!existsSync22(cacheDir))
64504
65324
  return;
64505
65325
  const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
64506
65326
  let cleared = 0;
@@ -64508,7 +65328,7 @@ function clearAllModelCaches() {
64508
65328
  const files = readdirSync5(cacheDir);
64509
65329
  for (const file2 of files) {
64510
65330
  if (cachePatterns.includes(file2)) {
64511
- unlinkSync7(join27(cacheDir, file2));
65331
+ unlinkSync7(join28(cacheDir, file2));
64512
65332
  cleared++;
64513
65333
  }
64514
65334
  }
@@ -64918,8 +65738,8 @@ Usage: claudish --models --provider <slug>`);
64918
65738
  });
64919
65739
  config3.resolvedDefaultProvider = resolved;
64920
65740
  if (resolved.legacyAutoPromoted && !config3.quiet) {
64921
- const markerFile = join27(homedir25(), ".claudish", ".legacy-litellm-hint-shown");
64922
- if (!existsSync21(markerFile)) {
65741
+ const markerFile = join28(homedir26(), ".claudish", ".legacy-litellm-hint-shown");
65742
+ if (!existsSync22(markerFile)) {
64923
65743
  const hint = buildLegacyHint(resolved);
64924
65744
  if (hint) {
64925
65745
  console.error(hint);
@@ -65986,7 +66806,7 @@ ${h("MORE INFO")}
65986
66806
  }
65987
66807
  function printAIAgentGuide() {
65988
66808
  try {
65989
- const guidePath = join27(__dirname3, "../AI_AGENT_GUIDE.md");
66809
+ const guidePath = join28(__dirname3, "../AI_AGENT_GUIDE.md");
65990
66810
  const guideContent = readFileSync21(guidePath, "utf-8");
65991
66811
  console.log(guideContent);
65992
66812
  } catch (error46) {
@@ -66003,19 +66823,19 @@ async function initializeClaudishSkill() {
66003
66823
  console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
66004
66824
  `);
66005
66825
  const cwd = process.cwd();
66006
- const claudeDir = join27(cwd, ".claude");
66007
- const skillsDir = join27(claudeDir, "skills");
66008
- const claudishSkillDir = join27(skillsDir, "claudish-usage");
66009
- const skillFile = join27(claudishSkillDir, "SKILL.md");
66010
- if (existsSync21(skillFile)) {
66826
+ const claudeDir = join28(cwd, ".claude");
66827
+ const skillsDir = join28(claudeDir, "skills");
66828
+ const claudishSkillDir = join28(skillsDir, "claudish-usage");
66829
+ const skillFile = join28(claudishSkillDir, "SKILL.md");
66830
+ if (existsSync22(skillFile)) {
66011
66831
  console.log("\u2705 Claudish skill already installed at:");
66012
66832
  console.log(` ${skillFile}
66013
66833
  `);
66014
66834
  console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
66015
66835
  return;
66016
66836
  }
66017
- const sourceSkillPath = join27(__dirname3, "../skills/claudish-usage/SKILL.md");
66018
- if (!existsSync21(sourceSkillPath)) {
66837
+ const sourceSkillPath = join28(__dirname3, "../skills/claudish-usage/SKILL.md");
66838
+ if (!existsSync22(sourceSkillPath)) {
66019
66839
  console.error("\u274C Error: Claudish skill file not found in installation.");
66020
66840
  console.error(` Expected at: ${sourceSkillPath}`);
66021
66841
  console.error(`
@@ -66024,15 +66844,15 @@ async function initializeClaudishSkill() {
66024
66844
  process.exit(1);
66025
66845
  }
66026
66846
  try {
66027
- if (!existsSync21(claudeDir)) {
66847
+ if (!existsSync22(claudeDir)) {
66028
66848
  mkdirSync13(claudeDir, { recursive: true });
66029
66849
  console.log("\uD83D\uDCC1 Created .claude/ directory");
66030
66850
  }
66031
- if (!existsSync21(skillsDir)) {
66851
+ if (!existsSync22(skillsDir)) {
66032
66852
  mkdirSync13(skillsDir, { recursive: true });
66033
66853
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
66034
66854
  }
66035
- if (!existsSync21(claudishSkillDir)) {
66855
+ if (!existsSync22(claudishSkillDir)) {
66036
66856
  mkdirSync13(claudishSkillDir, { recursive: true });
66037
66857
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
66038
66858
  }
@@ -66117,30 +66937,30 @@ __export(exports_update_checker, {
66117
66937
  clearCache: () => clearCache,
66118
66938
  checkForUpdates: () => checkForUpdates
66119
66939
  });
66120
- import { existsSync as existsSync22, mkdirSync as mkdirSync14, readFileSync as readFileSync22, unlinkSync as unlinkSync8, writeFileSync as writeFileSync16 } from "fs";
66121
- import { homedir as homedir26, platform as platform2, tmpdir } from "os";
66122
- import { join as join28 } from "path";
66940
+ import { existsSync as existsSync23, mkdirSync as mkdirSync14, readFileSync as readFileSync22, unlinkSync as unlinkSync8, writeFileSync as writeFileSync16 } from "fs";
66941
+ import { homedir as homedir27, platform as platform2, tmpdir } from "os";
66942
+ import { join as join29 } from "path";
66123
66943
  function getCacheFilePath() {
66124
66944
  let cacheDir;
66125
66945
  if (isWindows) {
66126
- const localAppData = process.env.LOCALAPPDATA || join28(homedir26(), "AppData", "Local");
66127
- cacheDir = join28(localAppData, "claudish");
66946
+ const localAppData = process.env.LOCALAPPDATA || join29(homedir27(), "AppData", "Local");
66947
+ cacheDir = join29(localAppData, "claudish");
66128
66948
  } else {
66129
- cacheDir = join28(homedir26(), ".cache", "claudish");
66949
+ cacheDir = join29(homedir27(), ".cache", "claudish");
66130
66950
  }
66131
66951
  try {
66132
- if (!existsSync22(cacheDir)) {
66952
+ if (!existsSync23(cacheDir)) {
66133
66953
  mkdirSync14(cacheDir, { recursive: true });
66134
66954
  }
66135
- return join28(cacheDir, "update-check.json");
66955
+ return join29(cacheDir, "update-check.json");
66136
66956
  } catch {
66137
- return join28(tmpdir(), "claudish-update-check.json");
66957
+ return join29(tmpdir(), "claudish-update-check.json");
66138
66958
  }
66139
66959
  }
66140
66960
  function readCache() {
66141
66961
  try {
66142
66962
  const cachePath = getCacheFilePath();
66143
- if (!existsSync22(cachePath)) {
66963
+ if (!existsSync23(cachePath)) {
66144
66964
  return null;
66145
66965
  }
66146
66966
  const data = JSON.parse(readFileSync22(cachePath, "utf-8"));
@@ -66166,7 +66986,7 @@ function isCacheValid(cache2) {
66166
66986
  function clearCache() {
66167
66987
  try {
66168
66988
  const cachePath = getCacheFilePath();
66169
- if (existsSync22(cachePath)) {
66989
+ if (existsSync23(cachePath)) {
66170
66990
  unlinkSync8(cachePath);
66171
66991
  }
66172
66992
  } catch {}
@@ -67051,11 +67871,11 @@ var init_local_liveness = __esm(() => {
67051
67871
  });
67052
67872
 
67053
67873
  // src/providers/probe-catalog.ts
67054
- import { existsSync as existsSync23, mkdirSync as mkdirSync15, readFileSync as readFileSync23, writeFileSync as writeFileSync17 } from "fs";
67055
- import { homedir as homedir27 } from "os";
67056
- import { dirname as dirname10, join as join29 } from "path";
67874
+ import { existsSync as existsSync24, mkdirSync as mkdirSync15, readFileSync as readFileSync23, writeFileSync as writeFileSync17 } from "fs";
67875
+ import { homedir as homedir28 } from "os";
67876
+ import { dirname as dirname10, join as join30 } from "path";
67057
67877
  function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
67058
- if (!existsSync23(path2))
67878
+ if (!existsSync24(path2))
67059
67879
  return null;
67060
67880
  let raw2;
67061
67881
  try {
@@ -67188,7 +68008,7 @@ function isValidResponse(raw2) {
67188
68008
  var PROBE_MODELS_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/probeModels", CACHE_TTL_MS4, FETCH_TIMEOUT_MS3 = 15000, PROBE_MODELS_CACHE_PATH, _inFlight = null;
67189
68009
  var init_probe_catalog = __esm(() => {
67190
68010
  CACHE_TTL_MS4 = 60 * 60 * 1000;
67191
- PROBE_MODELS_CACHE_PATH = join29(homedir27(), ".claudish", "probe-models.json");
68011
+ PROBE_MODELS_CACHE_PATH = join30(homedir28(), ".claudish", "probe-models.json");
67192
68012
  });
67193
68013
 
67194
68014
  // src/tui/constants.ts
@@ -73525,15 +74345,15 @@ __export(exports_claude_runner, {
73525
74345
  import { spawn as spawn4 } from "child_process";
73526
74346
  import {
73527
74347
  closeSync as closeSync5,
73528
- existsSync as existsSync24,
74348
+ existsSync as existsSync25,
73529
74349
  mkdirSync as mkdirSync16,
73530
74350
  openSync as openSync5,
73531
74351
  readFileSync as readFileSync24,
73532
74352
  unlinkSync as unlinkSync9,
73533
74353
  writeFileSync as writeFileSync18
73534
74354
  } from "fs";
73535
- import { homedir as homedir28, tmpdir as tmpdir2 } from "os";
73536
- import { join as join30 } from "path";
74355
+ import { homedir as homedir29, tmpdir as tmpdir2 } from "os";
74356
+ import { join as join31 } from "path";
73537
74357
  import { isatty } from "tty";
73538
74358
  function releaseTerminalIsolation() {
73539
74359
  if (!restoreTerminal)
@@ -73568,7 +74388,7 @@ function isProxyAuthMode(config3) {
73568
74388
  }
73569
74389
  function managedSettingsPath() {
73570
74390
  if (isWindows2()) {
73571
- return join30(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
74391
+ return join31(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
73572
74392
  }
73573
74393
  if (process.platform === "darwin") {
73574
74394
  return "/Library/Application Support/ClaudeCode/managed-settings.json";
@@ -73589,9 +74409,9 @@ function isWindows2() {
73589
74409
  }
73590
74410
  function createStatusLineScript(tokenFilePath) {
73591
74411
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
73592
- const claudishDir = join30(homeDir, ".claudish");
74412
+ const claudishDir = join31(homeDir, ".claudish");
73593
74413
  const timestamp = Date.now();
73594
- const scriptPath = join30(claudishDir, `status-${timestamp}.js`);
74414
+ const scriptPath = join31(claudishDir, `status-${timestamp}.js`);
73595
74415
  const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
73596
74416
  const script = `
73597
74417
  const fs = require('fs');
@@ -73714,13 +74534,13 @@ process.stdin.on('end', () => {
73714
74534
  }
73715
74535
  function createTempSettingsFile(_modelDisplay, port, proxyAuthMode) {
73716
74536
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
73717
- const claudishDir = join30(homeDir, ".claudish");
74537
+ const claudishDir = join31(homeDir, ".claudish");
73718
74538
  try {
73719
74539
  mkdirSync16(claudishDir, { recursive: true });
73720
74540
  } catch {}
73721
74541
  const timestamp = Date.now();
73722
- const tempPath = join30(claudishDir, `settings-${timestamp}.json`);
73723
- const tokenFilePath = join30(claudishDir, `tokens-${port}.json`);
74542
+ const tempPath = join31(claudishDir, `settings-${timestamp}.json`);
74543
+ const tokenFilePath = join31(claudishDir, `tokens-${port}.json`);
73724
74544
  let statusCommand;
73725
74545
  if (isWindows2()) {
73726
74546
  const scriptPath = createStatusLineScript(tokenFilePath);
@@ -73935,8 +74755,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
73935
74755
  console.error("Install it from: https://claude.com/claude-code");
73936
74756
  console.error(`
73937
74757
  Or set CLAUDE_PATH to your custom installation:`);
73938
- const home = homedir28();
73939
- const localPath = isWindows2() ? join30(home, ".claude", "local", "claude.exe") : join30(home, ".claude", "local", "claude");
74758
+ const home = homedir29();
74759
+ const localPath = isWindows2() ? join31(home, ".claude", "local", "claude.exe") : join31(home, ".claude", "local", "claude");
73940
74760
  console.error(` export CLAUDE_PATH=${localPath}`);
73941
74761
  process.exit(1);
73942
74762
  }
@@ -74016,23 +74836,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
74016
74836
  async function findClaudeBinary() {
74017
74837
  const isWindows3 = process.platform === "win32";
74018
74838
  if (process.env.CLAUDE_PATH) {
74019
- if (existsSync24(process.env.CLAUDE_PATH)) {
74839
+ if (existsSync25(process.env.CLAUDE_PATH)) {
74020
74840
  return process.env.CLAUDE_PATH;
74021
74841
  }
74022
74842
  }
74023
- const home = homedir28();
74024
- const localPath = isWindows3 ? join30(home, ".claude", "local", "claude.exe") : join30(home, ".claude", "local", "claude");
74025
- if (existsSync24(localPath)) {
74843
+ const home = homedir29();
74844
+ const localPath = isWindows3 ? join31(home, ".claude", "local", "claude.exe") : join31(home, ".claude", "local", "claude");
74845
+ if (existsSync25(localPath)) {
74026
74846
  return localPath;
74027
74847
  }
74028
74848
  if (isWindows3) {
74029
74849
  const windowsPaths = [
74030
- join30(home, "AppData", "Roaming", "npm", "claude.cmd"),
74031
- join30(home, ".npm-global", "claude.cmd"),
74032
- join30(home, "node_modules", ".bin", "claude.cmd")
74850
+ join31(home, "AppData", "Roaming", "npm", "claude.cmd"),
74851
+ join31(home, ".npm-global", "claude.cmd"),
74852
+ join31(home, "node_modules", ".bin", "claude.cmd")
74033
74853
  ];
74034
74854
  for (const path2 of windowsPaths) {
74035
- if (existsSync24(path2)) {
74855
+ if (existsSync25(path2)) {
74036
74856
  return path2;
74037
74857
  }
74038
74858
  }
@@ -74040,14 +74860,14 @@ async function findClaudeBinary() {
74040
74860
  const commonPaths = [
74041
74861
  "/usr/local/bin/claude",
74042
74862
  "/opt/homebrew/bin/claude",
74043
- join30(home, ".npm-global/bin/claude"),
74044
- join30(home, ".local/bin/claude"),
74045
- join30(home, "node_modules/.bin/claude"),
74863
+ join31(home, ".npm-global/bin/claude"),
74864
+ join31(home, ".local/bin/claude"),
74865
+ join31(home, "node_modules/.bin/claude"),
74046
74866
  "/data/data/com.termux/files/usr/bin/claude",
74047
- join30(home, "../usr/bin/claude")
74867
+ join31(home, "../usr/bin/claude")
74048
74868
  ];
74049
74869
  for (const path2 of commonPaths) {
74050
- if (existsSync24(path2)) {
74870
+ if (existsSync25(path2)) {
74051
74871
  return path2;
74052
74872
  }
74053
74873
  }
@@ -74105,17 +74925,17 @@ __export(exports_diag_output, {
74105
74925
  LogFileDiagOutput: () => LogFileDiagOutput
74106
74926
  });
74107
74927
  import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync17, unlinkSync as unlinkSync10, writeFileSync as writeFileSync19 } from "fs";
74108
- import { homedir as homedir29 } from "os";
74109
- import { join as join31 } from "path";
74928
+ import { homedir as homedir30 } from "os";
74929
+ import { join as join32 } from "path";
74110
74930
  function getClaudishDir() {
74111
- const dir = join31(homedir29(), ".claudish");
74931
+ const dir = join32(homedir30(), ".claudish");
74112
74932
  try {
74113
74933
  mkdirSync17(dir, { recursive: true });
74114
74934
  } catch {}
74115
74935
  return dir;
74116
74936
  }
74117
74937
  function getDiagLogPath() {
74118
- return join31(getClaudishDir(), `diag-${process.pid}.log`);
74938
+ return join32(getClaudishDir(), `diag-${process.pid}.log`);
74119
74939
  }
74120
74940
 
74121
74941
  class LogFileDiagOutput {
@@ -74326,9 +75146,9 @@ __export(exports_team_grid, {
74326
75146
  });
74327
75147
  import { spawn as spawn5 } from "child_process";
74328
75148
  import { execSync as execSync2 } from "child_process";
74329
- import { existsSync as existsSync25, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "fs";
75149
+ import { existsSync as existsSync26, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "fs";
74330
75150
  import { connect as netConnect } from "net";
74331
- import { dirname as dirname11, join as join32 } from "path";
75151
+ import { dirname as dirname11, join as join33 } from "path";
74332
75152
  import { setTimeout as wait } from "timers/promises";
74333
75153
  import { fileURLToPath as fileURLToPath3 } from "url";
74334
75154
  function resolveRouteInfo(modelId) {
@@ -74422,18 +75242,18 @@ function buildPaneHeader(model, prompt, bg) {
74422
75242
  function findMagmuxBinary() {
74423
75243
  const thisFile = fileURLToPath3(import.meta.url);
74424
75244
  const thisDir = dirname11(thisFile);
74425
- const pkgRoot = join32(thisDir, "..");
75245
+ const pkgRoot = join33(thisDir, "..");
74426
75246
  const platform3 = process.platform;
74427
75247
  const arch = process.arch;
74428
- const bundledMagmux = join32(pkgRoot, "native", `magmux-${platform3}-${arch}`);
74429
- if (existsSync25(bundledMagmux))
75248
+ const bundledMagmux = join33(pkgRoot, "native", `magmux-${platform3}-${arch}`);
75249
+ if (existsSync26(bundledMagmux))
74430
75250
  return bundledMagmux;
74431
75251
  try {
74432
75252
  const pkgName = `@claudish/magmux-${platform3}-${arch}`;
74433
75253
  let searchDir = pkgRoot;
74434
75254
  for (let i = 0;i < 5; i++) {
74435
- const candidate = join32(searchDir, "node_modules", pkgName, "bin", "magmux");
74436
- if (existsSync25(candidate))
75255
+ const candidate = join33(searchDir, "node_modules", pkgName, "bin", "magmux");
75256
+ if (existsSync26(candidate))
74437
75257
  return candidate;
74438
75258
  const parent = dirname11(searchDir);
74439
75259
  if (parent === searchDir)
@@ -74452,7 +75272,7 @@ function findMagmuxBinary() {
74452
75272
  async function subscribeToMagmux(sockPath, onEvent) {
74453
75273
  let client = null;
74454
75274
  for (let attempt = 0;attempt < 40; attempt++) {
74455
- if (existsSync25(sockPath)) {
75275
+ if (existsSync26(sockPath)) {
74456
75276
  try {
74457
75277
  client = await new Promise((resolve4, reject) => {
74458
75278
  const s = netConnect(sockPath);
@@ -74539,9 +75359,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
74539
75359
  const keep = opts?.keep ?? false;
74540
75360
  const manifest = setupSession(sessionPath, models, input);
74541
75361
  const startedAt = new Date().toISOString();
74542
- const gridfilePath = join32(sessionPath, "gridfile.txt");
74543
- const prompt = readFileSync25(join32(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
74544
- const rawPrompt = readFileSync25(join32(sessionPath, "input.md"), "utf-8");
75362
+ const gridfilePath = join33(sessionPath, "gridfile.txt");
75363
+ const prompt = readFileSync25(join33(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
75364
+ const rawPrompt = readFileSync25(join33(sessionPath, "input.md"), "utf-8");
74545
75365
  const usedBannerColors = new Set;
74546
75366
  const gridLines = Object.entries(manifest.models).map(([anonId]) => {
74547
75367
  const model = manifest.models[anonId].model;
@@ -74572,7 +75392,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
74572
75392
  });
74573
75393
  const [{ results }] = await Promise.all([subscription, procExit]);
74574
75394
  const status = buildTeamStatus(manifest, startedAt, results?.panes ?? null);
74575
- const statusPath = join32(sessionPath, "status.json");
75395
+ const statusPath = join33(sessionPath, "status.json");
74576
75396
  writeFileSync20(statusPath, JSON.stringify(status, null, 2), "utf-8");
74577
75397
  return status;
74578
75398
  }
@@ -74596,8 +75416,8 @@ var init_team_grid = __esm(() => {
74596
75416
  init_op_source();
74597
75417
  init_startup_trace();
74598
75418
  var import_dotenv3 = __toESM(require_main(), 1);
74599
- import { existsSync as existsSync26, readFileSync as readFileSync26 } from "fs";
74600
- import { join as join33, resolve as resolve4 } from "path";
75419
+ import { existsSync as existsSync27, readFileSync as readFileSync26 } from "fs";
75420
+ import { join as join34, resolve as resolve4 } from "path";
74601
75421
  import_dotenv3.config({ quiet: true });
74602
75422
  function classifyStartupKind() {
74603
75423
  const argv = process.argv.slice(2);
@@ -74696,7 +75516,7 @@ async function applyConfigOverride() {
74696
75516
  const { planConfigOverride: planConfigOverride2, setConfigFileOverride: setConfigFileOverride2 } = await Promise.resolve().then(() => exports_config_override);
74697
75517
  const plan = planConfigOverride2(process.argv.slice(2), process.env, {
74698
75518
  resolve: resolve4,
74699
- exists: existsSync26
75519
+ exists: existsSync27
74700
75520
  });
74701
75521
  if (plan.kind === "none")
74702
75522
  return;
@@ -74845,7 +75665,7 @@ async function runCli() {
74845
75665
  process.exit(1);
74846
75666
  }
74847
75667
  const mode = cliConfig.teamMode ?? "default";
74848
- const sessionPath = join33(process.cwd(), `.claudish-team-${Date.now()}`);
75668
+ const sessionPath = join34(process.cwd(), `.claudish-team-${Date.now()}`);
74849
75669
  if (mode === "json") {
74850
75670
  const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
74851
75671
  setupSession2(sessionPath, cliConfig.team, prompt);
@@ -74855,7 +75675,7 @@ async function runCli() {
74855
75675
  });
74856
75676
  const result = { ...status2, responses: {} };
74857
75677
  for (const anonId of Object.keys(status2.models)) {
74858
- const responsePath = join33(sessionPath, `response-${anonId}.md`);
75678
+ const responsePath = join34(sessionPath, `response-${anonId}.md`);
74859
75679
  try {
74860
75680
  const raw2 = readFileSync26(responsePath, "utf-8").trim();
74861
75681
  try {