claudish 14.18.2 → 14.18.4

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 +188 -106
  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.2";
5497
+ var VERSION = "14.18.4";
5498
5498
 
5499
5499
  // src/redact.ts
5500
5500
  function isPlaceholder(value) {
@@ -93087,8 +93087,29 @@ function bodyToForward(c, payload) {
93087
93087
  const inbound = c.get(INBOUND_BODY_KEY);
93088
93088
  return inbound !== undefined && inbound.canonical === serialized ? inbound.raw : serialized;
93089
93089
  }
93090
- 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;
93091
93111
  var init_anthropic_forward = __esm(() => {
93112
+ init_call_context();
93092
93113
  ALLOWED_NAMES = new Set([
93093
93114
  "authorization",
93094
93115
  "x-api-key",
@@ -93124,6 +93145,7 @@ var init_anthropic_forward = __esm(() => {
93124
93145
  "content-length"
93125
93146
  ]);
93126
93147
  ALLOWED_QUERY_NAMES = new Set(["beta"]);
93148
+ CLAUDE_LOGIN_BEARER = /^Bearer\s+sk-ant-oat\d+-/i;
93127
93149
  });
93128
93150
 
93129
93151
  // src/handlers/shared/thinking-signature.ts
@@ -93216,36 +93238,26 @@ class NativeHandler {
93216
93238
  }
93217
93239
  async handle(c, incoming) {
93218
93240
  const payload = await this.applyRequestHooks(c, incoming);
93219
- const headers = {
93220
- ...requestHeadersToForward(c.req.raw.headers),
93221
- ...inboundAuthHeaders(c.req.raw.headers)
93222
- };
93223
93241
  const target = payload.model;
93224
93242
  const strippedThinking = stripUnsignedThinkingBlocks(payload.messages);
93225
93243
  if (strippedThinking > 0) {
93226
93244
  log(`[Native] stripped ${strippedThinking} unsigned thinking block(s) from history for ${target} (foreign-provider origin)`);
93227
93245
  }
93228
93246
  const advisorSwapped = c.get(ADVISOR_SWAPPED_CONTEXT_KEY) === true;
93247
+ const inboundAuth = inboundAuthHeaders(c.req.raw.headers);
93229
93248
  log(`
93230
93249
  === [NATIVE] Claude Code \u2192 Anthropic API Request ===`);
93231
- log(`[Native] x-api-key: ${headers["x-api-key"] ? maskCredential(headers["x-api-key"]) : "(not set)"}`);
93232
- 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)"}`);
93233
93252
  log(`Request body (Model: ${target}):`);
93234
93253
  log(`=== End Request ===
93235
93254
  `);
93236
- headers["content-type"] = "application/json";
93237
- if (!headers["anthropic-version"])
93238
- headers["anthropic-version"] = "2023-06-01";
93239
- if (!headers.authorization && !headers["x-api-key"]) {
93240
- let fallbackKey = this.apiKey;
93241
- if (!fallbackKey) {
93242
- const auth = await credentials.getRequestAuth("native-anthropic", { model: target });
93243
- fallbackKey = auth.headers["x-api-key"];
93244
- }
93245
- if (fallbackKey) {
93246
- headers["x-api-key"] = fallbackKey;
93247
- }
93248
- }
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
+ });
93249
93261
  const incomingBeta = headers["anthropic-beta"];
93250
93262
  if (incomingBeta && advisorSwapped) {
93251
93263
  const { stripped, changed } = stripAdvisorBeta(incomingBeta);
@@ -93262,9 +93274,6 @@ class NativeHandler {
93262
93274
  else
93263
93275
  delete headers["anthropic-beta"];
93264
93276
  }
93265
- const url = `${this.baseUrl}/v1/messages${forwardedSearch(c)}`;
93266
- addSigningSecrets(c, credentialValuesFromRequest(headers, url));
93267
- const body = bodyToForward(c, payload);
93268
93277
  try {
93269
93278
  const anthropicResponse = await fetch(url, {
93270
93279
  method: "POST",
@@ -93419,7 +93428,6 @@ var init_native_handler = __esm(() => {
93419
93428
  init_native_handler_advisor();
93420
93429
  init_anthropic_error();
93421
93430
  init_anthropic_forward();
93422
- init_call_context();
93423
93431
  });
93424
93432
 
93425
93433
  // src/hooks/seam-hooks.ts
@@ -94471,43 +94479,31 @@ ${plan.hint}` : `[Route] ${plan.reason}`;
94471
94479
  });
94472
94480
  app.post("/v1/messages/count_tokens", async (c) => {
94473
94481
  try {
94474
- const body = await c.req.json();
94482
+ const rawBody = await c.req.text();
94483
+ const body = JSON.parse(rawBody);
94484
+ recordInboundBody(c, rawBody, body);
94475
94485
  if (typeof body?.model !== "string" || body.model.length === 0) {
94476
94486
  return c.json(wrapAnthropicError(400, "missing required field: model"), 400);
94477
94487
  }
94478
94488
  const handler = await getHandlerForRequest(body.model);
94479
94489
  if (handler instanceof NativeHandler) {
94480
- const inbound = c.req.header();
94481
- const headers = {
94482
- "Content-Type": "application/json",
94483
- "anthropic-version": inbound["anthropic-version"] || "2023-06-01"
94484
- };
94485
- if (inbound.authorization)
94486
- headers.authorization = inbound.authorization;
94487
- if (inbound["x-api-key"])
94488
- headers["x-api-key"] = inbound["x-api-key"];
94489
- if (inbound["anthropic-beta"])
94490
- headers["anthropic-beta"] = inbound["anthropic-beta"];
94491
- if (!inbound.authorization && !inbound["x-api-key"]) {
94492
- let fallbackKey = anthropicApiKey;
94493
- if (!fallbackKey) {
94494
- try {
94495
- const auth = await credentials.getRequestAuth("native-anthropic", {
94496
- model: body.model
94497
- });
94498
- fallbackKey = auth.headers["x-api-key"];
94499
- } catch (err) {
94500
- log(`[CountTokens] no resolvable Anthropic credential: ${err}`);
94501
- }
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;
94502
94501
  }
94503
- if (fallbackKey)
94504
- headers["x-api-key"] = fallbackKey;
94505
- }
94506
- addSigningSecrets(c, credentialValuesFromRequest(headers));
94507
- const res = await fetch(resolveUpstreamUrl("https://api.anthropic.com/v1/messages/count_tokens"), {
94502
+ });
94503
+ const res = await fetch(forward.url, {
94508
94504
  method: "POST",
94509
- headers,
94510
- body: JSON.stringify(body)
94505
+ headers: forward.headers,
94506
+ body: forward.body
94511
94507
  });
94512
94508
  if (res.status === 401 || res.status === 403) {
94513
94509
  log(`[CountTokens] upstream ${res.status} \u2014 falling back to the local estimate`);
@@ -96521,11 +96517,12 @@ function readProcessTable() {
96521
96517
  }
96522
96518
  return tableOf(stdout, spawnedAt);
96523
96519
  }
96524
- function readProcessTableAsync() {
96520
+ function readProcessTableAsync(cancelAfterMs) {
96521
+ const options = cancelAfterMs === undefined ? PS_OPTIONS : { ...PS_OPTIONS, timeout: cancelAfterMs, killSignal: "SIGKILL" };
96525
96522
  return new Promise((resolve) => {
96526
96523
  const spawnedAt = Date.now();
96527
96524
  try {
96528
- 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)));
96529
96526
  } catch {
96530
96527
  resolve(tableOf(null, spawnedAt));
96531
96528
  }
@@ -96582,11 +96579,14 @@ function escapedDescendants(table, pgid, inGroup) {
96582
96579
  }
96583
96580
  return out;
96584
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
+ }
96585
96586
  function liveEscaped(table, snap) {
96586
96587
  if (!snap?.escaped?.length)
96587
96588
  return [];
96588
- const keys = new Set(snap.escaped.map((m) => `${m.pid} ${collapse(m.lstart)}`));
96589
- return table.filter((r) => keys.has(`${r.pid} ${r.lstart}`)).map((r) => r.pid);
96589
+ return liveMembers(table, snap.escaped);
96590
96590
  }
96591
96591
  function mergeSnapshots(a, b, table) {
96592
96592
  if (!a)
@@ -97467,8 +97467,62 @@ function waitForExit(proc, ms) {
97467
97467
  t.unref?.();
97468
97468
  });
97469
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
+ }
97470
97523
  var KILL_PROCESS_GROUP;
97471
97524
  var init_process_tree = __esm(() => {
97525
+ init_process_identity();
97472
97526
  KILL_PROCESS_GROUP = process.platform !== "win32";
97473
97527
  });
97474
97528
 
@@ -98539,6 +98593,8 @@ async function computeMainThreadContextWindow(config, cachePath) {
98539
98593
  let min = Number.POSITIVE_INFINITY;
98540
98594
  const unresolved = [];
98541
98595
  for (const spec of specs) {
98596
+ if (signalShutdownExitCode() !== null)
98597
+ break;
98542
98598
  try {
98543
98599
  const resolved = await resolveLocalContextWindow(spec, cachePath);
98544
98600
  if (!resolved)
@@ -98671,6 +98727,7 @@ async function runClaudeWithProxy(config, proxyUrl, onCleanup) {
98671
98727
  statusLine,
98672
98728
  tokenFilePath
98673
98729
  } = createTempSettingsFile(modelId ?? "default", port, proxyAuthMode, userStatusLineCommand);
98730
+ const signalShutdown = setupSignalHandlers(tempSettingsPath, config.quiet, onCleanup);
98674
98731
  mergeUserSettingsIfPresent(config, tempSettingsPath, statusLine, proxyAuthMode);
98675
98732
  const claudeArgs = [];
98676
98733
  claudeArgs.push("--settings", tempSettingsPath);
@@ -98810,6 +98867,11 @@ async function runClaudeWithProxy(config, proxyUrl, onCleanup) {
98810
98867
  `);
98811
98868
  }
98812
98869
  const claudeBinary = await findClaudeBinary();
98870
+ const stoppedBeforeSpawn = signalShutdownExitCode();
98871
+ if (stoppedBeforeSpawn !== null) {
98872
+ signalShutdown.removeSettingsFile();
98873
+ return stoppedBeforeSpawn;
98874
+ }
98813
98875
  if (!claudeBinary) {
98814
98876
  console.error("Error: Claude Code CLI not found");
98815
98877
  console.error("Install it from: https://claude.com/claude-code");
@@ -98872,6 +98934,7 @@ Or set CLAUDE_PATH to your custom installation:`);
98872
98934
  stdio,
98873
98935
  shell: needsShell
98874
98936
  });
98937
+ signalShutdown.attachClaudeCode(proc);
98875
98938
  if (wrap) {
98876
98939
  wrap.watch(proc);
98877
98940
  }
@@ -98938,7 +99001,6 @@ Or set CLAUDE_PATH to your custom installation:`);
98938
99001
  } catch {}
98939
99002
  });
