claudish 7.44.0 → 7.45.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 +95 -24
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -729,7 +729,7 @@ var init_onepassword_config = __esm(() => {
729
729
  });
730
730
 
731
731
  // src/version.ts
732
- var VERSION = "7.44.0";
732
+ var VERSION = "7.45.0";
733
733
 
734
734
  // src/logger.ts
735
735
  var exports_logger = {};
@@ -28693,6 +28693,15 @@ function resolveModelNameSync(userInput, targetProvider) {
28693
28693
  }
28694
28694
  return { resolvedId: resolved, wasResolved: true, sourceLabel: `${targetProvider} catalog` };
28695
28695
  }
28696
+ function resolveTargetForCatalog(target, isExplicitProvider, model, provider, resolve = resolveModelNameSync) {
28697
+ if (!isExplicitProvider)
28698
+ return { target, resolution: null };
28699
+ const resolution = resolve(model, provider);
28700
+ return {
28701
+ target: resolution.wasResolved ? `${provider}@${resolution.resolvedId}` : target,
28702
+ resolution
28703
+ };
28704
+ }
28696
28705
  function logResolution(userInput, result, quiet = false) {
28697
28706
  if (result.wasResolved && !quiet) {
28698
28707
  process.stderr.write(`[Model] Resolved "${userInput}" \u2192 "${result.resolvedId}" (${result.sourceLabel})
@@ -36662,6 +36671,10 @@ function warnGoAliasDeprecatedOnce() {
36662
36671
  process.stderr.write(`[claudish] go@ is deprecated \u2014 use ag@<model> (Antigravity). Routing there.
36663
36672
  `);
36664
36673
  }
36674
+ function parseModelChain(modelSpec) {
36675
+ const parts = modelSpec.split(MODEL_CHAIN_SEPARATOR).map((s) => s.trim()).filter(Boolean);
36676
+ return parts.length > 0 ? parts : [modelSpec];
36677
+ }
36665
36678
  function parseModelSpec(modelSpec) {
36666
36679
  const original = modelSpec;
36667
36680
  if (modelSpec.startsWith("http://") || modelSpec.startsWith("https://")) {
@@ -36761,7 +36774,7 @@ function getLegacySyntaxWarning(parsed) {
36761
36774
  return `Deprecation warning: "${parsed.original}" uses legacy prefix syntax.
36762
36775
  ` + ` Consider using: ${newSyntax}`;
36763
36776
  }
36764
- var PROVIDER_SHORTCUTS, _goDeprecationWarned = false, LOCAL_PROVIDERS, NATIVE_MODEL_PATTERNS, LEGACY_PREFIX_PATTERNS;
36777
+ var PROVIDER_SHORTCUTS, _goDeprecationWarned = false, LOCAL_PROVIDERS, NATIVE_MODEL_PATTERNS, LEGACY_PREFIX_PATTERNS, MODEL_CHAIN_SEPARATOR = "+";
36765
36778
  var init_model_parser = __esm(() => {
36766
36779
  init_provider_definitions();
36767
36780
  PROVIDER_SHORTCUTS = getShortcuts();
@@ -40668,6 +40681,13 @@ class ComposedHandler {
40668
40681
  response = next;
40669
40682
  }
40670
40683
  }
40684
+ describeComposition() {
40685
+ return {
40686
+ transport: this.provider.name,
40687
+ streamFormat: this.resolveStreamFormat(),
40688
+ endpoint: this.provider.getEndpoint(this.bareModelName)
40689
+ };
40690
+ }
40671
40691
  resolveStreamFormat() {
40672
40692
  return this.provider.overrideStreamFormat?.() ?? this.explicitAdapter?.getStreamFormat() ?? this.modelAdapter?.getStreamFormat() ?? this.getAdapter().getStreamFormat();
40673
40693
  }
@@ -43170,11 +43190,15 @@ async function pinSpecFor(model, router = route) {
43170
43190
  const plan = await router(model);
43171
43191
  if (plan.kind !== "ok")
43172
43192
  return null;
43173
- return normalizePinnedSpec(plan.primary);
43193
+ return joinPinnedChain([plan.primary, ...plan.fallbacks]);
43174
43194
  } catch {
43175
43195
  return null;
43176
43196
  }
43177
43197
  }
43198
+ function joinPinnedChain(routes) {
43199
+ const specs = routes.map(normalizePinnedSpec).filter((s) => !!s);
43200
+ return specs.length > 0 ? specs.join(MODEL_CHAIN_SEPARATOR) : null;
43201
+ }
43178
43202
  function normalizePinnedSpec(r) {
43179
43203
  const spec = r.modelSpec?.trim();
43180
43204
  if (!spec)
@@ -43458,6 +43482,18 @@ var init_signal_watcher = __esm(() => {
43458
43482
  QUESTION_PATTERNS = [/\?\s*$/m, /\bchoose\b.*:/im, /\bselect\b.*:/im, /\benter\b.*:/im];
43459
43483
  });
43460
43484
 
43485
+ // src/spawn-claudish.ts
43486
+ function resolveClaudishSpawn(env = process.env) {
43487
+ const bin = env[CLAUDISH_BIN_ENV]?.trim();
43488
+ if (!bin)
43489
+ return { command: "claudish", prefixArgs: [] };
43490
+ if (/\.(ts|tsx|js|mjs|cjs)$/.test(bin)) {
43491
+ return { command: process.execPath, prefixArgs: ["run", bin] };
43492
+ }
43493
+ return { command: bin, prefixArgs: [] };
43494
+ }
43495
+ var CLAUDISH_BIN_ENV = "CLAUDISH_BIN";
43496
+
43461
43497
  // src/channel/session-manager.ts
43462
43498
  import { spawn } from "child_process";
43463
43499
  import { randomUUID as randomUUID4 } from "crypto";
@@ -43498,7 +43534,8 @@ class SessionManager {
43498
43534
  "--quiet",
43499
43535
  ...opts.claudishFlags ?? []
43500
43536
  ];
43501
- const proc = spawn("claudish", args, {
43537
+ const spawnTarget = resolveClaudishSpawn();
43538
+ const proc = spawn(spawnTarget.command, [...spawnTarget.prefixArgs, ...args], {
43502
43539
  cwd: opts.cwd ?? process.cwd(),
43503
43540
  stdio: ["pipe", "pipe", "pipe"],
43504
43541
  shell: false
@@ -46149,7 +46186,7 @@ ${summary}`);
46149
46186
  error: truncate(parseErrorMessage(e.message), 200)
46150
46187
  }))
