claudish 12.1.2 → 12.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +34 -11
  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.0";
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "12.1.2",
3
+ "version": "12.2.0",
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.0",
64
+ "@claudish/magmux-darwin-x64": "12.2.0",
65
+ "@claudish/magmux-linux-arm64": "12.2.0",
66
+ "@claudish/magmux-linux-x64": "12.2.0"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",