98940
99003
  }
98941
- const signalShutdown = setupSignalHandlers(proc, tempSettingsPath, config.quiet, onCleanup);
98942
99004
  const { exitCode, exitSignal } = await new Promise((resolve) => {
98943
99005
  proc.on("exit", (code, signal) => {
98944
99006
  setClaudeCodeRunning(false);
@@ -98962,58 +99024,62 @@ Or set CLAUDE_PATH to your custom installation:`);
98962
99024
  }
98963
99025
  log(exitSignal ? `[Claude Code] Exited from ${exitSignal} (exit code ${exitCode})` : `[Claude Code] Exited with code ${exitCode}`);
98964
99026
  releaseTerminalIsolation();
98965
- try {
98966
- unlinkSync11(tempSettingsPath);
98967
- } catch {}
98968
- signalShutdown.launcherCleanupDone();
98969
- if (signalShutdown.started())
98970
- return new Promise(() => {});
98971
- return exitCode;
99027
+ signalShutdown.removeSettingsFile();
99028
+ await signalShutdown.claudeCodeStopped();
99029
+ return signalShutdownExitCode() ?? exitCode;
98972
99030
  }
98973
99031
  function sessionOutcomeOf(exitCode) {
98974
99032
  return exitCode === 0 ? { state: "COMPLETED", reason: null, exitCode } : { state: "FAILED", reason: "child_exited", exitCode };
98975
99033
  }
98976
- function delay(ms) {
98977
- return new Promise((resolve) => {
98978
- const t = setTimeout(resolve, Math.max(0, ms));
98979
- t.unref?.();
98980
- });
99034
+ function signalShutdownExitCode() {
99035
+ return signalShutdownCode;
98981
99036
  }
98982
- function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
99037
+ function setupSignalHandlers(tempSettingsPath, quiet, onCleanup) {
98983
99038
  const signals = isWindows2() ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
98984
99039
  let shuttingDown = null;
98985
- let markLauncherCleanupDone = () => {};
98986
- const launcherCleanup = new Promise((resolve) => {
98987
- markLauncherCleanupDone = resolve;
98988
- });
98989
- const shutdown = async (signal) => {
98990
- const startedAt = Date.now();
99040
+ let claudeCode = null;
99041
+ let claudeCodeStopped = Promise.resolve();
99042
+ let settingsFileRemoved = false;
99043
+ const removeSettingsFile = () => {
99044
+ if (settingsFileRemoved)
99045
+ return;
99046
+ settingsFileRemoved = true;
99047
+ try {
99048
+ unlinkSync11(tempSettingsPath);
99049
+ } catch {}
99050
+ };
99051
+ const stopClaudeCode = async (proc) => {
98991
99052
  try {
98992
99053
  proc.kill("SIGTERM");
98993
- if (!await waitForExit(proc, SIGNAL_CHILD_EXIT_GRACE_MS)) {
98994
- log(`[claudish] Claude Code did not exit within ${SIGNAL_CHILD_EXIT_GRACE_MS} ms of SIGTERM; sending SIGKILL`);
98995
- try {
98996
- proc.kill("SIGKILL");
98997
- } catch {}
98998
- await waitForExit(proc, SIGNAL_CHILD_KILL_WAIT_MS);
99054
+ if (await waitForExit(proc, SIGNAL_CHILD_EXIT_GRACE_MS))
99055
+ return;
99056
+ log(`[claudish] Claude Code did not exit within ${SIGNAL_CHILD_EXIT_GRACE_MS} ms of SIGTERM; sending SIGKILL`);
99057
+ const killStepStartedAt = Date.now();
99058
+ const descendants = proc.pid ? await snapshotDescendants(proc.pid, SIGNAL_DESCENDANT_READ_MS) : [];
99059
+ if (proc.exitCode !== null || proc.signalCode !== null)
99060
+ return;
99061
+ let killed = 0;
99062
+ try {
99063
+ proc.kill("SIGKILL");
99064
+ } finally {
99065
+ killed = await killStillLiveMembers(descendants, SIGNAL_DESCENDANT_READ_MS);
98999
99066
  }
99000
- await Promise.race([
99001
- launcherCleanup,
99002
- delay(SIGNAL_SHUTDOWN_BUDGET_MS - (Date.now() - startedAt))
99003
- ]);
99067
+ log(`[claudish] Sent SIGKILL to Claude Code and ${killed} of ${descendants.length} descendants`);
99068
+ await waitForExit(proc, SIGNAL_CHILD_KILL_WAIT_MS - (Date.now() - killStepStartedAt));
99004
99069
  } catch (err) {
99005
99070
  log(`[claudish] Signal shutdown error: ${err}`);
99006
- } finally {
99007
- if (onCleanup) {
99008
- try {
99009
- onCleanup();
99010
- } catch {}
99011
- }
99071
+ }
99072
+ };
99073
+ const armDeadline = (code) => {
99074
+ const deadline = setTimeout(() => {
99075
+ log(`[claudish] Signal shutdown passed ${SIGNAL_SHUTDOWN_BUDGET_MS} ms; exiting`);
99012
99076
  try {
99013
- unlinkSync11(tempSettingsPath);
99077
+ onCleanup?.();
99014
99078
  } catch {}
99015
- process.exit(signalExitCode(signal));
99016
- }
99079
+ removeSettingsFile();
99080
+ process.exit(code);
99081
+ }, SIGNAL_SHUTDOWN_BUDGET_MS);
99082
+ deadline.unref?.();
99017
99083
  };
99018
99084
  claimSignalExit();
99019
99085
  for (const signal of signals) {
@@ -99023,17 +99089,25 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
99023
99089
  return;
99024
99090
  }
99025
99091
  shuttingDown = signal;
99092
+ const code = signalExitCode(signal);
99093
+ signalShutdownCode = code;
99094
+ process.exitCode = code;
99095
+ armDeadline(code);
99026
99096
  releaseTerminalIsolation();
99027
99097
  if (!quiet) {
99028
99098
  console.error(`
99029
99099
  [claudish] Received ${signal}, shutting down...`);
99030
99100
  }
99031
- shutdown(signal);
99101
+ if (claudeCode)
99102
+ claudeCodeStopped = stopClaudeCode(claudeCode);
99032
99103
  });
99033
99104
  }
99034
99105
  return {
99035
- started: () => shuttingDown !== null,
99036
- launcherCleanupDone: () => markLauncherCleanupDone()
99106
+ attachClaudeCode: (child) => {
99107
+ claudeCode = child;
99108
+ },
99109
+ removeSettingsFile,
99110
+ claudeCodeStopped: () => claudeCodeStopped
99037
99111
  };
99038
99112
  }
99039
99113
  async function findClaudeBinary(env = process.env) {
@@ -99135,7 +99209,7 @@ var restoreTerminal = null, macosKeychainAnthropicMemo, defaultKeychainAnthropic
99135
99209
  }
99136
99210
  macosKeychainAnthropicMemo.set(memoKey, found);
99137
99211
  return found;
99138
- }, 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;
99212
+ }, 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;
99139
99213
  var init_claude_runner = __esm(() => {
99140
99214
  init_model_catalog();
99141
99215
  init_claude_code_facts();
@@ -125287,11 +125361,18 @@ Team Status`);
125287
125361
  }
125288
125362
  finalizeStartupTrace("run", { quiet: cliConfig.quiet });
125289
125363
  let exitCode = 0;
125364
+ let diagCleaned = false;
125365
+ const cleanupDiag = () => {
125366
+ if (diagCleaned)
125367
+ return;
125368
+ diagCleaned = true;
125369
+ diag.cleanup();
125370
+ };
125290
125371
  try {
125291
- exitCode = await runClaudeWithProxy(cliConfig, proxy.url, () => diag.cleanup());
125372
+ exitCode = await runClaudeWithProxy(cliConfig, proxy.url, cleanupDiag);
125292
125373
  } finally {
125293
125374
  setDiagOutput(null);
125294
- diag.cleanup();
125375
+ cleanupDiag();
125295
125376
  if (!cliConfig.quiet) {
125296
125377
  const write = cliConfig.interactive ? console.log : console.error;
125297
125378
  write(`
@@ -125331,8 +125412,9 @@ Team Status`);
125331
125412
  console.error(`[claudish] session summary unavailable: ${e}`);
125332
125413
  }
125333
125414
  }
125415
+ exitCode = signalShutdownExitCode() ?? exitCode;
125334
125416
  const sessionLogPath = getAlwaysOnLogPath();
125335
- const quitBySignal = exitCode === 130 || exitCode === 143;
125417
+ const quitBySignal = exitCode === 130 || exitCode === 143 || signalShutdownExitCode() !== null;
125336
125418
  if (exitCode !== 0 && !quitBySignal && sessionLogPath && !cliConfig.quiet) {
125337
125419
  console.error(`
125338
125420
  [claudish] Session ended with errors (exit code ${exitCode}).`);
@@ -125347,6 +125429,6 @@ Team Status`);
125347
125429
  } catch (error) {
125348
125430
  console.error("[claudish] Fatal error:", error);
125349
125431
  console.error("[claudish] Stack:", error instanceof Error ? error.stack : "no stack");
125350
- process.exit(1);
125432
+ process.exit(signalShutdownExitCode() ?? 1);
125351
125433
  }
125352
125434
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "14.18.2",
3
+ "version": "14.18.4",
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.2",
75
- "@claudish/magmux-darwin-x64": "14.18.2",
76
- "@claudish/magmux-linux-arm64": "14.18.2",
77
- "@claudish/magmux-linux-x64": "14.18.2"
74
+ "@claudish/magmux-darwin-arm64": "14.18.4",
75
+ "@claudish/magmux-darwin-x64": "14.18.4",
76
+ "@claudish/magmux-linux-arm64": "14.18.4",
77
+ "@claudish/magmux-linux-x64": "14.18.4"
78
78
  },
79
79
  "author": "Jack Rudenko <i@madappgang.com>",
80
80
  "license": "MIT",