claudish 10.1.0 → 10.1.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 +613 -483
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -715,7 +715,7 @@ var init_onepassword_config = __esm(() => {
715
715
  });
716
716
 
717
717
  // src/version.ts
718
- var VERSION = "10.1.0";
718
+ var VERSION = "10.1.1";
719
719
 
720
720
  // src/logger.ts
721
721
  import { appendFile, existsSync as existsSync2, mkdirSync, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
@@ -18340,7 +18340,6 @@ var init_catalog_route_bindings = __esm(() => {
18340
18340
  "qwen-coding": { routeId: "qwen", routeProfileId: "modelstudio-coding-plan" },
18341
18341
  "qwen-token-plan": { routeId: "qwen", routeProfileId: "qwencloud-token-plan" },
18342
18342
  "qwen-payg": { routeId: "qwen", routeProfileId: "dashscope-direct" },
18343
- qwen: { routeId: "qwen", routeProfileId: "dashscope-direct" },
18344
18343
  "opencode-zen-go": { routeId: "opencode", routeProfileId: "go-subscription" },
18345
18344
  "opencode-zen": { routeId: "opencode", routeProfileId: "zen" },
18346
18345
  zen: { routeId: "opencode", routeProfileId: "zen" },
@@ -20290,10 +20289,7 @@ class BaseAPIFormat {
20290
20289
  const effort = this.resolveEffortLevel(originalRequest);
20291
20290
  if (!effort)
20292
20291
  return request;
20293
- if (effort === "none" || effort === "minimal") {
20294
- if (reasoning?.mandatory) {
20295
- return this.enableAnthropicEffort(request, effort, reasoning, "mandatory reasoning");
20296
- }
20292
+ if (this.meansReasoningOff(effort, reasoning)) {
20297
20293
  request.thinking = { type: "disabled" };
20298
20294
  log(`[${this.getName()}] effort ${effort} -> thinking.type: disabled for ${this.modelId}`);
20299
20295
  return request;
@@ -20348,9 +20344,23 @@ class BaseAPIFormat {
20348
20344
  if (Object.keys(request.output_config).length === 0)
20349
20345
  delete request.output_config;
20350
20346
  }
20347
+ meansReasoningOff(effort, reasoning) {
20348
+ if (effort !== "none" && effort !== "minimal")
20349
+ return false;
20350
+ if (reasoning?.mandatory)
20351
+ return false;
20352
+ if (effort === "none")
20353
+ return true;
20354
+ const advertised = (reasoning?.efforts ?? []).filter(isEffortLevel);
20355
+ if (advertised.length === 0)
20356
+ return true;
20357
+ const lowest = advertised.reduce((a, b) => EFFORT_ORDER.indexOf(a) <= EFFORT_ORDER.indexOf(b) ? a : b);
20358
+ return lowest === "none";
20359
+ }
20351
20360
  clampToAdvertisedEffort(requested, reasoning) {
20352
- if (this.pinnedEffort)
20361
+ if (this.pinnedEffort && this.pinnedEffort !== "none" && this.pinnedEffort !== "minimal") {
20353
20362
  return this.pinnedEffort;
20363
+ }
20354
20364
  const advertised = (reasoning.efforts ?? []).filter(isEffortLevel);
20355
20365
  if (advertised.length === 0) {
20356
20366
  return isEffortLevel(reasoning.defaultEffort) ? reasoning.defaultEffort : undefined;
@@ -20395,6 +20405,9 @@ class BaseAPIFormat {
20395
20405
  return 38912;
20396
20406
  case "max":
20397
20407
  return;
20408
+ case "none":
20409
+ case "minimal":
20410
+ return MIN_THINKING_BUDGET;
20398
20411
  default:
20399
20412
  return 8192;
20400
20413
  }
@@ -23302,7 +23315,7 @@ var init_deepseek_model_dialect = __esm(() => {
23302
23315
  applyNativeReasoning(request, originalRequest) {
23303
23316
  const effort = this.resolveEffortLevel(originalRequest);
23304
23317
  if (effort && this.acceptsReasoningControls()) {
23305
- if (effort === "none" || effort === "minimal") {
23318
+ if (this.meansReasoningOff(effort, this.lookupReasoningCapability())) {
23306
23319
  request.thinking = { type: "disabled" };
23307
23320
  if (request.reasoning_effort !== undefined)
23308
23321
  delete request.reasoning_effort;
@@ -23359,7 +23372,7 @@ var init_glm_model_dialect = __esm(() => {
23359
23372
  const effort = this.resolveEffortLevel(originalRequest);
23360
23373
  const reasoning = this.lookupReasoningCapability();
23361
23374
  if (effort && this.acceptsThinkingToggle(reasoning)) {
23362
- if (effort === "none" || effort === "minimal") {
23375
+ if (this.meansReasoningOff(effort, reasoning)) {
23363
23376
  request.thinking = { type: "disabled" };
23364
23377
  if (request.reasoning_effort !== undefined)
23365
23378
  delete request.reasoning_effort;
@@ -23758,7 +23771,7 @@ var init_qwen_model_dialect = __esm(() => {
23758
23771
  const effort = this.resolveEffortLevel(originalRequest);
23759
23772
  if (!effort)
23760
23773
  return request;
23761
- if (effort === "none" || effort === "minimal") {
23774
+ if (this.meansReasoningOff(effort, this.lookupReasoningCapability())) {
23762
23775
  request.enable_thinking = false;
23763
23776
  log(`[QwenModelDialect] effort ${effort} -> enable_thinking: false for ${this.modelId}`);
23764
23777
  } else {
@@ -25821,8 +25834,8 @@ async function fetchOllamaModels(options = {}) {
25821
25834
  const data = await response.json();
25822
25835
  const models = data.models || [];
25823
25836
  const enriched = await Promise.all(models.map(async (m) => {
25824
- let capabilities = [];
25825
- if (enrichCapabilities) {
25837
+ let capabilities = Array.isArray(m.capabilities) ? m.capabilities : [];
25838
+ if (enrichCapabilities && capabilities.length === 0) {
25826
25839
  try {
25827
25840
  const showResponse = await fetch(`${host}/api/show`, {
25828
25841
  method: "POST",
@@ -25836,9 +25849,8 @@ async function fetchOllamaModels(options = {}) {
25836
25849
  }
25837
25850
  } catch {}
25838
25851
  }
25839
- const nameLower = String(m.name).toLowerCase();
25840
25852
  const supportsTools = capabilities.includes("tools");
25841
- const isEmbeddingModel = capabilities.includes("embedding") || nameLower.includes("embed");
25853
+ const isEmbeddingModel = capabilities.includes("embedding");
25842
25854
  const sizeInfo = m.details?.parameter_size || "unknown size";
25843
25855
  const toolsIndicator = supportsTools ? "\u2713 tools" : "\u2717 no tools";
25844
25856
  return {
@@ -30287,6 +30299,461 @@ var init_devin = __esm(() => {
30287
30299
  SPEED_SUFFIXES = ["fast", "priority"];
30288
30300
  });
30289
30301
 
30302
+ // src/providers/transport/probe-discovery.ts
30303
+ function ollamaReported(row) {
30304
+ const caps = Array.isArray(row.capabilities) ? row.capabilities : [];
30305
+ if (caps.includes("completion"))
30306
+ return "chat";
30307
+ if (caps.includes("embedding"))
30308
+ return "not-chat";
30309
+ return;
30310
+ }
30311
+ function lmStudioReported(row) {
30312
+ if (row.type === "llm" || row.type === "vlm")
30313
+ return "chat";
30314
+ if (row.type === "embeddings" || row.type === "embedding")
30315
+ return "not-chat";
30316
+ return;
30317
+ }
30318
+ function isSmallName(name) {
30319
+ return SMALL_MODEL_PATTERNS.some((re) => re.test(name));
30320
+ }
30321
+ function _clearChatCapabilityIndex() {
30322
+ _catalogChatIndex.clear();
30323
+ }
30324
+ function catalogKey(name) {
30325
+ const lower = name.toLowerCase();
30326
+ return lower.includes("/") ? lower.slice(lower.lastIndexOf("/") + 1) : lower;
30327
+ }
30328
+ function indexOutputModality(index, keys, modalities) {
30329
+ if (!Array.isArray(modalities) || modalities.length === 0)
30330
+ return;
30331
+ const target = modalities.includes("text") ? index.textOutput : index.nonTextOutput;
30332
+ for (const k of keys)
30333
+ target.add(k);
30334
+ }
30335
+ function indexInputModality(index, keys, modalities) {
30336
+ if (!Array.isArray(modalities) || modalities.length === 0)
30337
+ return;
30338
+ if (modalities.includes("text"))
30339
+ return;
30340
+ for (const k of keys)
30341
+ index.nonTextInput.add(k);
30342
+ }
30343
+ function catalogCapabilityIndex(cachePath) {
30344
+ const key = cachePath ?? "";
30345
+ const hit = _catalogChatIndex.get(key);
30346
+ if (hit && hit.expiresAt > Date.now())
30347
+ return hit.index;
30348
+ const index = {
30349
+ chat: new Set,
30350
+ textOutput: new Set,
30351
+ nonTextOutput: new Set,
30352
+ nonTextInput: new Set,
30353
+ videoOutput: new Set,
30354
+ videoOutputKnown: new Set,
30355
+ known: new Set
30356
+ };
30357
+ for (const entry of readAllModelsCache(cachePath)?.entries ?? []) {
30358
+ const keys = [catalogKey(entry.modelId), ...(entry.aliases ?? []).map(catalogKey)];
30359
+ for (const k of keys)
30360
+ index.known.add(k);
30361
+ indexOutputModality(index, keys, entry.outputModalities);
30362
+ indexInputModality(index, keys, entry.inputModalities);
30363
+ if (entry.videoOutput !== undefined) {
30364
+ for (const k of keys)
30365
+ index.videoOutputKnown.add(k);
30366
+ }
30367
+ if (entry.videoOutput === true) {
30368
+ for (const k of keys)
30369
+ index.videoOutput.add(k);
30370
+ continue;
30371
+ }
30372
+ const chatShaped = entry.supportsTools === true || entry.supportsThinking === true;
30373
+ if (chatShaped)
30374
+ for (const k of keys)
30375
+ index.chat.add(k);
30376
+ }
30377
+ _catalogChatIndex.set(key, { index, expiresAt: Date.now() + CATALOG_CHAT_INDEX_TTL_MS });
30378
+ return index;
30379
+ }
30380
+ function classifyChatCapability(name, cachePath, reported) {
30381
+ if (name.includes("*"))
30382
+ return "not-chat";
30383
+ if (reported)
30384
+ return reported;
30385
+ const index = catalogCapabilityIndex(cachePath);
30386
+ const key = catalogKey(name);
30387
+ if (index.nonTextOutput.has(key))
30388
+ return "not-chat";
30389
+ if (index.nonTextInput.has(key))
30390
+ return "not-chat";
30391
+ if (index.textOutput.has(key))
30392
+ return "chat";
30393
+ if (index.videoOutput.has(key))
30394
+ return "not-chat";
30395
+ if (index.chat.has(key))
30396
+ return "chat";
30397
+ return "unknown";
30398
+ }
30399
+ function isChatCapable(name) {
30400
+ return classifyChatCapability(name) === "chat";
30401
+ }
30402
+ function isReportedChatCapable(name, reported) {
30403
+ return classifyChatCapability(name, undefined, reported) === "chat";
30404
+ }
30405
+ function unavailableForMissingCapability(names, reportedFor, cachePath) {
30406
+ const catalogSilent = [];
30407
+ const providerSilent = [];
30408
+ for (const name of names) {
30409
+ const reported = reportedFor?.(name);
30410
+ if (classifyChatCapability(name, cachePath, reported) !== "unknown")
30411
+ continue;
30412
+ const index = catalogCapabilityIndex(cachePath);
30413
+ if (index.known.has(catalogKey(name)))
30414
+ catalogSilent.push(name);
30415
+ else
30416
+ providerSilent.push(name);
30417
+ }
30418
+ return { catalogSilent, providerSilent };
30419
+ }
30420
+ function describeNoCandidates(ids, reportedFor, cachePath) {
30421
+ const { catalogSilent, providerSilent } = unavailableForMissingCapability(ids, reportedFor, cachePath);
30422
+ const undescribed = catalogSilent.length + providerSilent.length;
30423
+ if (undescribed === 0) {
30424
+ return `all ${ids.length} listed models are described as non-chat (image, embedding, audio)`;
30425
+ }
30426
+ const sample = [...catalogSilent, ...providerSilent].slice(0, 3).join(", ");
30427
+ const more = undescribed > 3 ? `, +${undescribed - 3} more` : "";
30428
+ const whose = providerSilent.length === 0 ? "the models catalog publishes them without modalities" : catalogSilent.length === 0 ? "this endpoint publishes no capability field" : "neither the models catalog nor this endpoint describes them";
30429
+ return `no capability data for ${undescribed} of ${ids.length} listed models \u2014 ${whose} (${sample}${more})`;
30430
+ }
30431
+ function isStandardName(name) {
30432
+ if (!name.includes("/"))
30433
+ return true;
30434
+ return STANDARD_VENDOR_PREFIXES.some((p) => name.toLowerCase().startsWith(p));
30435
+ }
30436
+ function rankProbeCandidates(names) {
30437
+ return names.filter((name) => !name.includes("*")).sort((a, b) => {
30438
+ const aStd = isStandardName(a);
30439
+ const bStd = isStandardName(b);
30440
+ if (aStd !== bStd)
30441
+ return aStd ? -1 : 1;
30442
+ const aSmall = isSmallName(a);
30443
+ const bSmall = isSmallName(b);
30444
+ if (aSmall !== bSmall)
30445
+ return aSmall ? -1 : 1;
30446
+ return a.localeCompare(b);
30447
+ });
30448
+ }
30449
+ function cacheGet(key, exclude = new Set) {
30450
+ const hit = _cache.get(key);
30451
+ if (!hit)
30452
+ return;
30453
+ if (Date.now() > hit.expiresAt) {
30454
+ _cache.delete(key);
30455
+ return;
30456
+ }
30457
+ if (hit.ranked.length === 0) {
30458
+ return { model: null, reason: hit.reason };
30459
+ }
30460
+ const pick = hit.ranked.find((m) => !exclude.has(m));
30461
+ if (!pick) {
30462
+ return {
30463
+ model: null,
30464
+ reason: `all ${hit.ranked.length} candidate model(s) already tried`
30465
+ };
30466
+ }
30467
+ return { model: pick };
30468
+ }
30469
+ function cacheSetFailure(key, reason) {
30470
+ _cache.set(key, { ranked: [], reason, expiresAt: Date.now() + CACHE_TTL_MS });
30471
+ }
30472
+ function cacheSetRanked(key, ranked) {
30473
+ _cache.set(key, { ranked, expiresAt: Date.now() + CACHE_TTL_MS });
30474
+ }
30475
+ async function discoverViaOpenAIModels(endpoint, headers, cacheKey) {
30476
+ const cached = cacheGet(cacheKey.key, cacheKey.exclude);
30477
+ if (cached !== undefined)
30478
+ return cached;
30479
+ let response;
30480
+ try {
30481
+ response = await fetch(endpoint, {
30482
+ method: "GET",
30483
+ headers,
30484
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
30485
+ });
30486
+ } catch (e) {
30487
+ const reason = classifyFetchError(e, endpoint);
30488
+ log(`[probe-discovery${cacheKey.displayName ? `:${cacheKey.displayName}` : ""}] fetch failed: ${reason}`);
30489
+ cacheSetFailure(cacheKey.key, reason);
30490
+ return { model: null, reason };
30491
+ }
30492
+ if (!response.ok) {
30493
+ const who = cacheKey.displayName ?? "this provider";
30494
+ const authFailure = response.status === 401 || response.status === 403 ? cacheKey.hasApiKey === false ? `the server requires an API key and none is configured for ${who}` : `the server rejected the configured API key for ${who}` : "";
30495
+ const reason = authFailure ? `HTTP ${response.status} from ${endpoint} \u2014 ${authFailure}` : `HTTP ${response.status} from ${endpoint}`;
30496
+ log(`[probe-discovery${cacheKey.displayName ? `:${cacheKey.displayName}` : ""}] ${reason}`);
30497
+ cacheSetFailure(cacheKey.key, reason);
30498
+ return { model: null, reason };
30499
+ }
30500
+ let body;
30501
+ try {
30502
+ body = await response.json();
30503
+ } catch {
30504
+ const reason = "invalid /v1/models response (not JSON)";
30505
+ cacheSetFailure(cacheKey.key, reason);
30506
+ return { model: null, reason };
30507
+ }
30508
+ const ids = extractModelIds(body);
30509
+ if (ids.length === 0) {
30510
+ const url = tryParseUrl(endpoint);
30511
+ const host = url?.host ?? endpoint;
30512
+ const reason = `${host} reachable but no models loaded \u2014 load a model in the server UI`;
30513
+ cacheSetFailure(cacheKey.key, reason);
30514
+ return { model: null, reason };
30515
+ }
30516
+ const ranked = rankProbeCandidates(ids.filter(isChatCapable));
30517
+ if (ranked.length === 0) {
30518
+ const reason = describeNoCandidates(ids);
30519
+ cacheSetFailure(cacheKey.key, reason);
30520
+ return { model: null, reason };
30521
+ }
30522
+ cacheSetRanked(cacheKey.key, ranked);
30523
+ const pick = ranked.find((m) => !cacheKey.exclude?.has(m));
30524
+ if (!pick) {
30525
+ return {
30526
+ model: null,
30527
+ reason: `all ${ranked.length} candidate model(s) already tried`
30528
+ };
30529
+ }
30530
+ return { model: pick };
30531
+ }
30532
+ function classifyFetchError(e, endpoint) {
30533
+ const name = e?.name ?? "";
30534
+ const code = e?.cause?.code ?? "";
30535
+ const msg = e instanceof Error ? e.message : String(e);
30536
+ const url = tryParseUrl(endpoint);
30537
+ const host = url?.host ?? endpoint;
30538
+ const isLocal = !!url && /^(localhost|127\.0\.0\.1|0\.0\.0\.0|::1)$/i.test(url.hostname);
30539
+ if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(msg)) {
30540
+ return `${host} unresponsive (>${FETCH_TIMEOUT_MS / 1000}s) \u2014 check if the server is overloaded`;
30541
+ }
30542
+ if (code === "ENOTFOUND" || code === "EAI_AGAIN") {
30543
+ return `cannot resolve host ${url?.hostname ?? endpoint} \u2014 check the URL`;
30544
+ }
30545
+ const isConnRefused = code === "ECONNREFUSED" || code === "ECONNRESET" || /unable to connect|connection refused|fetch failed/i.test(msg);
30546
+ if (isConnRefused) {
30547
+ if (isLocal) {
30548
+ return `${host} not reachable \u2014 is the server running? Press u to change URL.`;
30549
+ }
30550
+ return `${host} not reachable \u2014 check the URL or network. Press u to change.`;
30551
+ }
30552
+ return `${host}: ${msg}`;
30553
+ }
30554
+ function tryParseUrl(s) {
30555
+ try {
30556
+ return new URL(s);
30557
+ } catch {
30558
+ return null;
30559
+ }
30560
+ }
30561
+ function extractModelIds(body) {
30562
+ if (!body || typeof body !== "object")
30563
+ return [];
30564
+ const data = body;
30565
+ if (Array.isArray(data.data)) {
30566
+ return data.data.map((m) => m && typeof m === "object" ? m.id : null).filter((id) => typeof id === "string" && id.length > 0);
30567
+ }
30568
+ if (Array.isArray(data.models)) {
30569
+ return data.models.map((m) => m && typeof m === "object" ? m.id ?? m.model_name : null).filter((id) => typeof id === "string" && id.length > 0);
30570
+ }
30571
+ return [];
30572
+ }
30573
+ function orderByCost(models) {
30574
+ const sized = models.filter((m) => typeof m.size === "number");
30575
+ const unsized = models.filter((m) => typeof m.size !== "number");
30576
+ const bySize = [...sized].sort((a, b) => (a.size ?? Number.POSITIVE_INFINITY) - (b.size ?? Number.POSITIVE_INFINITY)).map((m) => m.name);
30577
+ return [...bySize, ...rankProbeCandidates(unsized.map((m) => m.name))];
30578
+ }
30579
+ async function discoverViaOllama(baseUrl, cacheKey) {
30580
+ const cached = cacheGet(cacheKey.key, cacheKey.exclude);
30581
+ if (cached !== undefined)
30582
+ return cached;
30583
+ const [psResult, tagsResult] = await Promise.allSettled([
30584
+ fetchOllamaModels2(`${baseUrl}/api/ps`),
30585
+ fetchOllamaModels2(`${baseUrl}/api/tags`)
30586
+ ]);
30587
+ const loadedRaw = psResult.status === "fulfilled" ? psResult.value : [];
30588
+ const tagsRaw = tagsResult.status === "fulfilled" ? tagsResult.value : [];
30589
+ const connectionError = psResult.status === "rejected" ? classifyFetchError(psResult.reason, `${baseUrl}/api/ps`) : tagsResult.status === "rejected" ? classifyFetchError(tagsResult.reason, `${baseUrl}/api/tags`) : undefined;
30590
+ const loaded = loadedRaw.filter((m) => isReportedChatCapable(m.name, ollamaReported(m)));
30591
+ const loadedNames = new Set(loaded.map((m) => m.name));
30592
+ const rest = tagsRaw.filter((m) => isReportedChatCapable(m.name, ollamaReported(m)) && !loadedNames.has(m.name));
30593
+ if (loaded.length === 0 && rest.length === 0) {
30594
+ const listed = [...loadedRaw, ...tagsRaw];
30595
+ const reportedFor = (name) => {
30596
+ const row = listed.find((m) => m.name === name);
30597
+ return row ? ollamaReported(row) : undefined;
30598
+ };
30599
+ const reason = connectionError ?? (listed.length === 0 ? `no models on ${baseUrl} (pull one: ollama pull llama3.2)` : `${describeNoCandidates(listed.map((m) => m.name), reportedFor)} on ${baseUrl}`);
30600
+ cacheSetFailure(cacheKey.key, reason);
30601
+ return { model: null, reason };
30602
+ }
30603
+ const ranked = [...orderByCost(loaded), ...orderByCost(rest)];
30604
+ if (ranked.length === 0) {
30605
+ const reason = "no chat-capable model on Ollama endpoint";
30606
+ cacheSetFailure(cacheKey.key, reason);
30607
+ return { model: null, reason };
30608
+ }
30609
+ cacheSetRanked(cacheKey.key, ranked);
30610
+ const pick = ranked.find((m) => !cacheKey.exclude?.has(m));
30611
+ if (!pick) {
30612
+ return {
30613
+ model: null,
30614
+ reason: `all ${ranked.length} candidate model(s) already tried`
30615
+ };
30616
+ }
30617
+ return { model: pick };
30618
+ }
30619
+ async function discoverViaLMStudio(baseUrl, headers, cacheKey) {
30620
+ const cached = cacheGet(cacheKey.key, cacheKey.exclude);
30621
+ if (cached !== undefined)
30622
+ return cached;
30623
+ let response;
30624
+ try {
30625
+ response = await fetch(`${baseUrl}/api/v0/models`, {
30626
+ method: "GET",
30627
+ headers,
30628
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
30629
+ });
30630
+ } catch (e) {
30631
+ return discoverViaOpenAIModels(`${baseUrl}/v1/models`, headers, cacheKey);
30632
+ }
30633
+ if (!response.ok) {
30634
+ return discoverViaOpenAIModels(`${baseUrl}/v1/models`, headers, cacheKey);
30635
+ }
30636
+ let body;
30637
+ try {
30638
+ body = await response.json();
30639
+ } catch {
30640
+ const reason = "invalid /api/v0/models response (not JSON)";
30641
+ cacheSetFailure(cacheKey.key, reason);
30642
+ return { model: null, reason };
30643
+ }
30644
+ const models = extractLMStudioModels(body);
30645
+ if (models.length === 0) {
30646
+ const url = tryParseUrl(baseUrl);
30647
+ const host = url?.host ?? baseUrl;
30648
+ const reason = `${host} reachable but no models present \u2014 download one in the LM Studio UI`;
30649
+ cacheSetFailure(cacheKey.key, reason);
30650
+ return { model: null, reason };
30651
+ }
30652
+ const chatModels = models.filter((m) => isReportedChatCapable(m.id, lmStudioReported(m)));
30653
+ const loaded = chatModels.filter((m) => m.state === "loaded");
30654
+ const notLoaded = chatModels.filter((m) => m.state !== "loaded");
30655
+ const ranked = [
30656
+ ...rankProbeCandidates(loaded.map((m) => m.id)),
30657
+ ...rankProbeCandidates(notLoaded.map((m) => m.id))
30658
+ ];
30659
+ if (ranked.length === 0) {
30660
+ const url = tryParseUrl(baseUrl);
30661
+ const host = url?.host ?? baseUrl;
30662
+ const reason = `${host} has ${models.length} model(s) but none are chat-capable`;
30663
+ cacheSetFailure(cacheKey.key, reason);
30664
+ return { model: null, reason };
30665
+ }
30666
+ cacheSetRanked(cacheKey.key, ranked);
30667
+ const pick = ranked.find((m) => !cacheKey.exclude?.has(m));
30668
+ if (!pick) {
30669
+ return {
30670
+ model: null,
30671
+ reason: `all ${ranked.length} candidate model(s) already tried`
30672
+ };
30673
+ }
30674
+ return { model: pick };
30675
+ }
30676
+ function extractLMStudioModels(body) {
30677
+ if (!body || typeof body !== "object")
30678
+ return [];
30679
+ const data = body.data;
30680
+ if (!Array.isArray(data))
30681
+ return [];
30682
+ const out = [];
30683
+ for (const m of data) {
30684
+ if (!m || typeof m !== "object")
30685
+ continue;
30686
+ const r = m;
30687
+ if (typeof r.id !== "string" || !r.id)
30688
+ continue;
30689
+ out.push({
30690
+ id: r.id,
30691
+ state: typeof r.state === "string" ? r.state : undefined,
30692
+ type: typeof r.type === "string" ? r.type : undefined
30693
+ });
30694
+ }
30695
+ return out;
30696
+ }
30697
+ async function fetchOllamaModels2(url) {
30698
+ const response = await fetch(url, {
30699
+ method: "GET",
30700
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
30701
+ });
30702
+ if (!response.ok)
30703
+ return [];
30704
+ const body = await response.json().catch(() => null);
30705
+ if (!body?.models)
30706
+ return [];
30707
+ return body.models.map((m) => ({
30708
+ name: typeof m.name === "string" ? m.name : "",
30709
+ size: typeof m.size === "number" ? m.size : undefined,
30710
+ capabilities: Array.isArray(m.capabilities) ? m.capabilities.filter((c) => typeof c === "string") : undefined
30711
+ })).filter((m) => m.name.length > 0);
30712
+ }
30713
+ function invalidateProbeDiscovery(providerSlug) {
30714
+ for (const key of _cache.keys()) {
30715
+ if (key.startsWith(`${providerSlug}:`)) {
30716
+ _cache.delete(key);
30717
+ }
30718
+ }
30719
+ }
30720
+ var _cache, CACHE_TTL_MS, FETCH_TIMEOUT_MS = 5000, SMALL_MODEL_PATTERNS, CATALOG_CHAT_INDEX_TTL_MS = 60000, _catalogChatIndex, STANDARD_VENDOR_PREFIXES;
30721
+ var init_probe_discovery = __esm(() => {
30722
+ init_logger();
30723
+ init_all_models_cache();
30724
+ _cache = new Map;
30725
+ CACHE_TTL_MS = 5 * 60 * 1000;
30726
+ SMALL_MODEL_PATTERNS = [
30727
+ /\bmini\b/i,
30728
+ /\bnano\b/i,
30729
+ /\bflash\b/i,
30730
+ /\blite\b/i,
30731
+ /\bhaiku\b/i,
30732
+ /\bsmall\b/i,
30733
+ /\btiny\b/i,
30734
+ /\b[12345]b\b/i,
30735
+ /\b[78]b\b/i
30736
+ ];
30737
+ _catalogChatIndex = new Map;
30738
+ STANDARD_VENDOR_PREFIXES = [
30739
+ "openai/",
30740
+ "anthropic/",
30741
+ "google/",
30742
+ "gemini/",
30743
+ "meta/",
30744
+ "meta-llama/",
30745
+ "mistralai/",
30746
+ "mistral/",
30747
+ "x-ai/",
30748
+ "deepseek/",
30749
+ "qwen/",
30750
+ "moonshot/",
30751
+ "moonshotai/",
30752
+ "zhipuai/",
30753
+ "z-ai/"
30754
+ ];
30755
+ });
30756
+
30290
30757
  // src/providers/model-discovery-builtins.ts
30291
30758
  function oneLine(text, max = 200) {
30292
30759
  const flat = text.replace(/\s+/g, " ").trim();
@@ -30317,7 +30784,7 @@ async function fetchDevinModelsCatalog() {
30317
30784
  endpoint,
30318
30785
  models: served.map((model) => {
30319
30786
  const { wireId, ...rest } = devinModelsCatalogEntry(model);
30320
- return { id: wireId, ...rest };
30787
+ return { id: wireId, ...rest, reported: "chat" };
30321
30788
  })
30322
30789
  };
30323
30790
  } catch (err) {
@@ -30356,7 +30823,12 @@ async function fetchAntigravityModelsCatalog() {
30356
30823
  endpoint,
30357
30824
  models: selectable.map((id) => {
30358
30825
  const m = meta[id];
30359
- return m?.contextWindow ? { id, contextWindow: m.contextWindow, ignoreCatalogReleaseDate: true } : { id, ignoreCatalogReleaseDate: true };
30826
+ return m?.contextWindow ? {
30827
+ id,
30828
+ contextWindow: m.contextWindow,
30829
+ ignoreCatalogReleaseDate: true,
30830
+ reported: "chat"
30831
+ } : { id, ignoreCatalogReleaseDate: true, reported: "chat" };
30360
30832
  })
30361
30833
  };
30362
30834
  } catch (err) {
@@ -30368,19 +30840,18 @@ async function fetchAntigravityModelsCatalog() {
30368
30840
  }
30369
30841
  async function fetchOllamaModelsCatalog() {
30370
30842
  await Promise.resolve();
30843
+ await Promise.resolve().then(() => init_probe_discovery());
30371
30844
  const endpoint = `${ollamaBaseUrl()}/api/tags`;
30372
30845
  try {
30373
- const installed = await fetchOllamaModels({
30374
- enrichCapabilities: false,
30375
- throwOnError: true
30376
- });
30846
+ const installed = await fetchOllamaModels({ throwOnError: true });
30377
30847
  return {
30378
30848
  kind: "models",
30379
30849
  endpoint,
30380
30850
  models: installed.map((model) => ({
30381
30851
  id: model.name,
30382
30852
  displayName: model.name,
30383
- supportsTools: model.supportsTools
30853
+ supportsTools: model.supportsTools,
30854
+ reported: ollamaReported(model)
30384
30855
  }))
30385
30856
  };
30386
30857
  } catch (err) {
@@ -30558,11 +31029,11 @@ async function discoverViaFetcher(providerName, format) {
30558
31029
  }
30559
31030
  _failures.delete(providerName);
30560
31031
  log(`[model-discovery:${providerName}] discovered ${models.length} models`);
30561
- _cache.set(providerName, { models, expiresAt: Date.now() + CACHE_TTL_MS });
31032
+ _cache2.set(providerName, { models, expiresAt: Date.now() + CACHE_TTL_MS2 });
30562
31033
  return { kind: "served", models };
30563
31034
  }
30564
31035
  async function discoverProviderModelsCatalog(providerName) {
30565
- const cached = _cache.get(providerName);
31036
+ const cached = _cache2.get(providerName);
30566
31037
  if (cached && cached.expiresAt > Date.now())
30567
31038
  return { kind: "served", models: cached.models };
30568
31039
  const def = getProviderByName(providerName);
@@ -30613,7 +31084,7 @@ async function discoverProviderModelsCatalog(providerName) {
30613
31084
  response = await fetch(endpoint, {
30614
31085
  method: "GET",
30615
31086
  headers,
30616
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
31087
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS2)
30617
31088
  });
30618
31089
  } catch (e) {
30619
31090
  return recordFailure({
@@ -30656,7 +31127,7 @@ async function discoverProviderModelsCatalog(providerName) {
30656
31127
  const models = parsed.models;
30657
31128
  _failures.delete(providerName);
30658
31129
  log(`[model-discovery:${providerName}] discovered ${models.length} models: ` + models.map((m) => `${m.id}(${m.contextWindow ?? "?"})`).join(", "));
30659
- _cache.set(providerName, { models, expiresAt: Date.now() + CACHE_TTL_MS });
31130
+ _cache2.set(providerName, { models, expiresAt: Date.now() + CACHE_TTL_MS2 });
30660
31131
  return { kind: "served", models };
30661
31132
  }
30662
31133
  async function discoverProviderModels(providerName) {
@@ -30674,438 +31145,18 @@ function rankDiscoveredModels(models) {
30674
31145
  return diff !== 0 ? diff : compareByReleaseDateDesc(a, b);
30675
31146
  });
30676
31147
  }
30677
- var _fetchers, CACHE_TTL_MS, FETCH_TIMEOUT_MS = 5000, _cache, _failures, MIN_CREATED_SECONDS = 946684800, MAX_CREATED_SECONDS = 4102444800, CONTINUATION_FIELDS;
31148
+ var _fetchers, CACHE_TTL_MS2, FETCH_TIMEOUT_MS2 = 5000, _cache2, _failures, MIN_CREATED_SECONDS = 946684800, MAX_CREATED_SECONDS = 4102444800, CONTINUATION_FIELDS;
30678
31149
  var init_model_discovery = __esm(() => {
30679
31150
  init_authority();
30680
31151
  init_logger();
30681
31152
  init_provider_definitions();
30682
31153
  _fetchers = new Map;
30683
- CACHE_TTL_MS = 5 * 60 * 1000;
30684
- _cache = new Map;
31154
+ CACHE_TTL_MS2 = 5 * 60 * 1000;
31155
+ _cache2 = new Map;
30685
31156
  _failures = new Map;
30686
31157
  CONTINUATION_FIELDS = ["has_more", "next", "next_page", "next_page_token"];
30687
31158
  });
30688
31159
 
30689
- // src/providers/transport/probe-discovery.ts
30690
- function isSmallName(name) {
30691
- return SMALL_MODEL_PATTERNS.some((re) => re.test(name));
30692
- }
30693
- function catalogKey(name) {
30694
- const lower = name.toLowerCase();
30695
- return lower.includes("/") ? lower.slice(lower.lastIndexOf("/") + 1) : lower;
30696
- }
30697
- function indexOutputModality(index, keys, modalities) {
30698
- if (!Array.isArray(modalities) || modalities.length === 0)
30699
- return;
30700
- const target = modalities.includes("text") ? index.textOutput : index.nonTextOutput;
30701
- for (const k of keys)
30702
- target.add(k);
30703
- }
30704
- function catalogCapabilityIndex(cachePath) {
30705
- const key = cachePath ?? "";
30706
- const hit = _catalogChatIndex.get(key);
30707
- if (hit && hit.expiresAt > Date.now())
30708
- return hit.index;
30709
- const index = {
30710
- chat: new Set,
30711
- textOutput: new Set,
30712
- nonTextOutput: new Set,
30713
- videoOutput: new Set,
30714
- videoOutputKnown: new Set
30715
- };
30716
- for (const entry of readAllModelsCache(cachePath)?.entries ?? []) {
30717
- const keys = [catalogKey(entry.modelId), ...(entry.aliases ?? []).map(catalogKey)];
30718
- indexOutputModality(index, keys, entry.outputModalities);
30719
- if (entry.videoOutput !== undefined) {
30720
- for (const k of keys)
30721
- index.videoOutputKnown.add(k);
30722
- }
30723
- if (entry.videoOutput === true) {
30724
- for (const k of keys)
30725
- index.videoOutput.add(k);
30726
- continue;
30727
- }
30728
- const chatShaped = entry.supportsTools === true || entry.supportsThinking === true || entry.supportsVision === true;
30729
- if (chatShaped)
30730
- for (const k of keys)
30731
- index.chat.add(k);
30732
- }
30733
- _catalogChatIndex.set(key, { index, expiresAt: Date.now() + CATALOG_CHAT_INDEX_TTL_MS });
30734
- return index;
30735
- }
30736
- function classifyChatCapability(name, cachePath) {
30737
- if (name.includes("*"))
30738
- return "not-chat";
30739
- const index = catalogCapabilityIndex(cachePath);
30740
- const key = catalogKey(name);
30741
- if (index.nonTextOutput.has(key))
30742
- return "not-chat";
30743
- if (index.textOutput.has(key))
30744
- return "chat";
30745
- if (index.videoOutput.has(key))
30746
- return "not-chat";
30747
- if (NON_CHAT_PATTERNS.some((re) => re.test(name)))
30748
- return "not-chat";
30749
- if (!index.videoOutputKnown.has(key) && VIDEO_OUTPUT_NAME_PATTERNS.some((re) => re.test(name))) {
30750
- return "not-chat";
30751
- }
30752
- if (index.chat.has(key))
30753
- return "chat";
30754
- return "unknown";
30755
- }
30756
- function isChatCapable(name) {
30757
- return classifyChatCapability(name) !== "not-chat";
30758
- }
30759
- function isStandardName(name) {
30760
- if (!name.includes("/"))
30761
- return true;
30762
- return STANDARD_VENDOR_PREFIXES.some((p) => name.toLowerCase().startsWith(p));
30763
- }
30764
- function rankProbeCandidates(names) {
30765
- return names.filter(isChatCapable).sort((a, b) => {
30766
- const aStd = isStandardName(a);
30767
- const bStd = isStandardName(b);
30768
- if (aStd !== bStd)
30769
- return aStd ? -1 : 1;
30770
- const aSmall = isSmallName(a);
30771
- const bSmall = isSmallName(b);
30772
- if (aSmall !== bSmall)
30773
- return aSmall ? -1 : 1;
30774
- return a.localeCompare(b);
30775
- });
30776
- }
30777
- function cacheGet(key, exclude = new Set) {
30778
- const hit = _cache2.get(key);
30779
- if (!hit)
30780
- return;
30781
- if (Date.now() > hit.expiresAt) {
30782
- _cache2.delete(key);
30783
- return;
30784
- }
30785
- if (hit.ranked.length === 0) {
30786
- return { model: null, reason: hit.reason };
30787
- }
30788
- const pick = hit.ranked.find((m) => !exclude.has(m));
30789
- if (!pick) {
30790
- return {
30791
- model: null,
30792
- reason: `all ${hit.ranked.length} candidate model(s) already tried`
30793
- };
30794
- }
30795
- return { model: pick };
30796
- }
30797
- function cacheSetFailure(key, reason) {
30798
- _cache2.set(key, { ranked: [], reason, expiresAt: Date.now() + CACHE_TTL_MS2 });
30799
- }
30800
- function cacheSetRanked(key, ranked) {
30801
- _cache2.set(key, { ranked, expiresAt: Date.now() + CACHE_TTL_MS2 });
30802
- }
30803
- async function discoverViaOpenAIModels(endpoint, headers, cacheKey) {
30804
- const cached = cacheGet(cacheKey.key, cacheKey.exclude);
30805
- if (cached !== undefined)
30806
- return cached;
30807
- let response;
30808
- try {
30809
- response = await fetch(endpoint, {
30810
- method: "GET",
30811
- headers,
30812
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS2)
30813
- });
30814
- } catch (e) {
30815
- const reason = classifyFetchError(e, endpoint);
30816
- log(`[probe-discovery${cacheKey.displayName ? `:${cacheKey.displayName}` : ""}] fetch failed: ${reason}`);
30817
- cacheSetFailure(cacheKey.key, reason);
30818
- return { model: null, reason };
30819
- }
30820
- if (!response.ok) {
30821
- const who = cacheKey.displayName ?? "this provider";
30822
- const authFailure = response.status === 401 || response.status === 403 ? cacheKey.hasApiKey === false ? `the server requires an API key and none is configured for ${who}` : `the server rejected the configured API key for ${who}` : "";
30823
- const reason = authFailure ? `HTTP ${response.status} from ${endpoint} \u2014 ${authFailure}` : `HTTP ${response.status} from ${endpoint}`;
30824
- log(`[probe-discovery${cacheKey.displayName ? `:${cacheKey.displayName}` : ""}] ${reason}`);
30825
- cacheSetFailure(cacheKey.key, reason);
30826
- return { model: null, reason };
30827
- }
30828
- let body;
30829
- try {
30830
- body = await response.json();
30831
- } catch {
30832
- const reason = "invalid /v1/models response (not JSON)";
30833
- cacheSetFailure(cacheKey.key, reason);
30834
- return { model: null, reason };
30835
- }
30836
- const ids = extractModelIds(body);
30837
- if (ids.length === 0) {
30838
- const url = tryParseUrl(endpoint);
30839
- const host = url?.host ?? endpoint;
30840
- const reason = `${host} reachable but no models loaded \u2014 load a model in the server UI`;
30841
- cacheSetFailure(cacheKey.key, reason);
30842
- return { model: null, reason };
30843
- }
30844
- const ranked = rankProbeCandidates(ids);
30845
- if (ranked.length === 0) {
30846
- const reason = `no chat-capable model among ${ids.length} listed`;
30847
- cacheSetFailure(cacheKey.key, reason);
30848
- return { model: null, reason };
30849
- }
30850
- cacheSetRanked(cacheKey.key, ranked);
30851
- const pick = ranked.find((m) => !cacheKey.exclude?.has(m));
30852
- if (!pick) {
30853
- return {
30854
- model: null,
30855
- reason: `all ${ranked.length} candidate model(s) already tried`
30856
- };
30857
- }
30858
- return { model: pick };
30859
- }
30860
- function classifyFetchError(e, endpoint) {
30861
- const name = e?.name ?? "";
30862
- const code = e?.cause?.code ?? "";
30863
- const msg = e instanceof Error ? e.message : String(e);
30864
- const url = tryParseUrl(endpoint);
30865
- const host = url?.host ?? endpoint;
30866
- const isLocal = !!url && /^(localhost|127\.0\.0\.1|0\.0\.0\.0|::1)$/i.test(url.hostname);
30867
- if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(msg)) {
30868
- return `${host} unresponsive (>${FETCH_TIMEOUT_MS2 / 1000}s) \u2014 check if the server is overloaded`;
30869
- }
30870
- if (code === "ENOTFOUND" || code === "EAI_AGAIN") {
30871
- return `cannot resolve host ${url?.hostname ?? endpoint} \u2014 check the URL`;
30872
- }
30873
- const isConnRefused = code === "ECONNREFUSED" || code === "ECONNRESET" || /unable to connect|connection refused|fetch failed/i.test(msg);
30874
- if (isConnRefused) {
30875
- if (isLocal) {
30876
- return `${host} not reachable \u2014 is the server running? Press u to change URL.`;
30877
- }
30878
- return `${host} not reachable \u2014 check the URL or network. Press u to change.`;
30879
- }
30880
- return `${host}: ${msg}`;
30881
- }
30882
- function tryParseUrl(s) {
30883
- try {
30884
- return new URL(s);
30885
- } catch {
30886
- return null;
30887
- }
30888
- }
30889
- function extractModelIds(body) {
30890
- if (!body || typeof body !== "object")
30891
- return [];
30892
- const data = body;
30893
- if (Array.isArray(data.data)) {
30894
- return data.data.map((m) => m && typeof m === "object" ? m.id : null).filter((id) => typeof id === "string" && id.length > 0);
30895
- }
30896
- if (Array.isArray(data.models)) {
30897
- return data.models.map((m) => m && typeof m === "object" ? m.id ?? m.model_name : null).filter((id) => typeof id === "string" && id.length > 0);
30898
- }
30899
- return [];
30900
- }
30901
- function orderByCost(models) {
30902
- const sized = models.filter((m) => typeof m.size === "number");
30903
- const unsized = models.filter((m) => typeof m.size !== "number");
30904
- const bySize = [...sized].sort((a, b) => (a.size ?? Number.POSITIVE_INFINITY) - (b.size ?? Number.POSITIVE_INFINITY)).map((m) => m.name);
30905
- return [...bySize, ...rankProbeCandidates(unsized.map((m) => m.name))];
30906
- }
30907
- async function discoverViaOllama(baseUrl, cacheKey) {
30908
- const cached = cacheGet(cacheKey.key, cacheKey.exclude);
30909
- if (cached !== undefined)
30910
- return cached;
30911
- const [psResult, tagsResult] = await Promise.allSettled([
30912
- fetchOllamaModels2(`${baseUrl}/api/ps`),
30913
- fetchOllamaModels2(`${baseUrl}/api/tags`)
30914
- ]);
30915
- const loadedRaw = psResult.status === "fulfilled" ? psResult.value : [];
30916
- const tagsRaw = tagsResult.status === "fulfilled" ? tagsResult.value : [];
30917
- const connectionError = psResult.status === "rejected" ? classifyFetchError(psResult.reason, `${baseUrl}/api/ps`) : tagsResult.status === "rejected" ? classifyFetchError(tagsResult.reason, `${baseUrl}/api/tags`) : undefined;
30918
- const loaded = loadedRaw.filter((m) => isChatCapable(m.name));
30919
- const loadedNames = new Set(loaded.map((m) => m.name));
30920
- const rest = tagsRaw.filter((m) => isChatCapable(m.name) && !loadedNames.has(m.name));
30921
- if (loaded.length === 0 && rest.length === 0) {
30922
- const reason = connectionError ?? (loadedRaw.length === 0 && tagsRaw.length === 0 ? `no models on ${baseUrl} (pull one: ollama pull llama3.2)` : `only embedding/non-chat models on ${baseUrl}`);
30923
- cacheSetFailure(cacheKey.key, reason);
30924
- return { model: null, reason };
30925
- }
30926
- const ranked = [...orderByCost(loaded), ...orderByCost(rest)];
30927
- if (ranked.length === 0) {
30928
- const reason = "no chat-capable model on Ollama endpoint";
30929
- cacheSetFailure(cacheKey.key, reason);
30930
- return { model: null, reason };
30931
- }
30932
- cacheSetRanked(cacheKey.key, ranked);
30933
- const pick = ranked.find((m) => !cacheKey.exclude?.has(m));
30934
- if (!pick) {
30935
- return {
30936
- model: null,
30937
- reason: `all ${ranked.length} candidate model(s) already tried`
30938
- };
30939
- }
30940
- return { model: pick };
30941
- }
30942
- async function discoverViaLMStudio(baseUrl, headers, cacheKey) {
30943
- const cached = cacheGet(cacheKey.key, cacheKey.exclude);
30944
- if (cached !== undefined)
30945
- return cached;
30946
- let response;
30947
- try {
30948
- response = await fetch(`${baseUrl}/api/v0/models`, {
30949
- method: "GET",
30950
- headers,
30951
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS2)
30952
- });
30953
- } catch (e) {
30954
- return discoverViaOpenAIModels(`${baseUrl}/v1/models`, headers, cacheKey);
30955
- }
30956
- if (!response.ok) {
30957
- return discoverViaOpenAIModels(`${baseUrl}/v1/models`, headers, cacheKey);
30958
- }
30959
- let body;
30960
- try {
30961
- body = await response.json();
30962
- } catch {
30963
- const reason = "invalid /api/v0/models response (not JSON)";
30964
- cacheSetFailure(cacheKey.key, reason);
30965
- return { model: null, reason };
30966
- }
30967
- const models = extractLMStudioModels(body);
30968
- if (models.length === 0) {
30969
- const url = tryParseUrl(baseUrl);
30970
- const host = url?.host ?? baseUrl;
30971
- const reason = `${host} reachable but no models present \u2014 download one in the LM Studio UI`;
30972
- cacheSetFailure(cacheKey.key, reason);
30973
- return { model: null, reason };
30974
- }
30975
- const chatModels = models.filter((m) => isChatCapable(m.id) && m.type !== "embeddings" && m.type !== "embedding");
30976
- const loaded = chatModels.filter((m) => m.state === "loaded");
30977
- const notLoaded = chatModels.filter((m) => m.state !== "loaded");
30978
- const ranked = [
30979
- ...rankProbeCandidates(loaded.map((m) => m.id)),
30980
- ...rankProbeCandidates(notLoaded.map((m) => m.id))
30981
- ];
30982
- if (ranked.length === 0) {
30983
- const url = tryParseUrl(baseUrl);
30984
- const host = url?.host ?? baseUrl;
30985
- const reason = `${host} has ${models.length} model(s) but none are chat-capable`;
30986
- cacheSetFailure(cacheKey.key, reason);
30987
- return { model: null, reason };
30988
- }
30989
- cacheSetRanked(cacheKey.key, ranked);
30990
- const pick = ranked.find((m) => !cacheKey.exclude?.has(m));
30991
- if (!pick) {
30992
- return {
30993
- model: null,
30994
- reason: `all ${ranked.length} candidate model(s) already tried`
30995
- };
30996
- }
30997
- return { model: pick };
30998
- }
30999
- function extractLMStudioModels(body) {
31000
- if (!body || typeof body !== "object")
31001
- return [];
31002
- const data = body.data;
31003
- if (!Array.isArray(data))
31004
- return [];
31005
- const out = [];
31006
- for (const m of data) {
31007
- if (!m || typeof m !== "object")
31008
- continue;
31009
- const r = m;
31010
- if (typeof r.id !== "string" || !r.id)
31011
- continue;
31012
- out.push({
31013
- id: r.id,
31014
- state: typeof r.state === "string" ? r.state : undefined,
31015
- type: typeof r.type === "string" ? r.type : undefined
31016
- });
31017
- }
31018
- return out;
31019
- }
31020
- async function fetchOllamaModels2(url) {
31021
- const response = await fetch(url, {
31022
- method: "GET",
31023
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS2)
31024
- });
31025
- if (!response.ok)
31026
- return [];
31027
- const body = await response.json().catch(() => null);
31028
- if (!body?.models)
31029
- return [];
31030
- return body.models.map((m) => ({
31031
- name: typeof m.name === "string" ? m.name : "",
31032
- size: typeof m.size === "number" ? m.size : undefined
31033
- })).filter((m) => m.name.length > 0);
31034
- }
31035
- function invalidateProbeDiscovery(providerSlug) {
31036
- for (const key of _cache2.keys()) {
31037
- if (key.startsWith(`${providerSlug}:`)) {
31038
- _cache2.delete(key);
31039
- }
31040
- }
31041
- }
31042
- var _cache2, CACHE_TTL_MS2, FETCH_TIMEOUT_MS2 = 5000, SMALL_MODEL_PATTERNS, NON_CHAT_PATTERNS, VIDEO_OUTPUT_NAME_PATTERNS, CATALOG_CHAT_INDEX_TTL_MS = 60000, _catalogChatIndex, STANDARD_VENDOR_PREFIXES;
31043
- var init_probe_discovery = __esm(() => {
31044
- init_logger();
31045
- init_all_models_cache();
31046
- _cache2 = new Map;
31047
- CACHE_TTL_MS2 = 5 * 60 * 1000;
31048
- SMALL_MODEL_PATTERNS = [
31049
- /\bmini\b/i,
31050
- /\bnano\b/i,
31051
- /\bflash\b/i,
31052
- /\blite\b/i,
31053
- /\bhaiku\b/i,
31054
- /\bsmall\b/i,
31055
- /\btiny\b/i,
31056
- /\b[12345]b\b/i,
31057
- /\b[78]b\b/i
31058
- ];
31059
- NON_CHAT_PATTERNS = [
31060
- /\bimage\b/i,
31061
- /\bembed/i,
31062
- /\bminilm\b/i,
31063
- /\bnomic-embed/i,
31064
- /\bbge-/i,
31065
- /\bmxbai-embed/i,
31066
- /\btts\b/i,
31067
- /\bwhisper\b/i,
31068
- /\baudio\b/i,
31069
- /\bvoxtral\b/i,
31070
- /\bdall-?e\b/i,
31071
- /\bmoderation\b/i,
31072
- /\brerank/i,
31073
- /\bspeech\b/i,
31074
- /\btranscribe\b/i,
31075
- /\btranscription\b/i,
31076
- /\bvoice\b/i,
31077
- /\brealtime\b/i,
31078
- /\blive\b/i,
31079
- /\btranslate\b/i,
31080
- /\btranslation\b/i,
31081
- /-(image|tts|audio|embedding|vision-only|transcribe|voice|speech|realtime|live|translate)(-|$)/i
31082
- ];
31083
- VIDEO_OUTPUT_NAME_PATTERNS = [
31084
- /\bvideo\b/i,
31085
- /(^|[-_.])(t2v|i2v|r2v|v2v)([-_.]|$)/i,
31086
- /\bveo\b/i,
31087
- /\bsora\b/i
31088
- ];
31089
- _catalogChatIndex = new Map;
31090
- STANDARD_VENDOR_PREFIXES = [
31091
- "openai/",
31092
- "anthropic/",
31093
- "google/",
31094
- "gemini/",
31095
- "meta/",
31096
- "meta-llama/",
31097
- "mistralai/",
31098
- "mistral/",
31099
- "x-ai/",
31100
- "deepseek/",
31101
- "qwen/",
31102
- "moonshot/",
31103
- "moonshotai/",
31104
- "zhipuai/",
31105
- "z-ai/"
31106
- ];
31107
- });
31108
-
31109
31160
  // src/providers/transport/provider-model-discovery.ts
31110
31161
  async function discoverProviderProbeModel(providerName, displayName, exclude) {
31111
31162
  const def = getProviderByName(providerName);
@@ -31123,7 +31174,7 @@ async function discoverProviderProbeModel(providerName, displayName, exclude) {
31123
31174
  reason: failure ? `${displayName}: ${describeDiscoveryFailure(failure)}` : `${displayName} listed no models at ${def.modelDiscovery.path} \u2014 check the API key and that the subscription is active`
31124
31175
  };
31125
31176
  }
31126
- const ranked = rankDiscoveredModels(discovered).map((model) => model.id).filter(isChatCapable);
31177
+ const ranked = rankDiscoveredModels(discovered).filter((model) => isReportedChatCapable(model.id, model.reported)).map((model) => model.id);
31127
31178
  if (ranked.length === 0) {
31128
31179
  return {
31129
31180
  model: null,
@@ -32945,11 +32996,14 @@ function sanitizeErrorMessage(message, maxLength = MAX_ERROR_MESSAGE_LENGTH) {
32945
32996
  return flattened;
32946
32997
  return `${flattened.slice(0, maxLength - 1).trimEnd()}\u2026`;
32947
32998
  }
32948
- function wrapAnthropicError(status, message, errorType, upstreamStatus) {
32999
+ function wrapAnthropicError(status, message, errorType, upstreamStatus, providerMessage) {
32949
33000
  const type = errorType || statusToErrorType(status);
32950
33001
  const error = { type, message: sanitizeErrorMessage(message) };
32951
33002
  if (upstreamStatus !== undefined)
32952
33003
  error.upstream_status = upstreamStatus;
33004
+ const oneLine = (providerMessage ?? "").replace(/\s+/g, " ").trim();
33005
+ if (oneLine)
33006
+ error.provider_message = sanitizeErrorMessage(oneLine);
32953
33007
  return { type: "error", error };
32954
33008
  }
32955
33009
  function extractUpstreamStatus(body) {
@@ -32963,11 +33017,38 @@ function extractUpstreamStatus(body) {
32963
33017
  return;
32964
33018
  }
32965
33019
  }
33020
+ function sseDataPayload(body) {
33021
+ if (!/^\s*(event|data):/.test(body))
33022
+ return;
33023
+ const lines = body.split(/\r?\n/).filter((line) => line.startsWith("data:"));
33024
+ if (lines.length > 0) {
33025
+ const joined = lines.map((line) => line.slice("data:".length).trim()).join("");
33026
+ if (joined.length > 0)
33027
+ return joined;
33028
+ }
33029
+ const at = body.search(/(^|\s)data:/);
33030
+ if (at === -1)
33031
+ return;
33032
+ const payload = body.slice(body.indexOf("data:", at) + "data:".length).trim();
33033
+ return payload.length > 0 ? payload : undefined;
33034
+ }
32966
33035
  function extractProviderMessage(body) {
32967
33036
  if (body == null)
32968
33037
  return "";
32969
- if (typeof body === "string")
33038
+ if (typeof body === "string") {
33039
+ const payload = sseDataPayload(body);
33040
+ if (payload) {
33041
+ try {
33042
+ const inner = extractProviderMessage(JSON.parse(payload));
33043
+ if (inner)
33044
+ return inner;
33045
+ } catch {
33046
+ return payload;
33047
+ }
33048
+ return payload;
33049
+ }
32970
33050
  return body;
33051
+ }
32971
33052
  const candidates = [
32972
33053
  body?.error?.message,
32973
33054
  body?.message,
@@ -32977,7 +33058,7 @@ function extractProviderMessage(body) {
32977
33058
  ];
32978
33059
  for (const c of candidates) {
32979
33060
  if (typeof c === "string" && c.length > 0)
32980
- return c;
33061
+ return extractProviderMessage(c);
32981
33062
  if (Array.isArray(c)) {
32982
33063
  const first = c.find((e) => typeof e?.msg === "string" && e.msg.length > 0);
32983
33064
  if (first)
@@ -33567,7 +33648,7 @@ var init_stream_head_sniffer = __esm(() => {
33567
33648
  });
33568
33649
 
33569
33650
  // src/handlers/shared/stream-parsers/anthropic-sse.ts
33570
- function sseDataPayload(line) {
33651
+ function sseDataPayload2(line) {
33571
33652
  if (!line.startsWith("data:"))
33572
33653
  return null;
33573
33654
  const rest = line.slice(5);
@@ -33805,7 +33886,7 @@ data: {"type":"ping"}
33805
33886
  buffer = lines.pop() || "";
33806
33887
  for (const line of lines) {
33807
33888
  totalLines++;
33808
- const payload = sseDataPayload(line);
33889
+ const payload = sseDataPayload2(line);
33809
33890
  if (filterThinking && payload !== null) {
33810
33891
  try {
33811
33892
  const data = JSON.parse(payload);
@@ -35918,7 +35999,8 @@ class ComposedHandler {
35918
35999
  parsedErrorBody = undefined;
35919
36000
  }
35920
36001
  const providerMsg = extractProviderMessage(parsedErrorBody ?? errorText);
35921
- const msgTail = providerMsg ? ` (${providerMsg.length > 200 ? `${providerMsg.slice(0, 200)}\u2026` : providerMsg})` : "";
36002
+ const oneLineMsg = providerMsg.replace(/\s+/g, " ").trim();
36003
+ const msgTail = oneLineMsg ? ` (${oneLineMsg.length > 200 ? `${oneLineMsg.slice(0, 200)}\u2026` : oneLineMsg})` : "";
35922
36004
  logStderr(`Error [${this.provider.displayName}]: HTTP ${response.status}. ${hint}${msgTail}`);
35923
36005
  let providerErrorType;
35924
36006
  try {
@@ -35971,7 +36053,7 @@ class ComposedHandler {
35971
36053
  providerMessage: providerMsg,
35972
36054
  leadPhrase: isContextOverflowError(response.status, errorText) ? CONTEXT_OVERFLOW_PHRASE : undefined
35973
36055
  });
35974
- return c.json(wrapAnthropicError(400, surfaced, "invalid_request_error", response.status), 400);
36056
+ return c.json(wrapAnthropicError(400, surfaced, "invalid_request_error", response.status, providerMsg), 400);
35975
36057
  }
35976
36058
  return c.json(ensureAnthropicErrorFormat(response.status, errorBody), response.status);
35977
36059
  }
@@ -36004,7 +36086,7 @@ class ComposedHandler {
36004
36086
  invocation_mode: this.options.invocationMode ?? "auto-route"
36005
36087
  });
36006
36088
  } catch {}
36007
- return c.json(wrapAnthropicError(503, surfaced, "overloaded_error"), 503);
36089
+ return c.json(wrapAnthropicError(503, surfaced, "overloaded_error", undefined, settled.message), 503);
36008
36090
  }
36009
36091
  response = settled.response;
36010
36092
  }
@@ -36046,7 +36128,7 @@ class ComposedHandler {
36046
36128
  invocation_mode: this.options.invocationMode ?? "auto-route"
36047
36129
  });
36048
36130
  } catch {}
36049
- return isTerminal ? c.json(wrapAnthropicError(400, surfaced, "invalid_request_error"), 400) : c.json(wrapAnthropicError(503, surfaced, "overloaded_error"), 503);
36131
+ return isTerminal ? c.json(wrapAnthropicError(400, surfaced, "invalid_request_error", undefined, settled.message), 400) : c.json(wrapAnthropicError(503, surfaced, "overloaded_error", undefined, settled.message), 503);
36050
36132
  }
36051
36133
  response = settled.response;
36052
36134
  }
@@ -38551,7 +38633,7 @@ var init_provider_definitions = __esm(() => {
38551
38633
  description: "Alibaba Model Studio PAYG (qpay@)"
38552
38634
  },
38553
38635
  {
38554
- createHandler: openaiHandler,
38636
+ createHandler: noHandler("virtual", "No baseUrl. Exists only so nativeModelPatterns can steer a bare qwen* name; qwen-payg serves dashscope."),
38555
38637
  tier: "native",
38556
38638
  name: "qwen",
38557
38639
  displayName: "Qwen",
@@ -38881,6 +38963,7 @@ async function refreshCatalog(timeoutMs, options = {}) {
38881
38963
  catalogGenerationId: generationId
38882
38964
  };
38883
38965
  writeAllModelsCache(cache, options.cachePath);
38966
+ _clearChatCapabilityIndex();
38884
38967
  _memCache = entries;
38885
38968
  _warmPromise = Promise.resolve();
38886
38969
  return {
@@ -38957,6 +39040,7 @@ var DEFAULT_CATALOG_URL = "https://us-central1-claudish-6da10.cloudfunctions.net
38957
39040
  var init_catalog_client = __esm(() => {
38958
39041
  init_all_models_cache();
38959
39042
  init_catalog_route_bindings();
39043
+ init_probe_discovery();
38960
39044
  });
38961
39045
 
38962
39046
  // src/config-schema.ts
@@ -40094,12 +40178,16 @@ function modelsCatalogHas(ids, wireId) {
40094
40178
  const needle = wireId.trim().toLowerCase();
40095
40179
  return ids.some((id) => id.trim().toLowerCase() === needle);
40096
40180
  }
40181
+ function resolveAgainstModelsCatalog(provider, wireId, models) {
40182
+ const entries = models.map(({ id, ...rest }) => ({ wireId: id, ...rest }));
40183
+ return expandSelection(provider, wireId, entries);
40184
+ }
40097
40185
  async function providerServesModel(provider, wireId) {
40098
40186
  const def = getProviderByName(provider);
40099
40187
  if (def?.modelDiscovery) {
40100
40188
  const models = await discoverProviderModels(provider);
40101
40189
  if (models.length > 0) {
40102
- return modelsCatalogHas(models.map((m) => m.id), wireId) ? "serves" : "not-served";
40190
+ return modelsCatalogHas(models.map((m) => m.id), resolveAgainstModelsCatalog(provider, wireId, models)) ? "serves" : "not-served";
40103
40191
  }
40104
40192
  getDiscoveryFailure(provider);
40105
40193
  return "unknown";
@@ -40117,6 +40205,7 @@ var init_model_availability = __esm(() => {
40117
40205
  init_catalog_route_bindings();
40118
40206
  init_catalog_client();
40119
40207
  init_model_discovery();
40208
+ init_registry2();
40120
40209
  init_provider_definitions();
40121
40210
  });
40122
40211
 
@@ -44954,17 +45043,32 @@ function truncateKeepingLink(text, max = 400) {
44954
45043
  const prose = (lastSpace > room * 0.5 ? head.slice(0, lastSpace) : head).trimEnd();
44955
45044
  return `${prose}... ${url}`;
44956
45045
  }
45046
+ function oneLine4(text) {
45047
+ return text.replace(/\s+/g, " ").trim();
45048
+ }
45049
+ function messageFromJson(text) {
45050
+ try {
45051
+ const parsed = JSON.parse(text);
45052
+ const msg = parsed?.error?.provider_message || parsed?.error?.message || parsed?.error?.error?.message || parsed?.message || parsed?.detail;
45053
+ return typeof msg === "string" && msg.length > 0 ? msg : undefined;
45054
+ } catch {
45055
+ return;
45056
+ }
45057
+ }
45058
+ function unwrapFrame(text) {
45059
+ const payload = sseDataPayload(text);
45060
+ if (!payload)
45061
+ return text;
45062
+ return messageFromJson(payload) ?? payload;
45063
+ }
44957
45064
  function extractErrorMessage(body) {
44958
45065
  if (!body)
44959
45066
  return;
44960
- try {
44961
- const parsed = JSON.parse(body);
44962
- const msg = parsed?.error?.message || parsed?.error?.error?.message || parsed?.message || parsed?.detail;
44963
- if (typeof msg === "string" && msg.length > 0) {
44964
- return truncateKeepingLink(msg);
44965
- }
44966
- } catch {}
44967
- const trimmed = body.trim();
45067
+ const direct = messageFromJson(body);
45068
+ if (direct)
45069
+ return truncateKeepingLink(oneLine4(unwrapFrame(direct)));
45070
+ const unwrapped = unwrapFrame(body);
45071
+ const trimmed = oneLine4(unwrapped);
44968
45072
  if (!trimmed)
44969
45073
  return;
44970
45074
  return truncateKeepingLink(trimmed);
@@ -45141,7 +45245,10 @@ function isContentEvent(parsed, eventType) {
45141
45245
  return false;
45142
45246
  }
45143
45247
  function withDetail(base, message) {
45144
- return message ? `${base} \u2014 ${message}` : base;
45248
+ return message ? `${base} \u2014 ${stripRedundantHead(message)}` : base;
45249
+ }
45250
+ function stripRedundantHead(message) {
45251
+ return message.replace(/^.{1,40}? error \(HTTP \d{3}\): /, "");
45145
45252
  }
45146
45253
  function describeProbeState(result) {
45147
45254
  const status = result.httpStatus ?? "";
@@ -59306,7 +59413,7 @@ function logModalityGapOnce(kept) {
59306
59413
  if (suspect.length === 0)
59307
59414
  return;
59308
59415
  _modalityGapLogged = true;
59309
- log(`[Models] ${suspect.length} row(s) may not be chat models and cannot be classified from the id: ` + `${suspect.slice(0, 8).map((m) => m.id).join(", ")}. The slim catalog carries no modality field \u2014 models-index gap, not a CLI regex.`);
59416
+ log(`[Models] ${suspect.length} row(s) the catalog publishes as chat, from a generator family: ` + `${suspect.slice(0, 8).map((m) => m.id).join(", ")}. If one is not a chat model, its models-index row is wrong.`);
59310
59417
  }
59311
59418
  async function getFreeModels() {
59312
59419
  return [];
@@ -59762,13 +59869,13 @@ async function buildDiscoveredModelOutcome(provider, displayName, catalog) {
59762
59869
  }
59763
59870
  const served = rankDiscoveredModels(modelsCatalog.models);
59764
59871
  const servedCount = served.length;
59765
- const discovered = served.filter((m) => isChatCapable(m.id));
59872
+ const discovered = served.filter((m) => isReportedChatCapable(m.id, m.reported));
59766
59873
  const chatCount = discovered.length;
59767
59874
  if (chatCount === 0) {
59768
59875
  return {
59769
59876
  kind: "all-filtered",
59770
59877
  servedCount,
59771
- sampleIds: served.filter((m) => !isChatCapable(m.id)).slice(0, 3).map((m) => m.id),
59878
+ sampleIds: served.filter((m) => !isReportedChatCapable(m.id, m.reported)).slice(0, 3).map((m) => m.id),
59772
59879
  fallbackRows
59773
59880
  };
59774
59881
  }
@@ -60848,14 +60955,15 @@ function useProbeStore(store) {
60848
60955
  }
60849
60956
  function deriveLayout(width) {
60850
60957
  if (width < 60) {
60851
- return { barWidth: 0, tokWidth: 0, showBreakdown: false, pillFallback: true };
60958
+ return { barWidth: 0, tokWidth: 0, showBreakdown: false, pillFallback: true, width };
60852
60959
  }
60853
60960
  if (width < 80) {
60854
60961
  return {
60855
60962
  barWidth: TIMELINE_BAR_NARROW,
60856
60963
  tokWidth: 0,
60857
60964
  showBreakdown: false,
60858
- pillFallback: false
60965
+ pillFallback: false,
60966
+ width
60859
60967
  };
60860
60968
  }
60861
60969
  if (width < 100) {
@@ -60863,14 +60971,16 @@ function deriveLayout(width) {
60863
60971
  barWidth: TIMELINE_BAR_FULL,
60864
60972
  tokWidth: 0,
60865
60973
  showBreakdown: true,
60866
- pillFallback: false
60974
+ pillFallback: false,
60975
+ width
60867
60976
  };
60868
60977
  }
60869
60978
  return {
60870
60979
  barWidth: TIMELINE_BAR_FULL,
60871
60980
  tokWidth: TOK_BAR_FULL,
60872
60981
  showBreakdown: true,
60873
- pillFallback: false
60982
+ pillFallback: false,
60983
+ width
60874
60984
  };
60875
60985
  }
60876
60986
  function computeRowWidth(layout, maxNameLen) {
@@ -60912,8 +61022,12 @@ function padEndSafe(s, n) {
60912
61022
  return s.slice(0, n);
60913
61023
  return s + " ".repeat(n - s.length);
60914
61024
  }
61025
+ function clipReason(s, width) {
61026
+ const room = Math.max(8, width - 2);
61027
+ return s.length <= room ? s : `${s.slice(0, room - 1)}\u2026`;
61028
+ }
60915
61029
  function stripAnsi3(text) {
60916
- return text.replace(/\x1b\[[0-9;]*[A-Za-z]/g, "");
61030
+ return text.replace(/\x1b\[[0-9;]*[A-Za-z]/g, "").replace(/\s+/g, " ").trim();
60917
61031
  }
60918
61032
  function ishGreen() {
60919
61033
  return getThemeMode() === "light" ? "#047857" : "#00ff7f";
@@ -61031,7 +61145,19 @@ function ProgressBar({
61031
61145
  return /* @__PURE__ */ jsxs9("text", {
61032
61146
  children: [
61033
61147
  prefix,
61034
- renderNonLiveStatus(link, false)
61148
+ renderNonLiveStatus(link, false, layout.width)
61149
+ ]
61150
+ });
61151
+ }
61152
+ if (link.status === "failed") {
61153
+ const used = ELAPSED_COL + maxNameLen + 2;
61154
+ return /* @__PURE__ */ jsxs9("text", {
61155
+ children: [
61156
+ prefix,
61157
+ /* @__PURE__ */ jsx12("span", {
61158
+ fg: C.red,
61159
+ children: clipReason(`\u2717 ${stripAnsi3(link.error || "failed")}`, layout.width - used)
61160
+ })
61035
61161
  ]
61036
61162
  });
61037
61163
  }
@@ -61044,7 +61170,7 @@ function ProgressBar({
61044
61170
  fg: C.dim,
61045
61171
  children: " "
61046
61172
  }),
61047
- renderNonLiveStatus(link, true)
61173
+ renderNonLiveStatus(link, true, layout.width)
61048
61174
  ]
61049
61175
  });
61050
61176
  }
@@ -61178,7 +61304,7 @@ function renderTimelineSlot(link, animFrame, barWidth) {
61178
61304
  });
61179
61305
  }
61180
61306
  }
61181
- function renderNonLiveStatus(link, hasSlot) {
61307
+ function renderNonLiveStatus(link, hasSlot, width) {
61182
61308
  switch (link.status) {
61183
61309
  case "probing": {
61184
61310
  const elapsedMs = link.startTime ? Date.now() - link.startTime : 0;
@@ -61193,7 +61319,7 @@ function renderNonLiveStatus(link, hasSlot) {
61193
61319
  children: "\u2717"
61194
61320
  }) : /* @__PURE__ */ jsx12("span", {
61195
61321
  fg: C.red,
61196
- children: `\u2717 ${stripAnsi3(link.error || "failed")}`
61322
+ children: clipReason(`\u2717 ${stripAnsi3(link.error || "failed")}`, width)
61197
61323
  });
61198
61324
  default:
61199
61325
  return /* @__PURE__ */ jsx12("span", {
@@ -61396,6 +61522,7 @@ function DetailLinkRow({
61396
61522
  ]
61397
61523
  });
61398
61524
  if (!isLive || !probe?.timing) {
61525
+ const used = 2 + 1 + 1 + provW + 2 + 3;
61399
61526
  return /* @__PURE__ */ jsxs9("text", {
61400
61527
  children: [
61401
61528
  lead,
@@ -61405,7 +61532,7 @@ function DetailLinkRow({
61405
61532
  }),
61406
61533
  /* @__PURE__ */ jsx12("span", {
61407
61534
  fg: C.red,
61408
- children: shortFailureReason(probe, link.hasCredentials)
61535
+ children: clipReason(shortFailureReason(probe, link.hasCredentials), layout.width - used)
61409
61536
  })
61410
61537
  ]
61411
61538
  });
@@ -62141,7 +62268,7 @@ function ProbeApp({
62141
62268
  ]
62142
62269
  }, state.phase);
62143
62270
  }
62144
- var ANIM_FRAMES2, TIMELINE_BAR_FULL = 24, TIMELINE_BAR_NARROW = 12, TOK_BAR_FULL = 14, TOTAL_COL = 7, STAGE_NUM_W2 = 6, BREAKDOWN_COL, TOK_VALUE_COL = 7, TRACK_CHAR = "\xB7", BAR_FILL = "\u2588", BANNER_ROWS = 7, SCROLL_HINT_ROWS = 1, LEGEND_ROWS = 2, MIN_LIST_H = 4, TAB_BAR_ROWS = 2;
62271
+ var ANIM_FRAMES2, TIMELINE_BAR_FULL = 24, TIMELINE_BAR_NARROW = 12, TOK_BAR_FULL = 14, TOTAL_COL = 7, ELAPSED_COL = 11, STAGE_NUM_W2 = 6, BREAKDOWN_COL, TOK_VALUE_COL = 7, TRACK_CHAR = "\xB7", BAR_FILL = "\u2588", BANNER_ROWS = 7, SCROLL_HINT_ROWS = 1, LEGEND_ROWS = 2, MIN_LIST_H = 4, TAB_BAR_ROWS = 2;
62145
62272
  var init_probe_tui_app = __esm(() => {
62146
62273
  init_probe_live();
62147
62274
  init_theme_mode();
@@ -63665,6 +63792,7 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
63665
63792
  activeTab: "summary"
63666
63793
  };
63667
63794
  const tui = await startProbeTui(initialState);
63795
+ setStderrQuiet(true);
63668
63796
  const addStep = (name, status) => {
63669
63797
  tui.store.setState((prev) => ({
63670
63798
  ...prev,
@@ -63852,6 +63980,7 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
63852
63980
  } catch {}
63853
63981
  }
63854
63982
  await tui.shutdown();
63983
+ setStderrQuiet(false);
63855
63984
  }
63856
63985
  }
63857
63986
  function printHelp2() {
@@ -64279,6 +64408,7 @@ var __filename3, __dirname3;
64279
64408
  var init_cli = __esm(() => {
64280
64409
  init_base_api_format();
64281
64410
  init_config2();
64411
+ init_logger();
64282
64412
  init_model_loader();
64283
64413
  init_model_selector();
64284
64414
  init_probe_results_printer();