claudish 12.1.2 → 12.2.1

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 +80 -23
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -901,7 +901,7 @@ var init_onepassword_config = __esm(() => {
901
901
  });
902
902
 
903
903
  // src/version.ts
904
- var VERSION = "12.1.2";
904
+ var VERSION = "12.2.1";
905
905
 
906
906
  // src/logger.ts
907
907
  import { appendFile, existsSync as existsSync2, mkdirSync, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
@@ -60382,10 +60382,13 @@ class FallbackHandler {
60382
60382
  async handle(c, payload) {
60383
60383
  const errors = [];
60384
60384
  const startIndex = this.lastSuccessIndex;
60385
+ let credentialStop;
60385
60386
  for (let attempt = 0;attempt < this.candidates.length; attempt++) {
60386
60387
  const idx = (startIndex + attempt) % this.candidates.length;
60387
60388
  const { name, handler, provider } = this.candidates[idx];
60388
60389
  const isLast = attempt === this.candidates.length - 1;
60390
+ if (credentialStop && !(provider && isSubscriptionProvider(provider)))
60391
+ continue;
60389
60392
  try {
60390
60393
  if (errors.length > 0 && handler instanceof ComposedHandler) {
60391
60394
  try {
@@ -60408,13 +60411,27 @@ class FallbackHandler {
60408
60411
  return response;
60409
60412
  }
60410
60413
  const verdict = authVerdict(response.headers);
60411
- if (verdict) {
60414
+ const subscriptionRejected = verdict === "terminal" && !!provider && isSubscriptionProvider(provider);
60415
+ if (verdict && !subscriptionRejected) {
60412
60416
  if (errors.length > 0) {
60413
60417
  logStderr(`[Fallback] ${name}: credential ${verdict === "terminal" ? "rejected" : "temporarily unavailable"} \u2014 stopping the chain here.`);
60414
60418
  }
60415
60419
  return response;
60416
60420
  }
60417
60421
  const errorBody = await response.clone().text();
60422
+ if (subscriptionRejected || isSubscriptionCredentialRejection(response.status, errorBody, provider)) {
60423
+ errors.push({ provider: name, status: response.status, message: errorBody });
60424
+ if (!credentialStop) {
60425
+ credentialStop = response;
60426
+ logStderr(`[Fallback] ${name}: subscription login rejected \u2014 trying the chain's other subscription providers only; metered providers are skipped.`);
60427
+ }
60428
+ continue;
60429
+ }
60430
+ if (credentialStop) {
60431
+ errors.push({ provider: name, status: response.status, message: errorBody });
60432
+ logStderr(`[Fallback] ${name} failed (HTTP ${response.status}), trying the next subscription provider...`);
60433
+ continue;
60434
+ }
60418
60435
  if (!isRetryableError(response.status, errorBody, name, response.headers, provider)) {
60419
60436
  if (errors.length > 0) {
60420
60437
  errors.push({ provider: name, status: response.status, message: errorBody });
@@ -60437,6 +60454,10 @@ class FallbackHandler {
60437
60454
  }
60438
60455
  }
60439
60456
  }
60457
+ if (credentialStop) {
60458
+ logStderr(`[Fallback] No subscription provider could serve ${payload.model || "the model"}; metered providers were skipped.`);
60459
+ return credentialStop;
60460
+ }
60440
60461
  return this.formatCombinedError(c, errors, payload.model);
60441
60462
  }
60442
60463
  formatCombinedError(c, errors, modelName) {
@@ -60464,6 +60485,15 @@ ${summary}`);
60464
60485
  }
60465
60486
  }
60466
60487
  }
60488
+ function isSubscriptionCredentialRejection(status, errorBody, providerId) {
60489
+ if (!providerId || !isSubscriptionProvider(providerId))
60490
+ return false;
60491
+ const recovered = status === 400 ? extractUpstreamStatus(errorBody) : undefined;
60492
+ if ((status === 401 || recovered === 401) && isCredentialRejection(401, errorBody)) {
60493
+ return true;
60494
+ }
60495
+ return status === 403 && isCredentialRejection(403, errorBody);
60496
+ }
60467
60497
  function isRetryableError(status, errorBody, provider, headers, providerId) {
60468
60498
  if (isClaudishConnectionVerdict(headers))
60469
60499
  return false;
@@ -60471,15 +60501,8 @@ function isRetryableError(status, errorBody, provider, headers, providerId) {
60471
60501
  return false;
60472
60502
  if (hasQuotaExhaustionWording(errorBody))
60473
60503
  return true;
60474
- if (providerId && isSubscriptionProvider(providerId)) {
60475
- const recovered = status === 400 ? extractUpstreamStatus(errorBody) : undefined;
60476
- if ((status === 401 || recovered === 401) && isCredentialRejection(401, errorBody)) {
60477
- return false;
60478
- }
60479
- if (status === 403 && isCredentialRejection(403, errorBody)) {
60480
- return false;
60481
- }
60482
- }
60504
+ if (isSubscriptionCredentialRejection(status, errorBody, providerId))
60505
+ return false;
60483
60506
  const upstream = status === 400 ? extractUpstreamStatus(errorBody) : undefined;
60484
60507
  if (upstream === 401 || upstream === 403 || upstream === 402 || upstream === 429) {
60485
60508
  return true;
@@ -63927,7 +63950,11 @@ function readProcessTable() {
63927
63950
  }
63928
63951
  function readProcessTableAsync() {
63929
63952
  return new Promise((resolve) => {
63930
- execFile("ps", PS_ARGS, { env: PS_ENV, encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }, (err, stdout) => resolve(err ? [] : parsePsTable(String(stdout))));
63953
+ try {
63954
+ execFile("ps", PS_ARGS, { env: PS_ENV, encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }, (err, stdout) => resolve(err ? [] : parsePsTable(String(stdout))));
63955
+ } catch {
63956
+ resolve([]);
63957
+ }
63931
63958
  });
63932
63959
  }
63933
63960
  function magmuxNeedle(paneId) {
@@ -69618,8 +69645,17 @@ var init_session_discovery = __esm(() => {
69618
69645
 
69619
69646
  // src/team-orchestrator.ts
69620
69647
  import { randomBytes as randomBytes8, randomUUID as randomUUID5 } from "crypto";
69621
- import { existsSync as existsSync31, mkdirSync as mkdirSync21, readFileSync as readFileSync31, readdirSync as readdirSync9, statSync as statSync12, writeFileSync as writeFileSync22 } from "fs";
69622
- import { basename as basename4, join as join50, resolve as resolve5 } from "path";
69648
+ import {
69649
+ existsSync as existsSync31,
69650
+ lstatSync as lstatSync3,
69651
+ mkdirSync as mkdirSync21,
69652
+ readFileSync as readFileSync31,
69653
+ readdirSync as readdirSync9,
69654
+ realpathSync as realpathSync6,
69655
+ statSync as statSync12,
69656
+ writeFileSync as writeFileSync22
69657
+ } from "fs";
69658
+ import { basename as basename4, dirname as dirname15, join as join50, resolve as resolve5, sep } from "path";
69623
69659
  function slotTerminal(e) {
69624
69660
  if (!e.session)
69625
69661
  return true;
@@ -70005,9 +70041,30 @@ function persistErrorLog(errorLogPath, header, sections) {
70005
70041
  }
70006
70042
  function validateSessionPath(sessionPath) {
70007
70043
  const resolved = resolve5(sessionPath);
70008
- const cwd = process.cwd();
70009
- if (!resolved.startsWith(`${cwd}/`) && resolved !== cwd) {
70010
- throw new Error(`Session path must be within current directory: ${sessionPath}`);
70044
+ const outside = () => new Error(`Session path must be within current directory: ${sessionPath}`);
70045
+ let existing = resolved;
70046
+ const tail = [];
70047
+ for (;; ) {
70048
+ try {
70049
+ lstatSync3(existing);
70050
+ break;
70051
+ } catch {
70052
+ const parent = dirname15(existing);
70053
+ if (parent === existing)
70054
+ break;
70055
+ tail.unshift(basename4(existing));
70056
+ existing = parent;
70057
+ }
70058
+ }
70059
+ let real;
70060
+ try {
70061
+ real = join50(realpathSync6(existing), ...tail);
70062
+ } catch {
70063
+ throw outside();
70064
+ }
70065
+ const cwd = realpathSync6(process.cwd());
70066
+ if (real !== cwd && !real.startsWith(cwd + sep)) {
70067
+ throw outside();
70011
70068
  }
70012
70069
  return resolved;
70013
70070
  }
@@ -70749,7 +70806,7 @@ import {
70749
70806
  statSync as statSync13,
70750
70807
  writeFileSync as writeFileSync23
70751
70808
  } from "fs";
70752
- import { join as join51, resolve as resolve6, sep } from "path";
70809
+ import { join as join51, resolve as resolve6, sep as sep2 } from "path";
70753
70810
  function normaliseTimeoutSeconds(raw) {
70754
70811
  const n = typeof raw === "string" && raw.trim() !== "" ? Number(raw) : raw;
70755
70812
  if (typeof n !== "number" || !Number.isFinite(n))
@@ -71592,7 +71649,7 @@ class SessionManager {
71592
71649
  const dir = resolve6(root, sessionId);
71593
71650
  if (dir !== join51(root, sessionId))
71594
71651
  return null;
71595
- if (!dir.startsWith(root + sep))
71652
+ if (!dir.startsWith(root + sep2))
71596
71653
  return null;
71597
71654
  return dir;
71598
71655
  }
@@ -72278,7 +72335,7 @@ var init_run_prompt_claude_code = __esm(() => {
72278
72335
  // src/mcp-server.ts
72279
72336
  import { existsSync as existsSync33, mkdirSync as mkdirSync24, readFileSync as readFileSync33, readdirSync as readdirSync10, writeFileSync as writeFileSync25 } from "fs";
72280
72337
  import { homedir as homedir35 } from "os";
72281
- import { dirname as dirname15, join as join53, resolve as resolve7 } from "path";
72338
+ import { dirname as dirname16, join as join53, resolve as resolve7 } from "path";
72282
72339
  import { fileURLToPath as fileURLToPath3 } from "url";
72283
72340
  async function loadAllModels(forceRefresh = false) {
72284
72341
  if (!forceRefresh && existsSync33(OPENROUTER_MODELS_CACHE_PATH)) {
@@ -73828,7 +73885,7 @@ var init_mcp_server = __esm(() => {
73828
73885
  import_dotenv2 = __toESM(require_main(), 1);
73829
73886
  import_dotenv2.config({ quiet: true });
73830
73887
  __filename3 = fileURLToPath3(import.meta.url);
73831
- __dirname3 = dirname15(__filename3);
73888
+ __dirname3 = dirname16(__filename3);
73832
73889
  CLAUDISH_CACHE_DIR = join53(homedir35(), ".claudish");
73833
73890
  OPENROUTER_MODELS_CACHE_PATH = join53(CLAUDISH_CACHE_DIR, "openrouter-models.json");
73834
73891
  NEXT_STEP = {
@@ -83719,7 +83776,7 @@ import {
83719
83776
  writeFileSync as writeFileSync28
83720
83777
  } from "fs";
83721
83778
  import { homedir as homedir37, tmpdir as tmpdir3 } from "os";
83722
- import { dirname as dirname16, join as join57 } from "path";
83779
+ import { dirname as dirname17, join as join57 } from "path";
83723
83780
  import { isatty } from "tty";
83724
83781
  function releaseTerminalIsolation() {
83725
83782
  if (!restoreTerminal)
@@ -83960,7 +84017,7 @@ process.stdin.on('end', () => {
83960
84017
  }
83961
84018
  function initializeTokenFile(tokenFilePath) {
83962
84019
  try {
83963
- mkdirSync25(dirname16(tokenFilePath), { recursive: true });
84020
+ mkdirSync25(dirname17(tokenFilePath), { recursive: true });
83964
84021
  writeFileSync28(tokenFilePath, JSON.stringify({
83965
84022
  input_tokens: 0,
83966
84023
  output_tokens: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "12.1.2",
3
+ "version": "12.2.1",
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",
@@ -60,10 +60,10 @@
60
60
  "ai"
61
61
  ],
62
62
  "optionalDependencies": {
63
- "@claudish/magmux-darwin-arm64": "12.1.2",
64
- "@claudish/magmux-darwin-x64": "12.1.2",
65
- "@claudish/magmux-linux-arm64": "12.1.2",
66
- "@claudish/magmux-linux-x64": "12.1.2"
63
+ "@claudish/magmux-darwin-arm64": "12.2.1",
64
+ "@claudish/magmux-darwin-x64": "12.2.1",
65
+ "@claudish/magmux-linux-arm64": "12.2.1",
66
+ "@claudish/magmux-linux-x64": "12.2.1"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",