claudish 6.13.0 → 6.13.2

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.
package/dist/index.js CHANGED
@@ -17621,11 +17621,7 @@ var init_remote_provider_types = __esm(() => {
17621
17621
  // src/adapters/model-catalog.ts
17622
17622
  function lookupModel(modelId) {
17623
17623
  const lower = modelId.toLowerCase();
17624
- let unprefixed = lower;
17625
- if (lower.includes("@"))
17626
- unprefixed = lower.substring(lower.indexOf("@") + 1);
17627
- else if (lower.includes("/"))
17628
- unprefixed = lower.substring(lower.lastIndexOf("/") + 1);
17624
+ const unprefixed = lower.includes("/") ? lower.substring(lower.lastIndexOf("/") + 1) : lower;
17629
17625
  for (const entry of MODEL_CATALOG) {
17630
17626
  if (unprefixed.includes(entry.pattern) || lower.includes(entry.pattern)) {
17631
17627
  return entry;
@@ -17975,7 +17971,7 @@ var init_openai_tools = __esm(() => {
17975
17971
  function matchesModelFamily(modelId, family) {
17976
17972
  const lower = modelId.toLowerCase();
17977
17973
  const fam = family.toLowerCase();
17978
- return lower.startsWith(fam) || lower.includes(`/${fam}`) || lower.includes(`@${fam}`);
17974
+ return lower.startsWith(fam) || lower.includes(`/${fam}`);
17979
17975
  }
17980
17976
 
17981
17977
  class BaseAPIFormat {
@@ -22367,7 +22363,7 @@ var init_profile_config = __esm(() => {
22367
22363
  });
22368
22364
 
22369
22365
  // src/version.ts
22370
- var VERSION = "6.13.0";
22366
+ var VERSION = "6.13.2";
22371
22367
 
22372
22368
  // src/telemetry.ts
22373
22369
  var exports_telemetry = {};
@@ -24115,29 +24111,34 @@ class ComposedHandler {
24115
24111
  middlewareManager;
24116
24112
  tokenTracker;
24117
24113
  targetModel;
24114
+ bareModelName;
24118
24115
  options;
24119
24116
  isInteractive;
24120
24117
  pendingFallbackMeta;
24121
24118
  constructor(provider, targetModel, modelName, port, options = {}) {
24119
+ if (modelName.includes("@")) {
24120
+ throw new Error(`ComposedHandler: modelName must not contain '@' (got "${modelName}"). ` + `Strip the provider routing prefix before passing modelName. ` + `If you need the full routed form, pass it as targetModel.`);
24121
+ }
24122
24122
  this.provider = provider;
24123
24123
  this.targetModel = targetModel;
24124
+ this.bareModelName = modelName;
24124
24125
  this.options = options;
24125
24126
  this.explicitAdapter = options.adapter;
24126
24127
  this.isInteractive = options.isInteractive ?? false;
24127
- this.adapterManager = new DialectManager(targetModel);
24128
+ this.adapterManager = new DialectManager(this.bareModelName);
24128
24129
  const resolvedModelAdapter = this.adapterManager.getAdapter();
24129
24130
  if (resolvedModelAdapter.getName() !== "DefaultAPIFormat") {
24130
24131
  this.modelAdapter = resolvedModelAdapter;
24131
24132
  }
24132
24133
  this.middlewareManager = new MiddlewareManager;
24133
- if (targetModel.includes("gemini") || targetModel.includes("google/")) {
24134
+ if (this.bareModelName.includes("gemini") || this.bareModelName.includes("google/")) {
24134
24135
  this.middlewareManager.register(new GeminiThoughtSignatureMiddleware);
24135
24136
  }
24136
- this.middlewareManager.initialize().catch((err) => log(`[ComposedHandler:${targetModel}] Middleware init error: ${err}`));
24137
+ this.middlewareManager.initialize().catch((err) => log(`[ComposedHandler:${this.bareModelName}] Middleware init error: ${err}`));
24137
24138
  this.tokenTracker = new TokenTracker(port, {
24138
24139
  contextWindow: this.getModelContextWindow(),
24139
24140
  providerName: provider.name,
24140
- modelName,
24141
+ modelName: this.bareModelName,
24141
24142
  providerDisplayName: provider.displayName
24142
24143
  });
24143
24144
  }
@@ -24166,9 +24167,9 @@ class ComposedHandler {
24166
24167
  adapter.reset();
24167
24168
  const messages = adapter.convertMessages(claudeRequest, filterIdentity);
24168
24169
  let tools = adapter.convertTools(claudeRequest, this.options.summarizeTools);
24169
- const maxToolCount = lookupModel(this.targetModel)?.maxToolCount;
24170
+ const maxToolCount = lookupModel(this.bareModelName)?.maxToolCount;
24170
24171
  if (maxToolCount && tools.length > maxToolCount) {
24171
- log(`[ComposedHandler] Truncating tools from ${tools.length} to ${maxToolCount} (model limit for ${this.targetModel})`);
24172
+ log(`[ComposedHandler] Truncating tools from ${tools.length} to ${maxToolCount} (model limit for ${this.bareModelName})`);
24172
24173
  tools = tools.slice(0, maxToolCount);
24173
24174
  }
24174
24175
  if (!this.getModelSupportsVision()) {
@@ -24293,7 +24294,7 @@ class ComposedHandler {
24293
24294
  requestPayload = this.provider.transformPayload(requestPayload);
24294
24295
  }
24295
24296
  await this.middlewareManager.beforeRequest({
24296
- modelId: this.targetModel,
24297
+ modelId: this.bareModelName,
24297
24298
  messages,
24298
24299
  tools,
24299
24300
  stream: true
@@ -24341,7 +24342,7 @@ class ComposedHandler {
24341
24342
  error_code,
24342
24343
  token_strategy: this.options.tokenStrategy ?? "standard",
24343
24344
  adapter_name: this.getActiveAdapterName(),
24344
- middleware_names: this.middlewareManager.getActiveNames(this.targetModel),
24345
+ middleware_names: this.middlewareManager.getActiveNames(this.bareModelName),
24345
24346
  fallback_used: fallbackMeta !== undefined,
24346
24347
  fallback_chain: fallbackMeta?.chain,
24347
24348
  fallback_attempts: fallbackMeta?.attempts,
@@ -24403,7 +24404,7 @@ class ComposedHandler {
24403
24404
  error_code,
24404
24405
  token_strategy: this.options.tokenStrategy ?? "standard",
24405
24406
  adapter_name: this.getActiveAdapterName(),
24406
- middleware_names: this.middlewareManager.getActiveNames(this.targetModel),
24407
+ middleware_names: this.middlewareManager.getActiveNames(this.bareModelName),
24407
24408
  fallback_used: fallbackMeta !== undefined,
24408
24409
  fallback_chain: fallbackMeta?.chain,
24409
24410
  fallback_attempts: fallbackMeta?.attempts,
@@ -24440,7 +24441,7 @@ class ComposedHandler {
24440
24441
  error_code,
24441
24442
  token_strategy: this.options.tokenStrategy ?? "standard",
24442
24443
  adapter_name: this.getActiveAdapterName(),
24443
- middleware_names: this.middlewareManager.getActiveNames(this.targetModel),
24444
+ middleware_names: this.middlewareManager.getActiveNames(this.bareModelName),
24444
24445
  fallback_used: fallbackMeta !== undefined,
24445
24446
  fallback_chain: fallbackMeta?.chain,
24446
24447
  fallback_attempts: fallbackMeta?.attempts,
@@ -24487,7 +24488,7 @@ class ComposedHandler {
24487
24488
  error_code,
24488
24489
  token_strategy: this.options.tokenStrategy ?? "standard",
24489
24490
  adapter_name: this.getActiveAdapterName(),
24490
- middleware_names: this.middlewareManager.getActiveNames(this.targetModel),
24491
+ middleware_names: this.middlewareManager.getActiveNames(this.bareModelName),
24491
24492
  fallback_used: fallbackMeta !== undefined,
24492
24493
  fallback_chain: fallbackMeta?.chain,
24493
24494
  fallback_attempts: fallbackMeta?.attempts,
@@ -24524,7 +24525,7 @@ class ComposedHandler {
24524
24525
  is_free_model: isFreeModel,
24525
24526
  token_strategy: this.options.tokenStrategy ?? "standard",
24526
24527
  adapter_name: this.getActiveAdapterName(),
24527
- middleware_names: this.middlewareManager.getActiveNames(this.targetModel),
24528
+ middleware_names: this.middlewareManager.getActiveNames(this.bareModelName),
24528
24529
  fallback_used: fallbackMeta !== undefined,
24529
24530
  fallback_chain: fallbackMeta?.chain,
24530
24531
  fallback_attempts: fallbackMeta?.attempts,
@@ -24559,19 +24560,19 @@ class ComposedHandler {
24559
24560
  onComplete = undefined;
24560
24561
  }
24561
24562
  };
24562
- const streamFormat = this.provider.overrideStreamFormat?.() ?? this.modelAdapter?.getStreamFormat() ?? this.getAdapter().getStreamFormat();
24563
+ const streamFormat = this.provider.overrideStreamFormat?.() ?? (this.explicitAdapter?.getStreamFormat() ?? this.modelAdapter?.getStreamFormat()) ?? this.getAdapter().getStreamFormat();
24563
24564
  switch (streamFormat) {
24564
24565
  case "openai-sse":
24565
- return createStreamingResponseHandler(c, response, adapter, this.targetModel, this.middlewareManager, onTokenUpdate, claudeRequest.tools, toolNameMap);
24566
+ return createStreamingResponseHandler(c, response, adapter, this.bareModelName, this.middlewareManager, onTokenUpdate, claudeRequest.tools, toolNameMap);
24566
24567
  case "openai-responses-sse":
24567
24568
  return createResponsesStreamHandler(c, response, {
24568
- modelName: this.targetModel,
24569
+ modelName: this.bareModelName,
24569
24570
  onTokenUpdate,
24570
24571
  toolNameMap: adapter.getToolNameMap()
24571
24572
  });
24572
24573
  case "anthropic-sse":
24573
24574
  return createAnthropicPassthroughStream(c, response, {
24574
- modelName: this.targetModel,
24575
+ modelName: this.bareModelName,
24575
24576
  onTokenUpdate
24576
24577
  });
24577
24578
  case "gemini-sse": {
@@ -24581,7 +24582,7 @@ class ComposedHandler {
24581
24582
  }
24582
24583
  };
24583
24584
  return createGeminiSseStream(c, response, {
24584
- modelName: this.targetModel,
24585
+ modelName: this.bareModelName,
24585
24586
  adapter,
24586
24587
  middlewareManager: this.middlewareManager,
24587
24588
  onTokenUpdate,
@@ -24591,7 +24592,7 @@ class ComposedHandler {
24591
24592
  }
24592
24593
  case "ollama-jsonl":
24593
24594
  return createOllamaJsonlStream(c, response, {
24594
- modelName: this.targetModel,
24595
+ modelName: this.bareModelName,
24595
24596
  onTokenUpdate
24596
24597
  });
24597
24598
  default:
@@ -24606,8 +24607,7 @@ class ComposedHandler {
24606
24607
  const fn = this.provider.getQuotaRemaining;
24607
24608
  if (typeof fn !== "function")
24608
24609
  return;
24609
- const bareModel = this.targetModel.includes("@") ? this.targetModel.split("@")[1] : this.targetModel;
24610
- const remaining = await fn.call(this.provider, bareModel);
24610
+ const remaining = await fn.call(this.provider, this.bareModelName);
24611
24611
  if (typeof remaining === "number") {
24612
24612
  this.tokenTracker.setQuotaRemaining(remaining);
24613
24613
  this.tokenTracker.rewrite();
@@ -24961,11 +24961,49 @@ var init_static_fallback = __esm(() => {
24961
24961
  };
24962
24962
  });
24963
24963
 
24964
- // src/providers/catalog-resolvers/openrouter.ts
24964
+ // src/providers/all-models-cache.ts
24965
24965
  import { readFileSync as readFileSync6, existsSync as existsSync8, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "fs";
24966
- import { join as join10 } from "path";
24966
+ import { join as join10, dirname as dirname2 } from "path";
24967
24967
  import { homedir as homedir9 } from "os";
24968
+ function readAllModelsCache(path = ALL_MODELS_CACHE_PATH) {
24969
+ if (!existsSync8(path))
24970
+ return null;
24971
+ let raw2;
24972
+ try {
24973
+ raw2 = JSON.parse(readFileSync6(path, "utf-8"));
24974
+ } catch {
24975
+ return null;
24976
+ }
24977
+ if (!raw2 || typeof raw2 !== "object")
24978
+ return null;
24979
+ const data = raw2;
24980
+ const lastUpdated = typeof data.lastUpdated === "string" ? data.lastUpdated : new Date(0).toISOString();
24981
+ const models = Array.isArray(data.models) ? data.models : [];
24982
+ const entries = Array.isArray(data.entries) ? data.entries : [];
24983
+ return {
24984
+ version: 2,
24985
+ lastUpdated,
24986
+ entries,
24987
+ models
24988
+ };
24989
+ }
24990
+ function writeAllModelsCache(data, path = ALL_MODELS_CACHE_PATH) {
24991
+ const existing = readAllModelsCache(path);
24992
+ const merged = {
24993
+ version: 2,
24994
+ lastUpdated: data.lastUpdated ?? new Date().toISOString(),
24995
+ entries: data.entries ?? existing?.entries ?? [],
24996
+ models: data.models ?? existing?.models ?? []
24997
+ };
24998
+ mkdirSync8(dirname2(path), { recursive: true });
24999
+ writeFileSync8(path, JSON.stringify(merged), "utf-8");
25000
+ }
25001
+ var ALL_MODELS_CACHE_PATH;
25002
+ var init_all_models_cache = __esm(() => {
25003
+ ALL_MODELS_CACHE_PATH = join10(homedir9(), ".claudish", "all-models.json");
25004
+ });
24968
25005
 
25006
+ // src/providers/catalog-resolvers/openrouter.ts
24969
25007
  class OpenRouterCatalogResolver {
24970
25008
  provider = "openrouter";
24971
25009
  resolveSync(userInput) {
@@ -25051,22 +25089,20 @@ class OpenRouterCatalogResolver {
25051
25089
  _getEntries() {
25052
25090
  if (_memCache)
25053
25091
  return _memCache;
25054
- if (existsSync8(DISK_CACHE_PATH)) {
25055
- try {
25056
- const data = JSON.parse(readFileSync6(DISK_CACHE_PATH, "utf-8"));
25057
- if (data.version === 2 && Array.isArray(data.entries) && data.entries.length > 0) {
25058
- _memCache = data.entries;
25059
- return _memCache;
25060
- }
25061
- if (Array.isArray(data.models) && data.models.length > 0) {
25062
- _memCache = data.models.map((m) => ({
25063
- modelId: m.id.includes("/") ? m.id.split("/").slice(1).join("/") : m.id,
25064
- aliases: [],
25065
- sources: { "openrouter-api": { externalId: m.id } }
25066
- }));
25067
- return _memCache;
25068
- }
25069
- } catch {}
25092
+ const cache = readAllModelsCache();
25093
+ if (!cache)
25094
+ return null;
25095
+ if (cache.entries.length > 0) {
25096
+ _memCache = cache.entries;
25097
+ return _memCache;
25098
+ }
25099
+ if (cache.models.length > 0) {
25100
+ _memCache = cache.models.map((m) => ({
25101
+ modelId: m.id.includes("/") ? m.id.split("/").slice(1).join("/") : m.id,
25102
+ aliases: [],
25103
+ sources: { "openrouter-api": { externalId: m.id } }
25104
+ }));
25105
+ return _memCache;
25070
25106
  }
25071
25107
  return null;
25072
25108
  }
@@ -25089,22 +25125,17 @@ class OpenRouterCatalogResolver {
25089
25125
  backwardCompatModels.push({ id: orSource.externalId });
25090
25126
  }
25091
25127
  }
25092
- const cacheDir = join10(homedir9(), ".claudish");
25093
- mkdirSync8(cacheDir, { recursive: true });
25094
- const diskData = {
25095
- version: 2,
25096
- lastUpdated: new Date().toISOString(),
25128
+ writeAllModelsCache({
25097
25129
  entries: data.models,
25098
25130
  models: backwardCompatModels
25099
- };
25100
- writeFileSync8(DISK_CACHE_PATH, JSON.stringify(diskData), "utf-8");
25131
+ });
25101
25132
  } catch {}
25102
25133
  }
25103
25134
  }
25104
- var FIREBASE_CATALOG_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/queryModels?status=active&catalog=slim&limit=1000", DISK_CACHE_PATH, _memCache = null, _warmPromise = null;
25135
+ var FIREBASE_CATALOG_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/queryModels?status=active&catalog=slim&limit=1000", _memCache = null, _warmPromise = null;
25105
25136
  var init_openrouter2 = __esm(() => {
25106
25137
  init_static_fallback();
25107
- DISK_CACHE_PATH = join10(homedir9(), ".claudish", "all-models.json");
25138
+ init_all_models_cache();
25108
25139
  });
25109
25140
 
25110
25141
  // src/providers/catalog-resolvers/litellm.ts
@@ -29380,10 +29411,12 @@ var init_port_manager = () => {};
29380
29411
  // src/mcp-server.ts
29381
29412
  var exports_mcp_server = {};
29382
29413
  __export(exports_mcp_server, {
29383
- startMcpServer: () => startMcpServer
29414
+ startMcpServer: () => startMcpServer,
29415
+ runPromptViaProxy: () => runPromptViaProxy,
29416
+ parseAnthropicSse: () => parseAnthropicSse
29384
29417
  });
29385
29418
  import { readFileSync as readFileSync18, existsSync as existsSync21, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, readdirSync as readdirSync3 } from "fs";
29386
- import { join as join23, dirname as dirname2 } from "path";
29419
+ import { join as join23, dirname as dirname3 } from "path";
29387
29420
  import { homedir as homedir22 } from "os";
29388
29421
  import { fileURLToPath as fileURLToPath2 } from "url";
29389
29422
  function loadRecommendedModels() {
@@ -29424,9 +29457,9 @@ function parseCtx(s) {
29424
29457
  return parseInt(s) || 0;
29425
29458
  }
29426
29459
  async function loadAllModels(forceRefresh = false) {
29427
- if (!forceRefresh && existsSync21(ALL_MODELS_CACHE_PATH)) {
29460
+ if (!forceRefresh && existsSync21(ALL_MODELS_CACHE_PATH2)) {
29428
29461
  try {
29429
- const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH, "utf-8"));
29462
+ const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH2, "utf-8"));
29430
29463
  const lastUpdated = new Date(cacheData.lastUpdated);
29431
29464
  const ageInDays = (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
29432
29465
  if (ageInDays <= CACHE_MAX_AGE_DAYS) {
@@ -29441,11 +29474,11 @@ async function loadAllModels(forceRefresh = false) {
29441
29474
  const data = await response.json();
29442
29475
  const models = data.data || [];
29443
29476
  mkdirSync10(CLAUDISH_CACHE_DIR, { recursive: true });
29444
- writeFileSync10(ALL_MODELS_CACHE_PATH, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
29477
+ writeFileSync10(ALL_MODELS_CACHE_PATH2, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
29445
29478
  return models;
29446
29479
  } catch {
29447
- if (existsSync21(ALL_MODELS_CACHE_PATH)) {
29448
- const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH, "utf-8"));
29480
+ if (existsSync21(ALL_MODELS_CACHE_PATH2)) {
29481
+ const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH2, "utf-8"));
29449
29482
  return cacheData.models || [];
29450
29483
  }
29451
29484
  return [];
@@ -30321,7 +30354,7 @@ function startMcpServer() {
30321
30354
  process.exit(1);
30322
30355
  });
30323
30356
  }
30324
- var import_dotenv2, __filename3, __dirname3, RECOMMENDED_MODELS_PATH, CLAUDISH_CACHE_DIR, ALL_MODELS_CACHE_PATH, CACHE_MAX_AGE_DAYS = 2, INSTRUCTIONS = `Claudish MCP server provides access to external AI models (OpenRouter, Ollama, LM Studio, etc.) for coding tasks.
30357
+ var import_dotenv2, __filename3, __dirname3, RECOMMENDED_MODELS_PATH, CLAUDISH_CACHE_DIR, ALL_MODELS_CACHE_PATH2, CACHE_MAX_AGE_DAYS = 2, INSTRUCTIONS = `Claudish MCP server provides access to external AI models (OpenRouter, Ollama, LM Studio, etc.) for coding tasks.
30325
30358
 
30326
30359
  ## Channel Mode \u2014 External Model Sessions
30327
30360
 
@@ -30357,10 +30390,10 @@ var init_mcp_server = __esm(() => {
30357
30390
  import_dotenv2 = __toESM(require_main(), 1);
30358
30391
  import_dotenv2.config();
30359
30392
  __filename3 = fileURLToPath2(import.meta.url);
30360
- __dirname3 = dirname2(__filename3);
30393
+ __dirname3 = dirname3(__filename3);
30361
30394
  RECOMMENDED_MODELS_PATH = join23(__dirname3, "../recommended-models.json");
30362
30395
  CLAUDISH_CACHE_DIR = join23(homedir22(), ".claudish");
30363
- ALL_MODELS_CACHE_PATH = join23(CLAUDISH_CACHE_DIR, "all-models.json");
30396
+ ALL_MODELS_CACHE_PATH2 = join23(CLAUDISH_CACHE_DIR, "all-models.json");
30364
30397
  });
30365
30398
 
30366
30399
  // ../../node_modules/.bun/@inquirer+core@11.0.1+04f2146be16c61ef/node_modules/@inquirer/core/dist/lib/key.js
@@ -43540,7 +43573,7 @@ import { EventEmitter } from "events";
43540
43573
  import { Buffer as Buffer2 } from "buffer";
43541
43574
  import { Buffer as Buffer3 } from "buffer";
43542
43575
  import { EventEmitter as EventEmitter2 } from "events";
43543
- import { resolve as resolve3, dirname as dirname3 } from "path";
43576
+ import { resolve as resolve3, dirname as dirname4 } from "path";
43544
43577
  import { fileURLToPath as fileURLToPath3 } from "url";
43545
43578
  import { resolve as resolve22, isAbsolute, parse as parse6 } from "path";
43546
43579
  import { existsSync as existsSync22 } from "fs";
@@ -45885,24 +45918,24 @@ function getParsers() {
45885
45918
  {
45886
45919
  filetype: "javascript",
45887
45920
  queries: {
45888
- highlights: [resolve3(dirname3(fileURLToPath3(import.meta.url)), highlights_default)]
45921
+ highlights: [resolve3(dirname4(fileURLToPath3(import.meta.url)), highlights_default)]
45889
45922
  },
45890
- wasm: resolve3(dirname3(fileURLToPath3(import.meta.url)), tree_sitter_javascript_default)
45923
+ wasm: resolve3(dirname4(fileURLToPath3(import.meta.url)), tree_sitter_javascript_default)
45891
45924
  },
45892
45925
  {
45893
45926
  filetype: "typescript",
45894
45927
  queries: {
45895
- highlights: [resolve3(dirname3(fileURLToPath3(import.meta.url)), highlights_default2)]
45928
+ highlights: [resolve3(dirname4(fileURLToPath3(import.meta.url)), highlights_default2)]
45896
45929
  },
45897
- wasm: resolve3(dirname3(fileURLToPath3(import.meta.url)), tree_sitter_typescript_default)
45930
+ wasm: resolve3(dirname4(fileURLToPath3(import.meta.url)), tree_sitter_typescript_default)
45898
45931
  },
45899
45932
  {
45900
45933
  filetype: "markdown",
45901
45934
  queries: {
45902
- highlights: [resolve3(dirname3(fileURLToPath3(import.meta.url)), highlights_default3)],
45903
- injections: [resolve3(dirname3(fileURLToPath3(import.meta.url)), injections_default)]
45935
+ highlights: [resolve3(dirname4(fileURLToPath3(import.meta.url)), highlights_default3)],
45936
+ injections: [resolve3(dirname4(fileURLToPath3(import.meta.url)), injections_default)]
45904
45937
  },
45905
- wasm: resolve3(dirname3(fileURLToPath3(import.meta.url)), tree_sitter_markdown_default),
45938
+ wasm: resolve3(dirname4(fileURLToPath3(import.meta.url)), tree_sitter_markdown_default),
45906
45939
  injectionMapping: {
45907
45940
  nodeTypes: {
45908
45941
  inline: "markdown_inline",
@@ -45921,16 +45954,16 @@ function getParsers() {
45921
45954
  {
45922
45955
  filetype: "markdown_inline",
45923
45956
  queries: {
45924
- highlights: [resolve3(dirname3(fileURLToPath3(import.meta.url)), highlights_default4)]
45957
+ highlights: [resolve3(dirname4(fileURLToPath3(import.meta.url)), highlights_default4)]
45925
45958
  },
45926
- wasm: resolve3(dirname3(fileURLToPath3(import.meta.url)), tree_sitter_markdown_inline_default)
45959
+ wasm: resolve3(dirname4(fileURLToPath3(import.meta.url)), tree_sitter_markdown_inline_default)
45927
45960
  },
45928
45961
  {
45929
45962
  filetype: "zig",
45930
45963
  queries: {
45931
- highlights: [resolve3(dirname3(fileURLToPath3(import.meta.url)), highlights_default5)]
45964
+ highlights: [resolve3(dirname4(fileURLToPath3(import.meta.url)), highlights_default5)]
45932
45965
  },
45933
- wasm: resolve3(dirname3(fileURLToPath3(import.meta.url)), tree_sitter_zig_default)
45966
+ wasm: resolve3(dirname4(fileURLToPath3(import.meta.url)), tree_sitter_zig_default)
45934
45967
  }
45935
45968
  ];
45936
45969
  }
@@ -100237,7 +100270,7 @@ import {
100237
100270
  unlinkSync as unlinkSync7
100238
100271
  } from "fs";
100239
100272
  import { fileURLToPath as fileURLToPath4 } from "url";
100240
- import { dirname as dirname4, join as join25 } from "path";
100273
+ import { dirname as dirname5, join as join25 } from "path";
100241
100274
  import { homedir as homedir23 } from "os";
100242
100275
  function getVersion3() {
100243
100276
  return VERSION;
@@ -102016,7 +102049,7 @@ var init_cli = __esm(async () => {
102016
102049
  init_provider_resolver();
102017
102050
  await init_probe_tui_runtime();
102018
102051
  __filename4 = fileURLToPath4(import.meta.url);
102019
- __dirname4 = dirname4(__filename4);
102052
+ __dirname4 = dirname5(__filename4);
102020
102053
  CLAUDISH_CACHE_DIR2 = join25(homedir23(), ".claudish");
102021
102054
  BUNDLED_MODELS_PATH = join25(__dirname4, "../recommended-models.json");
102022
102055
  CACHED_MODELS_PATH = join25(CLAUDISH_CACHE_DIR2, "recommended-models.json");
@@ -102382,7 +102415,7 @@ __export(exports_model_selector, {
102382
102415
  confirmAction: () => confirmAction
102383
102416
  });
102384
102417
  import { readFileSync as readFileSync22, writeFileSync as writeFileSync15, existsSync as existsSync27, mkdirSync as mkdirSync13 } from "fs";
102385
- import { join as join27, dirname as dirname5 } from "path";
102418
+ import { join as join27, dirname as dirname6 } from "path";
102386
102419
  import { homedir as homedir25 } from "os";
102387
102420
  import { fileURLToPath as fileURLToPath5 } from "url";
102388
102421
  function loadRecommendedModels2() {
@@ -103617,7 +103650,7 @@ var init_model_selector = __esm(() => {
103617
103650
  init_model_loader();
103618
103651
  init_provider_definitions();
103619
103652
  __filename5 = fileURLToPath5(import.meta.url);
103620
- __dirname5 = dirname5(__filename5);
103653
+ __dirname5 = dirname6(__filename5);
103621
103654
  CLAUDISH_CACHE_DIR3 = join27(homedir25(), ".claudish");
103622
103655
  ALL_MODELS_JSON_PATH2 = join27(CLAUDISH_CACHE_DIR3, "all-models.json");
103623
103656
  RECOMMENDED_MODELS_JSON_PATH = join27(__dirname5, "../recommended-models.json");
@@ -107726,14 +107759,14 @@ __export(exports_team_grid, {
107726
107759
  import { spawn as spawn5 } from "child_process";
107727
107760
  import {
107728
107761
  existsSync as existsSync29,
107729
- mkdirSync as mkdirSync16,
107730
107762
  readFileSync as readFileSync24,
107731
- unlinkSync as unlinkSync11,
107732
107763
  writeFileSync as writeFileSync18
107733
107764
  } from "fs";
107734
- import { dirname as dirname6, join as join30 } from "path";
107765
+ import { dirname as dirname7, join as join30 } from "path";
107735
107766
  import { fileURLToPath as fileURLToPath6 } from "url";
107736
107767
  import { execSync as execSync2 } from "child_process";
107768
+ import { connect as netConnect } from "net";
107769
+ import { setTimeout as wait } from "timers/promises";
107737
107770
  function resolveRouteInfo(modelId) {
107738
107771
  const parsed = parseModelSpec(modelId);
107739
107772
  if (parsed.isExplicitProvider) {
@@ -107787,21 +107820,22 @@ function resolveRouteInfo(modelId) {
107787
107820
  source: "auto"
107788
107821
  };
107789
107822
  }
107790
- function buildPaneHeader(model, prompt) {
107791
- const route = resolveRouteInfo(model);
107792
- const esc2 = (s) => s.replace(/'/g, "'\\''");
107793
- const bgColors = [
107794
- "48;2;40;90;180",
107795
- "48;2;140;60;160",
107796
- "48;2;30;130;100",
107797
- "48;2;160;80;40",
107798
- "48;2;60;120;60",
107799
- "48;2;160;50;70"
107800
- ];
107823
+ function pickBannerColor(model, used) {
107801
107824
  let hash = 0;
107802
107825
  for (let i = 0;i < model.length; i++)
107803
107826
  hash = (hash << 5) - hash + model.charCodeAt(i) | 0;
107804
- const bg2 = bgColors[Math.abs(hash) % bgColors.length];
107827
+ const start = Math.abs(hash) % BANNER_BG_COLORS.length;
107828
+ let idx = start;
107829
+ if (used.size < BANNER_BG_COLORS.length) {
107830
+ while (used.has(idx))
107831
+ idx = (idx + 1) % BANNER_BG_COLORS.length;
107832
+ }
107833
+ used.add(idx);
107834
+ return BANNER_BG_COLORS[idx];
107835
+ }
107836
+ function buildPaneHeader(model, prompt, bg2) {
107837
+ const route = resolveRouteInfo(model);
107838
+ const esc2 = (s) => s.replace(/'/g, "'\\''");
107805
107839
  const chainStr = route.chain.join(" \u2192 ");
107806
107840
  const sourceLabel = route.sourceDetail ? `${route.source}: ${route.sourceDetail}` : route.source;
107807
107841
  const lines = [];
@@ -107815,7 +107849,7 @@ function buildPaneHeader(model, prompt) {
107815
107849
  }
107816
107850
  function findMagmuxBinary() {
107817
107851
  const thisFile = fileURLToPath6(import.meta.url);
107818
- const thisDir = dirname6(thisFile);
107852
+ const thisDir = dirname7(thisFile);
107819
107853
  const pkgRoot = join30(thisDir, "..");
107820
107854
  const platform3 = process.platform;
107821
107855
  const arch = process.arch;
@@ -107829,7 +107863,7 @@ function findMagmuxBinary() {
107829
107863
  const candidate = join30(searchDir, "node_modules", pkgName, "bin", "magmux");
107830
107864
  if (existsSync29(candidate))
107831
107865
  return candidate;
107832
- const parent = dirname6(searchDir);
107866
+ const parent = dirname7(searchDir);
107833
107867
  if (parent === searchDir)
107834
107868
  break;
107835
107869
  searchDir = parent;
@@ -107843,133 +107877,113 @@ function findMagmuxBinary() {
107843
107877
  throw new Error(`magmux not found. Install it:
107844
107878
  brew install MadAppGang/tap/magmux`);
107845
107879
  }
107846
- function finalizeStatus(statusPath, sessionPath, anonIds, mode) {
107847
- const statusCache = JSON.parse(readFileSync24(statusPath, "utf-8"));
107848
- for (const anonId of anonIds) {
107849
- const current = statusCache.models[anonId];
107850
- if (current.state === "COMPLETED" || current.state === "FAILED")
107851
- continue;
107852
- const exitCodePath = join30(sessionPath, "work", anonId, ".exit-code");
107853
- if (existsSync29(exitCodePath)) {
107854
- const code = parseInt(readFileSync24(exitCodePath, "utf-8").trim(), 10);
107855
- statusCache.models[anonId] = {
107856
- ...current,
107857
- state: code === 0 ? "COMPLETED" : "FAILED",
107858
- exitCode: code,
107859
- startedAt: current.startedAt ?? statusCache.startedAt,
107860
- completedAt: new Date().toISOString()
107861
- };
107862
- } else if (mode === "interactive") {
107863
- statusCache.models[anonId] = {
107864
- ...current,
107865
- state: "COMPLETED",
107866
- exitCode: 0,
107867
- startedAt: current.startedAt ?? statusCache.startedAt,
107868
- completedAt: new Date().toISOString()
107880
+ async function subscribeToMagmux(sockPath, onEvent) {
107881
+ let client = null;
107882
+ for (let attempt = 0;attempt < 40; attempt++) {
107883
+ if (existsSync29(sockPath)) {
107884
+ try {
107885
+ client = await new Promise((resolve4, reject) => {
107886
+ const s = netConnect(sockPath);
107887
+ s.once("connect", () => resolve4(s));
107888
+ s.once("error", reject);
107889
+ });
107890
+ break;
107891
+ } catch {}
107892
+ }
107893
+ await wait(50);
107894
+ }
107895
+ if (!client) {
107896
+ return { results: null, client: null };
107897
+ }
107898
+ return await new Promise((resolve4) => {
107899
+ let buf = "";
107900
+ let finalResults = null;
107901
+ client.on("data", (chunk) => {
107902
+ buf += chunk.toString("utf-8");
107903
+ let nl = buf.indexOf(`
107904
+ `);
107905
+ while (nl >= 0) {
107906
+ const line = buf.slice(0, nl).trim();
107907
+ buf = buf.slice(nl + 1);
107908
+ nl = buf.indexOf(`
107909
+ `);
107910
+ if (!line)
107911
+ continue;
107912
+ try {
107913
+ const evt = JSON.parse(line);
107914
+ onEvent?.(evt);
107915
+ if (evt.type === "results") {
107916
+ finalResults = evt;
107917
+ }
107918
+ } catch {}
107919
+ }
107920
+ });
107921
+ const done = () => resolve4({ results: finalResults, client });
107922
+ client.once("end", done);
107923
+ client.once("close", done);
107924
+ client.once("error", done);
107925
+ });
107926
+ }
107927
+ function buildTeamStatus(manifest, startedAt, results) {
107928
+ const anonIds = Object.keys(manifest.models);
107929
+ const models = {};
107930
+ for (let i = 0;i < anonIds.length; i++) {
107931
+ const anonId = anonIds[i];
107932
+ const result = results?.find((r) => r.pane === i);
107933
+ if (!result) {
107934
+ models[anonId] = {
107935
+ state: "TIMEOUT",
107936
+ exitCode: null,
107937
+ startedAt,
107938
+ completedAt: null,
107939
+ outputSize: 0
107869
107940
  };
107870
- } else {
107871
- statusCache.models[anonId] = { ...current, state: "TIMEOUT" };
107941
+ continue;
107872
107942
  }
107943
+ let state;
107944
+ switch (result.state) {
107945
+ case "completed":
107946
+ case "awaiting_input":
107947
+ state = "COMPLETED";
107948
+ break;
107949
+ case "failed":
107950
+ state = "FAILED";
107951
+ break;
107952
+ default:
107953
+ state = "TIMEOUT";
107954
+ }
107955
+ models[anonId] = {
107956
+ state,
107957
+ exitCode: result.exitCode,
107958
+ startedAt: result.startedAt ?? startedAt,
107959
+ completedAt: result.completedAt ?? new Date().toISOString(),
107960
+ outputSize: result.response?.length ?? 0
107961
+ };
107873
107962
  }
107874
- writeFileSync18(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
107963
+ return { startedAt, models };
107875
107964
  }
107876
107965
  async function runWithGrid(sessionPath, models, input, opts) {
107877
107966
  const mode = opts?.mode ?? "default";
107878
107967
  const keep = opts?.keep ?? false;
107879
107968
  const manifest = setupSession(sessionPath, models, input);
107880
- mkdirSync16(join30(sessionPath, "errors"), { recursive: true });
107881
- for (const anonId of Object.keys(manifest.models)) {
107882
- const stale = join30(sessionPath, "work", anonId, ".exit-code");
107883
- try {
107884
- unlinkSync11(stale);
107885
- } catch {}
107886
- }
107969
+ const startedAt = new Date().toISOString();
107887
107970
  const gridfilePath = join30(sessionPath, "gridfile.txt");
107888
107971
  const prompt = readFileSync24(join30(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
107889
- const totalPanes = Object.keys(manifest.models).length;
107890
- const workDir = join30(sessionPath, "work");
107891
- const statusJsonAllDone = JSON.stringify({
107892
- cmd: "status",
107893
- text: `C: claudish team G: ${totalPanes} done G: complete D: __TS__ D: ctrl-g q to quit`
107894
- });
107895
- const statusJsonWithFails = JSON.stringify({
107896
- cmd: "status",
107897
- text: `C: claudish team G: __D__ done R: __F__ failed D: __TS__ D: ctrl-g q to quit`
107898
- });
107899
- const statusJsonRunning = JSON.stringify({
107900
- cmd: "status",
107901
- text: `C: claudish team G: __D__ done C: __R__ running R: __F__ failed D: __TS__`
107902
- });
107903
- const tplDir = join30(sessionPath, "status-tpl");
107904
- mkdirSync16(tplDir, { recursive: true });
107905
- writeFileSync18(join30(tplDir, "all-done.json"), statusJsonAllDone);
107906
- writeFileSync18(join30(tplDir, "with-fails.json"), statusJsonWithFails);
107907
- writeFileSync18(join30(tplDir, "running.json"), statusJsonRunning);
107908
- const statusFunc = [
107909
- `_update_bar() {`,
107910
- `_d=0; _f=0;`,
107911
- `for _ecf in $(find ${workDir} -name .exit-code 2>/dev/null); do`,
107912
- `_c=$(cat "$_ecf" 2>/dev/null);`,
107913
- `if [ "$_c" = "0" ]; then _d=$((_d+1)); else _f=$((_f+1)); fi;`,
107914
- `done;`,
107915
- `_r=$((${totalPanes}-_d-_f));`,
107916
- `_e=$SECONDS;`,
107917
- `if [ $_e -ge 60 ]; then _ts="$((_e/60))m $((_e%60))s"; else _ts="\${_e}s"; fi;`,
107918
- `if [ $_r -eq 0 ] && [ $_f -eq 0 ]; then`,
107919
- `sed "s/__TS__/\${_ts}/" ${tplDir}/all-done.json | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
107920
- `elif [ $_r -eq 0 ] && [ $_f -gt 0 ]; then`,
107921
- `sed -e "s/__D__/\${_d}/" -e "s/__F__/\${_f}/" -e "s/__TS__/\${_ts}/" ${tplDir}/with-fails.json | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
107922
- `else`,
107923
- `sed -e "s/__D__/\${_d}/" -e "s/__R__/\${_r}/" -e "s/__F__/\${_f}/" -e "s/__TS__/\${_ts}/" ${tplDir}/running.json | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
107924
- `fi;`,
107925
- `};`
107926
- ].join(" ");
107927
107972
  const rawPrompt = readFileSync24(join30(sessionPath, "input.md"), "utf-8");
107973
+ const usedBannerColors = new Set;
107928
107974
  const gridLines = Object.entries(manifest.models).map(([anonId]) => {
107929
- const errorLog = join30(sessionPath, "errors", `${anonId}.log`);
107930
- const exitCodeFile = join30(sessionPath, "work", anonId, ".exit-code");
107931
107975
  const model = manifest.models[anonId].model;
107932
- const paneIndex = Object.keys(manifest.models).indexOf(anonId);
107933
107976
  if (mode === "interactive") {
107934
- const modelList = Object.values(manifest.models).map((m2) => m2.model).join(", ");
107935
- const interactiveJson = JSON.stringify({
107936
- cmd: "status",
107937
- text: `C: claudish team W: ${modelList} D: ctrl-g Tab switch D: ctrl-g q quit`
107938
- });
107939
- const interactiveJsonFile = join30(tplDir, "interactive.json");
107940
- writeFileSync18(interactiveJsonFile, interactiveJson);
107941
- return [
107942
- `if [ -n "$MAGMUX_SOCK" ]; then cat ${interactiveJsonFile} | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null; fi;`,
107943
- `claudish --model ${model} -i --dangerously-skip-permissions '${prompt}' 2>${errorLog};`,
107944
- `_ec=$?; echo $_ec > ${exitCodeFile}`
107945
- ].join(" ");
107977
+ return `claudish --model ${model} -i --dangerously-skip-permissions '${prompt}'`;
107946
107978
  }
107947
- const header = buildPaneHeader(model, rawPrompt);
107948
- return [
107949
- `${statusFunc}`,
107950
- `if [ -n "$MAGMUX_SOCK" ]; then _update_bar; fi;`,
107951
- `${header}`,
107952
- `claudish --model ${model} -y --quiet '${prompt}' 2>${errorLog};`,
107953
- `_ec=$?; echo $_ec > ${exitCodeFile};`,
107954
- `if [ -n "$MAGMUX_SOCK" ]; then`,
107955
- ` _update_bar;`,
107956
- ` if [ $_ec -eq 0 ]; then`,
107957
- ` echo '{"cmd":"tint","pane":${paneIndex},"color":"green"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
107958
- ` echo '{"cmd":"overlay","pane":${paneIndex},"text":"DONE","color":"green"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
107959
- ` else`,
107960
- ` echo '{"cmd":"tint","pane":${paneIndex},"color":"red"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
107961
- ` echo '{"cmd":"overlay","pane":${paneIndex},"text":"FAIL","color":"red"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
107962
- ` fi;`,
107963
- `fi;`,
107964
- `exec sleep 86400`
107965
- ].join(" ");
107979
+ const bg2 = pickBannerColor(model, usedBannerColors);
107980
+ const header = buildPaneHeader(model, rawPrompt, bg2);
107981
+ return `${header} claudish --model ${model} -y --quiet '${prompt}'`;
107966
107982
  });
107967
107983
  writeFileSync18(gridfilePath, gridLines.join(`
107968
107984
  `) + `
107969
107985
  `, "utf-8");
107970
107986
  const magmuxPath = findMagmuxBinary();
107971
- const statusPath = join30(sessionPath, "status.json");
107972
- const anonIds = Object.keys(manifest.models);
107973
107987
  const spawnArgs = ["-g", gridfilePath];
107974
107988
  if (!keep && mode === "default") {
107975
107989
  spawnArgs.push("-w");
@@ -107978,19 +107992,33 @@ async function runWithGrid(sessionPath, models, input, opts) {
107978
107992
  stdio: "inherit",
107979
107993
  env: { ...process.env }
107980
107994
  });
107981
- await new Promise((resolve4) => {
107995
+ const sockPath = `/tmp/magmux-${proc.pid}.sock`;
107996
+ const subscription = subscribeToMagmux(sockPath);
107997
+ const procExit = new Promise((resolve4) => {
107982
107998
  proc.on("exit", () => resolve4());
107983
107999
  proc.on("error", () => resolve4());
107984
108000
  });
107985
- finalizeStatus(statusPath, sessionPath, anonIds, mode);
107986
- return JSON.parse(readFileSync24(statusPath, "utf-8"));
108001
+ const [{ results }] = await Promise.all([subscription, procExit]);
108002
+ const status = buildTeamStatus(manifest, startedAt, results?.panes ?? null);
108003
+ const statusPath = join30(sessionPath, "status.json");
108004
+ writeFileSync18(statusPath, JSON.stringify(status, null, 2), "utf-8");
108005
+ return status;
107987
108006
  }
108007
+ var BANNER_BG_COLORS;
107988
108008
  var init_team_grid = __esm(() => {
107989
108009
  init_team_orchestrator();
107990
108010
  init_model_parser();
107991
108011
  init_routing_rules();
107992
108012
  init_auto_route();
107993
108013
  init_profile_config();
108014
+ BANNER_BG_COLORS = [
108015
+ "48;2;40;90;180",
108016
+ "48;2;140;60;160",
108017
+ "48;2;30;130;100",
108018
+ "48;2;160;80;40",
108019
+ "48;2;60;120;60",
108020
+ "48;2;160;50;70"
108021
+ ];
107994
108022
  });
107995
108023
 
107996
108024
  // src/index.ts
@@ -108269,6 +108297,14 @@ Team Status`);
108269
108297
  }
108270
108298
  }
108271
108299
  }
108300
+ if (cliConfig.interactive && !cliConfig.monitor && process.stdin.isTTY) {
108301
+ if (typeof process.stdin.setRawMode === "function") {
108302
+ process.stdin.setRawMode(false);
108303
+ }
108304
+ process.stdin.pause();
108305
+ process.stdin.removeAllListeners("data");
108306
+ process.stdin.removeAllListeners("keypress");
108307
+ }
108272
108308
  if (!cliConfig.quiet) {
108273
108309
  const modelsToCheck = [
108274
108310
  cliConfig.model,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "6.13.0",
3
+ "version": "6.13.2",
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",
@@ -59,10 +59,10 @@
59
59
  "ai"
60
60
  ],
61
61
  "optionalDependencies": {
62
- "@claudish/magmux-darwin-arm64": "6.13.0",
63
- "@claudish/magmux-darwin-x64": "6.13.0",
64
- "@claudish/magmux-linux-arm64": "6.13.0",
65
- "@claudish/magmux-linux-x64": "6.13.0"
62
+ "@claudish/magmux-darwin-arm64": "6.13.2",
63
+ "@claudish/magmux-darwin-x64": "6.13.2",
64
+ "@claudish/magmux-linux-arm64": "6.13.2",
65
+ "@claudish/magmux-linux-x64": "6.13.2"
66
66
  },
67
67
  "author": "Jack Rudenko <i@madappgang.com>",
68
68
  "license": "MIT",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "1.2.0",
3
- "lastUpdated": "2026-04-14",
3
+ "lastUpdated": "2026-04-15",
4
4
  "source": "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
5
5
  "models": [
6
6
  {