claudish 13.0.3 → 13.2.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 +892 -363
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -575,7 +575,7 @@ var init_onepassword_config = __esm(() => {
575
575
  });
576
576
 
577
577
  // src/version.ts
578
- var VERSION = "13.0.3";
578
+ var VERSION = "13.2.0";
579
579
 
580
580
  // src/logger.ts
581
581
  import { appendFile, existsSync as existsSync2, mkdirSync, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
@@ -10403,9 +10403,6 @@ function acceptsReasoningEffort(modelId) {
10403
10403
  return reasoning.supported === true && reasoning.control === "effort";
10404
10404
  return true;
10405
10405
  }
10406
- function catalogReasoningFor(modelId) {
10407
- return lookupModelReasoning(norm(modelId)) ?? lookupModelReasoning(modelId);
10408
- }
10409
10406
  function rememberReasoningEffortRejected(modelId) {
10410
10407
  const id = norm(modelId);
10411
10408
  if (!id || learnedRejects.has(id))
@@ -10530,7 +10527,7 @@ var init_grok_model_dialect = __esm(() => {
10530
10527
  return;
10531
10528
  }
10532
10529
  let value;
10533
- const reasoning = catalogReasoningFor(this.modelId);
10530
+ const reasoning = this.lookupReasoningCapability();
10534
10531
  const clamped = reasoning ? this.clampToAdvertisedEffort(effort, reasoning) : undefined;
10535
10532
  if (clamped) {
10536
10533
  value = clamped;
@@ -10878,6 +10875,324 @@ var init_minimax_model_dialect = __esm(() => {
10878
10875
  };
10879
10876
  });
10880
10877
 
10878
+ // src/providers/keychain.ts
10879
+ function syncRun(args, stdin) {
10880
+ try {
10881
+ const proc = Bun.spawnSync([SECURITY_BIN, ...args], {
10882
+ stdin: stdin === undefined ? "ignore" : new TextEncoder().encode(stdin),
10883
+ stdout: "pipe",
10884
+ stderr: "pipe",
10885
+ timeout: SPAWN_TIMEOUT_MS
10886
+ });
10887
+ return normalizeResult(proc.exitCode, proc.signalCode, decode(proc.stdout), decode(proc.stderr));
10888
+ } catch (err) {
10889
+ return { code: 1, stdout: "", stderr: err instanceof Error ? err.message : String(err) };
10890
+ }
10891
+ }
10892
+ async function asyncRun(args, stdin) {
10893
+ try {
10894
+ const proc = Bun.spawn([SECURITY_BIN, ...args], {
10895
+ stdin: stdin === undefined ? "ignore" : new TextEncoder().encode(stdin),
10896
+ stdout: "pipe",
10897
+ stderr: "pipe",
10898
+ timeout: SPAWN_TIMEOUT_MS
10899
+ });
10900
+ const [stdout, stderr, exitCode] = await Promise.all([
10901
+ new Response(proc.stdout).text(),
10902
+ new Response(proc.stderr).text(),
10903
+ proc.exited
10904
+ ]);
10905
+ return normalizeResult(exitCode, proc.signalCode, stdout, stderr);
10906
+ } catch (err) {
10907
+ return { code: 1, stdout: "", stderr: err instanceof Error ? err.message : String(err) };
10908
+ }
10909
+ }
10910
+ function spawnAsyncRun(args, stdin) {
10911
+ try {
10912
+ const proc = Bun.spawn([SECURITY_BIN, ...args], {
10913
+ stdin: stdin === undefined ? "ignore" : new TextEncoder().encode(stdin),
10914
+ stdout: "pipe",
10915
+ stderr: "pipe"
10916
+ });
10917
+ const done = Promise.all([
10918
+ new Response(proc.stdout).text(),
10919
+ new Response(proc.stderr).text(),
10920
+ proc.exited
10921
+ ]).then(([stdout, stderr, exitCode]) => normalizeResult(exitCode, proc.signalCode, stdout, stderr), (err) => ({
10922
+ code: 1,
10923
+ stdout: "",
10924
+ stderr: err instanceof Error ? err.message : String(err)
10925
+ }));
10926
+ return { done, pid: proc.pid };
10927
+ } catch (err) {
10928
+ return {
10929
+ done: Promise.resolve({
10930
+ code: 1,
10931
+ stdout: "",
10932
+ stderr: err instanceof Error ? err.message : String(err)
10933
+ }),
10934
+ pid: undefined
10935
+ };
10936
+ }
10937
+ }
10938
+ function decode(buf) {
10939
+ return buf ? new TextDecoder().decode(buf) : "";
10940
+ }
10941
+ function normalizeResult(exitCode, signalCode, stdout, stderr) {
10942
+ if (typeof exitCode === "number")
10943
+ return { code: exitCode, stdout, stderr };
10944
+ const detail = signalCode ? `killed by ${signalCode}` : "terminated without an exit code";
10945
+ return { code: -1, stdout, stderr: stderr.trim() || `security ${detail}` };
10946
+ }
10947
+ function invalidateKeychainCache() {
10948
+ listMemo = null;
10949
+ valueMemo.clear();
10950
+ }
10951
+ function now() {
10952
+ return Date.now();
10953
+ }
10954
+ function isValidKeychainVarName(name) {
10955
+ return ENV_VAR_NAME.test(name);
10956
+ }
10957
+ function describeUnstorableValue(value) {
10958
+ if (value.length === 0)
10959
+ return "value is empty";
10960
+ if (CONTROL_CHARS.test(value)) {
10961
+ return "value contains control characters (tab/newline/etc), which the keychain read path cannot represent unambiguously";
10962
+ }
10963
+ return null;
10964
+ }
10965
+ function isKeychainSupported() {
10966
+ return deps.platform() === "darwin";
10967
+ }
10968
+ function keychainUnavailableReason() {
10969
+ if (!isKeychainSupported()) {
10970
+ return `the macOS Keychain is only available on macOS (this is ${deps.platform()})`;
10971
+ }
10972
+ return null;
10973
+ }
10974
+ function stripOneTrailingNewline(out) {
10975
+ return out.endsWith(`
10976
+ `) ? out.slice(0, -1) : out;
10977
+ }
10978
+ function keychainFileArgs() {
10979
+ const file = process.env.CLAUDISH_KEYCHAIN_FILE;
10980
+ return file ? [file] : [];
10981
+ }
10982
+ function findArgs(envVar) {
10983
+ return [
10984
+ "find-generic-password",
10985
+ "-s",
10986
+ KEYCHAIN_SERVICE,
10987
+ "-a",
10988
+ envVar,
10989
+ "-w",
10990
+ ...keychainFileArgs()
10991
+ ];
10992
+ }
10993
+ function interpretRead(envVar, res) {
10994
+ if (res.code === 0) {
10995
+ const value = stripOneTrailingNewline(res.stdout);
10996
+ return value.length > 0 ? value : null;
10997
+ }
10998
+ if (res.code === EXIT_ITEM_NOT_FOUND)
10999
+ return null;
11000
+ throw new KeychainError(`Keychain lookup for ${envVar} failed: ${res.stderr.trim() || `security exited ${res.code}`}`, res.code);
11001
+ }
11002
+ function readKeychainSecret(envVar) {
11003
+ if (!isKeychainSupported())
11004
+ return null;
11005
+ const cached = valueMemo.get(envVar);
11006
+ const at = now();
11007
+ if (cached && at - cached.at < MEMO_TTL_MS)
11008
+ return cached.value;
11009
+ const value = interpretRead(envVar, deps.run(findArgs(envVar)));
11010
+ valueMemo.set(envVar, { at, value });
11011
+ return value;
11012
+ }
11013
+ async function readKeychainSecretAsync(envVar) {
11014
+ if (!isKeychainSupported())
11015
+ return null;
11016
+ const cached = valueMemo.get(envVar);
11017
+ const at = now();
11018
+ if (cached && at - cached.at < MEMO_TTL_MS)
11019
+ return cached.value;
11020
+ const value = interpretRead(envVar, await deps.runAsync(findArgs(envVar)));
11021
+ valueMemo.set(envVar, { at, value });
11022
+ return value;
11023
+ }
11024
+ function genericPasswordArgs(query, withValue) {
11025
+ return [
11026
+ "find-generic-password",
11027
+ "-s",
11028
+ query.service,
11029
+ ...query.account !== undefined ? ["-a", query.account] : [],
11030
+ ...withValue ? ["-w"] : [],
11031
+ ...query.keychainFile !== undefined ? [query.keychainFile] : keychainFileArgs()
11032
+ ];
11033
+ }
11034
+ function interpretGenericPassword(res, withValue) {
11035
+ if (res.code === 0) {
11036
+ if (!withValue)
11037
+ return { kind: "found" };
11038
+ const value = stripOneTrailingNewline(res.stdout);
11039
+ return value.length > 0 ? { kind: "found", value } : { kind: "absent" };
11040
+ }
11041
+ if (res.code === EXIT_ITEM_NOT_FOUND)
11042
+ return { kind: "absent" };
11043
+ return {
11044
+ kind: "failed",
11045
+ code: res.code,
11046
+ error: res.stderr.trim() || `security exited ${res.code}`
11047
+ };
11048
+ }
11049
+ async function findGenericPasswordPresence(query) {
11050
+ if (!isKeychainSupported())
11051
+ return { kind: "absent" };
11052
+ const res = await deps.spawnAsync(genericPasswordArgs(query, false)).done;
11053
+ return interpretGenericPassword(res, false);
11054
+ }
11055
+ function startGenericPasswordRead(query) {
11056
+ if (!isKeychainSupported()) {
11057
+ return { done: Promise.resolve({ kind: "absent" }), pid: undefined };
11058
+ }
11059
+ const spawn = deps.spawnAsync(genericPasswordArgs(query, true));
11060
+ return { done: spawn.done.then((res) => interpretGenericPassword(res, true)), pid: spawn.pid };
11061
+ }
11062
+ function enumerateKeychainVars() {
11063
+ if (!isKeychainSupported())
11064
+ return { names: [], failed: false };
11065
+ const at = now();
11066
+ if (listMemo && at - listMemo.at < MEMO_TTL_MS)
11067
+ return listMemo.value;
11068
+ const res = deps.run(["dump-keychain", ...keychainFileArgs()]);
11069
+ const value = res.code === 0 ? { names: parseDumpAccounts(res.stdout), failed: false } : {
11070
+ names: [],
11071
+ failed: true,
11072
+ error: res.stderr.trim() || `security exited ${res.code}`
11073
+ };
11074
+ listMemo = { at, value };
11075
+ return value;
11076
+ }
11077
+ function listKeychainVars() {
11078
+ return enumerateKeychainVars().names;
11079
+ }
11080
+ function parseDumpAccounts(dump) {
11081
+ const found = new Set;
11082
+ for (const block of dump.split(/\nkeychain: /)) {
11083
+ if (!block.includes(SVCE_MATCH))
11084
+ continue;
11085
+ const m = block.match(ACCT_ATTR);
11086
+ if (m?.[1] && isValidKeychainVarName(m[1]))
11087
+ found.add(m[1]);
11088
+ }
11089
+ return Array.from(found).sort();
11090
+ }
11091
+ function lookupKeychainVar(envVar) {
11092
+ if (!isKeychainSupported())
11093
+ return { present: false, failed: false };
11094
+ const cached = valueMemo.get(envVar);
11095
+ if (cached && now() - cached.at < MEMO_TTL_MS && cached.value !== null) {
11096
+ return { present: true, failed: false };
11097
+ }
11098
+ const listed = enumerateKeychainVars();
11099
+ return { present: listed.names.includes(envVar), failed: listed.failed };
11100
+ }
11101
+ function toHex(value) {
11102
+ return Buffer.from(value, "utf8").toString("hex");
11103
+ }
11104
+ function quoteForStdin(value) {
11105
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
11106
+ }
11107
+ function writeKeychainSecret(envVar, value) {
11108
+ const unsupported = keychainUnavailableReason();
11109
+ if (unsupported)
11110
+ throw new KeychainError(`Cannot write ${envVar}: ${unsupported}`);
11111
+ if (!isValidKeychainVarName(envVar)) {
11112
+ throw new KeychainError(`Cannot write "${envVar}": not a valid environment variable name`);
11113
+ }
11114
+ const unstorable = describeUnstorableValue(value);
11115
+ if (unstorable)
11116
+ throw new KeychainError(`Cannot store ${envVar}: ${unstorable}`);
11117
+ invalidateKeychainCache();
11118
+ const cmd = [
11119
+ "add-generic-password",
11120
+ "-s",
11121
+ quoteForStdin(KEYCHAIN_SERVICE),
11122
+ "-a",
11123
+ quoteForStdin(envVar),
11124
+ "-l",
11125
+ quoteForStdin(`${KEYCHAIN_SERVICE}: ${envVar}`),
11126
+ "-D",
11127
+ quoteForStdin("application password"),
11128
+ "-j",
11129
+ quoteForStdin("Stored by claudish"),
11130
+ "-X",
11131
+ quoteForStdin(toHex(value)),
11132
+ "-U",
11133
+ "-T",
11134
+ quoteForStdin(SECURITY_BIN),
11135
+ ...keychainFileArgs().map(quoteForStdin)
11136
+ ].join(" ");
11137
+ const res = deps.run(["-i"], `${cmd}
11138
+ `);
11139
+ if (res.code !== 0) {
11140
+ throw new KeychainError(`Failed to store ${envVar} in the keychain: ${res.stderr.trim() || `security exited ${res.code}`}`, res.code);
11141
+ }
11142
+ invalidateKeychainCache();
11143
+ const readBack = readKeychainSecret(envVar);
11144
+ if (readBack !== value) {
11145
+ throw new KeychainError(`Keychain write for ${envVar} did not round-trip \u2014 the stored value differs from what was written. ` + "The item may exceed the keychain's size limit; nothing should be assumed saved.");
11146
+ }
11147
+ }
11148
+ function deleteKeychainSecret(envVar) {
11149
+ if (!isKeychainSupported())
11150
+ return false;
11151
+ invalidateKeychainCache();
11152
+ const res = deps.run([
11153
+ "delete-generic-password",
11154
+ "-s",
11155
+ KEYCHAIN_SERVICE,
11156
+ "-a",
11157
+ envVar,
11158
+ ...keychainFileArgs()
11159
+ ]);
11160
+ invalidateKeychainCache();
11161
+ if (res.code === 0)
11162
+ return true;
11163
+ if (res.code === EXIT_ITEM_NOT_FOUND)
11164
+ return false;
11165
+ throw new KeychainError(`Failed to delete ${envVar} from the keychain: ${res.stderr.trim() || `security exited ${res.code}`}`, res.code);
11166
+ }
11167
+ function valueTail2(value) {
11168
+ if (value.length <= 6)
11169
+ return "\u2022\u2022\u2022\u2022";
11170
+ return `\u2022\u2022\u2022\u2022${value.slice(-4)}`;
11171
+ }
11172
+ var KEYCHAIN_SERVICE = "claudish", SECURITY_BIN = "/usr/bin/security", EXIT_ITEM_NOT_FOUND = 44, MEMO_TTL_MS = 3000, SPAWN_TIMEOUT_MS = 1e4, KeychainError, defaultDeps, deps, listMemo = null, valueMemo, CONTROL_CHARS, ENV_VAR_NAME, ACCT_ATTR, SVCE_MATCH;
11173
+ var init_keychain = __esm(() => {
11174
+ KeychainError = class KeychainError extends Error {
11175
+ exitCode;
11176
+ constructor(message, exitCode) {
11177
+ super(message);
11178
+ this.exitCode = exitCode;
11179
+ this.name = "KeychainError";
11180
+ }
11181
+ };
11182
+ defaultDeps = {
11183
+ platform: () => process.platform,
11184
+ run: syncRun,
11185
+ runAsync: asyncRun,
11186
+ spawnAsync: spawnAsyncRun
11187
+ };
11188
+ deps = defaultDeps;
11189
+ valueMemo = new Map;
11190
+ CONTROL_CHARS = /[\u0000-\u001F\u007F]/;
11191
+ ENV_VAR_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
11192
+ ACCT_ATTR = /"acct"<blob>=(?:0x[0-9A-Fa-f]*\s+)?"([^"]*)"/;
11193
+ SVCE_MATCH = `"svce"<blob>="${KEYCHAIN_SERVICE}"`;
11194
+ });
11195
+
10881
11196
  // src/auth/antigravity-client-version.ts
10882
11197
  function getAgyClientVersion() {
10883
11198
  return version;
@@ -10999,6 +11314,46 @@ function defaultReadAgyVersion() {
10999
11314
  return null;
11000
11315
  }
11001
11316
  }
11317
+ function defaultAntigravityTokenDeps() {
11318
+ return { ...defaultDeps2 };
11319
+ }
11320
+ async function raceDeadline(work, deadlineAt) {
11321
+ let timer;
11322
+ const timedOut = new Promise((resolve) => {
11323
+ timer = setTimeout(() => resolve("timeout"), Math.max(0, deadlineAt - Date.now()));
11324
+ });
11325
+ try {
11326
+ return await Promise.race([work, timedOut]);
11327
+ } finally {
11328
+ if (timer)
11329
+ clearTimeout(timer);
11330
+ }
11331
+ }
11332
+ function classifyKeychainFailure(code) {
11333
+ return KEYCHAIN_LOCKED_EXIT_CODES.has(code) ? { kind: "locked" } : { kind: "failed" };
11334
+ }
11335
+ async function readAntigravityStoreClassified(deadlineMs) {
11336
+ if (process.env.CLAUDISH_DISABLE_KEYCHAIN === "1")
11337
+ return { kind: "failed" };
11338
+ const deadlineAt = Date.now() + deadlineMs;
11339
+ const query = { service: KC_SERVICE, account: KC_ACCOUNT };
11340
+ const presence = await raceDeadline(findGenericPasswordPresence(query), deadlineAt);
11341
+ if (presence === "timeout")
11342
+ return { kind: "timeout" };
11343
+ if (presence.kind === "absent")
11344
+ return { kind: "absent" };
11345
+ if (presence.kind === "failed")
11346
+ return classifyKeychainFailure(presence.code);
11347
+ const read = await raceDeadline(startGenericPasswordRead(query).done, deadlineAt);
11348
+ if (read === "timeout")
11349
+ return { kind: "timeout" };
11350
+ if (read.kind === "absent")
11351
+ return { kind: "absent" };
11352
+ if (read.kind === "failed")
11353
+ return classifyKeychainFailure(read.code);
11354
+ const raw = (read.value ?? "").trim();
11355
+ return raw.length > 0 ? { kind: "present", raw } : { kind: "absent" };
11356
+ }
11002
11357
  function parseRecord(raw) {
11003
11358
  if (!raw)
11004
11359
  return null;
@@ -11020,11 +11375,11 @@ function parseRecord(raw) {
11020
11375
  function encodeRecord(rec) {
11021
11376
  return PREFIX + Buffer.from(JSON.stringify(rec), "utf8").toString("base64");
11022
11377
  }
11023
- function readSharedAntigravityToken(deps = defaultDeps) {
11378
+ function readSharedAntigravityToken(deps = defaultDeps2) {
11024
11379
  const rec = parseRecord(deps.readStore());
11025
11380
  return rec ? rec.token : null;
11026
11381
  }
11027
- function hasSharedAntigravityToken(deps = defaultDeps) {
11382
+ function hasSharedAntigravityToken(deps = defaultDeps2) {
11028
11383
  const now = Date.now();
11029
11384
  if (cachedHasToken && now - cachedHasToken.at < HAS_TOKEN_TTL_MS)
11030
11385
  return cachedHasToken.value;
@@ -11037,7 +11392,7 @@ function hasSharedAntigravityToken(deps = defaultDeps) {
11037
11392
  cachedHasToken = { at: now, value };
11038
11393
  return value;
11039
11394
  }
11040
- function writeSharedAntigravityToken(tok, deps = defaultDeps) {
11395
+ function writeSharedAntigravityToken(tok, deps = defaultDeps2) {
11041
11396
  const existing = parseRecord(deps.readStore());
11042
11397
  const base = existing ?? { token: tok };
11043
11398
  const merged = {
@@ -11046,7 +11401,7 @@ function writeSharedAntigravityToken(tok, deps = defaultDeps) {
11046
11401
  };
11047
11402
  deps.writeStore(encodeRecord(merged));
11048
11403
  }
11049
- function deleteSharedAntigravityToken(deps = defaultDeps) {
11404
+ function deleteSharedAntigravityToken(deps = defaultDeps2) {
11050
11405
  (deps.deleteStore ?? defaultDeleteStore)();
11051
11406
  _resetAntigravityTokenState();
11052
11407
  }
@@ -11107,7 +11462,7 @@ function describeRefreshFailure(outcome) {
11107
11462
  return "The Antigravity session is expired and the Antigravity CLI refreshed it without " + "producing a valid token \u2014 the session has most likely been revoked. " + "Run `claudish login antigravity`.";
11108
11463
  }
11109
11464
  }
11110
- function getValidAntigravityAccessToken(deps = defaultDeps) {
11465
+ function getValidAntigravityAccessToken(deps = defaultDeps2) {
11111
11466
  if (inFlight)
11112
11467
  return inFlight;
11113
11468
  inFlight = resolveValidToken(deps).finally(() => {
@@ -11115,7 +11470,7 @@ function getValidAntigravityAccessToken(deps = defaultDeps) {
11115
11470
  });
11116
11471
  return inFlight;
11117
11472
  }
11118
- async function forceRefreshAntigravityToken(deps = defaultDeps) {
11473
+ async function forceRefreshAntigravityToken(deps = defaultDeps2) {
11119
11474
  if (process.platform !== "darwin") {
11120
11475
  throw terminalCredentialError("[Antigravity] The shared Antigravity token store is macOS-only for now. " + "Use g@<model> with GEMINI_API_KEY on this platform.");
11121
11476
  }
@@ -11156,10 +11511,11 @@ function _resetAntigravityTokenState() {
11156
11511
  cachedHasToken = null;
11157
11512
  invalidateReadStoreMemo();
11158
11513
  }
11159
- var KC_SERVICE = "gemini", KC_ACCOUNT = "antigravity", PREFIX = "go-keyring-base64:", EXPIRY_SKEW_MS = 120000, AGY_REFRESH_TIMEOUT_MS = 12000, AGY_VERSION_TIMEOUT_MS = 5000, READ_STORE_TTL_MS = 3000, cachedRawStore = null, defaultDeps, cachedHasToken = null, HAS_TOKEN_TTL_MS = 5000, inFlight = null;
11514
+ var KC_SERVICE = "gemini", KC_ACCOUNT = "antigravity", PREFIX = "go-keyring-base64:", EXPIRY_SKEW_MS = 120000, AGY_REFRESH_TIMEOUT_MS = 12000, AGY_VERSION_TIMEOUT_MS = 5000, READ_STORE_TTL_MS = 3000, cachedRawStore = null, defaultDeps2, KEYCHAIN_LOCKED_EXIT_CODES, cachedHasToken = null, HAS_TOKEN_TTL_MS = 5000, inFlight = null;
11160
11515
  var init_antigravity_token = __esm(() => {
11161
11516
  init_logger();
11162
- defaultDeps = {
11517
+ init_keychain();
11518
+ defaultDeps2 = {
11163
11519
  readStore: defaultReadStore,
11164
11520
  writeStore: defaultWriteStore,
11165
11521
  deleteStore: defaultDeleteStore,
@@ -11167,6 +11523,7 @@ var init_antigravity_token = __esm(() => {
11167
11523
  readAgyVersion: defaultReadAgyVersion,
11168
11524
  now: () => Date.now()
11169
11525
  };
11526
+ KEYCHAIN_LOCKED_EXIT_CODES = new Set([36, 51, 128]);
11170
11527
  });
11171
11528
 
11172
11529
  // src/auth/antigravity-user.ts
@@ -11182,11 +11539,18 @@ function makeTerminalSetupError(message) {
11182
11539
  err.terminal = true;
11183
11540
  return err;
11184
11541
  }
11542
+ function resolveAntigravityClientVersion() {
11543
+ const agy = getAgyClientVersion();
11544
+ return agy ? { version: agy, source: "agy" } : { version: AGY_FALLBACK_CLIENT_VERSION, source: "fallback" };
11545
+ }
11185
11546
  function antigravityClientVersion() {
11186
- return getAgyClientVersion() ?? AGY_FALLBACK_CLIENT_VERSION;
11547
+ return resolveAntigravityClientVersion().version;
11548
+ }
11549
+ function userAgentFor(version) {
11550
+ return `antigravity/cli/${version} (aidev_client; os_type=${process.platform}; arch=${process.arch}; auth_method=consumer)`;
11187
11551
  }
11188
11552
  function buildAntigravityUserAgent() {
11189
- return `antigravity/cli/${antigravityClientVersion()} (aidev_client; os_type=${process.platform}; arch=${process.arch}; auth_method=consumer)`;
11553
+ return userAgentFor(antigravityClientVersion());
11190
11554
  }
11191
11555
  function resetAntigravityUserCache() {
11192
11556
  cachedAgProjectId = null;
@@ -11278,6 +11642,45 @@ function flattenAgentModelSorts(sorts) {
11278
11642
  }
11279
11643
  return ids.length > 0 ? ids : undefined;
11280
11644
  }
11645
+ async function fetchAntigravityAvailableModelsRaw(accessToken, projectId, opts) {
11646
+ const url = `${apiBase()}:fetchAvailableModels`;
11647
+ const { version, source } = resolveAntigravityClientVersion();
11648
+ const base = {
11649
+ url,
11650
+ clientVersion: version,
11651
+ clientVersionSource: source
11652
+ };
11653
+ let res;
11654
+ try {
11655
+ res = await fetch(url, {
11656
+ method: "POST",
11657
+ headers: {
11658
+ Authorization: `Bearer ${accessToken}`,
11659
+ "Content-Type": "application/json",
11660
+ "User-Agent": userAgentFor(version)
11661
+ },
11662
+ body: JSON.stringify({ project: projectId }),
11663
+ ...opts?.signal ? { signal: opts.signal } : {}
11664
+ });
11665
+ } catch (error) {
11666
+ return { ...base, kind: "unreachable", error };
11667
+ }
11668
+ const fetchedAt = new Date((opts?.now ?? Date.now)()).toISOString();
11669
+ const answered = { ...base, kind: "answered", status: res.status, fetchedAt };
11670
+ if (!res.ok)
11671
+ return { ...answered, body: { kind: "unread" } };
11672
+ let text;
11673
+ try {
11674
+ text = await res.text();
11675
+ } catch {
11676
+ return { ...answered, body: { kind: "read-failed" } };
11677
+ }
11678
+ try {
11679
+ return { ...answered, body: { kind: "json", text, value: JSON.parse(text) } };
11680
+ } catch {
11681
+ return { ...answered, body: { kind: "not-json" } };
11682
+ }
11683
+ }
11281
11684
  async function getServedAntigravityModels(accessToken, projectId, opts) {
11282
11685
  const now = Date.now();
11283
11686
  const version = antigravityClientVersion();
@@ -11290,17 +11693,15 @@ async function getServedAntigravityModels(accessToken, projectId, opts) {
11290
11693
  return agServedCache;
11291
11694
  }
11292
11695
  try {
11293
- const res = await fetch(`${apiBase()}:fetchAvailableModels`, {
11294
- method: "POST",
11295
- headers: {
11296
- Authorization: `Bearer ${accessToken}`,
11297
- "Content-Type": "application/json",
11298
- "User-Agent": buildAntigravityUserAgent()
11299
- },
11300
- body: JSON.stringify({ project: projectId })
11301
- });
11302
- if (res.ok) {
11303
- const data = await res.json();
11696
+ const raw = await fetchAntigravityAvailableModelsRaw(accessToken, projectId);
11697
+ if (raw.kind === "unreachable") {
11698
+ log(`[Antigravity] fetchAvailableModels error: ${raw.error}`);
11699
+ } else if (raw.status < 200 || raw.status >= 300) {
11700
+ log(`[Antigravity] fetchAvailableModels failed: ${raw.status}`);
11701
+ } else if (raw.body.kind !== "json") {
11702
+ log(`[Antigravity] fetchAvailableModels error: ${raw.body.kind === "not-json" ? "the body is not JSON" : "the body could not be read"}`);
11703
+ } else {
11704
+ const data = raw.body.value;
11304
11705
  const servedIds = data.models ? Object.keys(data.models) : [];
11305
11706
  const defaultId = typeof data.defaultAgentModelId === "string" ? data.defaultAgentModelId : null;
11306
11707
  if (servedIds.length > 0) {
@@ -11347,11 +11748,9 @@ async function getServedAntigravityModels(accessToken, projectId, opts) {
11347
11748
  ...agentModelIds ? { agentModelIds } : {}
11348
11749
  };
11349
11750
  agServedCacheAt = now;
11350
- agServedCacheVersion = version;
11751
+ agServedCacheVersion = raw.clientVersion;
11351
11752
  return agServedCache;
11352
11753
  }
11353
- } else {
11354
- log(`[Antigravity] fetchAvailableModels failed: ${res.status}`);
11355
11754
  }
11356
11755
  } catch (err) {
11357
11756
  log(`[Antigravity] fetchAvailableModels error: ${err}`);
@@ -12914,7 +13313,7 @@ async function performRefresh(cred) {
12914
13313
  method: "POST",
12915
13314
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
12916
13315
  body,
12917
- signal: AbortSignal.timeout(TOKEN_REFRESH_TIMEOUT_MS)
13316
+ signal: AbortSignal.timeout(refreshTimeoutMs)
12918
13317
  });
12919
13318
  } catch (error) {
12920
13319
  throw Object.assign(new Error(`Could not reach ${tokenEndpoint} to refresh the Grok token: ${error.message}`, { cause: markOwnTimeout(error) }), { claudishEndpoint: tokenEndpoint });
@@ -12980,13 +13379,14 @@ function refreshShared(cred) {
12980
13379
  }
12981
13380
  return refreshInFlight;
12982
13381
  }
12983
- var GROK_PROXY_URL_ENV = "GROK_PROXY_URL", DEFAULT_GROK_PROXY_URL = "https://cli-chat-proxy.grok.com/v1", GROK_CLIENT_IDENTIFIER = "grok-shell", FALLBACK_GROK_CLIENT_VERSION = "1.0.4", LEGACY_SCOPE = "https://accounts.x.ai/sign-in", EXPIRY_SKEW_MS2, grokHomeOverride = null, claudishOAuthPathOverride = null, GROK_CHANNEL_URL = "https://x.ai/cli/stable", liveClientVersion = null, SIGN_IN_HINT, refreshInFlight = null;
13382
+ var GROK_PROXY_URL_ENV = "GROK_PROXY_URL", DEFAULT_GROK_PROXY_URL = "https://cli-chat-proxy.grok.com/v1", GROK_CLIENT_IDENTIFIER = "grok-shell", FALLBACK_GROK_CLIENT_VERSION = "1.0.4", LEGACY_SCOPE = "https://accounts.x.ai/sign-in", EXPIRY_SKEW_MS2, grokHomeOverride = null, claudishOAuthPathOverride = null, GROK_CHANNEL_URL = "https://x.ai/cli/stable", liveClientVersion = null, SIGN_IN_HINT, refreshInFlight = null, refreshTimeoutMs;
12984
13383
  var init_grok_credentials = __esm(() => {
12985
13384
  init_grok_oauth();
12986
13385
  init_connection_error();
12987
13386
  init_transient_retry();
12988
13387
  EXPIRY_SKEW_MS2 = 5 * 60 * 1000;
12989
13388
  SIGN_IN_HINT = "Run `claudish login grok` (no Grok CLI required \u2014 SuperGrok or X Premium+ subscription). " + "An existing `grok login` (~/.grok/auth.json) is also picked up automatically.";
13389
+ refreshTimeoutMs = TOKEN_REFRESH_TIMEOUT_MS;
12990
13390
  });
12991
13391
 
12992
13392
  // src/auth/quota/sources/grok.ts
@@ -13269,7 +13669,7 @@ function createGeminiThoughtSignatureHook() {
13269
13669
  description: "Sends Gemini's reasoning_details back with the assistant tool calls they were produced for",
13270
13670
  order: "pre",
13271
13671
  models: ["*gemini*", "*google/*"],
13272
- selectByUpstream: (upstream) => upstream.wireApi === "gemini" || upstream.vendor === "google",
13672
+ selectByUpstream: { wireApis: ["gemini"], vendors: ["google"] },
13273
13673
  routes: "all",
13274
13674
  defaultSeverity: "fix",
13275
13675
  statsName: GEMINI_THOUGHT_SIGNATURE_STATS_NAME,
@@ -16959,7 +17359,7 @@ var init_errors2 = __esm(() => {
16959
17359
  });
16960
17360
 
16961
17361
  // ../../node_modules/.bun/zod@4.1.13/node_modules/zod/v4/classic/parse.js
16962
- var parse4, parseAsync2, safeParse2, safeParseAsync2, encode, decode, encodeAsync, decodeAsync, safeEncode, safeDecode, safeEncodeAsync, safeDecodeAsync;
17362
+ var parse4, parseAsync2, safeParse2, safeParseAsync2, encode, decode2, encodeAsync, decodeAsync, safeEncode, safeDecode, safeEncodeAsync, safeDecodeAsync;
16963
17363
  var init_parse2 = __esm(() => {
16964
17364
  init_core2();
16965
17365
  init_errors2();
@@ -16968,7 +17368,7 @@ var init_parse2 = __esm(() => {
16968
17368
  safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
16969
17369
  safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
16970
17370
  encode = /* @__PURE__ */ _encode(ZodRealError);
16971
- decode = /* @__PURE__ */ _decode(ZodRealError);
17371
+ decode2 = /* @__PURE__ */ _decode(ZodRealError);
16972
17372
  encodeAsync = /* @__PURE__ */ _encodeAsync(ZodRealError);
16973
17373
  decodeAsync = /* @__PURE__ */ _decodeAsync(ZodRealError);
16974
17374
  safeEncode = /* @__PURE__ */ _safeEncode(ZodRealError);
@@ -17173,7 +17573,7 @@ var init_schemas2 = __esm(() => {
17173
17573
  inst.safeParseAsync = async (data, params) => safeParseAsync2(inst, data, params);
17174
17574
  inst.spa = inst.safeParseAsync;
17175
17575
  inst.encode = (data, params) => encode(inst, data, params);
17176
- inst.decode = (data, params) => decode(inst, data, params);
17576
+ inst.decode = (data, params) => decode2(inst, data, params);
17177
17577
  inst.encodeAsync = async (data, params) => encodeAsync(inst, data, params);
17178
17578
  inst.decodeAsync = async (data, params) => decodeAsync(inst, data, params);
17179
17579
  inst.safeEncode = (data, params) => safeEncode(inst, data, params);
@@ -18426,7 +18826,17 @@ async function prune(path) {
18426
18826
  await rename(tmp, path);
18427
18827
  log(`[behavior:journal] pruned ${lines.length - survivors.length} of ${lines.length} entries ` + `to stay under ${Math.round(MAX_JOURNAL_BYTES / 1e6)}MB`);
18428
18828
  }
18429
- async function recordDecision(entry, path = journalPath()) {
18829
+ function recordDecision(entry, path = journalPath()) {
18830
+ const previous = pendingAppends.get(path) ?? Promise.resolve();
18831
+ const next = previous.then(() => appendDecision(entry, path));
18832
+ pendingAppends.set(path, next);
18833
+ next.then(() => {
18834
+ if (pendingAppends.get(path) === next)
18835
+ pendingAppends.delete(path);
18836
+ });
18837
+ return next;
18838
+ }
18839
+ async function appendDecision(entry, path) {
18430
18840
  try {
18431
18841
  const size = await stat(path).then((s) => s.size, () => 0);
18432
18842
  if (size === 0)
@@ -18440,7 +18850,7 @@ async function recordDecision(entry, path = journalPath()) {
18440
18850
  log(`[behavior:journal] could not record: ${err}`);
18441
18851
  }
18442
18852
  }
18443
- var JOURNAL_SCHEMA_VERSION = 2, UPLOAD_SURFACES, UPLOAD_DECISIONS, MAX_DETAIL_CHARS = 200, MAX_JOURNAL_BYTES, PRUNE_TO_BYTES;
18853
+ var JOURNAL_SCHEMA_VERSION = 2, UPLOAD_SURFACES, UPLOAD_DECISIONS, MAX_DETAIL_CHARS = 200, MAX_JOURNAL_BYTES, PRUNE_TO_BYTES, pendingAppends;
18444
18854
  var init_journal = __esm(() => {
18445
18855
  init_logger();
18446
18856
  UPLOAD_SURFACES = new Set([
@@ -18458,6 +18868,7 @@ var init_journal = __esm(() => {
18458
18868
  ]);
18459
18869
  MAX_JOURNAL_BYTES = 32 * 1024 * 1024;
18460
18870
  PRUNE_TO_BYTES = Math.floor(MAX_JOURNAL_BYTES * 0.6);
18871
+ pendingAppends = new Map;
18461
18872
  });
18462
18873
 
18463
18874
  // src/hooks/output-capture.ts
@@ -19650,6 +20061,9 @@ var init_loader = __esm(() => {
19650
20061
  function isProxyEvent(event) {
19651
20062
  return PROXY_EVENTS.has(event);
19652
20063
  }
20064
+ function upstreamSelected(selector, upstream) {
20065
+ return upstream.wireApi !== null && selector.wireApis.includes(upstream.wireApi) || upstream.vendor !== null && selector.vendors.includes(upstream.vendor);
20066
+ }
19653
20067
  function eventsOf(def) {
19654
20068
  const events = [];
19655
20069
  const on = def.on ?? {};
@@ -19744,7 +20158,7 @@ function routeMatches(hook, route, upstream) {
19744
20158
  if (hook.routes === "foreign" && route.native)
19745
20159
  return false;
19746
20160
  if (upstream && hook.selectByUpstream)
19747
- return hook.selectByUpstream(upstream);
20161
+ return upstreamSelected(hook.selectByUpstream, upstream);
19748
20162
  return hook.models.some((glob) => globMatches(glob, route.modelId));
19749
20163
  }
19750
20164
  var CLOSED_HANDLER_KEYS, RAW_KEYS2, PROXY_EVENTS, ORDER_RANK;
@@ -22936,324 +23350,6 @@ var init_antigravity_credential = __esm(() => {
22936
23350
  init_antigravity_user();
22937
23351
  });
22938
23352
 
22939
- // src/providers/keychain.ts
22940
- function syncRun(args, stdin) {
22941
- try {
22942
- const proc = Bun.spawnSync([SECURITY_BIN, ...args], {
22943
- stdin: stdin === undefined ? "ignore" : new TextEncoder().encode(stdin),
22944
- stdout: "pipe",
22945
- stderr: "pipe",
22946
- timeout: SPAWN_TIMEOUT_MS
22947
- });
22948
- return normalizeResult(proc.exitCode, proc.signalCode, decode2(proc.stdout), decode2(proc.stderr));
22949
- } catch (err) {
22950
- return { code: 1, stdout: "", stderr: err instanceof Error ? err.message : String(err) };
22951
- }
22952
- }
22953
- async function asyncRun(args, stdin) {
22954
- try {
22955
- const proc = Bun.spawn([SECURITY_BIN, ...args], {
22956
- stdin: stdin === undefined ? "ignore" : new TextEncoder().encode(stdin),
22957
- stdout: "pipe",
22958
- stderr: "pipe",
22959
- timeout: SPAWN_TIMEOUT_MS
22960
- });
22961
- const [stdout, stderr, exitCode] = await Promise.all([
22962
- new Response(proc.stdout).text(),
22963
- new Response(proc.stderr).text(),
22964
- proc.exited
22965
- ]);
22966
- return normalizeResult(exitCode, proc.signalCode, stdout, stderr);
22967
- } catch (err) {
22968
- return { code: 1, stdout: "", stderr: err instanceof Error ? err.message : String(err) };
22969
- }
22970
- }
22971
- function spawnAsyncRun(args, stdin) {
22972
- try {
22973
- const proc = Bun.spawn([SECURITY_BIN, ...args], {
22974
- stdin: stdin === undefined ? "ignore" : new TextEncoder().encode(stdin),
22975
- stdout: "pipe",
22976
- stderr: "pipe"
22977
- });
22978
- const done = Promise.all([
22979
- new Response(proc.stdout).text(),
22980
- new Response(proc.stderr).text(),
22981
- proc.exited
22982
- ]).then(([stdout, stderr, exitCode]) => normalizeResult(exitCode, proc.signalCode, stdout, stderr), (err) => ({
22983
- code: 1,
22984
- stdout: "",
22985
- stderr: err instanceof Error ? err.message : String(err)
22986
- }));
22987
- return { done, pid: proc.pid };
22988
- } catch (err) {
22989
- return {
22990
- done: Promise.resolve({
22991
- code: 1,
22992
- stdout: "",
22993
- stderr: err instanceof Error ? err.message : String(err)
22994
- }),
22995
- pid: undefined
22996
- };
22997
- }
22998
- }
22999
- function decode2(buf) {
23000
- return buf ? new TextDecoder().decode(buf) : "";
23001
- }
23002
- function normalizeResult(exitCode, signalCode, stdout, stderr) {
23003
- if (typeof exitCode === "number")
23004
- return { code: exitCode, stdout, stderr };
23005
- const detail = signalCode ? `killed by ${signalCode}` : "terminated without an exit code";
23006
- return { code: -1, stdout, stderr: stderr.trim() || `security ${detail}` };
23007
- }
23008
- function invalidateKeychainCache() {
23009
- listMemo = null;
23010
- valueMemo.clear();
23011
- }
23012
- function now() {
23013
- return Date.now();
23014
- }
23015
- function isValidKeychainVarName(name) {
23016
- return ENV_VAR_NAME.test(name);
23017
- }
23018
- function describeUnstorableValue(value) {
23019
- if (value.length === 0)
23020
- return "value is empty";
23021
- if (CONTROL_CHARS.test(value)) {
23022
- return "value contains control characters (tab/newline/etc), which the keychain read path cannot represent unambiguously";
23023
- }
23024
- return null;
23025
- }
23026
- function isKeychainSupported() {
23027
- return deps.platform() === "darwin";
23028
- }
23029
- function keychainUnavailableReason() {
23030
- if (!isKeychainSupported()) {
23031
- return `the macOS Keychain is only available on macOS (this is ${deps.platform()})`;
23032
- }
23033
- return null;
23034
- }
23035
- function stripOneTrailingNewline(out) {
23036
- return out.endsWith(`
23037
- `) ? out.slice(0, -1) : out;
23038
- }
23039
- function keychainFileArgs() {
23040
- const file = process.env.CLAUDISH_KEYCHAIN_FILE;
23041
- return file ? [file] : [];
23042
- }
23043
- function findArgs(envVar) {
23044
- return [
23045
- "find-generic-password",
23046
- "-s",
23047
- KEYCHAIN_SERVICE,
23048
- "-a",
23049
- envVar,
23050
- "-w",
23051
- ...keychainFileArgs()
23052
- ];
23053
- }
23054
- function interpretRead(envVar, res) {
23055
- if (res.code === 0) {
23056
- const value = stripOneTrailingNewline(res.stdout);
23057
- return value.length > 0 ? value : null;
23058
- }
23059
- if (res.code === EXIT_ITEM_NOT_FOUND)
23060
- return null;
23061
- throw new KeychainError(`Keychain lookup for ${envVar} failed: ${res.stderr.trim() || `security exited ${res.code}`}`, res.code);
23062
- }
23063
- function readKeychainSecret(envVar) {
23064
- if (!isKeychainSupported())
23065
- return null;
23066
- const cached = valueMemo.get(envVar);
23067
- const at = now();
23068
- if (cached && at - cached.at < MEMO_TTL_MS)
23069
- return cached.value;
23070
- const value = interpretRead(envVar, deps.run(findArgs(envVar)));
23071
- valueMemo.set(envVar, { at, value });
23072
- return value;
23073
- }
23074
- async function readKeychainSecretAsync(envVar) {
23075
- if (!isKeychainSupported())
23076
- return null;
23077
- const cached = valueMemo.get(envVar);
23078
- const at = now();
23079
- if (cached && at - cached.at < MEMO_TTL_MS)
23080
- return cached.value;
23081
- const value = interpretRead(envVar, await deps.runAsync(findArgs(envVar)));
23082
- valueMemo.set(envVar, { at, value });
23083
- return value;
23084
- }
23085
- function genericPasswordArgs(query, withValue) {
23086
- return [
23087
- "find-generic-password",
23088
- "-s",
23089
- query.service,
23090
- ...query.account !== undefined ? ["-a", query.account] : [],
23091
- ...withValue ? ["-w"] : [],
23092
- ...query.keychainFile !== undefined ? [query.keychainFile] : keychainFileArgs()
23093
- ];
23094
- }
23095
- function interpretGenericPassword(res, withValue) {
23096
- if (res.code === 0) {
23097
- if (!withValue)
23098
- return { kind: "found" };
23099
- const value = stripOneTrailingNewline(res.stdout);
23100
- return value.length > 0 ? { kind: "found", value } : { kind: "absent" };
23101
- }
23102
- if (res.code === EXIT_ITEM_NOT_FOUND)
23103
- return { kind: "absent" };
23104
- return {
23105
- kind: "failed",
23106
- code: res.code,
23107
- error: res.stderr.trim() || `security exited ${res.code}`
23108
- };
23109
- }
23110
- async function findGenericPasswordPresence(query) {
23111
- if (!isKeychainSupported())
23112
- return { kind: "absent" };
23113
- const res = await deps.spawnAsync(genericPasswordArgs(query, false)).done;
23114
- return interpretGenericPassword(res, false);
23115
- }
23116
- function startGenericPasswordRead(query) {
23117
- if (!isKeychainSupported()) {
23118
- return { done: Promise.resolve({ kind: "absent" }), pid: undefined };
23119
- }
23120
- const spawn = deps.spawnAsync(genericPasswordArgs(query, true));
23121
- return { done: spawn.done.then((res) => interpretGenericPassword(res, true)), pid: spawn.pid };
23122
- }
23123
- function enumerateKeychainVars() {
23124
- if (!isKeychainSupported())
23125
- return { names: [], failed: false };
23126
- const at = now();
23127
- if (listMemo && at - listMemo.at < MEMO_TTL_MS)
23128
- return listMemo.value;
23129
- const res = deps.run(["dump-keychain", ...keychainFileArgs()]);
23130
- const value = res.code === 0 ? { names: parseDumpAccounts(res.stdout), failed: false } : {
23131
- names: [],
23132
- failed: true,
23133
- error: res.stderr.trim() || `security exited ${res.code}`
23134
- };
23135
- listMemo = { at, value };
23136
- return value;
23137
- }
23138
- function listKeychainVars() {
23139
- return enumerateKeychainVars().names;
23140
- }
23141
- function parseDumpAccounts(dump) {
23142
- const found = new Set;
23143
- for (const block of dump.split(/\nkeychain: /)) {
23144
- if (!block.includes(SVCE_MATCH))
23145
- continue;
23146
- const m = block.match(ACCT_ATTR);
23147
- if (m?.[1] && isValidKeychainVarName(m[1]))
23148
- found.add(m[1]);
23149
- }
23150
- return Array.from(found).sort();
23151
- }
23152
- function lookupKeychainVar(envVar) {
23153
- if (!isKeychainSupported())
23154
- return { present: false, failed: false };
23155
- const cached = valueMemo.get(envVar);
23156
- if (cached && now() - cached.at < MEMO_TTL_MS && cached.value !== null) {
23157
- return { present: true, failed: false };
23158
- }
23159
- const listed = enumerateKeychainVars();
23160
- return { present: listed.names.includes(envVar), failed: listed.failed };
23161
- }
23162
- function toHex(value) {
23163
- return Buffer.from(value, "utf8").toString("hex");
23164
- }
23165
- function quoteForStdin(value) {
23166
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
23167
- }
23168
- function writeKeychainSecret(envVar, value) {
23169
- const unsupported = keychainUnavailableReason();
23170
- if (unsupported)
23171
- throw new KeychainError(`Cannot write ${envVar}: ${unsupported}`);
23172
- if (!isValidKeychainVarName(envVar)) {
23173
- throw new KeychainError(`Cannot write "${envVar}": not a valid environment variable name`);
23174
- }
23175
- const unstorable = describeUnstorableValue(value);
23176
- if (unstorable)
23177
- throw new KeychainError(`Cannot store ${envVar}: ${unstorable}`);
23178
- invalidateKeychainCache();
23179
- const cmd = [
23180
- "add-generic-password",
23181
- "-s",
23182
- quoteForStdin(KEYCHAIN_SERVICE),
23183
- "-a",
23184
- quoteForStdin(envVar),
23185
- "-l",
23186
- quoteForStdin(`${KEYCHAIN_SERVICE}: ${envVar}`),
23187
- "-D",
23188
- quoteForStdin("application password"),
23189
- "-j",
23190
- quoteForStdin("Stored by claudish"),
23191
- "-X",
23192
- quoteForStdin(toHex(value)),
23193
- "-U",
23194
- "-T",
23195
- quoteForStdin(SECURITY_BIN),
23196
- ...keychainFileArgs().map(quoteForStdin)
23197
- ].join(" ");
23198
- const res = deps.run(["-i"], `${cmd}
23199
- `);
23200
- if (res.code !== 0) {
23201
- throw new KeychainError(`Failed to store ${envVar} in the keychain: ${res.stderr.trim() || `security exited ${res.code}`}`, res.code);
23202
- }
23203
- invalidateKeychainCache();
23204
- const readBack = readKeychainSecret(envVar);
23205
- if (readBack !== value) {
23206
- throw new KeychainError(`Keychain write for ${envVar} did not round-trip \u2014 the stored value differs from what was written. ` + "The item may exceed the keychain's size limit; nothing should be assumed saved.");
23207
- }
23208
- }
23209
- function deleteKeychainSecret(envVar) {
23210
- if (!isKeychainSupported())
23211
- return false;
23212
- invalidateKeychainCache();
23213
- const res = deps.run([
23214
- "delete-generic-password",
23215
- "-s",
23216
- KEYCHAIN_SERVICE,
23217
- "-a",
23218
- envVar,
23219
- ...keychainFileArgs()
23220
- ]);
23221
- invalidateKeychainCache();
23222
- if (res.code === 0)
23223
- return true;
23224
- if (res.code === EXIT_ITEM_NOT_FOUND)
23225
- return false;
23226
- throw new KeychainError(`Failed to delete ${envVar} from the keychain: ${res.stderr.trim() || `security exited ${res.code}`}`, res.code);
23227
- }
23228
- function valueTail2(value) {
23229
- if (value.length <= 6)
23230
- return "\u2022\u2022\u2022\u2022";
23231
- return `\u2022\u2022\u2022\u2022${value.slice(-4)}`;
23232
- }
23233
- var KEYCHAIN_SERVICE = "claudish", SECURITY_BIN = "/usr/bin/security", EXIT_ITEM_NOT_FOUND = 44, MEMO_TTL_MS = 3000, SPAWN_TIMEOUT_MS = 1e4, KeychainError, defaultDeps2, deps, listMemo = null, valueMemo, CONTROL_CHARS, ENV_VAR_NAME, ACCT_ATTR, SVCE_MATCH;
23234
- var init_keychain = __esm(() => {
23235
- KeychainError = class KeychainError extends Error {
23236
- exitCode;
23237
- constructor(message, exitCode) {
23238
- super(message);
23239
- this.exitCode = exitCode;
23240
- this.name = "KeychainError";
23241
- }
23242
- };
23243
- defaultDeps2 = {
23244
- platform: () => process.platform,
23245
- run: syncRun,
23246
- runAsync: asyncRun,
23247
- spawnAsync: spawnAsyncRun
23248
- };
23249
- deps = defaultDeps2;
23250
- valueMemo = new Map;
23251
- CONTROL_CHARS = /[\u0000-\u001F\u007F]/;
23252
- ENV_VAR_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
23253
- ACCT_ATTR = /"acct"<blob>=(?:0x[0-9A-Fa-f]*\s+)?"([^"]*)"/;
23254
- SVCE_MATCH = `"svce"<blob>="${KEYCHAIN_SERVICE}"`;
23255
- });
23256
-
23257
23353
  // src/auth/credentials/local-api-key.ts
23258
23354
  function resolveLocalApiKey(q) {
23259
23355
  return realValue(process.env[q.envVar]) || (q.aliases ?? []).map((a) => realValue(process.env[a])).find((v) => !!v) || realValue(getApiKey(q.envVar));
@@ -67956,6 +68052,9 @@ ${h("SUBCOMMANDS")}
67956
68052
  ${green("claudish providers")} ${yellow("[--json]")} Show provider credential status (no key material)
67957
68053
  ${green("claudish quota")} ${yellow("[provider]")} Show remaining quota/usage (alias: usage)
67958
68054
  ${green("claudish serve")} ${yellow("--port <n> --models <p>")} Run the Claude Desktop redirect gateway
68055
+ ${green("claudish subscription models antigravity")} ${yellow("--raw --json")}
68056
+ Print the raw Antigravity fetchAvailableModels
68057
+ ${dim("body as one JSON line (for models-index)")}
67959
68058
  ${green("claudish update")} Check for updates and install the latest version
67960
68059
 
67961
68060
  ${bold("Profiles:")}
@@ -69366,6 +69465,7 @@ var init_pane_launch = __esm(() => {
69366
69465
  "serve",
69367
69466
  "providers",
69368
69467
  "keychain",
69468
+ "subscription",
69369
69469
  "hooks",
69370
69470
  "team",
69371
69471
  "login",
@@ -72085,6 +72185,7 @@ class PaneSessionImpl {
72085
72185
  stderrHead = "";
72086
72186
  paneClosed = false;
72087
72187
  paneExited = false;
72188
+ exitCodeQuery = false;
72088
72189
  reaping = false;
72089
72190
  fastReap = false;
72090
72191
  reapPromise = null;
@@ -72595,7 +72696,7 @@ class PaneSessionImpl {
72595
72696
  }
72596
72697
  }
72597
72698
  checkLiveness() {
72598
- if (this.client || !this.panePidValue || this.paneExited)
72699
+ if (this.client || !this.panePidValue || this.paneExited || this.exitCodeQuery)
72599
72700
  return;
72600
72701
  const now = Date.now();
72601
72702
  if (now - this.lastLivenessAt < 1000)
@@ -72605,11 +72706,55 @@ class PaneSessionImpl {
72605
72706
  process.kill(this.panePidValue, 0);
72606
72707
  } catch (e) {
72607
72708
  if (e.code === "ESRCH") {
72608
- this.paneExited = true;
72609
- this.applyExitPath(null);
72709
+ this.exitCodeQuery = true;
72710
+ this.exitCodeFromMagmux().then((code) => {
72711
+ this.exitCodeQuery = false;
72712
+ if (this.paneExited || isTerminalPhase(this.phase))
72713
+ return;
72714
+ this.paneExited = true;
72715
+ this.exitCode = code;
72716
+ this.step(() => this.applyExitPath(code));
72717
+ });
72610
72718
  }
72611
72719
  }
72612
72720
  }
72721
+ async exitCodeFromMagmux() {
72722
+ const deadline = Date.now() + EXIT_CODE_QUERY_MS;
72723
+ const left = () => deadline - Date.now();
72724
+ const client = await this.dialWithin(left);
72725
+ if (!client)
72726
+ return null;
72727
+ try {
72728
+ while (left() > 0) {
72729
+ const r = await client.request({ type: "list" }, Math.max(1, left()));
72730
+ if (!r.ok)
72731
+ return null;
72732
+ const p0 = r.result.panes?.find((p) => p.pane === 0);
72733
+ if (!p0)
72734
+ return null;
72735
+ if (p0.dead === true)
72736
+ return typeof p0.exitCode === "number" ? p0.exitCode : null;
72737
+ await Bun.sleep(Math.min(EXIT_CODE_RETRY_MS, Math.max(0, left())));
72738
+ }
72739
+ return null;
72740
+ } finally {
72741
+ client.close();
72742
+ }
72743
+ }
72744
+ async dialWithin(left) {
72745
+ while (left() > 0 && !this.reaping && !isTerminalPhase(this.phase)) {
72746
+ try {
72747
+ const dial = MagmuxClient.dial(this.sockPath);
72748
+ const client = await Promise.race([dial, Bun.sleep(Math.max(0, left())).then(() => null)]);
72749
+ if (!client)
72750
+ dial.then((late) => late.close()).catch(() => {});
72751
+ return client;
72752
+ } catch {
72753
+ await Bun.sleep(Math.min(EXIT_CODE_RETRY_MS, Math.max(0, left())));
72754
+ }
72755
+ }
72756
+ return null;
72757
+ }
72613
72758
  t(key, dflt) {
72614
72759
  return this.o.timings?.[key] ?? dflt;
72615
72760
  }
@@ -74558,7 +74703,7 @@ async function startPaneSession(o) {
74558
74703
  await session.start({ magmuxBinary: magmux.binary, env: p.magmuxEnv, cwd: p.cwd });
74559
74704
  return session;
74560
74705
  }
74561
- var BOOT_TIMEOUT_MS = 90000, ADMIT_TIMEOUT_MS = 30000, DEGRADED_ENTRY_MS = 1e4, SCREEN_SETTLE_QUIET_MS = 3000, PANEL_SETTLE_MS = 500, SEND_CLIENT_SLACK_MS = 2000, MIN_READY_TIMEOUT_MS = 1000, BUSY_RETRY_MS = 250, MISMATCH_SETTLE_MS = 1000, CLEAR_WAIT_MS = 1000, BOOT_STATIC_MS = 5000, TICK_MS = 250, WATCH_FPS = 4, POLL_BACKSTOP_MS = 1000, TURN_END_MISSING_FACTOR = 3, RESIZE_REPLY_MS = 1e4, RESIZE_SCREEN_MS = 1000, GATE_POLL_MS = 250, GATE_REPLY_MS = 1000, GATE_STALE_MS = 1000, GATE_GRACE_MS, GATE_DEAD_BACKSTOP_MS = 1000, GATE_KINDLESS_REASONS, RUNTIME_DIALOG_KINDS, REGISTRY_READ_MS = 250, REGISTRY_DISAGREE_MS = 2000, REGISTRY_GATE_BOOT_DISAGREE_MS = 5000, REGISTRY_MISSING_MS = 5000, MAX_ANOMALY_KEYS = 64, KEPT_ANSWERS = 4, DEFAULT_MAX_CONSECUTIVE = 3, EVENT_REASON, VERDICT_EVENT, PaneStartError;
74706
+ var BOOT_TIMEOUT_MS = 90000, ADMIT_TIMEOUT_MS = 30000, DEGRADED_ENTRY_MS = 1e4, SCREEN_SETTLE_QUIET_MS = 3000, PANEL_SETTLE_MS = 500, SEND_CLIENT_SLACK_MS = 2000, MIN_READY_TIMEOUT_MS = 1000, BUSY_RETRY_MS = 250, MISMATCH_SETTLE_MS = 1000, CLEAR_WAIT_MS = 1000, BOOT_STATIC_MS = 5000, TICK_MS = 250, WATCH_FPS = 4, POLL_BACKSTOP_MS = 1000, TURN_END_MISSING_FACTOR = 3, RESIZE_REPLY_MS = 1e4, RESIZE_SCREEN_MS = 1000, GATE_POLL_MS = 250, GATE_REPLY_MS = 1000, GATE_STALE_MS = 1000, GATE_GRACE_MS, GATE_DEAD_BACKSTOP_MS = 1000, EXIT_CODE_QUERY_MS = 2000, EXIT_CODE_RETRY_MS = 50, GATE_KINDLESS_REASONS, RUNTIME_DIALOG_KINDS, REGISTRY_READ_MS = 250, REGISTRY_DISAGREE_MS = 2000, REGISTRY_GATE_BOOT_DISAGREE_MS = 5000, REGISTRY_MISSING_MS = 5000, MAX_ANOMALY_KEYS = 64, KEPT_ANSWERS = 4, DEFAULT_MAX_CONSECUTIVE = 3, EVENT_REASON, VERDICT_EVENT, PaneStartError;
74562
74707
  var init_pane_session = __esm(() => {
74563
74708
  init_queue();
74564
74709
  init_parent_session();
@@ -79759,10 +79904,26 @@ function hookRow(hook, severity) {
79759
79904
  severity,
79760
79905
  routes: hook.routes,
79761
79906
  models: [...hook.models],
79907
+ ...hook.selectByUpstream && {
79908
+ catalogSelection: {
79909
+ wireApis: [...hook.selectByUpstream.wireApis],
79910
+ vendors: [...hook.selectByUpstream.vendors]
79911
+ }
79912
+ },
79762
79913
  order: hook.order,
79763
79914
  unsafe: hook.unsafe
79764
79915
  };
79765
79916
  }
79917
+ function selectionOf(r) {
79918
+ const globs = r.models.join(", ");
79919
+ if (!r.catalogSelection)
79920
+ return r.models.join(",") !== "*" ? `models ${globs}` : null;
79921
+ const facts = [
79922
+ ...r.catalogSelection.wireApis.map((w) => `wire ${w}`),
79923
+ ...r.catalogSelection.vendors.map((v) => `vendor ${v}`)
79924
+ ].join(" or ");
79925
+ return `catalog ${facts}; without a catalog connection, models ${globs}`;
79926
+ }
79766
79927
  async function list(json) {
79767
79928
  const set = await loadHookSet({ hostMode: "other", moduleWarn: () => {} });
79768
79929
  const rows = set.registry.hooks.map((h) => hookRow(h, set.registry.severityOf(h)));
@@ -79789,7 +79950,7 @@ Hooks, in effective order
79789
79950
  `${r.source}`,
79790
79951
  `events ${r.events.join(", ")}`,
79791
79952
  `routes ${r.routes}`,
79792
- r.models.join(",") !== "*" ? `models ${r.models.join(", ")}` : null,
79953
+ selectionOf(r),
79793
79954
  r.order !== "normal" ? `order ${r.order}` : null
79794
79955
  ].filter(Boolean);
79795
79956
  console.log(` ${dim2(scope.join(" \xB7 "))}
@@ -81018,6 +81179,364 @@ var init_keychain_command = __esm(() => {
81018
81179
  VALUE_FLAGS = new Set(["--config", "--from", "--only"]);
81019
81180
  });
81020
81181
 
81182
+ // src/subscription-models-command.ts
81183
+ var exports_subscription_models_command = {};
81184
+ __export(exports_subscription_models_command, {
81185
+ EXIT: () => EXIT,
81186
+ FAILURE_CODES: () => FAILURE_CODES,
81187
+ INTERNAL_ERROR_MESSAGE: () => INTERNAL_ERROR_MESSAGE,
81188
+ SECRET_GUARD_MESSAGE: () => SECRET_GUARD_MESSAGE,
81189
+ SUBSCRIPTION_MODELS_USAGE: () => SUBSCRIPTION_MODELS_USAGE,
81190
+ SUBSCRIPTION_MODEL_LIST_SCHEMA: () => SUBSCRIPTION_MODEL_LIST_SCHEMA,
81191
+ defaultSubscriptionModelsDeps: () => defaultSubscriptionModelsDeps,
81192
+ exitCodeFor: () => exitCodeFor,
81193
+ parseSubscriptionModelsArgs: () => parseSubscriptionModelsArgs,
81194
+ reportSubscriptionInternalError: () => reportSubscriptionInternalError,
81195
+ runAntigravityRawModelList: () => runAntigravityRawModelList,
81196
+ subscriptionModelsCommand: () => subscriptionModelsCommand
81197
+ });
81198
+ function exitCodeFor(failure) {
81199
+ if (failure.class === "internal")
81200
+ return failure.code === "usage" ? EXIT.usage : EXIT.internal;
81201
+ return EXIT[failure.class];
81202
+ }
81203
+ function defaultSubscriptionModelsDeps() {
81204
+ return {
81205
+ platform: () => process.platform,
81206
+ readStore: readAntigravityStoreClassified,
81207
+ tokenDeps: defaultAntigravityTokenDeps,
81208
+ now: () => Date.now(),
81209
+ httpTimeoutMs: 30000,
81210
+ keychainDeadlineMs: 1e4,
81211
+ writeStdout: (line) => new Promise((resolve, reject) => {
81212
+ process.stdout.write(line, (err) => err ? reject(err) : resolve());
81213
+ }),
81214
+ writeStderr: (line) => {
81215
+ process.stderr.write(line);
81216
+ }
81217
+ };
81218
+ }
81219
+ function parseSubscriptionModelsArgs(argv) {
81220
+ const positionals = argv.filter((a) => !a.startsWith("-"));
81221
+ const flags = argv.filter((a) => a.startsWith("-"));
81222
+ const positionalsOk = positionals.length === 2 && positionals[0] === "models" && positionals[1] === "antigravity";
81223
+ const flagsOk = flags.length === 2 && flags.includes("--raw") && flags.includes("--json");
81224
+ return positionalsOk && flagsOk ? { ok: true, provider: "antigravity" } : { ok: false };
81225
+ }
81226
+ function addSecret(secrets, value) {
81227
+ if (typeof value === "string" && value.length > 0)
81228
+ secrets.values.add(value);
81229
+ }
81230
+ function buildEnvelope(facts, failure, body) {
81231
+ return {
81232
+ schema: SUBSCRIPTION_MODEL_LIST_SCHEMA,
81233
+ ...facts.provider !== undefined ? { provider: facts.provider } : {},
81234
+ claudishVersion: VERSION,
81235
+ ...facts.fetchedAt !== undefined ? { fetchedAt: facts.fetchedAt } : {},
81236
+ ...facts.sourceUrl !== undefined ? { sourceUrl: facts.sourceUrl } : {},
81237
+ ...facts.clientVersion !== undefined ? { clientVersion: facts.clientVersion } : {},
81238
+ ...facts.clientVersionSource !== undefined ? { clientVersionSource: facts.clientVersionSource } : {},
81239
+ tokenRefreshed: facts.tokenRefreshed,
81240
+ ...facts.httpStatus !== undefined ? { httpStatus: facts.httpStatus } : {},
81241
+ ...failure ? { failure } : {},
81242
+ ...body !== undefined ? { body } : {}
81243
+ };
81244
+ }
81245
+ function failureOf2(cls, code, httpStatus) {
81246
+ return { class: cls, code, ...httpStatus !== undefined ? { httpStatus } : {} };
81247
+ }
81248
+ function stripUserinfo(url) {
81249
+ try {
81250
+ const parsed = new URL(url);
81251
+ parsed.username = "";
81252
+ parsed.password = "";
81253
+ return parsed.toString();
81254
+ } catch {
81255
+ return url.replace(/^([a-z][a-z0-9+.-]*:\/\/)[^@/]*@/i, "$1");
81256
+ }
81257
+ }
81258
+ function storeReadFailure(read) {
81259
+ switch (read.kind) {
81260
+ case "absent":
81261
+ return failureOf2("credential_missing", "keychain_item_absent");
81262
+ case "locked":
81263
+ return failureOf2("keychain_locked", "keychain_locked");
81264
+ case "timeout":
81265
+ return failureOf2("keychain_locked", "keychain_read_timeout");
81266
+ default:
81267
+ return failureOf2("keychain_locked", "keychain_read_failed");
81268
+ }
81269
+ }
81270
+ function tokenFailure(refreshCalled, outcome) {
81271
+ if (!refreshCalled)
81272
+ return failureOf2("credential_missing", "token_unparseable");
81273
+ switch (outcome?.kind) {
81274
+ case "not-installed":
81275
+ return failureOf2("mint_failed", "agy_missing");
81276
+ case "timeout":
81277
+ return failureOf2("mint_failed", "agy_refresh_timeout");
81278
+ case "ran":
81279
+ return failureOf2("mint_failed", "agy_refresh_no_valid_token");
81280
+ default:
81281
+ return failureOf2("mint_failed", "agy_refresh_failed");
81282
+ }
81283
+ }
81284
+ function loadCodeAssistFailure(err) {
81285
+ const fields = err ?? {};
81286
+ const status = typeof fields.upstreamStatus === "number" ? fields.upstreamStatus : undefined;
81287
+ if (status !== undefined) {
81288
+ if (status === 429)
81289
+ return failureOf2("network", "load_code_assist_429", status);
81290
+ if (status >= 500 && status <= 599)
81291
+ return failureOf2("network", "load_code_assist_5xx", status);
81292
+ return failureOf2("mint_failed", "load_code_assist_4xx", status);
81293
+ }
81294
+ if (err instanceof SyntaxError)
81295
+ return failureOf2("mint_failed", "load_code_assist_bad_body");
81296
+ if (fields.terminal === true)
81297
+ return failureOf2("mint_failed", "load_code_assist_no_project");
81298
+ return failureOf2("network", "load_code_assist_network_error");
81299
+ }
81300
+ function listFailure(value, status) {
81301
+ const models = value !== null && typeof value === "object" && !Array.isArray(value) ? value.models : undefined;
81302
+ if (models === null || typeof models !== "object" || Array.isArray(models)) {
81303
+ return failureOf2("list_incomplete", "models_absent", status);
81304
+ }
81305
+ if (Object.keys(models).length === 0) {
81306
+ return failureOf2("list_incomplete", "models_empty", status);
81307
+ }
81308
+ return null;
81309
+ }
81310
+ async function raceTimeout(work, ms) {
81311
+ let timer;
81312
+ const timedOut = new Promise((resolve) => {
81313
+ timer = setTimeout(() => resolve(TIMED_OUT), ms);
81314
+ });
81315
+ work.catch(() => {});
81316
+ try {
81317
+ return await Promise.race([work, timedOut]);
81318
+ } finally {
81319
+ if (timer)
81320
+ clearTimeout(timer);
81321
+ }
81322
+ }
81323
+ function fail(facts, failure) {
81324
+ return { envelope: buildEnvelope(facts, failure), exitCode: exitCodeFor(failure) };
81325
+ }
81326
+ function lineOf(envelope) {
81327
+ return `${JSON.stringify(envelope)}
81328
+ `;
81329
+ }
81330
+ function containsSecret(secrets, ...texts) {
81331
+ for (const secret of secrets.values) {
81332
+ if (texts.some((text) => text?.includes(secret)))
81333
+ return true;
81334
+ }
81335
+ return false;
81336
+ }
81337
+ function safeStderr(deps, line) {
81338
+ try {
81339
+ deps.writeStderr(line);
81340
+ } catch {}
81341
+ }
81342
+ async function writeInternalFailure(deps, facts, code, stderrLine, secrets) {
81343
+ const failure = failureOf2("internal", code);
81344
+ safeStderr(deps, `${stderrLine}
81345
+ `);
81346
+ const line = lineOf(buildEnvelope(facts, failure));
81347
+ if (!secrets || !containsSecret(secrets, line)) {
81348
+ try {
81349
+ await deps.writeStdout(line);
81350
+ } catch {}
81351
+ }
81352
+ return exitCodeFor(failure);
81353
+ }
81354
+ async function reportSubscriptionInternalError(deps) {
81355
+ let resolved;
81356
+ try {
81357
+ resolved = deps ?? defaultSubscriptionModelsDeps();
81358
+ } catch {
81359
+ process.stderr.write(`${INTERNAL_ERROR_MESSAGE}
81360
+ `);
81361
+ return EXIT.internal;
81362
+ }
81363
+ return writeInternalFailure(resolved, { tokenRefreshed: false }, "internal_error", INTERNAL_ERROR_MESSAGE);
81364
+ }
81365
+ async function obtainAccessToken(deps, facts, secrets, preRaw) {
81366
+ const base = deps.tokenDeps();
81367
+ let firstRead = true;
81368
+ let refreshCalled = false;
81369
+ let refreshOutcome = null;
81370
+ const laterReads = [];
81371
+ const observed = {
81372
+ ...base,
81373
+ readStore: () => {
81374
+ if (firstRead) {
81375
+ firstRead = false;
81376
+ return preRaw;
81377
+ }
81378
+ const raw = base.readStore();
81379
+ if (raw)
81380
+ laterReads.push(raw);
81381
+ return raw;
81382
+ },
81383
+ runAgyRefresh: () => {
81384
+ refreshCalled = true;
81385
+ facts.tokenRefreshed = true;
81386
+ refreshOutcome = base.runAgyRefresh();
81387
+ return refreshOutcome;
81388
+ }
81389
+ };
81390
+ let accessToken;
81391
+ try {
81392
+ accessToken = await getValidAntigravityAccessToken(observed);
81393
+ } catch {
81394
+ return { ok: false, result: fail(facts, tokenFailure(refreshCalled, refreshOutcome)) };
81395
+ }
81396
+ addSecret(secrets, accessToken);
81397
+ for (const raw of [preRaw, ...laterReads]) {
81398
+ addSecret(secrets, raw);
81399
+ addSecret(secrets, readSharedAntigravityToken({ ...base, readStore: () => raw })?.refresh_token);
81400
+ }
81401
+ return { ok: true, accessToken };
81402
+ }
81403
+ function classifyAvailableModels(facts, raw, timedOut) {
81404
+ facts.sourceUrl = stripUserinfo(raw.url);
81405
+ facts.clientVersion = raw.clientVersion;
81406
+ facts.clientVersionSource = raw.clientVersionSource;
81407
+ const networkCode = timedOut ? "fetch_available_models_timeout" : "fetch_available_models_network_error";
81408
+ if (raw.kind === "unreachable")
81409
+ return fail(facts, failureOf2("network", networkCode));
81410
+ facts.fetchedAt = raw.fetchedAt;
81411
+ facts.httpStatus = raw.status;
81412
+ if (raw.status < 200 || raw.status >= 300) {
81413
+ return { envelope: buildEnvelope(facts), exitCode: EXIT.ok };
81414
+ }
81415
+ switch (raw.body.kind) {
81416
+ case "json": {
81417
+ const incomplete = listFailure(raw.body.value, raw.status);
81418
+ if (incomplete)
81419
+ return fail(facts, incomplete);
81420
+ return {
81421
+ envelope: buildEnvelope(facts, undefined, raw.body.text),
81422
+ exitCode: EXIT.ok,
81423
+ bodyText: raw.body.text
81424
+ };
81425
+ }
81426
+ case "not-json":
81427
+ return fail(facts, failureOf2("list_incomplete", "body_not_json", raw.status));
81428
+ default:
81429
+ return fail(facts, failureOf2("network", networkCode, raw.status));
81430
+ }
81431
+ }
81432
+ async function determine(deps, secrets, facts) {
81433
+ if (deps.platform() !== "darwin") {
81434
+ return fail(facts, failureOf2("credential_missing", "platform_unsupported"));
81435
+ }
81436
+ const read = await deps.readStore(deps.keychainDeadlineMs);
81437
+ if (read.kind !== "present")
81438
+ return fail(facts, storeReadFailure(read));
81439
+ addSecret(secrets, read.raw);
81440
+ const token = await obtainAccessToken(deps, facts, secrets, read.raw);
81441
+ if (!token.ok)
81442
+ return token.result;
81443
+ const version = resolveAntigravityClientVersion();
81444
+ facts.clientVersion = version.version;
81445
+ facts.clientVersionSource = version.source;
81446
+ let projectId;
81447
+ try {
81448
+ const setup = await raceTimeout(setupAntigravityUser(token.accessToken), deps.httpTimeoutMs);
81449
+ if (setup === TIMED_OUT)
81450
+ return fail(facts, failureOf2("network", "load_code_assist_timeout"));
81451
+ projectId = setup.projectId;
81452
+ } catch (err) {
81453
+ return fail(facts, loadCodeAssistFailure(err));
81454
+ }
81455
+ addSecret(secrets, projectId);
81456
+ const controller = new AbortController;
81457
+ const timer = setTimeout(() => controller.abort(), deps.httpTimeoutMs);
81458
+ try {
81459
+ const raw = await fetchAntigravityAvailableModelsRaw(token.accessToken, projectId, {
81460
+ signal: controller.signal,
81461
+ now: deps.now
81462
+ });
81463
+ return classifyAvailableModels(facts, raw, controller.signal.aborted);
81464
+ } finally {
81465
+ clearTimeout(timer);
81466
+ }
81467
+ }
81468
+ async function runAntigravityRawModelList(deps) {
81469
+ const secrets = { values: new Set };
81470
+ const facts = { provider: "antigravity", tokenRefreshed: false };
81471
+ let line;
81472
+ let exitCode;
81473
+ let bodyText;
81474
+ try {
81475
+ const result = await determine(deps, secrets, facts);
81476
+ line = lineOf(result.envelope);
81477
+ exitCode = result.exitCode;
81478
+ bodyText = result.bodyText;
81479
+ } catch {
81480
+ return writeInternalFailure(deps, { provider: facts.provider, tokenRefreshed: facts.tokenRefreshed }, "internal_error", INTERNAL_ERROR_MESSAGE, secrets);
81481
+ }
81482
+ if (containsSecret(secrets, line, bodyText)) {
81483
+ return writeInternalFailure(deps, facts, "secret_guard", SECRET_GUARD_MESSAGE, secrets);
81484
+ }
81485
+ try {
81486
+ await deps.writeStdout(line);
81487
+ } catch {
81488
+ safeStderr(deps, `${INTERNAL_ERROR_MESSAGE}
81489
+ `);
81490
+ return EXIT.internal;
81491
+ }
81492
+ return exitCode;
81493
+ }
81494
+ async function subscriptionModelsCommand(argv, deps = defaultSubscriptionModelsDeps()) {
81495
+ if (!parseSubscriptionModelsArgs(argv).ok) {
81496
+ return writeInternalFailure(deps, { tokenRefreshed: false }, "usage", SUBSCRIPTION_MODELS_USAGE);
81497
+ }
81498
+ return runAntigravityRawModelList(deps);
81499
+ }
81500
+ var SUBSCRIPTION_MODEL_LIST_SCHEMA = "claudish.subscription-model-list.v1", FAILURE_CODES, EXIT, SUBSCRIPTION_MODELS_USAGE = "usage: claudish subscription models antigravity --raw --json", SECRET_GUARD_MESSAGE = "[claudish subscription] refused: output contained a credential value", INTERNAL_ERROR_MESSAGE = "[claudish subscription] internal error", TIMED_OUT;
81501
+ var init_subscription_models_command = __esm(() => {
81502
+ init_antigravity_token();
81503
+ init_antigravity_user();
81504
+ FAILURE_CODES = {
81505
+ credential_missing: ["platform_unsupported", "keychain_item_absent", "token_unparseable"],
81506
+ keychain_locked: ["keychain_locked", "keychain_read_timeout", "keychain_read_failed"],
81507
+ mint_failed: [
81508
+ "agy_missing",
81509
+ "agy_refresh_failed",
81510
+ "agy_refresh_timeout",
81511
+ "agy_refresh_no_valid_token",
81512
+ "load_code_assist_4xx",
81513
+ "load_code_assist_no_project",
81514
+ "load_code_assist_bad_body"
81515
+ ],
81516
+ network: [
81517
+ "load_code_assist_network_error",
81518
+ "load_code_assist_429",
81519
+ "load_code_assist_5xx",
81520
+ "load_code_assist_timeout",
81521
+ "fetch_available_models_network_error",
81522
+ "fetch_available_models_timeout"
81523
+ ],
81524
+ list_incomplete: ["models_absent", "models_empty", "body_not_json"],
81525
+ internal: ["usage", "secret_guard", "internal_error"]
81526
+ };
81527
+ EXIT = {
81528
+ ok: 0,
81529
+ internal: 1,
81530
+ usage: 2,
81531
+ credential_missing: 3,
81532
+ keychain_locked: 4,
81533
+ mint_failed: 5,
81534
+ network: 6,
81535
+ list_incomplete: 7
81536
+ };
81537
+ TIMED_OUT = Symbol("timed-out");
81538
+ });
81539
+
81021
81540
  // src/auth/antigravity-oauth.ts
81022
81541
  import { spawnSync as spawnSync2 } from "child_process";
81023
81542
  import { existsSync as existsSync39, unlinkSync as unlinkSync9 } from "fs";
@@ -89414,7 +89933,7 @@ class InteractiveDriver {
89414
89933
  try {
89415
89934
  this.binding.fireEnd(outcome);
89416
89935
  } catch {}
89417
- await raceTimeout(this.binding.endSettled?.() ?? Promise.resolve(), SESSION_END_WAIT_MS);
89936
+ await raceTimeout2(this.binding.endSettled?.() ?? Promise.resolve(), SESSION_END_WAIT_MS);
89418
89937
  try {
89419
89938
  this.binding.sweepInbox?.();
89420
89939
  } catch {}
@@ -90057,7 +90576,7 @@ function fileSizeOf(path) {
90057
90576
  return 0;
90058
90577
  }
90059
90578
  }
90060
- function raceTimeout(p, ms) {
90579
+ function raceTimeout2(p, ms) {
90061
90580
  return new Promise((resolve) => {
90062
90581
  const t = setTimeout(resolve, ms);
90063
90582
  p.then(() => {
@@ -94346,6 +94865,7 @@ function classifyStartupKind() {
94346
94865
  "stats",
94347
94866
  "providers",
94348
94867
  "keychain",
94868
+ "subscription",
94349
94869
  "login",
94350
94870
  "logout",
94351
94871
  "quota",
@@ -94483,6 +95003,7 @@ var isConfigCommand = firstPositional === "config";
94483
95003
  var isServeCommand = firstPositional === "serve";
94484
95004
  var isProvidersCommand = firstPositional === "providers";
94485
95005
  var isKeychainCommand = firstPositional === "keychain";
95006
+ var isSubscriptionCommand = firstPositional === "subscription";
94486
95007
  var isHooksCommand = firstPositional === "hooks";
94487
95008
  var isTeamCommand = firstPositional === "team";
94488
95009
  var isLoginCommand = firstPositional === "login";
@@ -94528,6 +95049,14 @@ if (isMcpMode) {
94528
95049
  console.error(`[claudish keychain] ${e instanceof Error ? e.message : String(e)}`);
94529
95050
  process.exit(1);
94530
95051
  }));
95052
+ } else if (isSubscriptionCommand) {
95053
+ const subscriptionArgIndex = args.indexOf("subscription");
95054
+ const subscriptionModule = () => Promise.resolve().then(() => (init_subscription_models_command(), exports_subscription_models_command));
95055
+ subscriptionModule().then((m) => m.subscriptionModelsCommand(args.slice(subscriptionArgIndex + 1))).catch(() => subscriptionModule().then((m) => m.reportSubscriptionInternalError()).catch(() => {
95056
+ process.stderr.write(`[claudish subscription] internal error
95057
+ `);
95058
+ return 1;
95059
+ })).then((code) => process.exit(code));
94531
95060
  } else if (isLoginCommand) {
94532
95061
  const loginProviderArg = args.find((a, i) => i > args.indexOf("login") && !a.startsWith("-"));
94533
95062
  Promise.resolve().then(() => (init_auth_commands(), {})).then((m) => loginCommand(loginProviderArg).catch(handlePromptExit));