claudish 14.18.1 → 14.18.3

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 +356 -169
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -5494,7 +5494,7 @@ var init_onepassword_config = __esm(() => {
5494
5494
  });
5495
5495
 
5496
5496
  // src/version.ts
5497
- var VERSION = "14.18.1";
5497
+ var VERSION = "14.18.3";
5498
5498
 
5499
5499
  // src/redact.ts
5500
5500
  function isPlaceholder(value) {
@@ -26401,6 +26401,7 @@ var version2 = null, readForToken = null;
26401
26401
 
26402
26402
  // src/auth/antigravity-token.ts
26403
26403
  import { execFileSync } from "child_process";
26404
+ import { createHash as createHash3 } from "crypto";
26404
26405
  import { existsSync as existsSync11 } from "fs";
26405
26406
  import { homedir as homedir12 } from "os";
26406
26407
  import { join as join12 } from "path";
@@ -26408,6 +26409,8 @@ function invalidateReadStoreMemo() {
26408
26409
  cachedRawStore = null;
26409
26410
  }
26410
26411
  function defaultReadStore() {
26412
+ if (process.env.CLAUDISH_DISABLE_KEYCHAIN === "1")
26413
+ return null;
26411
26414
  if (process.platform !== "darwin") {
26412
26415
  logStderr("[Antigravity] Shared token store is macOS-only for now (other keyring backends are a follow-up).");
26413
26416
  return null;
@@ -26549,7 +26552,7 @@ function encodeRecord(rec) {
26549
26552
  return PREFIX + Buffer.from(JSON.stringify(rec), "utf8").toString("base64");
26550
26553
  }
26551
26554
  function readSharedAntigravityToken(deps = defaultDeps3) {
26552
- const rec = parseRecord2(deps.readStore());
26555
+ const rec = readObservedRecord(deps);
26553
26556
  return rec ? rec.token : null;
26554
26557
  }
26555
26558
  function hasSharedAntigravityToken(deps = defaultDeps3) {
@@ -26596,11 +26599,44 @@ function captureAgyClientVersion(accessToken, deps) {
26596
26599
  log("[Antigravity] Could not read the agy version" + (kept ? `; keeping ${kept}.` : "; using the fallback version."));
26597
26600
  }
26598
26601
  }
26602
+ function antigravityTokenLineageMaterial(token) {
26603
+ if (token.refresh_token)
26604
+ return `refresh:${token.refresh_token}`;
26605
+ if (token.access_token)
26606
+ return `access:${token.access_token}`;
26607
+ return;
26608
+ }
26609
+ function sha256(value) {
26610
+ return createHash3("sha256").update(value).digest("hex");
26611
+ }
26612
+ function observeLineage(token) {
26613
+ const material = token ? antigravityTokenLineageMaterial(token) : undefined;
26614
+ observedLineage = material ? sha256(material) : null;
26615
+ if (!observedLineage || !token?.access_token)
26616
+ return;
26617
+ const key = sha256(token.access_token);
26618
+ lineageByAccessToken.delete(key);
26619
+ lineageByAccessToken.set(key, observedLineage);
26620
+ if (lineageByAccessToken.size > MAX_TRACKED_ACCESS_TOKENS) {
26621
+ lineageByAccessToken.delete(lineageByAccessToken.keys().next().value);
26622
+ }
26623
+ }
26624
+ function readObservedRecord(deps) {
26625
+ const rec = parseRecord2(deps.readStore());
26626
+ observeLineage(rec ? rec.token : null);
26627
+ return rec;
26628
+ }
26629
+ function currentAntigravityTokenLineage() {
26630
+ return observedLineage;
26631
+ }
26632
+ function lineageForAntigravityAccessToken(accessToken) {
26633
+ return lineageByAccessToken.get(sha256(accessToken)) ?? null;
26634
+ }
26599
26635
  async function resolveValidToken(deps) {
26600
26636
  if (process.platform !== "darwin") {
26601
26637
  throw terminalCredentialError("[Antigravity] The shared Antigravity token store is macOS-only for now. " + "Use g@<model> with GEMINI_API_KEY on this platform.");
26602
26638
  }
26603
- const rec = parseRecord2(deps.readStore());
26639
+ const rec = readObservedRecord(deps);
26604
26640
  if (!rec) {
26605
26641
  throw terminalCredentialError("[Antigravity] No Antigravity session found. Sign in with `claudish login antigravity`, " + "or use g@<model> with GEMINI_API_KEY " + "(get one at https://aistudio.google.com/app/apikey).");
26606
26642
  }
@@ -26610,7 +26646,7 @@ async function resolveValidToken(deps) {
26610
26646
  }
26611
26647
  log("[Antigravity] Access token expired/near-expiry \u2014 asking the Antigravity CLI to refresh.");
26612
26648
  const outcome = deps.runAgyRefresh();
26613
- const refreshedRec = parseRecord2(deps.readStore());
26649
+ const refreshedRec = readObservedRecord(deps);
26614
26650
  if (refreshedRec && !needsRefresh(refreshedRec.token, deps.now())) {
26615
26651
  log("[Antigravity] Shared token refreshed by the Antigravity CLI.");
26616
26652
  captureAgyClientVersion(refreshedRec.token.access_token, deps);
@@ -26647,8 +26683,8 @@ async function forceRefreshAntigravityToken(deps = defaultDeps3) {
26647
26683
  if (process.platform !== "darwin") {
26648
26684
  throw terminalCredentialError("[Antigravity] The shared Antigravity token store is macOS-only for now. " + "Use g@<model> with GEMINI_API_KEY on this platform.");
26649
26685
  }
26650
- _resetAntigravityTokenState();
26651
- const rec = parseRecord2(deps.readStore());
26686
+ resetObservedTokenState();
26687
+ const rec = readObservedRecord(deps);
26652
26688
  if (!rec) {
26653
26689
  throw terminalCredentialError("[Antigravity] No Antigravity session found. Sign in with `claudish login antigravity`, " + "or use g@<model> with GEMINI_API_KEY " + "(get one at https://aistudio.google.com/app/apikey).");
26654
26690
  }
@@ -26656,7 +26692,7 @@ async function forceRefreshAntigravityToken(deps = defaultDeps3) {
26656
26692
  log("[Antigravity] Upstream rejected the current token \u2014 asking the Antigravity CLI to re-mint.");
26657
26693
  writeSharedAntigravityToken({ ...original, expiry: new Date(deps.now() - 1000).toISOString() }, deps);
26658
26694
  const outcome = deps.runAgyRefresh();
26659
- const refreshed = parseRecord2(deps.readStore());
26695
+ const refreshed = readObservedRecord(deps);
26660
26696
  const token = refreshed?.token;
26661
26697
  if (token && token.access_token !== original.access_token && !needsRefresh(token, deps.now())) {
26662
26698
  log("[Antigravity] Shared token re-minted by the Antigravity CLI.");
@@ -26666,7 +26702,7 @@ async function forceRefreshAntigravityToken(deps = defaultDeps3) {
26666
26702
  if (!refreshed || refreshed.token.access_token === original.access_token) {
26667
26703
  writeSharedAntigravityToken(original, deps);
26668
26704
  }
26669
- _resetAntigravityTokenState();
26705
+ resetObservedTokenState();
26670
26706
  if (outcome.kind === "timeout" || outcome.kind === "failed") {
26671
26707
  const message = `[Antigravity] ${describeRefreshFailure(outcome)}`;
26672
26708
  if (outcome.kind === "timeout") {
@@ -26680,11 +26716,16 @@ async function forceRefreshAntigravityToken(deps = defaultDeps3) {
26680
26716
  throw terminalCredentialError("[Antigravity] The Antigravity session was rejected upstream and could not be re-minted. " + "Run `claudish login antigravity` to sign in again.");
26681
26717
  }
26682
26718
  function _resetAntigravityTokenState() {
26719
+ resetObservedTokenState();
26720
+ lineageByAccessToken.clear();
26721
+ }
26722
+ function resetObservedTokenState() {
26683
26723
  inFlight = null;
26684
26724
  cachedHasToken = null;
26725
+ observedLineage = null;
26685
26726
  invalidateReadStoreMemo();
26686
26727
  }
26687
- 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, defaultDeps3, KEYCHAIN_LOCKED_EXIT_CODES, cachedHasToken = null, HAS_TOKEN_TTL_MS = 5000, inFlight = null;
26728
+ 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, defaultDeps3, KEYCHAIN_LOCKED_EXIT_CODES, cachedHasToken = null, HAS_TOKEN_TTL_MS = 5000, inFlight = null, observedLineage = null, MAX_TRACKED_ACCESS_TOKENS = 8, lineageByAccessToken;
26688
26729
  var init_antigravity_token = __esm(() => {
26689
26730
  init_logger();
26690
26731
  init_keychain();
@@ -26697,6 +26738,7 @@ var init_antigravity_token = __esm(() => {
26697
26738
  now: () => Date.now()
26698
26739
  };
26699
26740
  KEYCHAIN_LOCKED_EXIT_CODES = new Set([36, 51, 128]);
26741
+ lineageByAccessToken = new Map;
26700
26742
  });
26701
26743
 
26702
26744
  // src/auth/antigravity-user.ts
@@ -26749,6 +26791,26 @@ function resetAntigravityUserCache() {
26749
26791
  agServedCache = null;
26750
26792
  agServedCacheAt = 0;
26751
26793
  agServedCacheVersion = null;
26794
+ cachedAgLineage = null;
26795
+ }
26796
+ function syncAccountCaches() {
26797
+ const lineage = currentAntigravityTokenLineage();
26798
+ if (lineage === cachedAgLineage)
26799
+ return;
26800
+ if (cachedAgProjectId || agServedCache) {
26801
+ log("[Antigravity] Token lineage changed; dropping the cached project, tier and models.");
26802
+ }
26803
+ resetAntigravityUserCache();
26804
+ cachedAgLineage = lineage;
26805
+ }
26806
+ function lineageOfToken(accessToken) {
26807
+ return lineageForAntigravityAccessToken(accessToken) ?? currentAntigravityTokenLineage();
26808
+ }
26809
+ function mayPublishFor(lineage) {
26810
+ if (currentAntigravityTokenLineage() !== lineage)
26811
+ return false;
26812
+ syncAccountCaches();
26813
+ return true;
26752
26814
  }
26753
26815
  async function callLoadCodeAssistAntigravity(accessToken) {
26754
26816
  const res = await fetch(`${apiBase()}:loadCodeAssist`, {
@@ -26766,7 +26828,9 @@ async function callLoadCodeAssistAntigravity(accessToken) {
26766
26828
  return await res.json();
26767
26829
  }
26768
26830
  async function setupAntigravityUser(accessToken) {
26769
- if (cachedAgProjectId && cachedAgTierId) {
26831
+ syncAccountCaches();
26832
+ const lineage = lineageOfToken(accessToken);
26833
+ if (lineage === cachedAgLineage && cachedAgProjectId && cachedAgTierId) {
26770
26834
  return { projectId: cachedAgProjectId, tierId: cachedAgTierId };
26771
26835
  }
26772
26836
  const loadRes = await callLoadCodeAssistAntigravity(accessToken);
@@ -26776,13 +26840,18 @@ async function setupAntigravityUser(accessToken) {
26776
26840
  if (!projectId) {
26777
26841
  throw makeTerminalSetupError("Antigravity did not return a project for this account. Sign in to Antigravity " + "(`claudish login antigravity`) and try again, or use g@<model> with GEMINI_API_KEY " + "(get one at https://aistudio.google.com/app/apikey).");
26778
26842
  }
26779
- cachedAgProjectId = projectId;
26780
- cachedAgTierId = resolvedTier;
26781
- cachedAgTierName = loadRes.paidTier?.name || null;
26843
+ if (mayPublishFor(lineage)) {
26844
+ cachedAgProjectId = projectId;
26845
+ cachedAgTierId = resolvedTier;
26846
+ cachedAgTierName = loadRes.paidTier?.name || null;
26847
+ } else {
26848
+ log("[Antigravity] Token lineage changed during setup; the result is not cached.");
26849
+ }
26782
26850
  log(`[Antigravity] User set up, project: ${projectId}, tier: ${resolvedTier}`);
26783
26851
  return { projectId, tierId: resolvedTier };
26784
26852
  }
26785
26853
  function getAntigravityTierDisplayName() {
26854
+ syncAccountCaches();
26786
26855
  if (!cachedAgTierName && !cachedAgTierId)
26787
26856
  return "Antigravity";
26788
26857
  const id = cachedAgTierId || "";
@@ -26872,6 +26941,9 @@ async function fetchAntigravityAvailableModelsRaw(accessToken, projectId, opts)
26872
26941
  }
26873
26942
  }
26874
26943
  async function getServedAntigravityModels(accessToken, projectId, opts) {
26944
+ syncAccountCaches();
26945
+ const lineage = lineageOfToken(accessToken);
26946
+ const ownList = lineage === cachedAgLineage;
26875
26947
  const now = Date.now();
26876
26948
  const version = antigravityClientVersion();
26877
26949
  if (agServedCache && agServedCacheVersion !== version) {
@@ -26879,9 +26951,10 @@ async function getServedAntigravityModels(accessToken, projectId, opts) {
26879
26951
  agServedCache = null;
26880
26952
  agServedCacheAt = 0;
26881
26953
  }
26882
- if (!opts?.force && agServedCache && now - agServedCacheAt < SERVED_MODELS_TTL_MS) {
26954
+ if (!opts?.force && ownList && agServedCache && now - agServedCacheAt < SERVED_MODELS_TTL_MS) {
26883
26955
  return agServedCache;
26884
26956
  }
26957
+ const prior = ownList ? agServedCache : null;
26885
26958
  try {
26886
26959
  const raw = await fetchAntigravityAvailableModelsRaw(accessToken, projectId);
26887
26960
  if (raw.kind === "unreachable") {
@@ -26929,7 +27002,7 @@ async function getServedAntigravityModels(accessToken, projectId, opts) {
26929
27002
  deprecatedReplacements[oldId] = info.newModelId;
26930
27003
  }
26931
27004
  const agentModelIds = flattenAgentModelSorts(data.agentModelSorts);
26932
- agServedCache = {
27005
+ const served = {
26933
27006
  servedIds,
26934
27007
  defaultId,
26935
27008
  meta,
@@ -26937,26 +27010,34 @@ async function getServedAntigravityModels(accessToken, projectId, opts) {
26937
27010
  deprecatedReplacements,
26938
27011
  ...agentModelIds ? { agentModelIds } : {}
26939
27012
  };
27013
+ if (!mayPublishFor(lineage)) {
27014
+ log("[Antigravity] Token lineage changed during discovery; the result is not cached.");
27015
+ return served;
27016
+ }
27017
+ agServedCache = served;
26940
27018
  agServedCacheAt = now;
26941
27019
  agServedCacheVersion = raw.clientVersion;
26942
- return agServedCache;
27020
+ return served;
26943
27021
  }
26944
27022
  }
26945
27023
  } catch (err) {
26946
27024
  log(`[Antigravity] fetchAvailableModels error: ${err}`);
26947
27025
  }
26948
- if (agServedCache)
26949
- return agServedCache;
27026
+ if (prior)
27027
+ return prior;
26950
27028
  return { servedIds: [], defaultId: null, meta: {} };
26951
27029
  }
26952
27030
  function peekServedAntigravityModels() {
26953
27031
  if (!agServedCache || agServedCacheVersion !== antigravityClientVersion())
26954
27032
  return null;
27033
+ if (cachedAgLineage !== currentAntigravityTokenLineage())
27034
+ return null;
26955
27035
  return agServedCache;
26956
27036
  }
26957
- var ANTIGRAVITY_DEFAULT_HOST = "https://daily-cloudcode-pa.googleapis.com", SERVED_MODELS_TTL_MS, ANTIGRAVITY_IDE_TYPE = "ANTIGRAVITY", AGY_FALLBACK_CLIENT_VERSION = "1.1.9", cachedAgProjectId = null, cachedAgTierId = null, cachedAgTierName = null, agServedCache = null, agServedCacheAt = 0, agServedCacheVersion = null;
27037
+ var ANTIGRAVITY_DEFAULT_HOST = "https://daily-cloudcode-pa.googleapis.com", SERVED_MODELS_TTL_MS, ANTIGRAVITY_IDE_TYPE = "ANTIGRAVITY", AGY_FALLBACK_CLIENT_VERSION = "1.1.9", cachedAgProjectId = null, cachedAgTierId = null, cachedAgTierName = null, cachedAgLineage = null, agServedCache = null, agServedCacheAt = 0, agServedCacheVersion = null;
26958
27038
  var init_antigravity_user = __esm(() => {
26959
27039
  init_logger();
27040
+ init_antigravity_token();
26960
27041
  SERVED_MODELS_TTL_MS = 10 * 60 * 1000;
26961
27042
  });
26962
27043
 
@@ -27318,7 +27399,7 @@ var init_credential_file = __esm(() => {
27318
27399
 
27319
27400
  // src/auth/oauth-manager.ts
27320
27401
  import { exec as exec2 } from "child_process";
27321
- import { createHash as createHash3, randomBytes as randomBytes5 } from "crypto";
27402
+ import { createHash as createHash4, randomBytes as randomBytes5 } from "crypto";
27322
27403
  import { existsSync as existsSync12, mkdirSync as mkdirSync10, unlinkSync as unlinkSync5 } from "fs";
27323
27404
  import { homedir as homedir13 } from "os";
27324
27405
  import { join as join13 } from "path";
@@ -27421,7 +27502,7 @@ class OAuthManager {
27421
27502
  return randomBytes5(64).toString("base64url");
27422
27503
  }
27423
27504
  generateCodeChallenge(verifier) {
27424
- return createHash3("sha256").update(verifier).digest("base64url");
27505
+ return createHash4("sha256").update(verifier).digest("base64url");
27425
27506
  }
27426
27507
  async openBrowser(url, message) {
27427
27508
  try {
@@ -28787,9 +28868,9 @@ var init_registry2 = __esm(() => {
28787
28868
  });
28788
28869
 
28789
28870
  // src/code-mode/ids.ts
28790
- import { createHash as createHash4 } from "crypto";
28871
+ import { createHash as createHash5 } from "crypto";
28791
28872
  function sha256Hex(input) {
28792
- return createHash4("sha256").update(input).digest("hex");
28873
+ return createHash5("sha256").update(input).digest("hex");
28793
28874
  }
28794
28875
  function accountKeyFromBinding(binding) {
28795
28876
  const auth = binding?.auth;
@@ -28827,8 +28908,8 @@ function decodeNestedId(id) {
28827
28908
  return { execKey: match[1], seq: Number(match[2]) };
28828
28909
  }
28829
28910
  function uuidV5(namespace, name) {
28830
- const ns = createHash4("sha256").update(namespace).digest().subarray(0, 16);
28831
- const hash = createHash4("sha1").update(ns).update(name).digest();
28911
+ const ns = createHash5("sha256").update(namespace).digest().subarray(0, 16);
28912
+ const hash = createHash5("sha1").update(ns).update(name).digest();
28832
28913
  const bytes = Buffer.from(hash.subarray(0, 16));
28833
28914
  bytes[6] = bytes[6] & 15 | 80;
28834
28915
  bytes[8] = bytes[8] & 63 | 128;
@@ -29190,7 +29271,7 @@ var init_exec_tool = __esm(() => {
29190
29271
  });
29191
29272
 
29192
29273
  // src/code-mode/hashes.ts
29193
- import { createHash as createHash5 } from "crypto";
29274
+ import { createHash as createHash6 } from "crypto";
29194
29275
  function withoutCacheMarkers(value) {
29195
29276
  if (Array.isArray(value))
29196
29277
  return value.map(withoutCacheMarkers);
@@ -29213,7 +29294,7 @@ function canonicalJson(value) {
29213
29294
  return `{${body}}`;
29214
29295
  }
29215
29296
  function inputHash(input) {
29216
- return createHash5("sha256").update(canonicalJson(input ?? {})).digest("hex");
29297
+ return createHash6("sha256").update(canonicalJson(input ?? {})).digest("hex");
29217
29298
  }
29218
29299
  function compareIds(a, b) {
29219
29300
  const da = decodeNestedId(a);
@@ -29224,7 +29305,7 @@ function compareIds(a, b) {
29224
29305
  }
29225
29306
  function batchHash(entries) {
29226
29307
  const ordered = [...entries].sort((a, b) => compareIds(a.toolUseId, b.toolUseId));
29227
- const hash = createHash5("sha256");
29308
+ const hash = createHash6("sha256");
29228
29309
  for (const entry of ordered) {
29229
29310
  const canonical = entry.result ? canonicalJson([
29230
29311
  entry.toolUseId,
@@ -29238,7 +29319,7 @@ function batchHash(entries) {
29238
29319
  return hash.digest("hex");
29239
29320
  }
29240
29321
  function completionKey(batchHashes) {
29241
- const hash = createHash5("sha256");
29322
+ const hash = createHash6("sha256");
29242
29323
  for (const h of batchHashes) {
29243
29324
  hash.update(h);
29244
29325
  hash.update(`
@@ -33371,9 +33452,9 @@ var init_prelude = __esm(() => {
33371
33452
  });
33372
33453
 
33373
33454
  // src/code-mode/sandbox/script-runtime.ts
33374
- import { createHash as createHash6 } from "crypto";
33455
+ import { createHash as createHash7 } from "crypto";
33375
33456
  function seedNumber(seed) {
33376
- return createHash6("sha256").update(seed).digest().readUInt32BE(0);
33457
+ return createHash7("sha256").update(seed).digest().readUInt32BE(0);
33377
33458
  }
33378
33459
  function utf8Bytes2(text) {
33379
33460
  return Buffer.byteLength(text, "utf8");
@@ -33919,9 +34000,9 @@ var init_script_runtime = __esm(() => {
33919
34000
  });
33920
34001
 
33921
34002
  // src/code-mode/turn-records.ts
33922
- import { createHash as createHash7 } from "crypto";
34003
+ import { createHash as createHash8 } from "crypto";
33923
34004
  function sha256Hex2(text) {
33924
- return createHash7("sha256").update(text).digest("hex");
34005
+ return createHash8("sha256").update(text).digest("hex");
33925
34006
  }
33926
34007
  function recordKey(sessionKey, anchor) {
33927
34008
  return `${sessionKey}\x00${anchor}`;
@@ -34758,9 +34839,9 @@ var init_tool_results = __esm(() => {
34758
34839
  });
34759
34840
 
34760
34841
  // src/code-mode/transliterate.ts
34761
- import { createHash as createHash8 } from "crypto";
34842
+ import { createHash as createHash9 } from "crypto";
34762
34843
  function transliteratedCallId(firstToolUseId) {
34763
- return `call_${createHash8("sha256").update(firstToolUseId).digest("hex").slice(0, 32)}`;
34844
+ return `call_${createHash9("sha256").update(firstToolUseId).digest("hex").slice(0, 32)}`;
34764
34845
  }
34765
34846
  function callExpression(use, names) {
34766
34847
  const name = typeof use.name === "string" ? use.name : "";
@@ -34834,12 +34915,12 @@ function relayNestedInput(block, repair) {
34834
34915
  }
34835
34916
 
34836
34917
  // src/code-mode/input-builder.ts
34837
- import { createHash as createHash9 } from "crypto";
34918
+ import { createHash as createHash10 } from "crypto";
34838
34919
  function blocksOf2(message) {
34839
34920
  return message && Array.isArray(message.content) ? message.content : [];
34840
34921
  }
34841
34922
  function sha256Hex3(text) {
34842
- return createHash9("sha256").update(text).digest("hex");
34923
+ return createHash10("sha256").update(text).digest("hex");
34843
34924
  }
34844
34925
  function reasoningKey(item) {
34845
34926
  if (typeof item.id === "string" && item.id)
@@ -35590,7 +35671,7 @@ var init_stores = __esm(() => {
35590
35671
  });
35591
35672
 
35592
35673
  // src/code-mode/request.ts
35593
- import { createHash as createHash10 } from "crypto";
35674
+ import { createHash as createHash11 } from "crypto";
35594
35675
  function isLiteFallbackActive(model, now = Date.now()) {
35595
35676
  const until = liteFallbackUntil.get(model.toLowerCase());
35596
35677
  if (until === undefined)
@@ -35633,7 +35714,7 @@ function applyCodeModeToPayload(payload, ctx) {
35633
35714
  if (shape === "lite") {
35634
35715
  const reasoning = liteReasoning(payload, ctx.modelInfo);
35635
35716
  if (reasoning) {
35636
- const toolsHash = createHash10("sha256").update(JSON.stringify(ctx.execTool)).digest("hex");
35717
+ const toolsHash = createHash11("sha256").update(JSON.stringify(ctx.execTool)).digest("hex");
35637
35718
  payload.reasoning = reasoning;
35638
35719
  delete payload.tools;
35639
35720
  delete payload.instructions;
@@ -37911,7 +37992,7 @@ var init_output_capture = __esm(() => {
37911
37992
  });
37912
37993
 
37913
37994
  // src/hooks/telemetry/aggregate.ts
37914
- import { createHash as createHash11, randomBytes as randomBytes6 } from "crypto";
37995
+ import { createHash as createHash12, randomBytes as randomBytes6 } from "crypto";
37915
37996
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync11 } from "fs";
37916
37997
  import { homedir as homedir19 } from "os";
37917
37998
  import { dirname as dirname11, join as join19 } from "path";
@@ -37935,7 +38016,7 @@ function contextFillPct(peakTokens, window2 = enforcedContextWindow) {
37935
38016
  return Math.min(100, Math.max(0, Math.round(peakTokens / window2 * 100)));
37936
38017
  }
37937
38018
  function hashSessionId(rawSessionId, model) {
37938
- return createHash11("sha256").update(`${SESSION_SALT}:${rawSessionId}:${model}`).digest("hex");
38019
+ return createHash12("sha256").update(`${SESSION_SALT}:${rawSessionId}:${model}`).digest("hex");
37939
38020
  }
37940
38021
  function setTelemetryConsent(value) {
37941
38022
  consent = value;
@@ -42128,7 +42209,7 @@ class AntigravityCredentialProvider {
42128
42209
  const token = readSharedAntigravityToken();
42129
42210
  if (!token)
42130
42211
  return;
42131
- const lineage = token.refresh_token ? `refresh:${token.refresh_token}` : token.access_token ? `access:${token.access_token}` : undefined;
42212
+ const lineage = antigravityTokenLineageMaterial(token);
42132
42213
  return lineage ? `${lineage}
42133
42214
  ${antigravityHost()}` : undefined;
42134
42215
  }
@@ -44741,7 +44822,7 @@ var init_dist12 = __esm(() => {
44741
44822
 
44742
44823
  // src/auth/codex-pkce.ts
44743
44824
  import { exec as exec4 } from "child_process";
44744
- import { createHash as createHash12, randomBytes as randomBytes7 } from "crypto";
44825
+ import { createHash as createHash13, randomBytes as randomBytes7 } from "crypto";
44745
44826
  import { createServer } from "http";
44746
44827
  import { promisify as promisify3 } from "util";
44747
44828
  function loginClaims(idToken) {
@@ -44853,7 +44934,7 @@ function waitForCallback(options, deps) {
44853
44934
  async function loginCodexPkce(deps = {}) {
44854
44935
  log("[CodexOAuth] Starting OAuth login flow");
44855
44936
  const verifier = randomBytes7(64).toString("base64url");
44856
- const challenge = createHash12("sha256").update(verifier).digest("base64url");
44937
+ const challenge = createHash13("sha256").update(verifier).digest("base64url");
44857
44938
  const state = randomBytes7(32).toString("base64url");
44858
44939
  const options = {
44859
44940
  port: 1455,
@@ -48533,10 +48614,6 @@ var init_dynamic_models_catalog_store = __esm(() => {
48533
48614
 
48534
48615
  // src/providers/dynamic-models-catalog.ts
48535
48616
  import { createHmac as createHmac2, randomBytes as randomBytes11 } from "crypto";
48536
- function isPersistedListProvider(provider) {
48537
- const def = getProviderByName(provider);
48538
- return def !== undefined && def.modelDiscovery !== undefined && !def.isLocal && (def.tier === "subscription" || def.tier === "dynamic-subscription");
48539
- }
48540
48617
  function nowOf2(opts) {
48541
48618
  return opts?.now ? opts.now() : Date.now();
48542
48619
  }
@@ -48740,6 +48817,7 @@ var init_dynamic_models_catalog = __esm(() => {
48740
48817
  inFlight4 = new Map;
48741
48818
  listeners = new Set;
48742
48819
  credentials.onInvalidate((name) => {
48820
+ invalidateModelDiscovery(name);
48743
48821
  if (name) {
48744
48822
  identityMemo.delete(name);
48745
48823
  liveMemory.delete(name);
@@ -50183,6 +50261,7 @@ var init_devin_request = __esm(() => {
50183
50261
  });
50184
50262
 
50185
50263
  // src/providers/devin/devin-models.ts
50264
+ import { createHash as createHash14 } from "crypto";
50186
50265
  function unaryMetadata(apiKey) {
50187
50266
  return msg(bytes(1, "chisel"), bytes(2, DEVIN_CLI_VERSION), bytes(3, apiKey), bytes(4, "en"), bytes(5, process.platform), bytes(7, DEVIN_CLI_VERSION));
50188
50267
  }
@@ -50370,20 +50449,25 @@ function decodeAllowedUids(body) {
50370
50449
  }
50371
50450
  return uids;
50372
50451
  }
50452
+ function hashApiKey(apiKey) {
50453
+ return createHash14("sha256").update(apiKey).digest("hex");
50454
+ }
50373
50455
  async function getServedDevinModels(opts) {
50374
50456
  const now = Date.now();
50375
- if (!opts?.force && modelsCatalogCache && now - modelsCatalogCacheAt < MODELS_CATALOG_TTL_MS)
50376
- return modelsCatalogCache;
50377
50457
  const apiKey = opts?.apiKey ?? readDevinApiKey();
50378
50458
  if (!apiKey)
50379
- return modelsCatalogCache ?? [];
50459
+ return [];
50460
+ const keyHash = hashApiKey(apiKey);
50461
+ const sameKeyCache = modelsCatalogCacheKeyHash === keyHash ? modelsCatalogCache : null;
50462
+ if (!opts?.force && sameKeyCache && now - modelsCatalogCacheAt < MODELS_CATALOG_TTL_MS)
50463
+ return sameKeyCache;
50380
50464
  try {
50381
50465
  const [configs, allowed] = await Promise.all([
50382
50466
  fetchDevinModelConfigs(apiKey),
50383
50467
  fetchDevinAllowedUids(apiKey)
50384
50468
  ]);
50385
50469
  if (configs.length === 0)
50386
- return modelsCatalogCache ?? [];
50470
+ return sameKeyCache ?? [];
50387
50471
  const entitled = new Set(allowed);
50388
50472
  const served = configs.filter((config) => config.contextWindow > 0 && (entitled.size === 0 || entitled.has(config.uid)));
50389
50473
  if (entitled.size === 0) {
@@ -50391,13 +50475,14 @@ async function getServedDevinModels(opts) {
50391
50475
  }
50392
50476
  modelsCatalogCache = served;
50393
50477
  modelsCatalogCacheAt = now;
50478
+ modelsCatalogCacheKeyHash = keyHash;
50394
50479
  return served;
50395
50480
  } catch (err) {
50396
50481
  log(`[Devin] served-model discovery error: ${err}`);
50397
- return modelsCatalogCache ?? [];
50482
+ return sameKeyCache ?? [];
50398
50483
  }
50399
50484
  }
50400
- var MODEL_CONFIGS_PATH = "/exa.api_server_pb.ApiServerService/GetCliModelConfigs", TEAM_SETTINGS_PATH = "/exa.seat_management_pb.SeatManagementService/GetCliTeamSettings", MODELS_CATALOG_TTL_MS, UNARY_TIMEOUT_MS = 1e4, modelsCatalogCache = null, modelsCatalogCacheAt = 0;
50485
+ var MODEL_CONFIGS_PATH = "/exa.api_server_pb.ApiServerService/GetCliModelConfigs", TEAM_SETTINGS_PATH = "/exa.seat_management_pb.SeatManagementService/GetCliTeamSettings", MODELS_CATALOG_TTL_MS, UNARY_TIMEOUT_MS = 1e4, modelsCatalogCache = null, modelsCatalogCacheAt = 0, modelsCatalogCacheKeyHash = null;
50401
50486
  var init_devin_models = __esm(() => {
50402
50487
  init_logger();
50403
50488
  init_devin_credentials();
@@ -50863,6 +50948,7 @@ var init_model_discovery_builtins = __esm(() => {
50863
50948
  });
50864
50949
 
50865
50950
  // src/providers/model-discovery.ts
50951
+ import { createHash as createHash15 } from "crypto";
50866
50952
  function toModelsCatalogEntry(model) {
50867
50953
  const { id, ...rest } = model;
50868
50954
  return { wireId: id, ...rest };
@@ -50873,6 +50959,10 @@ function registerModelDiscoveryFetcher(format, fetcher) {
50873
50959
  function getModelDiscoveryFetcher(format) {
50874
50960
  return _fetchers.get(format);
50875
50961
  }
50962
+ async function accountFingerprint(providerName) {
50963
+ const identity = await credentials.accountIdentity(providerName, { allowOpPrompt: false });
50964
+ return identity ? createHash15("sha256").update(identity).digest("hex") : undefined;
50965
+ }
50876
50966
  function recordFailure(failure) {
50877
50967
  _failures.set(failure.provider, failure);
50878
50968
  log(`[model-discovery:${failure.provider}] ${describeDiscoveryFailure(failure)}`);
@@ -50910,15 +51000,20 @@ function describeDiscoveryFailure(failure) {
50910
51000
  return `the endpoint answered${at} but listed no models`;
50911
51001
  }
50912
51002
  }
51003
+ function invalidationCount(providerName) {
51004
+ return invalidationsOfAll + (invalidationsByProvider.get(providerName) ?? 0);
51005
+ }
50913
51006
  function invalidateModelDiscovery(provider) {
50914
51007
  if (provider) {
50915
51008
  _cache2.delete(provider);
50916
51009
  _failures.delete(provider);
50917
51010
  coldRefreshes.delete(provider);
51011
+ invalidationsByProvider.set(provider, (invalidationsByProvider.get(provider) ?? 0) + 1);
50918
51012
  } else {
50919
51013
  _cache2.clear();
50920
51014
  _failures.clear();
50921
51015
  coldRefreshes.clear();
51016
+ invalidationsOfAll++;
50922
51017
  }
50923
51018
  }
50924
51019
  function registryModelsEndpoint(providerName, def) {
@@ -51041,7 +51136,6 @@ async function discoverViaFetcher(providerName, format) {
51041
51136
  }
51042
51137
  _failures.delete(providerName);
51043
51138
  log(`[model-discovery:${providerName}] discovered ${models.length} models`);
51044
- _cache2.set(providerName, { models, expiresAt: Date.now() + CACHE_TTL_MS2 });
51045
51139
  return { kind: "served", models };
51046
51140
  }
51047
51141
  async function discoverProviderModelsCatalog(providerName) {
@@ -51075,9 +51169,32 @@ function peekDiscoveredModels(providerName) {
51075
51169
  return cached && cached.expiresAt > Date.now() ? cached.models : undefined;
51076
51170
  }
51077
51171
  async function discoverEveryServedModel(providerName) {
51172
+ if (!getProviderByName(providerName)?.modelDiscovery) {
51173
+ return { kind: "unsupported", reason: "no-descriptor" };
51174
+ }
51175
+ const invalidationsBefore = invalidationCount(providerName);
51176
+ const perAccount = isPersistedListProvider(providerName);
51177
+ const accountBefore = perAccount ? await accountFingerprint(providerName) : undefined;
51078
51178
  const cached = _cache2.get(providerName);
51079
- if (cached && cached.expiresAt > Date.now())
51179
+ if (cached && cached.expiresAt > Date.now() && cached.account === accountBefore) {
51080
51180
  return { kind: "served", models: cached.models };
51181
+ }
51182
+ const outcome = await fetchServedModels(providerName);
51183
+ if (outcome.kind !== "served")
51184
+ return outcome;
51185
+ const accountAfter = perAccount ? await accountFingerprint(providerName) : undefined;
51186
+ if (accountBefore && accountAfter && accountBefore !== accountAfter)
51187
+ return outcome;
51188
+ if (invalidationCount(providerName) !== invalidationsBefore)
51189
+ return outcome;
51190
+ _cache2.set(providerName, {
51191
+ models: outcome.models,
51192
+ expiresAt: Date.now() + CACHE_TTL_MS2,
51193
+ account: accountAfter ?? accountBefore
51194
+ });
51195
+ return outcome;
51196
+ }
51197
+ async function fetchServedModels(providerName) {
51081
51198
  const def = getProviderByName(providerName);
51082
51199
  const descriptor = def?.modelDiscovery;
51083
51200
  if (!def || !descriptor)
@@ -51171,7 +51288,6 @@ async function discoverEveryServedModel(providerName) {
51171
51288
  const models = parsed.models;
51172
51289
  _failures.delete(providerName);
51173
51290
  log(`[model-discovery:${providerName}] discovered ${models.length} models from ${endpoint}: ` + models.map((m) => `${m.id}(${m.contextWindow ?? "?"})`).join(", "));
51174
- _cache2.set(providerName, { models, expiresAt: Date.now() + CACHE_TTL_MS2 });
51175
51291
  return { kind: "served", models };
51176
51292
  }
51177
51293
  async function discoverProviderModels(providerName) {
@@ -51234,7 +51350,7 @@ function rankDiscoveredModels(models) {
51234
51350
  return diff !== 0 ? diff : compareByReleaseDateDesc(a, b);
51235
51351
  });
51236
51352
  }
51237
- var _fetchers, CACHE_TTL_MS2, FETCH_TIMEOUT_MS3 = 5000, _cache2, _failures, coldRefreshes, MIN_CREATED_SECONDS = 946684800, MAX_CREATED_SECONDS = 4102444800, CONTINUATION_FIELDS, LIVE_DISCOVERY_BOUND_MS = 2000;
51353
+ var _fetchers, CACHE_TTL_MS2, FETCH_TIMEOUT_MS3 = 5000, _cache2, _failures, coldRefreshes, invalidationsByProvider, invalidationsOfAll = 0, MIN_CREATED_SECONDS = 946684800, MAX_CREATED_SECONDS = 4102444800, CONTINUATION_FIELDS, LIVE_DISCOVERY_BOUND_MS = 2000;
51238
51354
  var init_model_discovery = __esm(() => {
51239
51355
  init_authority();
51240
51356
  init_logger();
@@ -51245,6 +51361,7 @@ var init_model_discovery = __esm(() => {
51245
51361
  _cache2 = new Map;
51246
51362
  _failures = new Map;
51247
51363
  coldRefreshes = new Map;
51364
+ invalidationsByProvider = new Map;
51248
51365
  CONTINUATION_FIELDS = ["has_more", "next", "next_page", "next_page_token"];
51249
51366
  });
51250
51367
 
@@ -59790,12 +59907,12 @@ var init_ollamacloud = __esm(() => {
59790
59907
  });
59791
59908
 
59792
59909
  // src/providers/transport/conversation-key.ts
59793
- import { createHash as createHash13, randomBytes as randomBytes13 } from "crypto";
59910
+ import { createHash as createHash16, randomBytes as randomBytes13 } from "crypto";
59794
59911
  function conversationKey(claudeRequest) {
59795
59912
  const sessionId = extractSessionId(claudeRequest);
59796
59913
  if (!sessionId)
59797
59914
  return `claudish_${FALLBACK_CONVERSATION_KEY}`;
59798
- return `claudish_${createHash13("sha256").update(sessionId).digest("hex").slice(0, 32)}`;
59915
+ return `claudish_${createHash16("sha256").update(sessionId).digest("hex").slice(0, 32)}`;
59799
59916
  }
59800
59917
  var FALLBACK_CONVERSATION_KEY;
59801
59918
  var init_conversation_key = __esm(() => {
@@ -61315,6 +61432,10 @@ function getProviderByName(name) {
61315
61432
  return builtin;
61316
61433
  return getRuntimeProviders().get(name);
61317
61434
  }
61435
+ function isPersistedListProvider(provider) {
61436
+ const def = getProviderByName(provider);
61437
+ return def !== undefined && def.modelDiscovery !== undefined && !def.isLocal && (def.tier === "subscription" || def.tier === "dynamic-subscription");
61438
+ }
61318
61439
  function getApiKeyInfo(providerName) {
61319
61440
  const def = getProviderByName(providerName);
61320
61441
  if (!def)
@@ -74653,14 +74774,14 @@ var init_prehydrate = __esm(() => {
74653
74774
  });
74654
74775
 
74655
74776
  // src/auth/claude-code-facts.ts
74656
- import { createHash as createHash14 } from "crypto";
74777
+ import { createHash as createHash17 } from "crypto";
74657
74778
  import { homedir as homedir33 } from "os";
74658
74779
  import { isAbsolute as isAbsolute2, resolve as resolve4 } from "path";
74659
74780
  function defaultConfigDir(env) {
74660
74781
  return resolve4(env.HOME || homedir33(), ".claude");
74661
74782
  }
74662
74783
  function configDirHash(configDir) {
74663
- return createHash14("sha256").update(configDir).digest("hex").slice(0, 8);
74784
+ return createHash17("sha256").update(configDir).digest("hex").slice(0, 8);
74664
74785
  }
74665
74786
  function claudeCodeKeychainService(env = process.env) {
74666
74787
  const raw = env.CLAUDE_CONFIG_DIR?.trim();
@@ -92966,8 +93087,29 @@ function bodyToForward(c, payload) {
92966
93087
  const inbound = c.get(INBOUND_BODY_KEY);
92967
93088
  return inbound !== undefined && inbound.canonical === serialized ? inbound.raw : serialized;
92968
93089
  }
92969
- var ALLOWED_NAMES, HOP_BY_HOP, INTERNAL_PREFIX = "x-claudish-", ALLOWED_QUERY_NAMES, INBOUND_BODY_KEY = "inboundBody";
93090
+ async function buildForwardRequest(c, payload, endpoint, fallbackKey) {
93091
+ const headers = {
93092
+ ...requestHeadersToForward(c.req.raw.headers),
93093
+ ...inboundAuthHeaders(c.req.raw.headers)
93094
+ };
93095
+ if (headers.authorization && CLAUDE_LOGIN_BEARER.test(headers.authorization)) {
93096
+ delete headers["x-api-key"];
93097
+ }
93098
+ headers["content-type"] = "application/json";
93099
+ if (!headers["anthropic-version"])
93100
+ headers["anthropic-version"] = "2023-06-01";
93101
+ if (!headers.authorization && !headers["x-api-key"]) {
93102
+ const key = await fallbackKey();
93103
+ if (key)
93104
+ headers["x-api-key"] = key;
93105
+ }
93106
+ const url = `${endpoint}${forwardedSearch(c)}`;
93107
+ addSigningSecrets(c, credentialValuesFromRequest(headers, url));
93108
+ return { headers, url, body: bodyToForward(c, payload) };
93109
+ }
93110
+ var ALLOWED_NAMES, HOP_BY_HOP, INTERNAL_PREFIX = "x-claudish-", ALLOWED_QUERY_NAMES, INBOUND_BODY_KEY = "inboundBody", CLAUDE_LOGIN_BEARER;
92970
93111
  var init_anthropic_forward = __esm(() => {
93112
+ init_call_context();
92971
93113
  ALLOWED_NAMES = new Set([
92972
93114
  "authorization",
92973
93115
  "x-api-key",
@@ -93003,6 +93145,7 @@ var init_anthropic_forward = __esm(() => {
93003
93145
  "content-length"
93004
93146
  ]);
93005
93147
  ALLOWED_QUERY_NAMES = new Set(["beta"]);
93148
+ CLAUDE_LOGIN_BEARER = /^Bearer\s+sk-ant-oat\d+-/i;
93006
93149
  });
93007
93150
 
93008
93151
  // src/handlers/shared/thinking-signature.ts
@@ -93095,36 +93238,26 @@ class NativeHandler {
93095
93238
  }
93096
93239
  async handle(c, incoming) {
93097
93240
  const payload = await this.applyRequestHooks(c, incoming);
93098
- const headers = {
93099
- ...requestHeadersToForward(c.req.raw.headers),
93100
- ...inboundAuthHeaders(c.req.raw.headers)
93101
- };
93102
93241
  const target = payload.model;
93103
93242
  const strippedThinking = stripUnsignedThinkingBlocks(payload.messages);
93104
93243
  if (strippedThinking > 0) {
93105
93244
  log(`[Native] stripped ${strippedThinking} unsigned thinking block(s) from history for ${target} (foreign-provider origin)`);
93106
93245
  }
93107
93246
  const advisorSwapped = c.get(ADVISOR_SWAPPED_CONTEXT_KEY) === true;
93247
+ const inboundAuth = inboundAuthHeaders(c.req.raw.headers);
93108
93248
  log(`
93109
93249
  === [NATIVE] Claude Code \u2192 Anthropic API Request ===`);
93110
- log(`[Native] x-api-key: ${headers["x-api-key"] ? maskCredential(headers["x-api-key"]) : "(not set)"}`);
93111
- log(`[Native] authorization: ${headers.authorization ? maskCredential(headers.authorization) : "(not set)"}`);
93250
+ log(`[Native] x-api-key: ${inboundAuth["x-api-key"] ? maskCredential(inboundAuth["x-api-key"]) : "(not set)"}`);
93251
+ log(`[Native] authorization: ${inboundAuth.authorization ? maskCredential(inboundAuth.authorization) : "(not set)"}`);
93112
93252
  log(`Request body (Model: ${target}):`);
93113
93253
  log(`=== End Request ===
93114
93254
  `);
93115
- headers["content-type"] = "application/json";
93116
- if (!headers["anthropic-version"])
93117
- headers["anthropic-version"] = "2023-06-01";
93118
- if (!headers.authorization && !headers["x-api-key"]) {
93119
- let fallbackKey = this.apiKey;
93120
- if (!fallbackKey) {
93121
- const auth = await credentials.getRequestAuth("native-anthropic", { model: target });
93122
- fallbackKey = auth.headers["x-api-key"];
93123
- }
93124
- if (fallbackKey) {
93125
- headers["x-api-key"] = fallbackKey;
93126
- }
93127
- }
93255
+ const { headers, url, body } = await buildForwardRequest(c, payload, `${this.baseUrl}/v1/messages`, async () => {
93256
+ if (this.apiKey)
93257
+ return this.apiKey;
93258
+ const auth = await credentials.getRequestAuth("native-anthropic", { model: target });
93259
+ return auth.headers["x-api-key"];
93260
+ });
93128
93261
  const incomingBeta = headers["anthropic-beta"];
93129
93262
  if (incomingBeta && advisorSwapped) {
93130
93263
  const { stripped, changed } = stripAdvisorBeta(incomingBeta);
@@ -93141,9 +93274,6 @@ class NativeHandler {
93141
93274
  else
93142
93275
  delete headers["anthropic-beta"];
93143
93276
  }
93144
- const url = `${this.baseUrl}/v1/messages${forwardedSearch(c)}`;
93145
- addSigningSecrets(c, credentialValuesFromRequest(headers, url));
93146
- const body = bodyToForward(c, payload);
93147
93277
  try {
93148
93278
  const anthropicResponse = await fetch(url, {
93149
93279
  method: "POST",
@@ -93298,7 +93428,6 @@ var init_native_handler = __esm(() => {
93298
93428
  init_native_handler_advisor();
93299
93429
  init_anthropic_error();
93300
93430
  init_anthropic_forward();
93301
- init_call_context();
93302
93431
  });
93303
93432
 
93304
93433
  // src/hooks/seam-hooks.ts
@@ -94350,43 +94479,31 @@ ${plan.hint}` : `[Route] ${plan.reason}`;
94350
94479
  });
94351
94480
  app.post("/v1/messages/count_tokens", async (c) => {
94352
94481
  try {
94353
- const body = await c.req.json();
94482
+ const rawBody = await c.req.text();
94483
+ const body = JSON.parse(rawBody);
94484
+ recordInboundBody(c, rawBody, body);
94354
94485
  if (typeof body?.model !== "string" || body.model.length === 0) {
94355
94486
  return c.json(wrapAnthropicError(400, "missing required field: model"), 400);
94356
94487
  }
94357
94488
  const handler = await getHandlerForRequest(body.model);
94358
94489
  if (handler instanceof NativeHandler) {
94359
- const inbound = c.req.header();
94360
- const headers = {
94361
- "Content-Type": "application/json",
94362
- "anthropic-version": inbound["anthropic-version"] || "2023-06-01"
94363
- };
94364
- if (inbound.authorization)
94365
- headers.authorization = inbound.authorization;
94366
- if (inbound["x-api-key"])
94367
- headers["x-api-key"] = inbound["x-api-key"];
94368
- if (inbound["anthropic-beta"])
94369
- headers["anthropic-beta"] = inbound["anthropic-beta"];
94370
- if (!inbound.authorization && !inbound["x-api-key"]) {
94371
- let fallbackKey = anthropicApiKey;
94372
- if (!fallbackKey) {
94373
- try {
94374
- const auth = await credentials.getRequestAuth("native-anthropic", {
94375
- model: body.model
94376
- });
94377
- fallbackKey = auth.headers["x-api-key"];
94378
- } catch (err) {
94379
- log(`[CountTokens] no resolvable Anthropic credential: ${err}`);
94380
- }
94490
+ const forward = await buildForwardRequest(c, body, resolveUpstreamUrl("https://api.anthropic.com/v1/messages/count_tokens"), async () => {
94491
+ if (anthropicApiKey)
94492
+ return anthropicApiKey;
94493
+ try {
94494
+ const auth = await credentials.getRequestAuth("native-anthropic", {
94495
+ model: body.model
94496
+ });
94497
+ return auth.headers["x-api-key"];
94498
+ } catch (err) {
94499
+ log(`[CountTokens] no resolvable Anthropic credential: ${err}`);
94500
+ return;
94381
94501
  }
94382
- if (fallbackKey)
94383
- headers["x-api-key"] = fallbackKey;
94384
- }
94385
- addSigningSecrets(c, credentialValuesFromRequest(headers));
94386
- const res = await fetch(resolveUpstreamUrl("https://api.anthropic.com/v1/messages/count_tokens"), {
94502
+ });
94503
+ const res = await fetch(forward.url, {
94387
94504
  method: "POST",
94388
- headers,
94389
- body: JSON.stringify(body)
94505
+ headers: forward.headers,
94506
+ body: forward.body
94390
94507
  });
94391
94508
  if (res.status === 401 || res.status === 403) {
94392
94509
  log(`[CountTokens] upstream ${res.status} \u2014 falling back to the local estimate`);
@@ -96400,11 +96517,12 @@ function readProcessTable() {
96400
96517
  }
96401
96518
  return tableOf(stdout, spawnedAt);
96402
96519
  }
96403
- function readProcessTableAsync() {
96520
+ function readProcessTableAsync(cancelAfterMs) {
96521
+ const options = cancelAfterMs === undefined ? PS_OPTIONS : { ...PS_OPTIONS, timeout: cancelAfterMs, killSignal: "SIGKILL" };
96404
96522
  return new Promise((resolve) => {
96405
96523
  const spawnedAt = Date.now();
96406
96524
  try {
96407
- psSpawn.execFile("ps", PS_ARGS, PS_OPTIONS, (err, stdout) => resolve(tableOf(err ? null : String(stdout), spawnedAt)));
96525
+ psSpawn.execFile("ps", PS_ARGS, options, (err, stdout) => resolve(tableOf(err ? null : String(stdout), spawnedAt)));
96408
96526
  } catch {
96409
96527
  resolve(tableOf(null, spawnedAt));
96410
96528
  }
@@ -96461,11 +96579,14 @@ function escapedDescendants(table, pgid, inGroup) {
96461
96579
  }
96462
96580
  return out;
96463
96581
  }
96582
+ function liveMembers(table, members) {
96583
+ const keys = new Set(members.map((m) => `${m.pid} ${collapse(m.lstart)}`));
96584
+ return table.filter((r) => keys.has(`${r.pid} ${r.lstart}`)).map((r) => r.pid);
96585
+ }
96464
96586
  function liveEscaped(table, snap) {
96465
96587
  if (!snap?.escaped?.length)
96466
96588
  return [];
96467
- const keys = new Set(snap.escaped.map((m) => `${m.pid} ${collapse(m.lstart)}`));
96468
- return table.filter((r) => keys.has(`${r.pid} ${r.lstart}`)).map((r) => r.pid);
96589
+ return liveMembers(table, snap.escaped);
96469
96590
  }
96470
96591
  function mergeSnapshots(a, b, table) {
96471
96592
  if (!a)
@@ -97346,8 +97467,62 @@ function waitForExit(proc, ms) {
97346
97467
  t.unref?.();
97347
97468
  });
97348
97469
  }
97470
+ function descendantsOf(table, rootPid) {
97471
+ const childrenOf = new Map;
97472
+ for (const { pid, ppid, lstart } of table) {
97473
+ const siblings = childrenOf.get(ppid);
97474
+ if (siblings)
97475
+ siblings.push({ pid, lstart });
97476
+ else
97477
+ childrenOf.set(ppid, [{ pid, lstart }]);
97478
+ }
97479
+ const seen = new Set([rootPid, process.pid]);
97480
+ const out = [];
97481
+ const queue = [rootPid];
97482
+ for (let parent = queue.shift();parent !== undefined; parent = queue.shift()) {
97483
+ for (const child of childrenOf.get(parent) ?? []) {
97484
+ if (child.pid <= 1 || seen.has(child.pid))
97485
+ continue;
97486
+ seen.add(child.pid);
97487
+ out.push(child);
97488
+ queue.push(child.pid);
97489
+ }
97490
+ }
97491
+ return out;
97492
+ }
97493
+ async function readTableWithin(budgetMs) {
97494
+ let timer;
97495
+ const table = await Promise.race([
97496
+ readProcessTableAsync(budgetMs),
97497
+ new Promise((resolve) => {
97498
+ timer = setTimeout(() => resolve(null), budgetMs);
97499
+ timer.unref?.();
97500
+ })
97501
+ ]);
97502
+ clearTimeout(timer);
97503
+ return table;
97504
+ }
97505
+ async function snapshotDescendants(rootPid, budgetMs) {
97506
+ const table = await readTableWithin(budgetMs);
97507
+ return table ? descendantsOf(table, rootPid) : [];
97508
+ }
97509
+ async function killStillLiveMembers(members, budgetMs) {
97510
+ if (members.length === 0)
97511
+ return 0;
97512
+ const table = await readTableWithin(budgetMs);
97513
+ if (!table)
97514
+ return 0;
97515
+ const pids = liveMembers(table, members);
97516
+ for (const pid of pids) {
97517
+ try {
97518
+ process.kill(pid, "SIGKILL");
97519
+ } catch {}
97520
+ }
97521
+ return pids.length;
97522
+ }
97349
97523
  var KILL_PROCESS_GROUP;
97350
97524
  var init_process_tree = __esm(() => {
97525
+ init_process_identity();
97351
97526
  KILL_PROCESS_GROUP = process.platform !== "win32";
97352
97527
  });
97353
97528
 
@@ -98841,58 +99016,61 @@ Or set CLAUDE_PATH to your custom installation:`);
98841
99016
  }
98842
99017
  log(exitSignal ? `[Claude Code] Exited from ${exitSignal} (exit code ${exitCode})` : `[Claude Code] Exited with code ${exitCode}`);
98843
99018
  releaseTerminalIsolation();
98844
- try {
98845
- unlinkSync11(tempSettingsPath);
98846
- } catch {}
98847
- signalShutdown.launcherCleanupDone();
98848
- if (signalShutdown.started())
98849
- return new Promise(() => {});
98850
- return exitCode;
99019
+ signalShutdown.removeSettingsFile();
99020
+ await signalShutdown.claudeCodeStopped();
99021
+ return signalShutdownExitCode() ?? exitCode;
98851
99022
  }
98852
99023
  function sessionOutcomeOf(exitCode) {
98853
99024
  return exitCode === 0 ? { state: "COMPLETED", reason: null, exitCode } : { state: "FAILED", reason: "child_exited", exitCode };
98854
99025
  }
98855
- function delay(ms) {
98856
- return new Promise((resolve) => {
98857
- const t = setTimeout(resolve, Math.max(0, ms));
98858
- t.unref?.();
98859
- });
99026
+ function signalShutdownExitCode() {
99027
+ return signalShutdownCode;
98860
99028
  }
98861
99029
  function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
98862
99030
  const signals = isWindows2() ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
98863
99031
  let shuttingDown = null;
98864
- let markLauncherCleanupDone = () => {};
98865
- const launcherCleanup = new Promise((resolve) => {
98866
- markLauncherCleanupDone = resolve;
98867
- });
98868
- const shutdown = async (signal) => {
98869
- const startedAt = Date.now();
99032
+ let claudeCodeStopped = Promise.resolve();
99033
+ let settingsFileRemoved = false;
99034
+ const removeSettingsFile = () => {
99035
+ if (settingsFileRemoved)
99036
+ return;
99037
+ settingsFileRemoved = true;
99038
+ try {
99039
+ unlinkSync11(tempSettingsPath);
99040
+ } catch {}
99041
+ };
99042
+ const stopClaudeCode = async () => {
98870
99043
  try {
98871
99044
  proc.kill("SIGTERM");
98872
- if (!await waitForExit(proc, SIGNAL_CHILD_EXIT_GRACE_MS)) {
98873
- log(`[claudish] Claude Code did not exit within ${SIGNAL_CHILD_EXIT_GRACE_MS} ms of SIGTERM; sending SIGKILL`);
98874
- try {
98875
- proc.kill("SIGKILL");
98876
- } catch {}
98877
- await waitForExit(proc, SIGNAL_CHILD_KILL_WAIT_MS);
99045
+ if (await waitForExit(proc, SIGNAL_CHILD_EXIT_GRACE_MS))
99046
+ return;
99047
+ log(`[claudish] Claude Code did not exit within ${SIGNAL_CHILD_EXIT_GRACE_MS} ms of SIGTERM; sending SIGKILL`);
99048
+ const killStepStartedAt = Date.now();
99049
+ const descendants = proc.pid ? await snapshotDescendants(proc.pid, SIGNAL_DESCENDANT_READ_MS) : [];
99050
+ if (proc.exitCode !== null || proc.signalCode !== null)
99051
+ return;
99052
+ let killed = 0;
99053
+ try {
99054
+ proc.kill("SIGKILL");
99055
+ } finally {
99056
+ killed = await killStillLiveMembers(descendants, SIGNAL_DESCENDANT_READ_MS);
98878
99057
  }
98879
- await Promise.race([
98880
- launcherCleanup,
98881
- delay(SIGNAL_SHUTDOWN_BUDGET_MS - (Date.now() - startedAt))
98882
- ]);
99058
+ log(`[claudish] Sent SIGKILL to Claude Code and ${killed} of ${descendants.length} descendants`);
99059
+ await waitForExit(proc, SIGNAL_CHILD_KILL_WAIT_MS - (Date.now() - killStepStartedAt));
98883
99060
  } catch (err) {
98884
99061
  log(`[claudish] Signal shutdown error: ${err}`);
98885
- } finally {
98886
- if (onCleanup) {
98887
- try {
98888
- onCleanup();
98889
- } catch {}
98890
- }
99062
+ }
99063
+ };
99064
+ const armDeadline = (code) => {
99065
+ const deadline = setTimeout(() => {
99066
+ log(`[claudish] Signal shutdown passed ${SIGNAL_SHUTDOWN_BUDGET_MS} ms; exiting`);
98891
99067
  try {
98892
- unlinkSync11(tempSettingsPath);
99068
+ onCleanup?.();
98893
99069
  } catch {}
98894
- process.exit(signalExitCode(signal));
98895
- }
99070
+ removeSettingsFile();
99071
+ process.exit(code);
99072
+ }, SIGNAL_SHUTDOWN_BUDGET_MS);
99073
+ deadline.unref?.();
98896
99074
  };
98897
99075
  claimSignalExit();
98898
99076
  for (const signal of signals) {
@@ -98902,18 +99080,19 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
98902
99080
  return;
98903
99081
  }
98904
99082
  shuttingDown = signal;
99083
+ const code = signalExitCode(signal);
99084
+ signalShutdownCode = code;
99085
+ process.exitCode = code;
99086
+ armDeadline(code);
98905
99087
  releaseTerminalIsolation();
98906
99088
  if (!quiet) {
98907
99089
  console.error(`
98908
99090
  [claudish] Received ${signal}, shutting down...`);
98909
99091
  }
98910
- shutdown(signal);
99092
+ claudeCodeStopped = stopClaudeCode();
98911
99093
  });
98912
99094
  }
98913
- return {
98914
- started: () => shuttingDown !== null,
98915
- launcherCleanupDone: () => markLauncherCleanupDone()
98916
- };
99095
+ return { removeSettingsFile, claudeCodeStopped: () => claudeCodeStopped };
98917
99096
  }
98918
99097
  async function findClaudeBinary(env = process.env) {
98919
99098
  const isWindows = process.platform === "win32";
@@ -99014,7 +99193,7 @@ var restoreTerminal = null, macosKeychainAnthropicMemo, defaultKeychainAnthropic
99014
99193
  }
99015
99194
  macosKeychainAnthropicMemo.set(memoKey, found);
99016
99195
  return found;
99017
- }, CLAUDISH_PLACEHOLDER_API_KEY = "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx", CLAUDISH_PLACEHOLDER_AUTH_TOKEN = "placeholder-token-not-used-proxy-handles-auth", STALE_TOKEN_FILE_MS, MAX_TOKEN_FILES_SCANNED = 4000, CLAUDE_CODE_DEFAULT_MAX_CONTEXT = 200000, USER_STATUS_LINE_TIMEOUT_SECONDS = 3, MIN_AUTO_COMPACT_WINDOW = 200000, MAX_AUTO_COMPACT_WINDOW = 1e6, ADVISOR_TOOL_ENV_VAR = "CLAUDE_CODE_ENABLE_EXPERIMENTAL_ADVISOR_TOOL", CLAUDISH_CHILD_ADVISOR_MODEL = "sonnet", CHILD_STDERR_NOISE, SIGNAL_CHILD_EXIT_GRACE_MS = 3000, SIGNAL_CHILD_KILL_WAIT_MS = 500, SIGNAL_SHUTDOWN_BUDGET_MS = 4000;
99196
+ }, CLAUDISH_PLACEHOLDER_API_KEY = "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx", CLAUDISH_PLACEHOLDER_AUTH_TOKEN = "placeholder-token-not-used-proxy-handles-auth", STALE_TOKEN_FILE_MS, MAX_TOKEN_FILES_SCANNED = 4000, CLAUDE_CODE_DEFAULT_MAX_CONTEXT = 200000, USER_STATUS_LINE_TIMEOUT_SECONDS = 3, MIN_AUTO_COMPACT_WINDOW = 200000, MAX_AUTO_COMPACT_WINDOW = 1e6, ADVISOR_TOOL_ENV_VAR = "CLAUDE_CODE_ENABLE_EXPERIMENTAL_ADVISOR_TOOL", CLAUDISH_CHILD_ADVISOR_MODEL = "sonnet", CHILD_STDERR_NOISE, SIGNAL_CHILD_EXIT_GRACE_MS = 2000, SIGNAL_CHILD_KILL_WAIT_MS = 500, SIGNAL_DESCENDANT_READ_MS = 200, SIGNAL_SHUTDOWN_BUDGET_MS = 4500, signalShutdownCode = null;
99018
99197
  var init_claude_runner = __esm(() => {
99019
99198
  init_model_catalog();
99020
99199
  init_claude_code_facts();
@@ -122069,14 +122248,14 @@ function reportFetchFailure(state, cache, now) {
122069
122248
  if (state === "stale") {
122070
122249
  const ageMs = now.getTime() - Date.parse(cache.lastUpdated);
122071
122250
  const ageStr = humanizeAge(ageMs);
122072
- process.stderr.write(`WARNING: Catalog stale (${ageStr}). Using cached version. Run \`claudish --models-refresh\` to retry.
122251
+ process.stderr.write(`WARNING: The ${MODEL_CATALOG_NAME} is stale (${ageStr}). Using cached version. Run \`claudish --models-refresh\` to retry.
122073
122252
  `);
122074
122253
  return "warned";
122075
122254
  }
122076
122255
  if (state === "fresh") {
122077
122256
  const ageMs = now.getTime() - Date.parse(cache.lastUpdated);
122078
122257
  const ageStr = humanizeAge(ageMs);
122079
- process.stderr.write(`WARNING: Catalog refresh failed (cache age ${ageStr}). Using cached version.
122258
+ process.stderr.write(`WARNING: Could not refresh the ${MODEL_CATALOG_NAME} (cache age ${ageStr}). Using cached version.
122080
122259
  `);
122081
122260
  return "warned";
122082
122261
  }
@@ -125166,11 +125345,18 @@ Team Status`);
125166
125345
  }
125167
125346
  finalizeStartupTrace("run", { quiet: cliConfig.quiet });
125168
125347
  let exitCode = 0;
125348
+ let diagCleaned = false;
125349
+ const cleanupDiag = () => {
125350
+ if (diagCleaned)
125351
+ return;
125352
+ diagCleaned = true;
125353
+ diag.cleanup();
125354
+ };
125169
125355
  try {
125170
- exitCode = await runClaudeWithProxy(cliConfig, proxy.url, () => diag.cleanup());
125356
+ exitCode = await runClaudeWithProxy(cliConfig, proxy.url, cleanupDiag);
125171
125357
  } finally {
125172
125358
  setDiagOutput(null);
125173
- diag.cleanup();
125359
+ cleanupDiag();
125174
125360
  if (!cliConfig.quiet) {
125175
125361
  const write = cliConfig.interactive ? console.log : console.error;
125176
125362
  write(`
@@ -125210,8 +125396,9 @@ Team Status`);
125210
125396
  console.error(`[claudish] session summary unavailable: ${e}`);
125211
125397
  }
125212
125398
  }
125399
+ exitCode = signalShutdownExitCode() ?? exitCode;
125213
125400
  const sessionLogPath = getAlwaysOnLogPath();
125214
- const quitBySignal = exitCode === 130 || exitCode === 143;
125401
+ const quitBySignal = exitCode === 130 || exitCode === 143 || signalShutdownExitCode() !== null;
125215
125402
  if (exitCode !== 0 && !quitBySignal && sessionLogPath && !cliConfig.quiet) {
125216
125403
  console.error(`
125217
125404
  [claudish] Session ended with errors (exit code ${exitCode}).`);
@@ -125226,6 +125413,6 @@ Team Status`);
125226
125413
  } catch (error) {
125227
125414
  console.error("[claudish] Fatal error:", error);
125228
125415
  console.error("[claudish] Stack:", error instanceof Error ? error.stack : "no stack");
125229
- process.exit(1);
125416
+ process.exit(signalShutdownExitCode() ?? 1);
125230
125417
  }
125231
125418
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "14.18.1",
3
+ "version": "14.18.3",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -71,10 +71,10 @@
71
71
  "ai"
72
72
  ],
73
73
  "optionalDependencies": {
74
- "@claudish/magmux-darwin-arm64": "14.18.1",
75
- "@claudish/magmux-darwin-x64": "14.18.1",
76
- "@claudish/magmux-linux-arm64": "14.18.1",
77
- "@claudish/magmux-linux-x64": "14.18.1"
74
+ "@claudish/magmux-darwin-arm64": "14.18.3",
75
+ "@claudish/magmux-darwin-x64": "14.18.3",
76
+ "@claudish/magmux-linux-arm64": "14.18.3",
77
+ "@claudish/magmux-linux-x64": "14.18.3"
78
78
  },
79
79
  "author": "Jack Rudenko <i@madappgang.com>",
80
80
  "license": "MIT",