46151
46188
  }
46152
- }, 502);
46189
+ }, exhaustedChainStatus(errors3));
46153
46190
  }
46154
46191
  async shutdown() {
46155
46192
  for (const { handler } of this.candidates) {
@@ -46183,6 +46220,9 @@ function isRetryableError(status, errorBody, provider) {
46183
46220
  if (provider?.toLowerCase().includes("antigravity") && lower.includes("invalid argument")) {
46184
46221
  return true;
46185
46222
  }
46223
+ if (isProvider(provider, "opencodezen") && (lower.includes("upstream request failed") || lower.includes("error from provider ("))) {
46224
+ return true;
46225
+ }
46186
46226
  }
46187
46227
  if (status === 500) {
46188
46228
  if (lower.includes("insufficient balance") || lower.includes("insufficient credit") || lower.includes("quota exceeded") || lower.includes("billing")) {
@@ -46191,6 +46231,17 @@ function isRetryableError(status, errorBody, provider) {
46191
46231
  }
46192
46232
  return false;
46193
46233
  }
46234
+ function exhaustedChainStatus(errors3) {
46235
+ if (errors3.length === 0)
46236
+ return 400;
46237
+ const allTransient = errors3.every((e) => e.status === 429 || e.status === 503 || hasQuotaExhaustionWording(e.message));
46238
+ return allTransient ? 503 : 400;
46239
+ }
46240
+ function isProvider(provider, needle) {
46241
+ if (!provider)
46242
+ return false;
46243
+ return provider.toLowerCase().replace(/[^a-z0-9]/g, "").includes(needle);
46244
+ }
46194
46245
  function parseErrorMessage(body) {
46195
46246
  try {
46196
46247
  const parsed = JSON.parse(body);
@@ -47795,17 +47846,6 @@ var init_provider_profiles = __esm(() => {
47795
47846
  createHandler(ctx) {
47796
47847
  const zenApiKey = ctx.apiKey;
47797
47848
  const isGoProvider = ctx.provider.name === "opencode-zen-go";
47798
- if (ctx.modelName.toLowerCase().includes("minimax")) {
47799
- const bearerProvider = { ...ctx.provider, authScheme: "bearer" };
47800
- const transport2 = new AnthropicProviderTransport(bearerProvider, zenApiKey);
47801
- const adapter2 = new AnthropicAPIFormat(ctx.modelName, ctx.provider.name);
47802
- const handler2 = new ComposedHandler(transport2, ctx.targetModel, ctx.modelName, ctx.port, {
47803
- adapter: adapter2,
47804
- ...ctx.sharedOpts
47805
- });
47806
- log(`[Proxy] Created OpenCode Zen${isGoProvider ? " Go" : ""} (Anthropic composed): ${ctx.modelName}`);
47807
- return handler2;
47808
- }
47809
47849
  if (ctx.modelName.toLowerCase().startsWith("gpt-")) {
47810
47850
  const responsesProvider = { ...ctx.provider, apiPath: "/v1/responses" };
47811
47851
  const transport2 = new OpenAIProviderTransport(responsesProvider, ctx.modelName, zenApiKey);
@@ -48920,13 +48960,38 @@ async function createProxyServer(port, _openrouterApiKey, model, monitorMode = f
48920
48960
  target = model;
48921
48961
  }
48922
48962
  const invocationMode = detectInvocationMode(target, wasFromModelMap);
48963
+ if (options.modelChain && options.modelChain.length > 1 && target === options.modelChain[0]) {
48964
+ const cacheKey = `chain:${options.modelChain.join("+")}`;
48965
+ const cached2 = fallbackHandlerCache.get(cacheKey);
48966
+ if (cached2)
48967
+ return cached2;
48968
+ await ensureCatalogReady(5000);
48969
+ const candidates = [];
48970
+ for (const spec of options.modelChain) {
48971
+ const parsed = parseModelSpec(spec);
48972
+ const resolvedSpec = resolveTargetForCatalog(spec, parsed.isExplicitProvider, parsed.model, parsed.provider).target;
48973
+ const handler = parsed.provider === "openrouter" ? getOpenRouterHandler(resolvedSpec, invocationMode) : await getRemoteProviderHandler(resolvedSpec, invocationMode) ?? getLocalProviderHandler(resolvedSpec, invocationMode);
48974
+ if (handler) {
48975
+ candidates.push({ name: DISPLAY_NAMES[parsed.provider] ?? parsed.provider, handler });
48976
+ }
48977
+ }
48978
+ if (candidates.length > 0) {
48979
+ const resultHandler = candidates.length > 1 ? new FallbackHandler(candidates) : candidates[0].handler;
48980
+ fallbackHandlerCache.set(cacheKey, resultHandler);
48981
+ if (!options.quiet && candidates.length > 1) {
48982
+ logStderr(`[Route] ${candidates.length} pinned providers for ${target}: ${candidates.map((c) => c.name).join(" \u2192 ")}`);
48983
+ }
48984
+ return resultHandler;
48985
+ }
48986
+ }
48923
48987
  {
48924
48988
  const parsedTarget = parseModelSpec(target);
48925
- await ensureCatalogReady(5000);
48926
- const resolution = resolveModelNameSync(parsedTarget.model, parsedTarget.provider);
48927
- logResolution(parsedTarget.model, resolution, options.quiet);
48928
- if (resolution.wasResolved) {
48929
- target = `${parsedTarget.provider}@${resolution.resolvedId}`;
48989
+ if (parsedTarget.isExplicitProvider) {
48990
+ await ensureCatalogReady(5000);
48991
+ const outcome = resolveTargetForCatalog(target, parsedTarget.isExplicitProvider, parsedTarget.model, parsedTarget.provider);
48992
+ if (outcome.resolution)
48993
+ logResolution(parsedTarget.model, outcome.resolution, options.quiet);
48994
+ target = outcome.target;
48930
48995
  }
48931
48996
  }
48932
48997
  {
@@ -49143,6 +49208,7 @@ var init_proxy_server = __esm(() => {
49143
49208
  init_model_loader();
49144
49209
  init_profile_config();
49145
49210
  init_api_key_map();
49211
+ init_auto_route();
49146
49212
  init_catalog_client();
49147
49213
  init_custom_endpoints_loader();
49148
49214
  init_model_parser();
@@ -49537,7 +49603,8 @@ async function runModels(sessionPath, opts = {}) {
49537
49603
  state: "RUNNING",
49538
49604
  startedAt: new Date().toISOString()
49539
49605
  });
49540
- const proc = spawn2("claudish", args, {
49606
+ const teamSpawnTarget = resolveClaudishSpawn();
49607
+ const proc = spawn2(teamSpawnTarget.command, [...teamSpawnTarget.prefixArgs, ...args], {
49541
49608
  stdio: ["pipe", "pipe", "pipe"],
49542
49609
  shell: false,
49543
49610
  env: {
@@ -68112,7 +68179,10 @@ async function parseArgs(args) {
68112
68179
  printAvailableModels();
68113
68180
  process.exit(1);
68114
68181
  }
68115
- config3.model = modelArg;
68182
+ const chain = parseModelChain(modelArg);
68183
+ config3.model = chain[0];
68184
+ if (chain.length > 1)
68185
+ config3.modelChain = chain;
68116
68186
  } else if (arg === "--model-opus") {
68117
68187
  const val = args[++i];
68118
68188
  if (val)
@@ -78701,7 +78771,8 @@ Team Status`);
78701
78771
  quiet: cliConfig.quiet,
78702
78772
  isInteractive: cliConfig.interactive,
78703
78773
  advisorModels: cliConfig.advisorModels,
78704
- advisorCollector: cliConfig.advisorCollector
78774
+ advisorCollector: cliConfig.advisorCollector,
78775
+ modelChain: cliConfig.monitor ? undefined : cliConfig.modelChain
78705
78776
  }));
78706
78777
  const diag = createDiagOutput2({
78707
78778
  interactive: cliConfig.interactive,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "7.44.0",
3
+ "version": "7.45.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": "7.44.0",
64
- "@claudish/magmux-darwin-x64": "7.44.0",
65
- "@claudish/magmux-linux-arm64": "7.44.0",
66
- "@claudish/magmux-linux-x64": "7.44.0"
63
+ "@claudish/magmux-darwin-arm64": "7.45.0",
64
+ "@claudish/magmux-darwin-x64": "7.45.0",
65
+ "@claudish/magmux-linux-arm64": "7.45.0",
66
+ "@claudish/magmux-linux-x64": "7.45.0"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",