claudish 10.2.0 → 10.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1538 -998
- 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.
|
|
718
|
+
var VERSION = "10.3.0";
|
|
719
719
|
|
|
720
720
|
// src/logger.ts
|
|
721
721
|
import { appendFile, existsSync as existsSync2, mkdirSync, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
@@ -5328,6 +5328,56 @@ var init_onepassword_command = __esm(() => {
|
|
|
5328
5328
|
` + " claudish --op 'op://Jack/My Item/*/*_API_KEY' --model gpt-4o 'task'";
|
|
5329
5329
|
});
|
|
5330
5330
|
|
|
5331
|
+
// src/default-provider.ts
|
|
5332
|
+
function resolveDefaultProvider(opts) {
|
|
5333
|
+
const env = opts.env ?? process.env;
|
|
5334
|
+
if (opts.cliFlag && opts.cliFlag.length > 0) {
|
|
5335
|
+
return { provider: opts.cliFlag, source: "cli-flag", legacyAutoPromoted: false };
|
|
5336
|
+
}
|
|
5337
|
+
const envVal = env.CLAUDISH_DEFAULT_PROVIDER;
|
|
5338
|
+
if (envVal !== undefined) {
|
|
5339
|
+
return { provider: envVal, source: "env-var", legacyAutoPromoted: false };
|
|
5340
|
+
}
|
|
5341
|
+
const configured = opts.config.defaultProvider;
|
|
5342
|
+
if (typeof configured === "string") {
|
|
5343
|
+
return { provider: configured, source: "config-file", legacyAutoPromoted: false };
|
|
5344
|
+
}
|
|
5345
|
+
if (env.OPENROUTER_API_KEY) {
|
|
5346
|
+
return { provider: "openrouter", source: "openrouter-key", legacyAutoPromoted: false };
|
|
5347
|
+
}
|
|
5348
|
+
return { provider: "openrouter", source: "hardcoded", legacyAutoPromoted: false };
|
|
5349
|
+
}
|
|
5350
|
+
function planDefaultProviderFlag(argv) {
|
|
5351
|
+
const rest = [];
|
|
5352
|
+
let value;
|
|
5353
|
+
for (let i = 0;i < argv.length; i++) {
|
|
5354
|
+
const arg = argv[i];
|
|
5355
|
+
if (arg === "--") {
|
|
5356
|
+
rest.push(...argv.slice(i));
|
|
5357
|
+
break;
|
|
5358
|
+
}
|
|
5359
|
+
if (arg === DEFAULT_PROVIDER_FLAG) {
|
|
5360
|
+
const next = argv[i + 1];
|
|
5361
|
+
if (next === undefined || next.startsWith("-")) {
|
|
5362
|
+
return {
|
|
5363
|
+
kind: "error",
|
|
5364
|
+
message: `${DEFAULT_PROVIDER_FLAG} requires a provider name ("" for no fallback provider)`
|
|
5365
|
+
};
|
|
5366
|
+
}
|
|
5367
|
+
value = next;
|
|
5368
|
+
i++;
|
|
5369
|
+
continue;
|
|
5370
|
+
}
|
|
5371
|
+
if (arg.startsWith(`${DEFAULT_PROVIDER_FLAG}=`)) {
|
|
5372
|
+
value = arg.slice(DEFAULT_PROVIDER_FLAG.length + 1);
|
|
5373
|
+
continue;
|
|
5374
|
+
}
|
|
5375
|
+
rest.push(arg);
|
|
5376
|
+
}
|
|
5377
|
+
return value === undefined ? { kind: "none" } : { kind: "apply", value, argv: rest };
|
|
5378
|
+
}
|
|
5379
|
+
var DEFAULT_PROVIDER_FLAG = "--default-provider";
|
|
5380
|
+
|
|
5331
5381
|
// ../../node_modules/.bun/zod@4.1.13/node_modules/zod/v4/core/core.js
|
|
5332
5382
|
function $constructor(name, initializer, params) {
|
|
5333
5383
|
function init(inst, def) {
|
|
@@ -18304,30 +18354,37 @@ var init_all_models_cache = __esm(() => {
|
|
|
18304
18354
|
|
|
18305
18355
|
// src/providers/catalog-route-bindings.ts
|
|
18306
18356
|
function catalogRouteForProvider(provider) {
|
|
18307
|
-
return CATALOG_ROUTE_BINDINGS[provider];
|
|
18308
|
-
}
|
|
18309
|
-
function providerForCatalogRoute(route) {
|
|
18310
|
-
return providersForCatalogRoute(route)[0];
|
|
18357
|
+
return CATALOG_ROUTE_BINDINGS[provider] ?? LOOKUP_ONLY_ROUTE_BINDINGS[provider];
|
|
18311
18358
|
}
|
|
18312
|
-
function
|
|
18359
|
+
function namesBoundTo(table, route) {
|
|
18313
18360
|
if (!route)
|
|
18314
18361
|
return [];
|
|
18315
|
-
return Object.entries(
|
|
18362
|
+
return Object.entries(table).filter(([, binding]) => binding.routeId === route.routeId && binding.routeProfileId === route.routeProfileId).map(([name]) => name);
|
|
18363
|
+
}
|
|
18364
|
+
function routingProvidersForRoute(route) {
|
|
18365
|
+
return namesBoundTo(CATALOG_ROUTE_BINDINGS, route);
|
|
18366
|
+
}
|
|
18367
|
+
function catalogReadProvidersForRoute(route) {
|
|
18368
|
+
return [
|
|
18369
|
+
...namesBoundTo(CATALOG_ROUTE_BINDINGS, route),
|
|
18370
|
+
...namesBoundTo(LOOKUP_ONLY_ROUTE_BINDINGS, route)
|
|
18371
|
+
];
|
|
18372
|
+
}
|
|
18373
|
+
function providerForCatalogRoute(route) {
|
|
18374
|
+
return catalogReadProvidersForRoute(route)[0];
|
|
18316
18375
|
}
|
|
18317
18376
|
function catalogRouteMatchesProvider(route, provider) {
|
|
18318
18377
|
const binding = catalogRouteForProvider(provider);
|
|
18319
18378
|
return route !== undefined && binding !== undefined && route.routeId === binding.routeId && route.routeProfileId === binding.routeProfileId;
|
|
18320
18379
|
}
|
|
18321
|
-
var CATALOG_ROUTE_BINDINGS;
|
|
18380
|
+
var CATALOG_ROUTE_BINDINGS, LOOKUP_ONLY_ROUTE_BINDINGS;
|
|
18322
18381
|
var init_catalog_route_bindings = __esm(() => {
|
|
18323
18382
|
CATALOG_ROUTE_BINDINGS = {
|
|
18324
18383
|
"native-anthropic": { routeId: "anthropic", routeProfileId: "claude-code-subscription" },
|
|
18325
|
-
anthropic: { routeId: "anthropic", routeProfileId: "direct-api" },
|
|
18326
18384
|
"openai-codex": { routeId: "openai", routeProfileId: "codex-subscription" },
|
|
18327
18385
|
openai: { routeId: "openai", routeProfileId: "direct-api" },
|
|
18328
18386
|
"kimi-coding": { routeId: "moonshotai", routeProfileId: "kimi-code-subscription" },
|
|
18329
18387
|
kimi: { routeId: "moonshotai", routeProfileId: "direct-api" },
|
|
18330
|
-
moonshotai: { routeId: "moonshotai", routeProfileId: "direct-api" },
|
|
18331
18388
|
"glm-coding": { routeId: "z-ai", routeProfileId: "glm-coding-subscription" },
|
|
18332
18389
|
"z-ai": { routeId: "z-ai", routeProfileId: "direct-api" },
|
|
18333
18390
|
glm: { routeId: "z-ai", routeProfileId: "direct-api" },
|
|
@@ -18345,7 +18402,6 @@ var init_catalog_route_bindings = __esm(() => {
|
|
|
18345
18402
|
"qwen-payg": { routeId: "qwen", routeProfileId: "dashscope-direct" },
|
|
18346
18403
|
"opencode-zen-go": { routeId: "opencode", routeProfileId: "go-subscription" },
|
|
18347
18404
|
"opencode-zen": { routeId: "opencode", routeProfileId: "zen" },
|
|
18348
|
-
zen: { routeId: "opencode", routeProfileId: "zen" },
|
|
18349
18405
|
ollamacloud: { routeId: "ollama", routeProfileId: "cloud" },
|
|
18350
18406
|
openrouter: { routeId: "openrouter", routeProfileId: "gateway" },
|
|
18351
18407
|
together: { routeId: "together-ai", routeProfileId: "gateway" },
|
|
@@ -18355,6 +18411,11 @@ var init_catalog_route_bindings = __esm(() => {
|
|
|
18355
18411
|
deepseek: { routeId: "deepseek", routeProfileId: "direct-api" },
|
|
18356
18412
|
mistralai: { routeId: "mistralai", routeProfileId: "direct-api" }
|
|
18357
18413
|
};
|
|
18414
|
+
LOOKUP_ONLY_ROUTE_BINDINGS = {
|
|
18415
|
+
anthropic: { routeId: "anthropic", routeProfileId: "direct-api" },
|
|
18416
|
+
moonshotai: { routeId: "moonshotai", routeProfileId: "direct-api" },
|
|
18417
|
+
zen: { routeId: "opencode", routeProfileId: "zen" }
|
|
18418
|
+
};
|
|
18358
18419
|
});
|
|
18359
18420
|
|
|
18360
18421
|
// src/providers/model-ordering.ts
|
|
@@ -28360,7 +28421,7 @@ class AntigravityProviderTransport {
|
|
|
28360
28421
|
rewriteModelNotFound(response, capacityFallbacksExhausted = false) {
|
|
28361
28422
|
const served = this.servedModels;
|
|
28362
28423
|
if (!capacityFallbacksExhausted && served.includes(this.servedModelName)) {
|
|
28363
|
-
log(`[Antigravity] 404 for ${this.servedModelName}, which IS in the
|
|
28424
|
+
log(`[Antigravity] 404 for ${this.servedModelName}, which IS in the dynamic models catalog \u2014 passing through unmodified`);
|
|
28364
28425
|
return response;
|
|
28365
28426
|
}
|
|
28366
28427
|
response.text().catch(() => {});
|
|
@@ -32662,6 +32723,40 @@ var init_pro_injection = __esm(() => {
|
|
|
32662
32723
|
init_session_events();
|
|
32663
32724
|
});
|
|
32664
32725
|
|
|
32726
|
+
// src/providers/claude-code-aliases.ts
|
|
32727
|
+
function claudeCodeTierAlias(model) {
|
|
32728
|
+
return TIER_ALIASES[model.trim().toLowerCase()] ?? null;
|
|
32729
|
+
}
|
|
32730
|
+
function isClaudeCodeModelName(name) {
|
|
32731
|
+
const normalized = name.trim().toLowerCase();
|
|
32732
|
+
if (normalized.startsWith("claude-"))
|
|
32733
|
+
return true;
|
|
32734
|
+
const alias = normalized.endsWith(ONE_MILLION_CONTEXT_SUFFIX) ? normalized.slice(0, -ONE_MILLION_CONTEXT_SUFFIX.length) : normalized;
|
|
32735
|
+
return CLAUDE_CODE_MODEL_ALIASES.includes(alias);
|
|
32736
|
+
}
|
|
32737
|
+
function normalizeNativeModelSpec(spec) {
|
|
32738
|
+
return claudeCodeTierAlias(spec) ?? spec;
|
|
32739
|
+
}
|
|
32740
|
+
var TIER_ALIASES, CLAUDE_CODE_MODEL_ALIASES, ONE_MILLION_CONTEXT_SUFFIX = "[1m]";
|
|
32741
|
+
var init_claude_code_aliases = __esm(() => {
|
|
32742
|
+
TIER_ALIASES = {
|
|
32743
|
+
opus: "opus",
|
|
32744
|
+
sonnet: "sonnet",
|
|
32745
|
+
haiku: "haiku",
|
|
32746
|
+
internal: "opus",
|
|
32747
|
+
default: "opus"
|
|
32748
|
+
};
|
|
32749
|
+
CLAUDE_CODE_MODEL_ALIASES = [
|
|
32750
|
+
"opus",
|
|
32751
|
+
"sonnet",
|
|
32752
|
+
"haiku",
|
|
32753
|
+
"internal",
|
|
32754
|
+
"default",
|
|
32755
|
+
"opusplan",
|
|
32756
|
+
"best"
|
|
32757
|
+
];
|
|
32758
|
+
});
|
|
32759
|
+
|
|
32665
32760
|
// src/providers/model-parser.ts
|
|
32666
32761
|
function parseModelChain(modelSpec) {
|
|
32667
32762
|
const parts = modelSpec.split(MODEL_CHAIN_SEPARATOR).map((s) => s.trim()).filter(Boolean);
|
|
@@ -32744,13 +32839,18 @@ function parseModelSpec(modelSpec) {
|
|
|
32744
32839
|
};
|
|
32745
32840
|
}
|
|
32746
32841
|
return {
|
|
32747
|
-
provider:
|
|
32842
|
+
provider: lastResortProvider(modelSpec),
|
|
32748
32843
|
model: modelSpec,
|
|
32749
32844
|
original,
|
|
32750
32845
|
isLegacySyntax: false,
|
|
32751
32846
|
isExplicitProvider: false
|
|
32752
32847
|
};
|
|
32753
32848
|
}
|
|
32849
|
+
function lastResortProvider(modelSpec) {
|
|
32850
|
+
const name = modelSpec.trim();
|
|
32851
|
+
const isNative = name === "" || name.startsWith("@") || isClaudeCodeModelName(name);
|
|
32852
|
+
return isNative ? "native-anthropic" : AUTO_ROUTE_PROVIDER;
|
|
32853
|
+
}
|
|
32754
32854
|
function isLocalProviderName(provider) {
|
|
32755
32855
|
return LOCAL_PROVIDERS.has(provider.toLowerCase());
|
|
32756
32856
|
}
|
|
@@ -32762,8 +32862,9 @@ function getLegacySyntaxWarning(parsed) {
|
|
|
32762
32862
|
return `Deprecation warning: "${parsed.original}" uses legacy prefix syntax.
|
|
32763
32863
|
` + ` Consider using: ${newSyntax}`;
|
|
32764
32864
|
}
|
|
32765
|
-
var PROVIDER_SHORTCUTS, LOCAL_PROVIDERS, NATIVE_MODEL_PATTERNS, LEGACY_PREFIX_PATTERNS, MODEL_CHAIN_SEPARATOR = "+";
|
|
32865
|
+
var AUTO_ROUTE_PROVIDER = "auto-route", PROVIDER_SHORTCUTS, LOCAL_PROVIDERS, NATIVE_MODEL_PATTERNS, LEGACY_PREFIX_PATTERNS, MODEL_CHAIN_SEPARATOR = "+";
|
|
32766
32866
|
var init_model_parser = __esm(() => {
|
|
32867
|
+
init_claude_code_aliases();
|
|
32767
32868
|
init_provider_definitions();
|
|
32768
32869
|
PROVIDER_SHORTCUTS = getShortcuts();
|
|
32769
32870
|
LOCAL_PROVIDERS = {
|
|
@@ -37129,7 +37230,7 @@ class ComposedHandler {
|
|
|
37129
37230
|
...this.recoveryStats(recoveryTally)
|
|
37130
37231
|
});
|
|
37131
37232
|
} catch {}
|
|
37132
|
-
return c.json(wrapAnthropicError(503, surfaced, "overloaded_error", undefined, settled.message), 503);
|
|
37233
|
+
return c.json(wrapAnthropicError(503, surfaced, "overloaded_error", undefined, settled.message), 503, settled.unreachable ? connectionFaultHeaders() : undefined);
|
|
37133
37234
|
}
|
|
37134
37235
|
response = settled.response;
|
|
37135
37236
|
}
|
|
@@ -37172,7 +37273,7 @@ class ComposedHandler {
|
|
|
37172
37273
|
...this.recoveryStats(recoveryTally)
|
|
37173
37274
|
});
|
|
37174
37275
|
} catch {}
|
|
37175
|
-
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);
|
|
37276
|
+
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, settled.kind === "exhausted" && settled.unreachable ? connectionFaultHeaders() : undefined);
|
|
37176
37277
|
}
|
|
37177
37278
|
response = settled.response;
|
|
37178
37279
|
}
|
|
@@ -37242,7 +37343,8 @@ class ComposedHandler {
|
|
|
37242
37343
|
kind: "exhausted",
|
|
37243
37344
|
code: verdict.code,
|
|
37244
37345
|
message: `${verdict.message} (retry could not reach the provider: ${error})`,
|
|
37245
|
-
attempts: attempt + 1
|
|
37346
|
+
attempts: attempt + 1,
|
|
37347
|
+
unreachable: true
|
|
37246
37348
|
};
|
|
37247
37349
|
}
|
|
37248
37350
|
if (!next.ok) {
|
|
@@ -37291,7 +37393,8 @@ class ComposedHandler {
|
|
|
37291
37393
|
kind: "exhausted",
|
|
37292
37394
|
code: verdict.code,
|
|
37293
37395
|
message: `${verdict.message} (retry could not reach the provider: ${error})`,
|
|
37294
|
-
attempts: attempt + 1
|
|
37396
|
+
attempts: attempt + 1,
|
|
37397
|
+
unreachable: true
|
|
37295
37398
|
};
|
|
37296
37399
|
}
|
|
37297
37400
|
if (!next.ok) {
|
|
@@ -40116,16 +40219,9 @@ function requireKeyUnlessNoAuth(ep, ctx) {
|
|
|
40116
40219
|
});
|
|
40117
40220
|
}
|
|
40118
40221
|
}
|
|
40119
|
-
var
|
|
40222
|
+
var CustomEndpointAuthSchemeSchema, CustomEndpointSimpleSchema, CustomEndpointComplexSchema, CustomEndpointSchema, PredefinedEndpointsConfigSchema;
|
|
40120
40223
|
var init_config_schema = __esm(() => {
|
|
40121
40224
|
init_zod();
|
|
40122
|
-
BuiltinDefaultProviderSchema = _enum([
|
|
40123
|
-
"openrouter",
|
|
40124
|
-
"litellm",
|
|
40125
|
-
"openai",
|
|
40126
|
-
"anthropic",
|
|
40127
|
-
"google"
|
|
40128
|
-
]);
|
|
40129
40225
|
CustomEndpointAuthSchemeSchema = _enum(["bearer", "x-api-key", "none"]);
|
|
40130
40226
|
CustomEndpointSimpleSchema = object2({
|
|
40131
40227
|
kind: literal("simple"),
|
|
@@ -40158,7 +40254,6 @@ var init_config_schema = __esm(() => {
|
|
|
40158
40254
|
disable: array(string2()).optional(),
|
|
40159
40255
|
enable: array(string2()).optional()
|
|
40160
40256
|
});
|
|
40161
|
-
DefaultProviderSchema = union([BuiltinDefaultProviderSchema, string2().min(1)]);
|
|
40162
40257
|
});
|
|
40163
40258
|
|
|
40164
40259
|
// src/providers/endpoint-diagnostics.ts
|
|
@@ -40991,6 +41086,54 @@ var init_endpoint_registration = __esm(() => {
|
|
|
40991
41086
|
warnedMessages4 = new Set;
|
|
40992
41087
|
});
|
|
40993
41088
|
|
|
41089
|
+
// src/providers/native-route.ts
|
|
41090
|
+
function proxyRouteDecision(target) {
|
|
41091
|
+
const parsed = parseModelSpec(target);
|
|
41092
|
+
if (parsed.isExplicitProvider) {
|
|
41093
|
+
return {
|
|
41094
|
+
type: "explicit",
|
|
41095
|
+
provider: parsed.provider,
|
|
41096
|
+
model: parsed.model,
|
|
41097
|
+
spec: target,
|
|
41098
|
+
via: "model-spec"
|
|
41099
|
+
};
|
|
41100
|
+
}
|
|
41101
|
+
if (target.startsWith(POE_PREFIX)) {
|
|
41102
|
+
return { type: "poe", model: target.slice(POE_PREFIX.length) };
|
|
41103
|
+
}
|
|
41104
|
+
if (parsed.provider === "native-anthropic") {
|
|
41105
|
+
if (target.includes("/")) {
|
|
41106
|
+
return {
|
|
41107
|
+
type: "explicit",
|
|
41108
|
+
provider: "openrouter",
|
|
41109
|
+
model: target,
|
|
41110
|
+
spec: target,
|
|
41111
|
+
via: "vendor-qualified-id"
|
|
41112
|
+
};
|
|
41113
|
+
}
|
|
41114
|
+
return { type: "native", route: nativeRouteOf(target) };
|
|
41115
|
+
}
|
|
41116
|
+
return { type: "bare", model: parsed.model };
|
|
41117
|
+
}
|
|
41118
|
+
function nativeRouteOf(model) {
|
|
41119
|
+
return {
|
|
41120
|
+
provider: "native-anthropic",
|
|
41121
|
+
modelSpec: normalizeNativeModelSpec(model),
|
|
41122
|
+
displayName: getProviderByName("native-anthropic")?.displayName ?? "Anthropic (Native)",
|
|
41123
|
+
isTierAlias: claudeCodeTierAlias(model) !== null
|
|
41124
|
+
};
|
|
41125
|
+
}
|
|
41126
|
+
function nativeRouteFor(model) {
|
|
41127
|
+
const decision = proxyRouteDecision(model);
|
|
41128
|
+
return decision.type === "native" ? decision.route : null;
|
|
41129
|
+
}
|
|
41130
|
+
var NATIVE_NOT_PROBED = "not probed \u2014 served on Claude Code's own auth, which this process cannot forward", POE_PREFIX = "poe:";
|
|
41131
|
+
var init_native_route = __esm(() => {
|
|
41132
|
+
init_claude_code_aliases();
|
|
41133
|
+
init_model_parser();
|
|
41134
|
+
init_provider_definitions();
|
|
41135
|
+
});
|
|
41136
|
+
|
|
40994
41137
|
// src/providers/provider-registry.ts
|
|
40995
41138
|
function resolveBaseUrl2(envVar, fallbackEnvVars, staticDefault) {
|
|
40996
41139
|
for (const v of [envVar, ...fallbackEnvVars]) {
|
|
@@ -41158,7 +41301,7 @@ var init_remote_provider_registry = __esm(() => {
|
|
|
41158
41301
|
});
|
|
41159
41302
|
|
|
41160
41303
|
// src/providers/routing-hints.ts
|
|
41161
|
-
function buildCredentialHint(modelName, providers) {
|
|
41304
|
+
function buildCredentialHint(modelName, providers, options = {}) {
|
|
41162
41305
|
const seen = new Set;
|
|
41163
41306
|
const lines = [`No credentials found for "${modelName}". Options:`];
|
|
41164
41307
|
let hasOption = false;
|
|
@@ -41182,7 +41325,7 @@ function buildCredentialHint(modelName, providers) {
|
|
|
41182
41325
|
hasOption = true;
|
|
41183
41326
|
}
|
|
41184
41327
|
}
|
|
41185
|
-
if (!seen.has("openrouter")) {
|
|
41328
|
+
if (!seen.has("openrouter") && options.suggestOpenRouter !== false) {
|
|
41186
41329
|
lines.push(` Use: claudish --model or@${modelName} (route via OpenRouter)`);
|
|
41187
41330
|
hasOption = true;
|
|
41188
41331
|
}
|
|
@@ -41415,17 +41558,17 @@ async function fetchProbeModels(url = PROBE_MODELS_URL, timeoutMs = FETCH_TIMEOU
|
|
|
41415
41558
|
for (const route of Object.values(envelope.data.routes)) {
|
|
41416
41559
|
if (!route || typeof route !== "object" || typeof route.externalModelId !== "string")
|
|
41417
41560
|
continue;
|
|
41418
|
-
const provider
|
|
41419
|
-
if (provider)
|
|
41561
|
+
for (const provider of catalogReadProvidersForRoute(route.route)) {
|
|
41420
41562
|
providers[provider] = route.externalModelId;
|
|
41563
|
+
}
|
|
41421
41564
|
}
|
|
41422
41565
|
const unavailable = {};
|
|
41423
41566
|
for (const route of Object.values(envelope.data.unavailableRoutes)) {
|
|
41424
41567
|
if (!route || typeof route !== "object" || typeof route.reason !== "string")
|
|
41425
41568
|
continue;
|
|
41426
|
-
const provider
|
|
41427
|
-
if (provider)
|
|
41569
|
+
for (const provider of catalogReadProvidersForRoute(route.route)) {
|
|
41428
41570
|
unavailable[provider] = route.reason;
|
|
41571
|
+
}
|
|
41429
41572
|
}
|
|
41430
41573
|
if (Object.keys(providers).length + Object.keys(unavailable).length === 0) {
|
|
41431
41574
|
return { kind: "invalid", reason: "no supported probe routes" };
|
|
@@ -41518,6 +41661,9 @@ var init_probe_catalog = __esm(() => {
|
|
|
41518
41661
|
});
|
|
41519
41662
|
|
|
41520
41663
|
// src/providers/route-candidates.ts
|
|
41664
|
+
function bandRank(tier) {
|
|
41665
|
+
return tier === "dynamic-subscription" ? TIER_RANK.subscription : TIER_RANK[tier];
|
|
41666
|
+
}
|
|
41521
41667
|
function routeLabel(route) {
|
|
41522
41668
|
return route ? `${route.routeId}/${route.routeProfileId}` : "(no route)";
|
|
41523
41669
|
}
|
|
@@ -41538,7 +41684,7 @@ function gatherFromConnections(entry, candidates, unmappedRoutes) {
|
|
|
41538
41684
|
for (const connection of entry.aggregators ?? []) {
|
|
41539
41685
|
if (connection.routeStatus !== "mapped")
|
|
41540
41686
|
continue;
|
|
41541
|
-
const bound =
|
|
41687
|
+
const bound = routingProvidersForRoute(connection.route);
|
|
41542
41688
|
const routable = bound.filter((name) => getProviderByName(name)?.tier !== undefined);
|
|
41543
41689
|
if (routable.length === 0) {
|
|
41544
41690
|
unmappedRoutes.add(routeLabel(connection.route));
|
|
@@ -41566,6 +41712,15 @@ function gatherFromConnections(entry, candidates, unmappedRoutes) {
|
|
|
41566
41712
|
function isVendorOwnRoute(route, entry) {
|
|
41567
41713
|
return route !== undefined && entry?.provider !== undefined && route.routeId === entry.provider;
|
|
41568
41714
|
}
|
|
41715
|
+
function nativeProviderForVendor(vendorSlug) {
|
|
41716
|
+
for (const [provider, binding] of Object.entries(CATALOG_ROUTE_BINDINGS)) {
|
|
41717
|
+
if (binding.routeId !== vendorSlug)
|
|
41718
|
+
continue;
|
|
41719
|
+
if (getProviderByName(provider)?.tier === "native")
|
|
41720
|
+
return provider;
|
|
41721
|
+
}
|
|
41722
|
+
return;
|
|
41723
|
+
}
|
|
41569
41724
|
function gatherFromNamespaceClaims(model, entry, candidates) {
|
|
41570
41725
|
for (const def of getAllProviders()) {
|
|
41571
41726
|
if (def.tier !== "dynamic-subscription")
|
|
@@ -41583,11 +41738,14 @@ function gatherFromNamespaceClaims(model, entry, candidates) {
|
|
|
41583
41738
|
}
|
|
41584
41739
|
}
|
|
41585
41740
|
function compareRouteCandidates(a, b) {
|
|
41741
|
+
const byBand = bandRank(a.tier) - bandRank(b.tier);
|
|
41742
|
+
if (byBand !== 0)
|
|
41743
|
+
return byBand;
|
|
41744
|
+
if (a.isVendorOwn !== b.isVendorOwn)
|
|
41745
|
+
return a.isVendorOwn ? -1 : 1;
|
|
41586
41746
|
const byTier = TIER_RANK[a.tier] - TIER_RANK[b.tier];
|
|
41587
41747
|
if (byTier !== 0)
|
|
41588
41748
|
return byTier;
|
|
41589
|
-
if (a.isVendorOwn !== b.isVendorOwn)
|
|
41590
|
-
return a.isVendorOwn ? -1 : 1;
|
|
41591
41749
|
const byPrice = compareByConnectionPrice(a.price, b.price);
|
|
41592
41750
|
if (byPrice !== 0)
|
|
41593
41751
|
return byPrice;
|
|
@@ -41666,44 +41824,79 @@ var init_route_candidates = __esm(() => {
|
|
|
41666
41824
|
|
|
41667
41825
|
// src/providers/routing-rules.ts
|
|
41668
41826
|
function loadRoutingRules(sources) {
|
|
41669
|
-
const local
|
|
41670
|
-
const global_ = sources ? sources.globalRules : loadConfig().routing ?? {};
|
|
41671
|
-
validateRoutingRules(local);
|
|
41672
|
-
validateRoutingRules(global_);
|
|
41827
|
+
const { localRules: local, globalRules: global_ } = sources ?? loadRoutingRuleSources();
|
|
41673
41828
|
return { ...global_, ...local };
|
|
41674
41829
|
}
|
|
41675
|
-
function
|
|
41830
|
+
function loadRoutingRuleSources() {
|
|
41831
|
+
const localRules = loadLocalConfig()?.routing ?? {};
|
|
41832
|
+
const globalRules = loadConfig().routing ?? {};
|
|
41833
|
+
return { globalRules, localRules };
|
|
41834
|
+
}
|
|
41835
|
+
function routingRuleProblems(sources) {
|
|
41836
|
+
return [
|
|
41837
|
+
...ruleTableProblems(sources.globalRules, "global"),
|
|
41838
|
+
...ruleTableProblems(sources.localRules, "project")
|
|
41839
|
+
];
|
|
41840
|
+
}
|
|
41841
|
+
function ruleTableProblems(rules, scope) {
|
|
41842
|
+
const problems = [];
|
|
41676
41843
|
const seenLower = new Map;
|
|
41677
41844
|
for (const key of Object.keys(rules)) {
|
|
41678
41845
|
if (key !== "*" && (key.match(/\*/g) || []).length > 1) {
|
|
41679
|
-
|
|
41846
|
+
problems.push({ scope, pattern: key, problem: "multiple-wildcards" });
|
|
41680
41847
|
}
|
|
41681
41848
|
const lower = key.toLowerCase();
|
|
41682
41849
|
const prior = seenLower.get(lower);
|
|
41683
41850
|
if (prior !== undefined && prior !== key) {
|
|
41684
|
-
|
|
41851
|
+
problems.push({ scope, pattern: key, problem: "case-collision", collidesWith: prior });
|
|
41685
41852
|
} else {
|
|
41686
41853
|
seenLower.set(lower, key);
|
|
41687
41854
|
}
|
|
41855
|
+
for (const entry of rules[key] ?? []) {
|
|
41856
|
+
if (!isKnownProvider(ruleEntryProvider(entry))) {
|
|
41857
|
+
problems.push({ scope, pattern: key, problem: "unknown-provider", entry });
|
|
41858
|
+
}
|
|
41859
|
+
}
|
|
41860
|
+
}
|
|
41861
|
+
return problems;
|
|
41862
|
+
}
|
|
41863
|
+
function ruleEntryProvider(entry) {
|
|
41864
|
+
const atIdx = entry.indexOf("@");
|
|
41865
|
+
const providerRaw = atIdx === -1 ? entry : entry.slice(0, atIdx);
|
|
41866
|
+
return PROVIDER_SHORTCUTS[providerRaw.toLowerCase()] ?? providerRaw.toLowerCase();
|
|
41867
|
+
}
|
|
41868
|
+
function isKnownProvider(provider) {
|
|
41869
|
+
return getProviderByName(provider) !== undefined || PREDEFINED_ENDPOINTS.some((row) => row.name.toLowerCase() === provider);
|
|
41870
|
+
}
|
|
41871
|
+
function describeRoutingRuleProblem(problem) {
|
|
41872
|
+
switch (problem.problem) {
|
|
41873
|
+
case "multiple-wildcards":
|
|
41874
|
+
return `routing pattern "${problem.pattern}" (${problem.scope}) has more than one * \u2014 ` + "only a single * is supported, so it may not match as expected.";
|
|
41875
|
+
case "case-collision":
|
|
41876
|
+
return `routing patterns "${problem.collidesWith}" and "${problem.pattern}" (${problem.scope}) ` + "differ only in case. Matching ignores case, so one silently shadows the other: " + "pick one casing and remove the duplicate.";
|
|
41877
|
+
case "unknown-provider": {
|
|
41878
|
+
const entry = problem.entry ?? "";
|
|
41879
|
+
return `routing rule "${problem.pattern}" (${problem.scope}) names "${entry}", but no ` + `provider "${ruleEntryProvider(entry)}" exists, so that entry never routes.`;
|
|
41880
|
+
}
|
|
41688
41881
|
}
|
|
41689
41882
|
}
|
|
41690
|
-
function
|
|
41883
|
+
function matchRoutingRuleKey(modelName, rules) {
|
|
41691
41884
|
const lowered = modelName.toLowerCase();
|
|
41692
|
-
for (const
|
|
41885
|
+
for (const key of Object.keys(rules)) {
|
|
41693
41886
|
if (!key.includes("*") && key.toLowerCase() === lowered)
|
|
41694
|
-
return
|
|
41887
|
+
return key;
|
|
41695
41888
|
}
|
|
41696
41889
|
const globKeys = Object.keys(rules).filter((k) => k !== "*" && k.includes("*")).sort((a, b) => b.length - a.length);
|
|
41697
41890
|
for (const pattern of globKeys) {
|
|
41698
41891
|
if (globMatch(pattern, modelName))
|
|
41699
|
-
return
|
|
41892
|
+
return pattern;
|
|
41700
41893
|
}
|
|
41701
41894
|
if (rules["*"] !== undefined)
|
|
41702
|
-
return
|
|
41895
|
+
return "*";
|
|
41703
41896
|
return null;
|
|
41704
41897
|
}
|
|
41705
|
-
function
|
|
41706
|
-
const
|
|
41898
|
+
function resolveRoutingEntries(entries, originalModelName, cachePath) {
|
|
41899
|
+
const resolved = [];
|
|
41707
41900
|
for (const entry of entries) {
|
|
41708
41901
|
const atIdx = entry.indexOf("@");
|
|
41709
41902
|
let providerRaw;
|
|
@@ -41719,8 +41912,10 @@ function buildRoutingChain(entries, originalModelName, cachePath) {
|
|
|
41719
41912
|
let wireIdResolved = false;
|
|
41720
41913
|
if (atIdx === -1) {
|
|
41721
41914
|
const routing = resolveSubscriptionRouting(modelName, provider, cachePath);
|
|
41722
|
-
if (routing.kind === "not-served")
|
|
41915
|
+
if (routing.kind === "not-served") {
|
|
41916
|
+
resolved.push({ route: routeFor(provider, modelName), excludedByMembership: true });
|
|
41723
41917
|
continue;
|
|
41918
|
+
}
|
|
41724
41919
|
if (routing.kind === "serves") {
|
|
41725
41920
|
modelName = routing.externalId;
|
|
41726
41921
|
wireIdResolved = true;
|
|
@@ -41729,9 +41924,9 @@ function buildRoutingChain(entries, originalModelName, cachePath) {
|
|
|
41729
41924
|
if (!wireIdResolved) {
|
|
41730
41925
|
modelName = resolveExternalId(modelName, provider, cachePath) ?? modelName;
|
|
41731
41926
|
}
|
|
41732
|
-
|
|
41927
|
+
resolved.push({ route: routeFor(provider, modelName), excludedByMembership: false });
|
|
41733
41928
|
}
|
|
41734
|
-
return
|
|
41929
|
+
return resolved;
|
|
41735
41930
|
}
|
|
41736
41931
|
function routeFor(provider, wireId) {
|
|
41737
41932
|
const modelSpec = provider === "openrouter" ? wireId : `${PROVIDER_TO_PREFIX[provider] ?? provider}@${wireId}`;
|
|
@@ -41750,29 +41945,67 @@ function globMatch(pattern, value) {
|
|
|
41750
41945
|
async function hasCredentialsForProvider(provider) {
|
|
41751
41946
|
return credentials.isAvailable(provider);
|
|
41752
41947
|
}
|
|
41753
|
-
|
|
41754
|
-
|
|
41755
|
-
|
|
41948
|
+
function explainCandidate(route, position, outcome, gathered) {
|
|
41949
|
+
const tier = gathered ? gathered.tier : getProviderByName(route.provider)?.tier;
|
|
41950
|
+
return {
|
|
41951
|
+
provider: route.provider,
|
|
41952
|
+
displayName: route.displayName,
|
|
41953
|
+
modelSpec: route.modelSpec,
|
|
41954
|
+
wireId: wireIdOf(route),
|
|
41955
|
+
position,
|
|
41956
|
+
...tier !== undefined ? { tier } : {},
|
|
41957
|
+
...gathered ? { isVendorOwn: gathered.isVendorOwn, price: gathered.price } : {},
|
|
41958
|
+
...gathered?.contextWindow !== undefined ? { contextWindow: gathered.contextWindow } : {},
|
|
41959
|
+
outcome
|
|
41960
|
+
};
|
|
41961
|
+
}
|
|
41962
|
+
function entryOutcome(resolved) {
|
|
41963
|
+
return resolved.excludedByMembership ? "excluded-by-membership" : "kept";
|
|
41964
|
+
}
|
|
41965
|
+
async function explainExplicitSpec(requestedModel, modelSpec, model, provider, cachePath) {
|
|
41966
|
+
const credentialed = await hasCredentialsForProvider(provider);
|
|
41967
|
+
const [resolved] = resolveRoutingEntries([modelSpec], model, cachePath);
|
|
41968
|
+
const candidate = explainCandidate(resolved.route, "candidate", entryOutcome(resolved));
|
|
41969
|
+
const explanation = {
|
|
41970
|
+
requestedModel,
|
|
41971
|
+
routedModel: model,
|
|
41972
|
+
source: "explicit",
|
|
41973
|
+
via: "model-spec",
|
|
41974
|
+
candidates: [candidate],
|
|
41975
|
+
outcome: { kind: "ok" },
|
|
41976
|
+
warnings: []
|
|
41977
|
+
};
|
|
41978
|
+
if (!credentialed) {
|
|
41979
|
+
candidate.outcome = "no-credential";
|
|
41980
|
+
explanation.outcome = {
|
|
41756
41981
|
kind: "no-route",
|
|
41982
|
+
cause: "explicit-no-credential",
|
|
41757
41983
|
reason: `No credentials configured for "${provider}".`,
|
|
41758
41984
|
hint: buildCredentialHint(model, [provider]) ?? undefined
|
|
41759
41985
|
};
|
|
41986
|
+
return explanation;
|
|
41760
41987
|
}
|
|
41761
|
-
|
|
41762
|
-
|
|
41763
|
-
return {
|
|
41988
|
+
if (resolved.excludedByMembership) {
|
|
41989
|
+
explanation.outcome = {
|
|
41764
41990
|
kind: "no-route",
|
|
41991
|
+
cause: "explicit-unbuildable",
|
|
41765
41992
|
reason: `Could not build a route for "${modelSpec}".`
|
|
41766
41993
|
};
|
|
41994
|
+
return explanation;
|
|
41767
41995
|
}
|
|
41768
|
-
|
|
41769
|
-
|
|
41996
|
+
const availability = await providerServesModel(candidate.provider, candidate.wireId);
|
|
41997
|
+
if (availability === "not-served") {
|
|
41998
|
+
candidate.outcome = "not-served";
|
|
41999
|
+
explanation.outcome = {
|
|
41770
42000
|
kind: "no-route",
|
|
41771
|
-
|
|
42001
|
+
cause: "explicit-not-served",
|
|
42002
|
+
reason: `${candidate.displayName} does not serve "${model}".`,
|
|
41772
42003
|
hint: `Check the model id, or use a bare \`${model}\` to let claudish pick a provider ` + "that carries it."
|
|
41773
42004
|
};
|
|
42005
|
+
return explanation;
|
|
41774
42006
|
}
|
|
41775
|
-
|
|
42007
|
+
candidate.availability = availability;
|
|
42008
|
+
return explanation;
|
|
41776
42009
|
}
|
|
41777
42010
|
function fallbackProviderFor(defaultProvider) {
|
|
41778
42011
|
if (defaultProvider !== undefined && defaultProvider.length === 0)
|
|
@@ -41780,39 +42013,100 @@ function fallbackProviderFor(defaultProvider) {
|
|
|
41780
42013
|
const named = defaultProvider ?? DEFAULT_FALLBACK_PROVIDER;
|
|
41781
42014
|
return PROVIDER_SHORTCUTS[named.toLowerCase()] ?? named.toLowerCase();
|
|
41782
42015
|
}
|
|
41783
|
-
function
|
|
42016
|
+
function effectiveDefaultProvider() {
|
|
42017
|
+
return resolveDefaultProvider({ config: loadConfig(), env: process.env }).provider;
|
|
42018
|
+
}
|
|
42019
|
+
function explainCatalogChain(model, defaultProvider, cachePath) {
|
|
41784
42020
|
ensureEndpointsRegistered();
|
|
41785
42021
|
const gathering = gatherRouteCandidates(model, cachePath);
|
|
41786
|
-
const
|
|
42022
|
+
const candidates = gathering.candidates.map((candidate) => explainCandidate(routeFor(candidate.provider, candidate.wireId), "candidate", "kept", candidate));
|
|
42023
|
+
const catalog = !gathering.catalogReadable ? "unreadable" : gathering.catalogMiss ? "absent" : "found";
|
|
41787
42024
|
const fallback = fallbackProviderFor(defaultProvider);
|
|
41788
|
-
|
|
41789
|
-
|
|
42025
|
+
let fallbackWithheld;
|
|
42026
|
+
if (!fallback) {
|
|
42027
|
+
fallbackWithheld = "disabled";
|
|
42028
|
+
} else if (!gathering.catalogReadable) {
|
|
42029
|
+
fallbackWithheld = "catalog-unreadable";
|
|
42030
|
+
} else if (candidates.some((candidate) => candidate.provider === fallback)) {
|
|
42031
|
+
fallbackWithheld = "already-gathered";
|
|
42032
|
+
} else if (catalogDeniesProvider(fallback, model, cachePath)) {
|
|
42033
|
+
fallbackWithheld = "catalog-denies";
|
|
42034
|
+
} else {
|
|
42035
|
+
for (const resolved of resolveRoutingEntries([fallback], model, cachePath)) {
|
|
42036
|
+
candidates.push(explainCandidate(resolved.route, "fallback", entryOutcome(resolved)));
|
|
42037
|
+
}
|
|
42038
|
+
}
|
|
42039
|
+
return { candidates, catalog, ...fallbackWithheld ? { fallbackWithheld } : {} };
|
|
42040
|
+
}
|
|
42041
|
+
function emptyChainOutcome(model, nativeProvider, cause, cachePath) {
|
|
42042
|
+
return {
|
|
42043
|
+
kind: "no-route",
|
|
42044
|
+
cause,
|
|
42045
|
+
reason: cause === "rule-empty" ? `A routing rule matched "${model}" and named no provider.` : `No provider in the catalog serves "${model}".`,
|
|
42046
|
+
hint: emptyChainHint(model, nativeProvider, cause, cachePath)
|
|
42047
|
+
};
|
|
42048
|
+
}
|
|
42049
|
+
function emptyChainHint(model, nativeProvider, cause, cachePath) {
|
|
42050
|
+
if (nativeProvider !== AUTO_ROUTE_PROVIDER) {
|
|
42051
|
+
return buildCredentialHint(model, [nativeProvider]) ?? undefined;
|
|
41790
42052
|
}
|
|
41791
|
-
|
|
42053
|
+
const suggestOpenRouter = cause === "rule-empty" || !catalogDeniesProvider("openrouter", model, cachePath);
|
|
42054
|
+
return buildCredentialHint(model, [], { suggestOpenRouter }) ?? undefined;
|
|
41792
42055
|
}
|
|
41793
|
-
|
|
41794
|
-
|
|
41795
|
-
|
|
41796
|
-
|
|
41797
|
-
|
|
42056
|
+
function ruleProblemWarnings(problems) {
|
|
42057
|
+
return (problems ?? []).map((problem) => ({
|
|
42058
|
+
type: "rule-problem",
|
|
42059
|
+
problem,
|
|
42060
|
+
message: describeRoutingRuleProblem(problem)
|
|
42061
|
+
}));
|
|
42062
|
+
}
|
|
42063
|
+
async function explainBareName(requestedModel, model, nativeProvider, routing, cachePath) {
|
|
42064
|
+
const matchedKey = matchRoutingRuleKey(model, routing.rules);
|
|
42065
|
+
const matched = matchedKey === null ? null : routing.rules[matchedKey];
|
|
42066
|
+
let explanation;
|
|
42067
|
+
if (matchedKey !== null && matched !== null) {
|
|
42068
|
+
explanation = {
|
|
42069
|
+
requestedModel,
|
|
42070
|
+
routedModel: model,
|
|
42071
|
+
source: "user-rule",
|
|
42072
|
+
matchedPattern: matchedKey,
|
|
42073
|
+
...routing.scopeOf ? { ruleScope: routing.scopeOf(matchedKey) } : {},
|
|
42074
|
+
candidates: resolveRoutingEntries(matched, model, cachePath).map((resolved) => explainCandidate(resolved.route, "candidate", entryOutcome(resolved))),
|
|
42075
|
+
outcome: { kind: "ok" },
|
|
42076
|
+
warnings: ruleProblemWarnings(routing.ruleProblems)
|
|
42077
|
+
};
|
|
41798
42078
|
} else {
|
|
41799
|
-
const
|
|
41800
|
-
|
|
41801
|
-
|
|
41802
|
-
|
|
41803
|
-
|
|
41804
|
-
|
|
41805
|
-
|
|
41806
|
-
|
|
41807
|
-
|
|
42079
|
+
const chain = explainCatalogChain(model, routing.defaultProvider, cachePath);
|
|
42080
|
+
explanation = {
|
|
42081
|
+
requestedModel,
|
|
42082
|
+
routedModel: model,
|
|
42083
|
+
source: "catalog",
|
|
42084
|
+
catalog: chain.catalog,
|
|
42085
|
+
candidates: chain.candidates,
|
|
42086
|
+
...chain.fallbackWithheld ? { fallbackWithheld: chain.fallbackWithheld } : {},
|
|
42087
|
+
outcome: { kind: "ok" },
|
|
42088
|
+
warnings: ruleProblemWarnings(routing.ruleProblems)
|
|
42089
|
+
};
|
|
41808
42090
|
}
|
|
41809
|
-
|
|
41810
|
-
|
|
42091
|
+
const remaining = explanation.candidates.filter((candidate) => candidate.outcome !== "excluded-by-membership");
|
|
42092
|
+
if (explanation.catalog === "unreadable" && remaining.length === 0) {
|
|
42093
|
+
explanation.outcome = {
|
|
41811
42094
|
kind: "no-route",
|
|
41812
|
-
|
|
41813
|
-
|
|
42095
|
+
cause: "catalog-unreadable",
|
|
42096
|
+
reason: `No model catalog available, so "${model}" cannot be routed by name.`,
|
|
42097
|
+
hint: "Run `claudish --models-refresh` to fetch the catalog, or name the provider " + `explicitly (e.g. \`openrouter@${model}\`).`
|
|
41814
42098
|
};
|
|
42099
|
+
return explanation;
|
|
42100
|
+
}
|
|
42101
|
+
if (remaining.length === 0) {
|
|
42102
|
+
explanation.outcome = emptyChainOutcome(model, nativeProvider, explanation.source === "user-rule" ? "rule-empty" : "catalog-empty", cachePath);
|
|
42103
|
+
return explanation;
|
|
41815
42104
|
}
|
|
42105
|
+
await applyCandidateFilters(explanation, remaining);
|
|
42106
|
+
return explanation;
|
|
42107
|
+
}
|
|
42108
|
+
async function applyCandidateFilters(explanation, candidates) {
|
|
42109
|
+
const model = explanation.routedModel;
|
|
41816
42110
|
const credentialed = [];
|
|
41817
42111
|
const skipped = [];
|
|
41818
42112
|
const skippedFailed = [];
|
|
@@ -41830,45 +42124,63 @@ async function routeBare(model, nativeProvider, rules, defaultProvider, cachePat
|
|
|
41830
42124
|
return;
|
|
41831
42125
|
}
|
|
41832
42126
|
skipped.push(candidate.provider);
|
|
41833
|
-
if (verdict.readiness === "failed")
|
|
42127
|
+
if (verdict.readiness === "failed") {
|
|
41834
42128
|
skippedFailed.push(candidate.provider);
|
|
42129
|
+
candidate.outcome = "credential-unreadable";
|
|
42130
|
+
} else {
|
|
42131
|
+
candidate.outcome = "no-credential";
|
|
42132
|
+
}
|
|
41835
42133
|
});
|
|
41836
42134
|
if (credentialed.length === 0) {
|
|
41837
|
-
|
|
42135
|
+
explanation.outcome = {
|
|
41838
42136
|
kind: "no-route",
|
|
42137
|
+
cause: "no-credential",
|
|
41839
42138
|
reason: skipped.length > 0 ? `No credentialed providers in chain for "${model}" (tried: ${skipped.join(", ")}).` : `No providers available for "${model}".`,
|
|
41840
42139
|
hint: buildCredentialHint(model, skipped) ?? undefined
|
|
41841
42140
|
};
|
|
42141
|
+
return;
|
|
41842
42142
|
}
|
|
41843
|
-
const availability = await Promise.all(credentialed.map((candidate) => providerServesModel(candidate.provider,
|
|
42143
|
+
const availability = await Promise.all(credentialed.map((candidate) => providerServesModel(candidate.provider, candidate.wireId)));
|
|
41844
42144
|
const serving = [];
|
|
41845
42145
|
const notServing = [];
|
|
41846
42146
|
credentialed.forEach((candidate, i) => {
|
|
41847
|
-
|
|
42147
|
+
const verdict = availability[i];
|
|
42148
|
+
if (verdict === "not-served") {
|
|
41848
42149
|
notServing.push(candidate.provider);
|
|
42150
|
+
candidate.outcome = "not-served";
|
|
41849
42151
|
} else {
|
|
41850
42152
|
serving.push(candidate);
|
|
42153
|
+
candidate.availability = verdict;
|
|
41851
42154
|
}
|
|
41852
42155
|
});
|
|
41853
42156
|
if (serving.length === 0) {
|
|
41854
|
-
|
|
42157
|
+
explanation.outcome = {
|
|
41855
42158
|
kind: "no-route",
|
|
42159
|
+
cause: "not-served",
|
|
41856
42160
|
reason: `No provider serves "${model}" (checked: ${notServing.join(", ")}).`,
|
|
41857
42161
|
hint: buildCredentialHint(model, notServing) ?? undefined
|
|
41858
42162
|
};
|
|
42163
|
+
return;
|
|
41859
42164
|
}
|
|
41860
42165
|
if (notServing.length > 0) {
|
|
41861
|
-
log(`[routing] ${model}: skipped ${notServing.join(", ")} \u2014 does not serve this model`);
|
|
41862
42166
|
const droppedSubscription = notServing.filter((p) => isSubscriptionProvider(p));
|
|
41863
42167
|
if (droppedSubscription.length > 0 && !isSubscriptionProvider(serving[0].provider)) {
|
|
41864
|
-
|
|
42168
|
+
explanation.warnings.push({
|
|
42169
|
+
type: "subscription-not-served",
|
|
42170
|
+
providers: droppedSubscription,
|
|
42171
|
+
usedInstead: serving[0].provider,
|
|
42172
|
+
message: `${droppedSubscription.join(", ")} does not serve ${model} \u2014 ` + `using ${serving[0].displayName}, which bills per token.`
|
|
42173
|
+
});
|
|
41865
42174
|
}
|
|
41866
42175
|
}
|
|
41867
42176
|
if (skippedFailed.length > 0 && !isSubscriptionProvider(serving[0].provider)) {
|
|
41868
|
-
|
|
42177
|
+
explanation.warnings.push({
|
|
42178
|
+
type: "subscription-credential-unreadable",
|
|
42179
|
+
providers: skippedFailed,
|
|
42180
|
+
usedInstead: serving[0].provider,
|
|
42181
|
+
message: `${skippedFailed.join(", ")}: the credential could not be READ (not "no key") \u2014 ` + `using ${serving[0].displayName}, which bills per token.`
|
|
42182
|
+
});
|
|
41869
42183
|
}
|
|
41870
|
-
const [primary, ...fallbacks] = serving;
|
|
41871
|
-
return { kind: "ok", primary, fallbacks };
|
|
41872
42184
|
}
|
|
41873
42185
|
function wireIdOf(route) {
|
|
41874
42186
|
const at = route.modelSpec.indexOf("@");
|
|
@@ -41878,15 +42190,174 @@ function normalizeGlmSlug(model) {
|
|
|
41878
42190
|
return model.replace(/^glm-(\d+)-(\d+)(-.*)?$/i, (_m, major, minor, suffix) => `glm-${major}.${minor}${suffix ?? ""}`);
|
|
41879
42191
|
}
|
|
41880
42192
|
async function route(modelSpec, rulesOverride, defaultProviderOverride, cachePath) {
|
|
42193
|
+
const explanation = await explainRoutePlan(modelSpec, () => {
|
|
42194
|
+
const rules = rulesOverride ?? loadRoutingRules();
|
|
42195
|
+
const defaultProvider = defaultProviderOverride !== undefined ? defaultProviderOverride : rulesOverride !== undefined ? undefined : effectiveDefaultProvider();
|
|
42196
|
+
return { rules, defaultProvider };
|
|
42197
|
+
}, cachePath);
|
|
42198
|
+
emitRouteNotices(explanation);
|
|
42199
|
+
return toRoutePlan(explanation);
|
|
42200
|
+
}
|
|
42201
|
+
async function explainRoutePlan(modelSpec, bareRouting, cachePath, requestedModel = modelSpec) {
|
|
41881
42202
|
const parsed = parseModelSpec(modelSpec);
|
|
41882
42203
|
if (parsed.isExplicitProvider) {
|
|
41883
|
-
return
|
|
42204
|
+
return explainExplicitSpec(requestedModel, modelSpec, parsed.model, parsed.provider, cachePath);
|
|
42205
|
+
}
|
|
42206
|
+
return explainBareName(requestedModel, normalizeGlmSlug(parsed.model), parsed.provider, bareRouting(), cachePath);
|
|
42207
|
+
}
|
|
42208
|
+
async function explainRoute(target, opts = {}) {
|
|
42209
|
+
const decision = proxyRouteDecision(target);
|
|
42210
|
+
if (decision.type === "native") {
|
|
42211
|
+
return {
|
|
42212
|
+
requestedModel: target,
|
|
42213
|
+
routedModel: target,
|
|
42214
|
+
source: "native",
|
|
42215
|
+
candidates: [],
|
|
42216
|
+
outcome: { kind: "ok" },
|
|
42217
|
+
warnings: [],
|
|
42218
|
+
native: decision.route
|
|
42219
|
+
};
|
|
42220
|
+
}
|
|
42221
|
+
if (decision.type === "poe") {
|
|
42222
|
+
return explainUnroutedExplicit(target, "poe", "poe", decision.model);
|
|
41884
42223
|
}
|
|
41885
|
-
|
|
41886
|
-
|
|
41887
|
-
|
|
42224
|
+
if (decision.type === "explicit" && decision.via === "vendor-qualified-id") {
|
|
42225
|
+
return explainUnroutedExplicit(target, "vendor-qualified-id", decision.provider, decision.model);
|
|
42226
|
+
}
|
|
42227
|
+
const routeTarget = decision.type === "explicit" ? decision.spec : decision.model;
|
|
42228
|
+
return explainRoutePlan(routeTarget, () => bareRoutingFor(opts), opts.cachePath, target);
|
|
41888
42229
|
}
|
|
41889
|
-
|
|
42230
|
+
async function explainUnroutedExplicit(requestedModel, via, provider, wireId) {
|
|
42231
|
+
const credentialed = await hasCredentialsForProvider(provider);
|
|
42232
|
+
const tier = getProviderByName(provider)?.tier;
|
|
42233
|
+
return {
|
|
42234
|
+
requestedModel,
|
|
42235
|
+
routedModel: wireId,
|
|
42236
|
+
source: "explicit",
|
|
42237
|
+
via,
|
|
42238
|
+
candidates: [
|
|
42239
|
+
{
|
|
42240
|
+
provider,
|
|
42241
|
+
displayName: DISPLAY_NAMES[provider] ?? provider,
|
|
42242
|
+
modelSpec: requestedModel,
|
|
42243
|
+
wireId,
|
|
42244
|
+
position: "candidate",
|
|
42245
|
+
...tier !== undefined ? { tier } : {},
|
|
42246
|
+
outcome: credentialed ? "kept" : "no-credential"
|
|
42247
|
+
}
|
|
42248
|
+
],
|
|
42249
|
+
outcome: credentialed ? { kind: "ok" } : {
|
|
42250
|
+
kind: "no-route",
|
|
42251
|
+
cause: "explicit-no-credential",
|
|
42252
|
+
reason: `No credentials configured for "${provider}".`,
|
|
42253
|
+
hint: buildCredentialHint(wireId, [provider]) ?? undefined
|
|
42254
|
+
},
|
|
42255
|
+
warnings: []
|
|
42256
|
+
};
|
|
42257
|
+
}
|
|
42258
|
+
function bareRoutingFor(opts) {
|
|
42259
|
+
if (opts.rules !== undefined) {
|
|
42260
|
+
return { rules: opts.rules, defaultProvider: opts.defaultProvider };
|
|
42261
|
+
}
|
|
42262
|
+
const sources = loadRoutingRuleSources();
|
|
42263
|
+
return {
|
|
42264
|
+
rules: loadRoutingRules(sources),
|
|
42265
|
+
defaultProvider: opts.defaultProvider !== undefined ? opts.defaultProvider : effectiveDefaultProvider(),
|
|
42266
|
+
scopeOf: (ruleKey) => Object.hasOwn(sources.localRules, ruleKey) ? "project" : "global",
|
|
42267
|
+
ruleProblems: ruleProblemsAfterRegistration(sources)
|
|
42268
|
+
};
|
|
42269
|
+
}
|
|
42270
|
+
function ruleProblemsAfterRegistration(sources) {
|
|
42271
|
+
ensureEndpointsRegistered();
|
|
42272
|
+
return routingRuleProblems(sources);
|
|
42273
|
+
}
|
|
42274
|
+
function toRoutePlan(explanation) {
|
|
42275
|
+
const { outcome } = explanation;
|
|
42276
|
+
if (outcome.kind === "no-route") {
|
|
42277
|
+
return "hint" in outcome ? { kind: "no-route", reason: outcome.reason, hint: outcome.hint } : { kind: "no-route", reason: outcome.reason };
|
|
42278
|
+
}
|
|
42279
|
+
const [primary, ...fallbacks] = explanation.candidates.filter((candidate) => candidate.outcome === "kept").map(routeOf);
|
|
42280
|
+
if (!primary) {
|
|
42281
|
+
throw new Error(`toRoutePlan: "${explanation.requestedModel}" (${explanation.source}) has no kept candidate, so it has no RoutePlan.`);
|
|
42282
|
+
}
|
|
42283
|
+
return { kind: "ok", primary, fallbacks };
|
|
42284
|
+
}
|
|
42285
|
+
function routeOf(candidate) {
|
|
42286
|
+
return {
|
|
42287
|
+
provider: candidate.provider,
|
|
42288
|
+
modelSpec: candidate.modelSpec,
|
|
42289
|
+
displayName: candidate.displayName
|
|
42290
|
+
};
|
|
42291
|
+
}
|
|
42292
|
+
function emitRouteNotices(explanation) {
|
|
42293
|
+
if (explanation.outcome.kind !== "ok")
|
|
42294
|
+
return;
|
|
42295
|
+
const notServing = explanation.candidates.filter((candidate) => candidate.outcome === "not-served").map((candidate) => candidate.provider);
|
|
42296
|
+
if (notServing.length > 0) {
|
|
42297
|
+
log(`[routing] ${explanation.routedModel}: skipped ${notServing.join(", ")} \u2014 does not serve this model`);
|
|
42298
|
+
}
|
|
42299
|
+
for (const warning of explanation.warnings) {
|
|
42300
|
+
if (warning.type === "rule-problem")
|
|
42301
|
+
continue;
|
|
42302
|
+
logStderr(warning.message);
|
|
42303
|
+
}
|
|
42304
|
+
}
|
|
42305
|
+
function hopLabel(candidate) {
|
|
42306
|
+
if (candidate.position === "fallback")
|
|
42307
|
+
return TIER_LABEL.fallback;
|
|
42308
|
+
return candidate.tier ? TIER_LABEL[candidate.tier] : "unregistered provider";
|
|
42309
|
+
}
|
|
42310
|
+
function describeRouteExplanation(explanation) {
|
|
42311
|
+
const line = describeOrigin(explanation);
|
|
42312
|
+
const routed = explanation.source === "user-rule" || explanation.source === "catalog";
|
|
42313
|
+
return routed && explanation.requestedModel !== explanation.routedModel ? `${line} \xB7 asked as ${explanation.routedModel}` : line;
|
|
42314
|
+
}
|
|
42315
|
+
function describeOrigin(explanation) {
|
|
42316
|
+
switch (explanation.source) {
|
|
42317
|
+
case "native":
|
|
42318
|
+
return "native \xB7 Claude Code's own auth \xB7 not probed";
|
|
42319
|
+
case "explicit": {
|
|
42320
|
+
const name = explanation.candidates[0]?.displayName ?? explanation.routedModel;
|
|
42321
|
+
return explanation.via === "vendor-qualified-id" ? `explicit \xB7 ${name} \xB7 vendor-qualified id sent verbatim` : `explicit \xB7 ${name}`;
|
|
42322
|
+
}
|
|
42323
|
+
case "user-rule": {
|
|
42324
|
+
const scope = explanation.ruleScope ? ` (${explanation.ruleScope})` : "";
|
|
42325
|
+
return `user rule "${explanation.matchedPattern}"${scope}`;
|
|
42326
|
+
}
|
|
42327
|
+
case "catalog":
|
|
42328
|
+
return describeCatalogOrigin(explanation);
|
|
42329
|
+
}
|
|
42330
|
+
}
|
|
42331
|
+
function describeCatalogOrigin(explanation) {
|
|
42332
|
+
if (explanation.catalog === "unreadable") {
|
|
42333
|
+
const refresh = "run claudish --models-refresh";
|
|
42334
|
+
return explanation.candidates.length > 0 ? `no cloud models catalog \xB7 ${firstHopPhrase(explanation)} \xB7 ${refresh}` : `no cloud models catalog \xB7 ${refresh}`;
|
|
42335
|
+
}
|
|
42336
|
+
if (explanation.catalog === "absent")
|
|
42337
|
+
return describeAbsentEntry(explanation);
|
|
42338
|
+
return `catalog \xB7 ${firstHopPhrase(explanation)}`;
|
|
42339
|
+
}
|
|
42340
|
+
function describeAbsentEntry(explanation) {
|
|
42341
|
+
const head = `catalog has no entry for "${explanation.routedModel}"`;
|
|
42342
|
+
const withheld = explanation.fallbackWithheld;
|
|
42343
|
+
if (explanation.candidates.some((candidate) => candidate.position === "candidate")) {
|
|
42344
|
+
const noFallback = withheld && withheld !== "already-gathered" ? ` \xB7 no fallback (${withheld})` : "";
|
|
42345
|
+
return `${head} \xB7 ${firstHopPhrase(explanation)}${noFallback}`;
|
|
42346
|
+
}
|
|
42347
|
+
if (withheld)
|
|
42348
|
+
return `${head} \xB7 no fallback (${withheld})`;
|
|
42349
|
+
const fallback = explanation.candidates.find((candidate) => candidate.position === "fallback");
|
|
42350
|
+
if (!fallback)
|
|
42351
|
+
return `${head} \xB7 ${firstHopPhrase(explanation)}`;
|
|
42352
|
+
return fallback.outcome === "kept" ? `${head} \xB7 fallback only` : `${head} \xB7 fallback ${fallback.displayName} ${DROPPED_FALLBACK_PHRASE[fallback.outcome]}`;
|
|
42353
|
+
}
|
|
42354
|
+
function firstHopPhrase(explanation) {
|
|
42355
|
+
if (explanation.outcome.kind === "no-route")
|
|
42356
|
+
return `no route (${explanation.outcome.cause})`;
|
|
42357
|
+
const first = explanation.candidates.find((candidate) => candidate.outcome === "kept");
|
|
42358
|
+
return first ? `${hopLabel(first)} first` : "no route";
|
|
42359
|
+
}
|
|
42360
|
+
var DEFAULT_FALLBACK_PROVIDER = "openrouter", TIER_LABEL, DROPPED_FALLBACK_PHRASE;
|
|
41890
42361
|
var init_routing_rules = __esm(() => {
|
|
41891
42362
|
init_model_catalog();
|
|
41892
42363
|
init_authority();
|
|
@@ -41899,9 +42370,24 @@ var init_routing_rules = __esm(() => {
|
|
|
41899
42370
|
init_model_availability();
|
|
41900
42371
|
init_model_parser();
|
|
41901
42372
|
init_model_parser();
|
|
42373
|
+
init_native_route();
|
|
42374
|
+
init_predefined_catalog();
|
|
41902
42375
|
init_provider_definitions();
|
|
41903
42376
|
init_route_candidates();
|
|
41904
42377
|
init_routing_hints();
|
|
42378
|
+
TIER_LABEL = {
|
|
42379
|
+
subscription: "subscription",
|
|
42380
|
+
"dynamic-subscription": "subscription \xB7 account decides models",
|
|
42381
|
+
native: "native API",
|
|
42382
|
+
gateway: "gateway",
|
|
42383
|
+
fallback: "fallback"
|
|
42384
|
+
};
|
|
42385
|
+
DROPPED_FALLBACK_PHRASE = {
|
|
42386
|
+
"no-credential": "has no credential",
|
|
42387
|
+
"credential-unreadable": "has a credential that could not be read",
|
|
42388
|
+
"not-served": "does not serve it",
|
|
42389
|
+
"excluded-by-membership": "is outside its plan's membership"
|
|
42390
|
+
};
|
|
41905
42391
|
});
|
|
41906
42392
|
|
|
41907
42393
|
// src/providers/provider-resolver.ts
|
|
@@ -41947,6 +42433,19 @@ function resolveModelProvider(modelId) {
|
|
|
41947
42433
|
deprecationWarning: deprecationWarning || undefined,
|
|
41948
42434
|
concurrency: parsed.concurrency
|
|
41949
42435
|
});
|
|
42436
|
+
if (parsed.provider === AUTO_ROUTE_PROVIDER) {
|
|
42437
|
+
return addCommonFields({
|
|
42438
|
+
category: "auto-route",
|
|
42439
|
+
catalogName: null,
|
|
42440
|
+
providerName: "unresolved (routed on the first request)",
|
|
42441
|
+
modelName: parsed.model,
|
|
42442
|
+
fullModelId: modelId,
|
|
42443
|
+
requiredApiKeyEnvVar: null,
|
|
42444
|
+
apiKeyAvailable: true,
|
|
42445
|
+
apiKeyDescription: null,
|
|
42446
|
+
apiKeyUrl: null
|
|
42447
|
+
});
|
|
42448
|
+
}
|
|
41950
42449
|
if (isLocalProviderName(parsed.provider)) {
|
|
41951
42450
|
const resolved = resolveProvider(modelId);
|
|
41952
42451
|
const urlParsed = parseUrlModel(modelId);
|
|
@@ -42124,7 +42623,7 @@ function getMissingKeyError(resolution) {
|
|
|
42124
42623
|
}
|
|
42125
42624
|
{
|
|
42126
42625
|
const parsed = resolution.parsed;
|
|
42127
|
-
if (parsed && !parsed.isExplicitProvider && parsed.provider !== "unknown" && parsed.provider !== "native-anthropic") {
|
|
42626
|
+
if (parsed && !parsed.isExplicitProvider && parsed.provider !== "unknown" && parsed.provider !== "native-anthropic" && parsed.provider !== AUTO_ROUTE_PROVIDER) {
|
|
42128
42627
|
const hint = buildCredentialHint(parsed.model, [parsed.provider]);
|
|
42129
42628
|
if (hint) {
|
|
42130
42629
|
lines.push("");
|
|
@@ -42233,10 +42732,7 @@ async function pinRoutes(models, into, router) {
|
|
|
42233
42732
|
} catch {}
|
|
42234
42733
|
}
|
|
42235
42734
|
function isRoutablyPinnable(model) {
|
|
42236
|
-
|
|
42237
|
-
return false;
|
|
42238
|
-
const parsed = parseModelSpec(model);
|
|
42239
|
-
return !parsed.isExplicitProvider && parsed.provider !== "native-anthropic";
|
|
42735
|
+
return proxyRouteDecision(model).type === "bare";
|
|
42240
42736
|
}
|
|
42241
42737
|
async function prepareParentRoutingContext() {
|
|
42242
42738
|
if (!parentRoutingContextReady) {
|
|
@@ -42294,6 +42790,7 @@ var init_prehydrate = __esm(() => {
|
|
|
42294
42790
|
init_catalog_client();
|
|
42295
42791
|
init_endpoint_registration();
|
|
42296
42792
|
init_model_parser();
|
|
42793
|
+
init_native_route();
|
|
42297
42794
|
init_onepassword();
|
|
42298
42795
|
init_provider_resolver();
|
|
42299
42796
|
init_routing_rules();
|
|
@@ -45743,7 +46240,7 @@ function getAvailableModels() {
|
|
|
45743
46240
|
_cachedModelIds = result;
|
|
45744
46241
|
return result;
|
|
45745
46242
|
}
|
|
45746
|
-
var _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels = null, FIREBASE_BASE_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/queryModels", FIREBASE_RECOMMENDED_URL, RECOMMENDED_MODELS_CACHE_PATH, RECOMMENDED_FETCH_TIMEOUT_MS = 5000, SEARCH_FETCH_TIMEOUT_MS = 1e4,
|
|
46243
|
+
var _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels = null, FIREBASE_BASE_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/queryModels", FIREBASE_RECOMMENDED_URL, RECOMMENDED_MODELS_CACHE_PATH, RECOMMENDED_FETCH_TIMEOUT_MS = 5000, SEARCH_FETCH_TIMEOUT_MS = 1e4, RECOMMENDED_ROUTE_TIER_ORDER;
|
|
45747
46244
|
var init_model_loader = __esm(() => {
|
|
45748
46245
|
init_all_models_cache();
|
|
45749
46246
|
init_auto_route();
|
|
@@ -45752,18 +46249,6 @@ var init_model_loader = __esm(() => {
|
|
|
45752
46249
|
init_catalog_route_bindings();
|
|
45753
46250
|
FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
|
|
45754
46251
|
RECOMMENDED_MODELS_CACHE_PATH = join32(homedir30(), ".claudish", "recommended-models-cache.json");
|
|
45755
|
-
FIREBASE_SLUG_TO_PROVIDER_NAME = {
|
|
45756
|
-
openai: "openai",
|
|
45757
|
-
google: "google",
|
|
45758
|
-
"x-ai": "x-ai",
|
|
45759
|
-
"z-ai": "z-ai",
|
|
45760
|
-
moonshotai: "kimi",
|
|
45761
|
-
minimax: "minimax",
|
|
45762
|
-
qwen: "qwen",
|
|
45763
|
-
deepseek: "deepseek",
|
|
45764
|
-
mistralai: "mistralai",
|
|
45765
|
-
sakana: "sakana"
|
|
45766
|
-
};
|
|
45767
46252
|
RECOMMENDED_ROUTE_TIER_ORDER = {
|
|
45768
46253
|
native: 0,
|
|
45769
46254
|
general: 1,
|
|
@@ -45801,44 +46286,6 @@ async function isPortAvailable(port) {
|
|
|
45801
46286
|
}
|
|
45802
46287
|
var init_port_manager = () => {};
|
|
45803
46288
|
|
|
45804
|
-
// src/providers/claude-code-aliases.ts
|
|
45805
|
-
function claudeCodeTierAlias(model) {
|
|
45806
|
-
return TIER_ALIASES[model.trim().toLowerCase()] ?? null;
|
|
45807
|
-
}
|
|
45808
|
-
function normalizeNativeModelSpec(spec) {
|
|
45809
|
-
return claudeCodeTierAlias(spec) ?? spec;
|
|
45810
|
-
}
|
|
45811
|
-
var TIER_ALIASES;
|
|
45812
|
-
var init_claude_code_aliases = __esm(() => {
|
|
45813
|
-
TIER_ALIASES = {
|
|
45814
|
-
opus: "opus",
|
|
45815
|
-
sonnet: "sonnet",
|
|
45816
|
-
haiku: "haiku",
|
|
45817
|
-
internal: "opus",
|
|
45818
|
-
default: "opus"
|
|
45819
|
-
};
|
|
45820
|
-
});
|
|
45821
|
-
|
|
45822
|
-
// src/providers/native-route.ts
|
|
45823
|
-
function nativeRouteFor(model) {
|
|
45824
|
-
if (model.includes("/"))
|
|
45825
|
-
return null;
|
|
45826
|
-
const parsed = parseModelSpec(model);
|
|
45827
|
-
if (parsed.isExplicitProvider || parsed.provider !== "native-anthropic")
|
|
45828
|
-
return null;
|
|
45829
|
-
return {
|
|
45830
|
-
provider: "native-anthropic",
|
|
45831
|
-
modelSpec: normalizeNativeModelSpec(model),
|
|
45832
|
-
displayName: getProviderByName("native-anthropic")?.displayName ?? "Anthropic (Native)",
|
|
45833
|
-
isTierAlias: claudeCodeTierAlias(model) !== null
|
|
45834
|
-
};
|
|
45835
|
-
}
|
|
45836
|
-
var init_native_route = __esm(() => {
|
|
45837
|
-
init_claude_code_aliases();
|
|
45838
|
-
init_model_parser();
|
|
45839
|
-
init_provider_definitions();
|
|
45840
|
-
});
|
|
45841
|
-
|
|
45842
46289
|
// src/providers/probe-live.ts
|
|
45843
46290
|
function effortForProvider(provider) {
|
|
45844
46291
|
if (EFFORT_OMITTED.has(provider))
|
|
@@ -48859,7 +49306,7 @@ function prepareAdvisorPanelMessages(messages, toolUseId) {
|
|
|
48859
49306
|
});
|
|
48860
49307
|
return prepared;
|
|
48861
49308
|
}
|
|
48862
|
-
function
|
|
49309
|
+
function routeOf2(kind, wireModel) {
|
|
48863
49310
|
const url = ADVISOR_ENDPOINTS[kind];
|
|
48864
49311
|
return { kind, host: new URL(url).host, url, credential: kind, wireModel };
|
|
48865
49312
|
}
|
|
@@ -48869,21 +49316,21 @@ function advisorRouteFor(modelSpec, role) {
|
|
|
48869
49316
|
const model = parsed.model;
|
|
48870
49317
|
const tier = anthropicTierAlias(model);
|
|
48871
49318
|
if (!tier)
|
|
48872
|
-
return
|
|
49319
|
+
return routeOf2("anthropic", model);
|
|
48873
49320
|
const resolved = findEntryByAlias(model)?.modelId ?? latestAnthropicTierModelId(tier);
|
|
48874
49321
|
if (!resolved)
|
|
48875
|
-
return { ...
|
|
48876
|
-
return
|
|
49322
|
+
return { ...routeOf2("anthropic", model), unresolvedAlias: model };
|
|
49323
|
+
return routeOf2("anthropic", resolved);
|
|
48877
49324
|
}
|
|
48878
49325
|
const provider = parsed.provider;
|
|
48879
49326
|
if (provider === "google" || provider === "gemini")
|
|
48880
|
-
return
|
|
49327
|
+
return routeOf2("google", parsed.model);
|
|
48881
49328
|
if (provider === "openai" || provider === "oai")
|
|
48882
|
-
return
|
|
49329
|
+
return routeOf2("openai", parsed.model);
|
|
48883
49330
|
if (!parsed.isExplicitProvider || provider === "openrouter") {
|
|
48884
|
-
return
|
|
49331
|
+
return routeOf2("openrouter", openRouterWireModelFor(null, parsed.model));
|
|
48885
49332
|
}
|
|
48886
|
-
return
|
|
49333
|
+
return routeOf2("openrouter", openRouterWireModelFor(provider, parsed.model));
|
|
48887
49334
|
}
|
|
48888
49335
|
function openRouterIdOf(entry) {
|
|
48889
49336
|
return entry.aggregators?.find((a) => catalogRouteMatchesProvider(a.route, "openrouter"))?.externalModelId ?? null;
|
|
@@ -49858,6 +50305,8 @@ function isRetryableError(status, errorBody, provider, headers) {
|
|
|
49858
50305
|
return true;
|
|
49859
50306
|
if (status === 429)
|
|
49860
50307
|
return true;
|
|
50308
|
+
if (status === 502 || status === 503 || status === 504)
|
|
50309
|
+
return true;
|
|
49861
50310
|
const lower = errorBody.toLowerCase();
|
|
49862
50311
|
if (status === 422) {
|
|
49863
50312
|
if (lower.includes("not available") || lower.includes("model not found") || lower.includes("not supported")) {
|
|
@@ -49885,13 +50334,14 @@ function isRetryableError(status, errorBody, provider, headers) {
|
|
|
49885
50334
|
function exhaustedChainStatus(errors) {
|
|
49886
50335
|
if (errors.length === 0)
|
|
49887
50336
|
return 400;
|
|
50337
|
+
const TRANSIENT = new Set([429, 502, 503, 504]);
|
|
49888
50338
|
const isTransient = (e) => {
|
|
49889
|
-
if (
|
|
50339
|
+
if (TRANSIENT.has(e.status))
|
|
49890
50340
|
return true;
|
|
49891
50341
|
if (hasQuotaExhaustionWording(e.message))
|
|
49892
50342
|
return true;
|
|
49893
50343
|
const upstream = e.status === 400 ? extractUpstreamStatus(e.message) : undefined;
|
|
49894
|
-
return upstream
|
|
50344
|
+
return upstream !== undefined && TRANSIENT.has(upstream);
|
|
49895
50345
|
};
|
|
49896
50346
|
return errors.every(isTransient) ? 503 : 400;
|
|
49897
50347
|
}
|
|
@@ -51104,7 +51554,12 @@ async function createProxyServer(port, _openrouterApiKey, model, monitorMode = f
|
|
|
51104
51554
|
}
|
|
51105
51555
|
return null;
|
|
51106
51556
|
};
|
|
51107
|
-
const
|
|
51557
|
+
const routingRuleSources = loadRoutingRuleSources();
|
|
51558
|
+
const effectiveRoutingRules = loadRoutingRules(routingRuleSources);
|
|
51559
|
+
for (const problem of routingRuleProblems(routingRuleSources)) {
|
|
51560
|
+
logStderr(`Warning: ${describeRoutingRuleProblem(problem)}`);
|
|
51561
|
+
}
|
|
51562
|
+
const effectiveFallbackProvider = effectiveDefaultProvider();
|
|
51108
51563
|
const fallbackHandlerCache = new Map;
|
|
51109
51564
|
const detectInvocationMode = (target, wasFromModelMap) => {
|
|
51110
51565
|
if (wasFromModelMap)
|
|
@@ -51187,14 +51642,14 @@ async function createProxyServer(port, _openrouterApiKey, model, monitorMode = f
|
|
|
51187
51642
|
}
|
|
51188
51643
|
}
|
|
51189
51644
|
{
|
|
51190
|
-
const
|
|
51191
|
-
if (
|
|
51645
|
+
const decision = proxyRouteDecision(target);
|
|
51646
|
+
if (decision.type === "bare") {
|
|
51192
51647
|
const cacheKey = `fallback:${target}`;
|
|
51193
51648
|
if (fallbackHandlerCache.has(cacheKey)) {
|
|
51194
51649
|
return fallbackHandlerCache.get(cacheKey);
|
|
51195
51650
|
}
|
|
51196
51651
|
await ensureCatalogReady(5000);
|
|
51197
|
-
const plan = await route(
|
|
51652
|
+
const plan = await route(decision.model, effectiveRoutingRules, effectiveFallbackProvider);
|
|
51198
51653
|
if (plan.kind === "ok") {
|
|
51199
51654
|
const chain = [plan.primary, ...plan.fallbacks];
|
|
51200
51655
|
const candidates = [];
|
|
@@ -51212,8 +51667,11 @@ async function createProxyServer(port, _openrouterApiKey, model, monitorMode = f
|
|
|
51212
51667
|
if (candidates.length > 0) {
|
|
51213
51668
|
const resultHandler = candidates.length > 1 ? new FallbackHandler(candidates) : candidates[0].handler;
|
|
51214
51669
|
fallbackHandlerCache.set(cacheKey, resultHandler);
|
|
51670
|
+
const routeLine = `[Route] ${candidates.length} ${candidates.length === 1 ? "provider" : "providers"} for ${decision.model}: ${candidates.map((c) => c.name).join(" \u2192 ")}`;
|
|
51215
51671
|
if (!options.quiet && candidates.length > 1) {
|
|
51216
|
-
logStderr(
|
|
51672
|
+
logStderr(routeLine);
|
|
51673
|
+
} else {
|
|
51674
|
+
log(routeLine);
|
|
51217
51675
|
}
|
|
51218
51676
|
return resultHandler;
|
|
51219
51677
|
}
|
|
@@ -51442,6 +51900,7 @@ var init_proxy_server = __esm(() => {
|
|
|
51442
51900
|
init_endpoint_diagnostics();
|
|
51443
51901
|
init_endpoint_registration();
|
|
51444
51902
|
init_model_parser();
|
|
51903
|
+
init_native_route();
|
|
51445
51904
|
init_provider_definitions();
|
|
51446
51905
|
init_provider_profiles();
|
|
51447
51906
|
init_provider_registry();
|
|
@@ -51762,7 +52221,7 @@ Tokens: ${result.usage.input} input, ${result.usage.output} output`;
|
|
|
51762
52221
|
const { flagship, fast } = groupRecommendedModels(doc.models);
|
|
51763
52222
|
const providerByName = new Map(BUILTIN_PROVIDERS.map((p) => [p.name, p]));
|
|
51764
52223
|
const getNativePrefix = (firebaseSlug) => {
|
|
51765
|
-
const canonical =
|
|
52224
|
+
const canonical = nativeProviderForVendor(firebaseSlug);
|
|
51766
52225
|
if (!canonical)
|
|
51767
52226
|
return null;
|
|
51768
52227
|
const def = providerByName.get(canonical);
|
|
@@ -52054,7 +52513,7 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
|
|
|
52054
52513
|
const native = nativeRouteFor(model);
|
|
52055
52514
|
if (native) {
|
|
52056
52515
|
nativeModels.push(model);
|
|
52057
|
-
rows.push(`| \`${model}\` | ${native.displayName} | native | ${
|
|
52516
|
+
rows.push(`| \`${model}\` | ${native.displayName} | native | ${NATIVE_NOT_PROBED} | \`${native.modelSpec}\` |`);
|
|
52058
52517
|
continue;
|
|
52059
52518
|
}
|
|
52060
52519
|
let plan;
|
|
@@ -52849,6 +53308,7 @@ var init_mcp_server = __esm(() => {
|
|
|
52849
53308
|
init_onepassword();
|
|
52850
53309
|
init_probe_live();
|
|
52851
53310
|
init_provider_definitions();
|
|
53311
|
+
init_route_candidates();
|
|
52852
53312
|
init_routing_rules();
|
|
52853
53313
|
init_proxy_server();
|
|
52854
53314
|
init_redact();
|
|
@@ -53436,66 +53896,26 @@ import { existsSync as existsSync28, readFileSync as readFileSync28, writeFileSy
|
|
|
53436
53896
|
import { connect as netConnect } from "net";
|
|
53437
53897
|
import { join as join37 } from "path";
|
|
53438
53898
|
import { setTimeout as wait } from "timers/promises";
|
|
53439
|
-
function
|
|
53440
|
-
const
|
|
53441
|
-
if (
|
|
53442
|
-
return
|
|
53443
|
-
}
|
|
53444
|
-
|
|
53445
|
-
|
|
53446
|
-
|
|
53447
|
-
|
|
53448
|
-
|
|
53449
|
-
|
|
53450
|
-
|
|
53451
|
-
|
|
53452
|
-
|
|
53453
|
-
|
|
53454
|
-
|
|
53455
|
-
|
|
53456
|
-
return false;
|
|
53457
|
-
});
|
|
53458
|
-
return {
|
|
53459
|
-
chain: routes.map((r) => r.displayName),
|
|
53460
|
-
source: "project routing",
|
|
53461
|
-
sourceDetail: pattern
|
|
53462
|
-
};
|
|
53463
|
-
}
|
|
53464
|
-
}
|
|
53465
|
-
const global_ = loadConfig();
|
|
53466
|
-
if (global_.routing && Object.keys(global_.routing).length > 0) {
|
|
53467
|
-
const matched = matchRoutingRule(parsed.model, global_.routing);
|
|
53468
|
-
if (matched) {
|
|
53469
|
-
const routes = buildRoutingChain(matched, parsed.model);
|
|
53470
|
-
const pattern = Object.keys(global_.routing).find((k) => {
|
|
53471
|
-
if (k === parsed.model)
|
|
53472
|
-
return true;
|
|
53473
|
-
if (k.includes("*")) {
|
|
53474
|
-
const star = k.indexOf("*");
|
|
53475
|
-
return parsed.model.startsWith(k.slice(0, star)) && parsed.model.endsWith(k.slice(star + 1));
|
|
53476
|
-
}
|
|
53477
|
-
return false;
|
|
53478
|
-
});
|
|
53479
|
-
return {
|
|
53480
|
-
chain: routes.map((r) => r.displayName),
|
|
53481
|
-
source: "user routing",
|
|
53482
|
-
sourceDetail: pattern
|
|
53483
|
-
};
|
|
53899
|
+
function paneRouteLine(explanation) {
|
|
53900
|
+
const origin = describeRouteExplanation(explanation);
|
|
53901
|
+
if (explanation.outcome.kind === "no-route") {
|
|
53902
|
+
return `no route \u2014 ${explanation.outcome.reason} (${origin})`;
|
|
53903
|
+
}
|
|
53904
|
+
if (explanation.native)
|
|
53905
|
+
return `${explanation.native.displayName} (${origin})`;
|
|
53906
|
+
const hops = explanation.candidates.filter((candidate) => candidate.outcome === "kept").map((candidate) => candidate.displayName);
|
|
53907
|
+
return `${hops.join(" \u2192 ")} (${origin})`;
|
|
53908
|
+
}
|
|
53909
|
+
async function resolvePaneRouteLines(models) {
|
|
53910
|
+
const unique = [...new Set(models)];
|
|
53911
|
+
const entries = await Promise.all(unique.map(async (model) => {
|
|
53912
|
+
try {
|
|
53913
|
+
return [model, paneRouteLine(await explainRoute(model))];
|
|
53914
|
+
} catch (err) {
|
|
53915
|
+
return [model, `unknown \u2014 ${err instanceof Error ? err.message : String(err)}`];
|
|
53484
53916
|
}
|
|
53485
|
-
}
|
|
53486
|
-
|
|
53487
|
-
const matched = matchRoutingRule(parsed.model, merged);
|
|
53488
|
-
if (matched) {
|
|
53489
|
-
const routes = buildRoutingChain(matched, parsed.model);
|
|
53490
|
-
return {
|
|
53491
|
-
chain: routes.map((r) => r.displayName),
|
|
53492
|
-
source: "auto"
|
|
53493
|
-
};
|
|
53494
|
-
}
|
|
53495
|
-
return {
|
|
53496
|
-
chain: [],
|
|
53497
|
-
source: "auto"
|
|
53498
|
-
};
|
|
53917
|
+
}));
|
|
53918
|
+
return new Map(entries);
|
|
53499
53919
|
}
|
|
53500
53920
|
function pickBannerColor(model, used) {
|
|
53501
53921
|
let hash = 0;
|
|
@@ -53510,14 +53930,11 @@ function pickBannerColor(model, used) {
|
|
|
53510
53930
|
used.add(idx);
|
|
53511
53931
|
return BANNER_BG_COLORS[idx];
|
|
53512
53932
|
}
|
|
53513
|
-
function buildPaneHeader(model, prompt, bg) {
|
|
53514
|
-
const route = resolveRouteInfo(model);
|
|
53933
|
+
function buildPaneHeader(model, routeLine, prompt, bg) {
|
|
53515
53934
|
const esc = (s) => s.replace(/'/g, "'\\''");
|
|
53516
|
-
const chainStr = route.chain.join(" \u2192 ");
|
|
53517
|
-
const sourceLabel = route.sourceDetail ? `${route.source}: ${route.sourceDetail}` : route.source;
|
|
53518
53935
|
const lines = [];
|
|
53519
53936
|
lines.push(`printf '\\033[1;97;${bg}m %s \\033[0m\\n' '${esc(model)}';`);
|
|
53520
|
-
lines.push(`printf '\\033[2m route:
|
|
53937
|
+
lines.push(`printf '\\033[2m route: %s\\033[0m\\n' '${esc(routeLine)}';`);
|
|
53521
53938
|
lines.push(`printf '\\033[2m %s\\033[0m\\n' '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500';`);
|
|
53522
53939
|
const promptForShell = esc(prompt).replace(/\n/g, "\\n");
|
|
53523
53940
|
lines.push(`printf '%b\\n' '${promptForShell}' | fold -s -w 78 | sed 's/^/ /';`);
|
|
@@ -53623,13 +54040,14 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
53623
54040
|
const prompt = readFileSync28(join37(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
|
|
53624
54041
|
const rawPrompt = readFileSync28(join37(sessionPath, "input.md"), "utf-8");
|
|
53625
54042
|
const usedBannerColors = new Set;
|
|
54043
|
+
const routeLines = mode === "interactive" ? new Map : await resolvePaneRouteLines(Object.values(manifest.models).map((entry) => entry.model));
|
|
53626
54044
|
const gridLines = Object.entries(manifest.models).map(([anonId]) => {
|
|
53627
54045
|
const model = manifest.models[anonId].model;
|
|
53628
54046
|
if (mode === "interactive") {
|
|
53629
54047
|
return `claudish --model ${model} -i --dangerously-skip-permissions '${prompt}'`;
|
|
53630
54048
|
}
|
|
53631
54049
|
const bg = pickBannerColor(model, usedBannerColors);
|
|
53632
|
-
const header = buildPaneHeader(model, rawPrompt, bg);
|
|
54050
|
+
const header = buildPaneHeader(model, routeLines.get(model) ?? "", rawPrompt, bg);
|
|
53633
54051
|
return `${header} claudish --model ${model} -y --quiet '${prompt}'`;
|
|
53634
54052
|
});
|
|
53635
54053
|
writeFileSync17(gridfilePath, `${gridLines.join(`
|
|
@@ -53659,8 +54077,6 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
53659
54077
|
var BANNER_BG_COLORS;
|
|
53660
54078
|
var init_team_grid = __esm(() => {
|
|
53661
54079
|
init_magmux_binary();
|
|
53662
|
-
init_profile_config();
|
|
53663
|
-
init_model_parser();
|
|
53664
54080
|
init_routing_rules();
|
|
53665
54081
|
init_team_orchestrator();
|
|
53666
54082
|
BANNER_BG_COLORS = [
|
|
@@ -57112,32 +57528,6 @@ var init_quota_command = __esm(() => {
|
|
|
57112
57528
|
};
|
|
57113
57529
|
});
|
|
57114
57530
|
|
|
57115
|
-
// src/default-provider.ts
|
|
57116
|
-
function resolveDefaultProvider(opts) {
|
|
57117
|
-
const env = opts.env ?? process.env;
|
|
57118
|
-
if (opts.cliFlag && opts.cliFlag.length > 0) {
|
|
57119
|
-
return { provider: opts.cliFlag, source: "cli-flag", legacyAutoPromoted: false };
|
|
57120
|
-
}
|
|
57121
|
-
const envVal = env.CLAUDISH_DEFAULT_PROVIDER;
|
|
57122
|
-
if (envVal && envVal.length > 0) {
|
|
57123
|
-
return { provider: envVal, source: "env-var", legacyAutoPromoted: false };
|
|
57124
|
-
}
|
|
57125
|
-
if (opts.config.defaultProvider && opts.config.defaultProvider.length > 0) {
|
|
57126
|
-
return {
|
|
57127
|
-
provider: opts.config.defaultProvider,
|
|
57128
|
-
source: "config-file",
|
|
57129
|
-
legacyAutoPromoted: false
|
|
57130
|
-
};
|
|
57131
|
-
}
|
|
57132
|
-
if (env.OPENROUTER_API_KEY) {
|
|
57133
|
-
return { provider: "openrouter", source: "openrouter-key", legacyAutoPromoted: false };
|
|
57134
|
-
}
|
|
57135
|
-
return { provider: "openrouter", source: "hardcoded", legacyAutoPromoted: false };
|
|
57136
|
-
}
|
|
57137
|
-
function buildLegacyHint(_resolved) {
|
|
57138
|
-
return null;
|
|
57139
|
-
}
|
|
57140
|
-
|
|
57141
57531
|
// src/providers/model-catalog.ts
|
|
57142
57532
|
function aggregatorProviderSlugs(readSlimCache) {
|
|
57143
57533
|
const cache = readSlimCache();
|
|
@@ -57293,9 +57683,9 @@ var init_model_catalog2 = __esm(() => {
|
|
|
57293
57683
|
"opencode-zen",
|
|
57294
57684
|
"opencode-zen-go",
|
|
57295
57685
|
"fireworks",
|
|
57296
|
-
"together
|
|
57686
|
+
"together"
|
|
57297
57687
|
]);
|
|
57298
|
-
NO_CATALOG_VENDOR_SLUGS = new Set(["litellm", "ollama", "lmstudio"
|
|
57688
|
+
NO_CATALOG_VENDOR_SLUGS = new Set(["litellm", "ollama", "lmstudio"]);
|
|
57299
57689
|
});
|
|
57300
57690
|
|
|
57301
57691
|
// src/theme/renderer-theme.ts
|
|
@@ -61275,21 +61665,141 @@ var init_model_selector = __esm(() => {
|
|
|
61275
61665
|
_modelsCatalogCollapse = { collapse: collapseModelsCatalog };
|
|
61276
61666
|
});
|
|
61277
61667
|
|
|
61668
|
+
// src/probe/probe-chain.ts
|
|
61669
|
+
function probeChainFrom(explanation, credentials) {
|
|
61670
|
+
if (explanation.source === "native" && explanation.native) {
|
|
61671
|
+
return { chain: [nativeLinkOf(explanation.native)], dropped: [] };
|
|
61672
|
+
}
|
|
61673
|
+
const chain = [];
|
|
61674
|
+
const dropped = [];
|
|
61675
|
+
for (const candidate of explanation.candidates) {
|
|
61676
|
+
if (candidate.outcome === "kept")
|
|
61677
|
+
chain.push(keptLinkOf(candidate, credentials));
|
|
61678
|
+
else
|
|
61679
|
+
dropped.push(droppedLinkOf(candidate, candidate.outcome, credentials));
|
|
61680
|
+
}
|
|
61681
|
+
return { chain, dropped };
|
|
61682
|
+
}
|
|
61683
|
+
function nativeLinkOf(native) {
|
|
61684
|
+
return {
|
|
61685
|
+
provider: native.provider,
|
|
61686
|
+
displayName: native.displayName,
|
|
61687
|
+
modelSpec: native.modelSpec,
|
|
61688
|
+
wireId: native.modelSpec,
|
|
61689
|
+
position: "candidate",
|
|
61690
|
+
label: NATIVE_LINK_LABEL,
|
|
61691
|
+
hasCredentials: true,
|
|
61692
|
+
notProbed: "native-auth"
|
|
61693
|
+
};
|
|
61694
|
+
}
|
|
61695
|
+
function keptLinkOf(candidate, credentials) {
|
|
61696
|
+
const provenance = credentials.provenanceFor(candidate.provider);
|
|
61697
|
+
return {
|
|
61698
|
+
provider: candidate.provider,
|
|
61699
|
+
displayName: candidate.displayName,
|
|
61700
|
+
modelSpec: candidate.modelSpec,
|
|
61701
|
+
wireId: candidate.wireId,
|
|
61702
|
+
position: candidate.position,
|
|
61703
|
+
...candidate.tier !== undefined ? { tier: candidate.tier } : {},
|
|
61704
|
+
label: hopLabel(candidate),
|
|
61705
|
+
...candidate.availability ? { availability: candidate.availability } : {},
|
|
61706
|
+
hasCredentials: true,
|
|
61707
|
+
...provenance ? { provenance } : {}
|
|
61708
|
+
};
|
|
61709
|
+
}
|
|
61710
|
+
function droppedLinkOf(candidate, outcome, credentials) {
|
|
61711
|
+
const hint = outcome === "no-credential" ? credentials.hintFor(candidate.provider) : undefined;
|
|
61712
|
+
return {
|
|
61713
|
+
provider: candidate.provider,
|
|
61714
|
+
displayName: candidate.displayName,
|
|
61715
|
+
wireId: candidate.wireId,
|
|
61716
|
+
position: candidate.position,
|
|
61717
|
+
...candidate.tier !== undefined ? { tier: candidate.tier } : {},
|
|
61718
|
+
label: hopLabel(candidate),
|
|
61719
|
+
outcome,
|
|
61720
|
+
...hint ? { credentialHint: hint } : {}
|
|
61721
|
+
};
|
|
61722
|
+
}
|
|
61723
|
+
function routingFieldsFrom(explanation) {
|
|
61724
|
+
const { outcome } = explanation;
|
|
61725
|
+
return {
|
|
61726
|
+
routingSource: explanation.source,
|
|
61727
|
+
routingExplanation: describeRouteExplanation(explanation),
|
|
61728
|
+
...explanation.matchedPattern !== undefined ? { matchedPattern: explanation.matchedPattern } : {},
|
|
61729
|
+
...explanation.ruleScope ? { ruleScope: explanation.ruleScope } : {},
|
|
61730
|
+
...outcome.kind === "no-route" ? {
|
|
61731
|
+
noRoute: {
|
|
61732
|
+
reason: outcome.reason,
|
|
61733
|
+
...outcome.hint !== undefined ? { hint: outcome.hint } : {}
|
|
61734
|
+
}
|
|
61735
|
+
} : {},
|
|
61736
|
+
warnings: explanation.warnings
|
|
61737
|
+
};
|
|
61738
|
+
}
|
|
61739
|
+
function resultLinksFrom(chain, dropped) {
|
|
61740
|
+
return [
|
|
61741
|
+
...chain.map((link) => ({
|
|
61742
|
+
provider: link.provider,
|
|
61743
|
+
displayName: link.displayName,
|
|
61744
|
+
modelId: link.wireId,
|
|
61745
|
+
label: link.label,
|
|
61746
|
+
hasCredentials: link.hasCredentials,
|
|
61747
|
+
...link.credentialHint ? { credentialHint: link.credentialHint } : {},
|
|
61748
|
+
...link.notProbed ? { notProbed: link.notProbed } : {},
|
|
61749
|
+
...link.probe ? { probe: link.probe } : {}
|
|
61750
|
+
})),
|
|
61751
|
+
...dropped.map((entry) => ({
|
|
61752
|
+
provider: entry.provider,
|
|
61753
|
+
displayName: entry.displayName,
|
|
61754
|
+
modelId: entry.wireId,
|
|
61755
|
+
label: entry.label,
|
|
61756
|
+
hasCredentials: entry.outcome === "not-served",
|
|
61757
|
+
...entry.credentialHint ? { credentialHint: entry.credentialHint } : {},
|
|
61758
|
+
dropped: entry.outcome
|
|
61759
|
+
}))
|
|
61760
|
+
];
|
|
61761
|
+
}
|
|
61762
|
+
var NATIVE_LINK_LABEL = "Claude Code's own auth";
|
|
61763
|
+
var init_probe_chain = __esm(() => {
|
|
61764
|
+
init_routing_rules();
|
|
61765
|
+
});
|
|
61766
|
+
|
|
61278
61767
|
// src/providers/probe-runner.ts
|
|
61279
61768
|
function pinProbeModelSpec(link) {
|
|
61280
61769
|
if (link.provider === "native-anthropic")
|
|
61281
61770
|
return link.modelSpec;
|
|
61282
61771
|
return link.modelSpec.includes("@") ? link.modelSpec : `${link.provider}@${link.modelSpec}`;
|
|
61283
61772
|
}
|
|
61773
|
+
function droppedRemedy(credentialHint) {
|
|
61774
|
+
if (!credentialHint)
|
|
61775
|
+
return;
|
|
61776
|
+
return /^[A-Z][A-Z0-9_]*$/.test(credentialHint) ? `set ${credentialHint}` : credentialHint;
|
|
61777
|
+
}
|
|
61778
|
+
function describeDropped(outcome, credentialHint) {
|
|
61779
|
+
const remedy = droppedRemedy(credentialHint);
|
|
61780
|
+
return remedy ? `${DROPPED_LABEL[outcome]} \xB7 ${remedy}` : DROPPED_LABEL[outcome];
|
|
61781
|
+
}
|
|
61782
|
+
function probeTargets(explanation) {
|
|
61783
|
+
return explanation.candidates.filter((candidate) => candidate.outcome === "kept").map((candidate) => ({
|
|
61784
|
+
...candidate,
|
|
61785
|
+
probeSpec: explanation.source === "explicit" ? explanation.requestedModel : pinProbeModelSpec(candidate)
|
|
61786
|
+
}));
|
|
61787
|
+
}
|
|
61284
61788
|
function probeProviderRoute(proxyUrl, link, timeoutMs) {
|
|
61285
61789
|
return probeLink(proxyUrl, {
|
|
61286
61790
|
...link,
|
|
61287
61791
|
modelSpec: pinProbeModelSpec(link)
|
|
61288
61792
|
}, timeoutMs);
|
|
61289
61793
|
}
|
|
61290
|
-
var INTERACTIVE_PROBE_TIMEOUT_MS = 60000;
|
|
61794
|
+
var INTERACTIVE_PROBE_TIMEOUT_MS = 60000, DROPPED_LABEL;
|
|
61291
61795
|
var init_probe_runner = __esm(() => {
|
|
61292
61796
|
init_probe_live();
|
|
61797
|
+
DROPPED_LABEL = {
|
|
61798
|
+
"no-credential": "no credential",
|
|
61799
|
+
"credential-unreadable": "credential could not be read",
|
|
61800
|
+
"not-served": "account does not serve it",
|
|
61801
|
+
"excluded-by-membership": "not in the plan's membership"
|
|
61802
|
+
};
|
|
61293
61803
|
});
|
|
61294
61804
|
|
|
61295
61805
|
// src/probe/probe-results-printer.ts
|
|
@@ -61383,7 +61893,6 @@ function computeBarScales(results) {
|
|
|
61383
61893
|
maxTokPerSec = scaledTps;
|
|
61384
61894
|
};
|
|
61385
61895
|
for (const r of results) {
|
|
61386
|
-
consider(r.directProbe);
|
|
61387
61896
|
for (const c of r.chain ?? [])
|
|
61388
61897
|
consider(c.probe);
|
|
61389
61898
|
}
|
|
@@ -61607,6 +62116,16 @@ function buildRowData(result, isLiveProbe) {
|
|
|
61607
62116
|
return result.chain.map((entry, i) => {
|
|
61608
62117
|
const isFastest = i === fastestIdx;
|
|
61609
62118
|
const isSlowest = i === slowestIdx;
|
|
62119
|
+
if (entry.notProbed) {
|
|
62120
|
+
return {
|
|
62121
|
+
num: `${i + 1}`,
|
|
62122
|
+
provider: entry.displayName,
|
|
62123
|
+
label: entry.label ?? "",
|
|
62124
|
+
spec: entry.modelSpec,
|
|
62125
|
+
status: `${pc.cyan}\u25D0 native \u2014 not probed${pc.reset}`,
|
|
62126
|
+
note: NATIVE_NOT_PROBED
|
|
62127
|
+
};
|
|
62128
|
+
}
|
|
61610
62129
|
let status = shortStatusLabel(entry.probe, entry.hasCredentials, entry.credentialHint);
|
|
61611
62130
|
if (isFastest) {
|
|
61612
62131
|
status = `${status} ${pc.brightGreen}\u25CF${pc.reset}`;
|
|
@@ -61619,6 +62138,7 @@ function buildRowData(result, isLiveProbe) {
|
|
|
61619
62138
|
return {
|
|
61620
62139
|
num: `${i + 1}`,
|
|
61621
62140
|
provider: entry.displayName,
|
|
62141
|
+
label: entry.label ?? "",
|
|
61622
62142
|
spec: entry.modelSpec,
|
|
61623
62143
|
status,
|
|
61624
62144
|
errorDetail,
|
|
@@ -61628,40 +62148,19 @@ function buildRowData(result, isLiveProbe) {
|
|
|
61628
62148
|
};
|
|
61629
62149
|
});
|
|
61630
62150
|
}
|
|
61631
|
-
function
|
|
61632
|
-
|
|
61633
|
-
|
|
61634
|
-
|
|
61635
|
-
|
|
61636
|
-
|
|
61637
|
-
status
|
|
61638
|
-
|
|
61639
|
-
|
|
61640
|
-
}
|
|
61641
|
-
}
|
|
61642
|
-
let errorDetail;
|
|
61643
|
-
if (probe && isFailureState(probe.state) && probe.errorMessage) {
|
|
61644
|
-
errorDetail = stripAnsi2(probe.errorMessage).replace(/\s+/g, " ").trim();
|
|
61645
|
-
}
|
|
61646
|
-
const barsTiming = probe?.state === "live" && probe.timing ? probe.timing : undefined;
|
|
61647
|
-
return [
|
|
61648
|
-
{
|
|
61649
|
-
num: "1",
|
|
61650
|
-
provider: result.nativeProvider,
|
|
61651
|
-
spec: pinProbeModelSpec({ provider: result.nativeProvider, modelSpec: result.model }),
|
|
61652
|
-
status,
|
|
61653
|
-
errorDetail,
|
|
61654
|
-
barsTiming
|
|
61655
|
-
}
|
|
61656
|
-
];
|
|
62151
|
+
function buildDroppedRowData(result) {
|
|
62152
|
+
return (result.dropped ?? []).map((entry) => ({
|
|
62153
|
+
num: "\u2013",
|
|
62154
|
+
provider: entry.displayName,
|
|
62155
|
+
label: entry.label ?? "",
|
|
62156
|
+
spec: entry.wireId,
|
|
62157
|
+
status: `${pc.dim}\u2013 ${DROPPED_LABEL[entry.outcome]}${pc.reset}`,
|
|
62158
|
+
note: droppedRemedy(entry.credentialHint)
|
|
62159
|
+
}));
|
|
61657
62160
|
}
|
|
61658
62161
|
function computeColumnWidths(rows) {
|
|
61659
|
-
const
|
|
61660
|
-
|
|
61661
|
-
const wProv = Math.max(headers[1].length, ...rows.map((r) => visibleLength(r.provider)));
|
|
61662
|
-
const wSpec = Math.max(headers[2].length, ...rows.map((r) => visibleLength(r.spec)));
|
|
61663
|
-
const wStatus = Math.max(headers[3].length, ...rows.map((r) => visibleLength(r.status)));
|
|
61664
|
-
return [wNum, wProv, wSpec, wStatus];
|
|
62162
|
+
const cells = (r) => [r.num, r.provider, r.label, r.spec, r.status];
|
|
62163
|
+
return COLUMN_HEADERS.map((header, col) => Math.max(header.length, ...rows.map((r) => visibleLength(cells(r)[col]))));
|
|
61665
62164
|
}
|
|
61666
62165
|
function computeCardWidth(_rows, widths, topTitleVis, topSummaryVis, footerVis) {
|
|
61667
62166
|
const tableRowWidth = 2 + CARD_PADDING_LEFT + widths.reduce((a, b) => a + b, 0) + (widths.length - 1) * 3 + CARD_PADDING_RIGHT;
|
|
@@ -61682,6 +62181,9 @@ function formatContextWindow(ctx) {
|
|
|
61682
62181
|
return `${Math.round(ctx / 1000)}K`;
|
|
61683
62182
|
}
|
|
61684
62183
|
function buildKeyLine(activeEntry, directKeyVar) {
|
|
62184
|
+
if (activeEntry?.notProbed) {
|
|
62185
|
+
return `${pc.bold}Key${pc.reset} ${pc.dim}Claude Code's own auth (not visible to this process)${pc.reset}`;
|
|
62186
|
+
}
|
|
61685
62187
|
if (activeEntry?.provenance) {
|
|
61686
62188
|
const p = activeEntry.provenance;
|
|
61687
62189
|
const subject = p.effectiveLabel ?? `$${p.envVar}`;
|
|
@@ -61702,21 +62204,29 @@ function buildWireLine(wiring, activeProvider) {
|
|
|
61702
62204
|
const head = activeProvider ? `${activeProvider} \u2192 ` : "";
|
|
61703
62205
|
return `${pc.bold}Wire${pc.reset} ${head}${wiring.effectiveStreamFormat} \xB7 ${wiring.modelTranslator} \xB7 ${ctx}`;
|
|
61704
62206
|
}
|
|
62207
|
+
function cardSummary(result) {
|
|
62208
|
+
const first = result.chain[0];
|
|
62209
|
+
if (!first)
|
|
62210
|
+
return { text: result.routingExplanation || "no route", color: pc.red };
|
|
62211
|
+
if (first.notProbed)
|
|
62212
|
+
return { text: `${first.displayName} \xB7 not probed`, color: pc.cyan };
|
|
62213
|
+
const probed = result.chain.filter((c) => !c.notProbed);
|
|
62214
|
+
const live = probed.filter((c) => c.probe?.state === "live").length;
|
|
62215
|
+
return {
|
|
62216
|
+
text: `${first.displayName} \xB7 ${live}/${probed.length} live`,
|
|
62217
|
+
color: summaryColor(live, probed.length)
|
|
62218
|
+
};
|
|
62219
|
+
}
|
|
61705
62220
|
function buildCardLayout(result, isLiveProbe, directKeyVar) {
|
|
61706
|
-
const rows =
|
|
61707
|
-
const
|
|
61708
|
-
const
|
|
61709
|
-
const
|
|
61710
|
-
const
|
|
61711
|
-
const titleText = result.model;
|
|
61712
|
-
const sumColor = summaryColor(effLive, effTotal);
|
|
61713
|
-
const summaryPlain = `${result.nativeProvider} \xB7 ${effLive}/${effTotal} live`;
|
|
61714
|
-
const titleStyled = `${pc.bold}${pc.cyan}${titleText}${pc.reset}`;
|
|
61715
|
-
const summaryStyled = `${sumColor}${summaryPlain}${pc.reset}`;
|
|
61716
|
-
const activeEntry = result.chain?.find((c) => c.probe?.state === "live") ?? result.chain?.find((c) => c.hasCredentials);
|
|
62221
|
+
const rows = [...buildRowData(result, isLiveProbe), ...buildDroppedRowData(result)];
|
|
62222
|
+
const summary = cardSummary(result);
|
|
62223
|
+
const titleStyled = `${pc.bold}${pc.cyan}${result.model}${pc.reset}`;
|
|
62224
|
+
const summaryStyled = `${summary.color}${summary.text}${pc.reset}`;
|
|
62225
|
+
const activeEntry = result.chain.find((c) => c.probe?.state === "live") ?? result.chain.find((c) => c.hasCredentials);
|
|
61717
62226
|
const keyLine = buildKeyLine(activeEntry, directKeyVar);
|
|
61718
|
-
const wireLine = result.wiring ? buildWireLine(result.wiring, activeEntry?.displayName
|
|
61719
|
-
const
|
|
62227
|
+
const wireLine = result.wiring && !activeEntry?.notProbed ? buildWireLine(result.wiring, activeEntry?.displayName) : "";
|
|
62228
|
+
const routeLine = result.routingExplanation ? `${pc.bold}Route${pc.reset} ${result.routingExplanation}` : "";
|
|
62229
|
+
const footerVis = Math.max(visibleLength(keyLine), visibleLength(wireLine), visibleLength(routeLine));
|
|
61720
62230
|
const widths = computeColumnWidths(rows);
|
|
61721
62231
|
return {
|
|
61722
62232
|
rows,
|
|
@@ -61725,6 +62235,7 @@ function buildCardLayout(result, isLiveProbe, directKeyVar) {
|
|
|
61725
62235
|
summaryStyled,
|
|
61726
62236
|
keyLine,
|
|
61727
62237
|
wireLine,
|
|
62238
|
+
routeLine,
|
|
61728
62239
|
footerVis,
|
|
61729
62240
|
activeEntry
|
|
61730
62241
|
};
|
|
@@ -61736,17 +62247,12 @@ function computeRequiredWidth(result, isLiveProbe, directKeyVar) {
|
|
|
61736
62247
|
}
|
|
61737
62248
|
function renderCard(result, isLiveProbe, w, width, scales, directKeyVar) {
|
|
61738
62249
|
const layout = buildCardLayout(result, isLiveProbe, directKeyVar);
|
|
61739
|
-
const { rows, widths, titleStyled, summaryStyled, keyLine, wireLine } = layout;
|
|
62250
|
+
const { rows, widths, titleStyled, summaryStyled, keyLine, wireLine, routeLine } = layout;
|
|
61740
62251
|
w(`${renderBorderTop(titleStyled, summaryStyled, width)}
|
|
61741
62252
|
`);
|
|
61742
62253
|
w(`${renderBlankLine(width)}
|
|
61743
62254
|
`);
|
|
61744
|
-
const headerCells =
|
|
61745
|
-
`${pc.dim}#${pc.reset}`,
|
|
61746
|
-
`${pc.dim}Provider${pc.reset}`,
|
|
61747
|
-
`${pc.dim}Model Spec${pc.reset}`,
|
|
61748
|
-
`${pc.dim}Status${pc.reset}`
|
|
61749
|
-
];
|
|
62255
|
+
const headerCells = COLUMN_HEADERS.map((h) => `${pc.dim}${h}${pc.reset}`);
|
|
61750
62256
|
w(`${renderRow(headerCells, widths, width)}
|
|
61751
62257
|
`);
|
|
61752
62258
|
w(`${renderSepRow(widths, width)}
|
|
@@ -61754,7 +62260,13 @@ function renderCard(result, isLiveProbe, w, width, scales, directKeyVar) {
|
|
|
61754
62260
|
for (let rowIdx = 0;rowIdx < rows.length; rowIdx++) {
|
|
61755
62261
|
const r = rows[rowIdx];
|
|
61756
62262
|
const bg = r.fastest ? pc.bgFastest : r.slowest ? pc.bgSlowest : undefined;
|
|
61757
|
-
const cells = [
|
|
62263
|
+
const cells = [
|
|
62264
|
+
r.num,
|
|
62265
|
+
r.provider,
|
|
62266
|
+
`${pc.dim}${r.label}${pc.reset}`,
|
|
62267
|
+
`${pc.dim}${r.spec}${pc.reset}`,
|
|
62268
|
+
r.status
|
|
62269
|
+
];
|
|
61758
62270
|
w(`${renderRow(cells, widths, width, bg)}
|
|
61759
62271
|
`);
|
|
61760
62272
|
if (r.barsTiming) {
|
|
@@ -61768,36 +62280,10 @@ function renderCard(result, isLiveProbe, w, width, scales, directKeyVar) {
|
|
|
61768
62280
|
`);
|
|
61769
62281
|
}
|
|
61770
62282
|
}
|
|
61771
|
-
if (r.errorDetail)
|
|
61772
|
-
|
|
61773
|
-
|
|
61774
|
-
|
|
61775
|
-
const textWidth = innerUsable - errorIndent - prefixVis;
|
|
61776
|
-
const MAX_ERROR_LINES = 4;
|
|
61777
|
-
if (textWidth > 0) {
|
|
61778
|
-
let wrapped = wordWrap(r.errorDetail, textWidth);
|
|
61779
|
-
let truncated = false;
|
|
61780
|
-
if (wrapped.length > MAX_ERROR_LINES) {
|
|
61781
|
-
wrapped = wrapped.slice(0, MAX_ERROR_LINES);
|
|
61782
|
-
truncated = true;
|
|
61783
|
-
}
|
|
61784
|
-
if (truncated) {
|
|
61785
|
-
const last = wrapped[wrapped.length - 1];
|
|
61786
|
-
if (last.length >= textWidth) {
|
|
61787
|
-
wrapped[wrapped.length - 1] = `${last.slice(0, textWidth - 1)}\u2026`;
|
|
61788
|
-
} else {
|
|
61789
|
-
wrapped[wrapped.length - 1] = `${last}\u2026`;
|
|
61790
|
-
}
|
|
61791
|
-
}
|
|
61792
|
-
const indentStr = " ".repeat(errorIndent);
|
|
61793
|
-
for (let i = 0;i < wrapped.length; i++) {
|
|
61794
|
-
const prefix = i === 0 ? "\u2514 " : " ";
|
|
61795
|
-
const body = `${indentStr}${pc.dim}${pc.red}${prefix}${wrapped[i]}${pc.reset}`;
|
|
61796
|
-
w(`${renderTextLine(body, width, bg)}
|
|
61797
|
-
`);
|
|
61798
|
-
}
|
|
61799
|
-
}
|
|
61800
|
-
}
|
|
62283
|
+
if (r.errorDetail)
|
|
62284
|
+
writeSubRows(w, r.errorDetail, `${pc.dim}${pc.red}`, width, bg);
|
|
62285
|
+
if (r.note)
|
|
62286
|
+
writeSubRows(w, r.note, pc.dim, width, bg);
|
|
61801
62287
|
}
|
|
61802
62288
|
w(`${renderBlankLine(width)}
|
|
61803
62289
|
`);
|
|
@@ -61809,14 +62295,61 @@ function renderCard(result, isLiveProbe, w, width, scales, directKeyVar) {
|
|
|
61809
62295
|
w(`${renderTextLine(wireLine, width)}
|
|
61810
62296
|
`);
|
|
61811
62297
|
}
|
|
61812
|
-
if (
|
|
61813
|
-
|
|
61814
|
-
w(`${renderTextLine(note, width)}
|
|
62298
|
+
if (visibleLength(routeLine) > 0) {
|
|
62299
|
+
w(`${renderTextLine(routeLine, width)}
|
|
61815
62300
|
`);
|
|
61816
62301
|
}
|
|
62302
|
+
writeDecisionNotes(w, result, width);
|
|
61817
62303
|
w(`${renderBorderBottom(width)}
|
|
61818
62304
|
`);
|
|
61819
62305
|
}
|
|
62306
|
+
function writeDecisionNotes(w, result, width) {
|
|
62307
|
+
const textWidth = cardTextWidth(width);
|
|
62308
|
+
if (result.noRoute) {
|
|
62309
|
+
const head = "No route ";
|
|
62310
|
+
wordWrap(result.noRoute.reason, textWidth - head.length).forEach((line, i) => {
|
|
62311
|
+
const lead = i === 0 ? `${pc.red}No route${pc.reset} ` : " ".repeat(head.length);
|
|
62312
|
+
w(`${renderTextLine(`${lead}${line}`, width)}
|
|
62313
|
+
`);
|
|
62314
|
+
});
|
|
62315
|
+
const hintLines = (result.noRoute.hint ?? "").split(`
|
|
62316
|
+
`).filter((l) => l.trim());
|
|
62317
|
+
const fitted = hintLines.flatMap((l) => l.length <= textWidth ? [l] : wordWrap(l, textWidth));
|
|
62318
|
+
for (const line of fitted) {
|
|
62319
|
+
w(`${renderTextLine(`${pc.dim}${line}${pc.reset}`, width)}
|
|
62320
|
+
`);
|
|
62321
|
+
}
|
|
62322
|
+
}
|
|
62323
|
+
const notices = (result.warnings ?? []).filter((warning) => warning.type !== "rule-problem");
|
|
62324
|
+
for (const line of notices.flatMap((warning) => wordWrap(`\u26A0 ${warning.message}`, textWidth))) {
|
|
62325
|
+
w(`${renderTextLine(`${pc.yellow}${line}${pc.reset}`, width)}
|
|
62326
|
+
`);
|
|
62327
|
+
}
|
|
62328
|
+
}
|
|
62329
|
+
function cardTextWidth(width) {
|
|
62330
|
+
return Math.max(10, width - 2 - CARD_PADDING_LEFT - CARD_PADDING_RIGHT);
|
|
62331
|
+
}
|
|
62332
|
+
function writeSubRows(w, text, color, width, bg) {
|
|
62333
|
+
const indent = 4;
|
|
62334
|
+
const prefixVis = 2;
|
|
62335
|
+
const textWidth = cardTextWidth(width) - indent - prefixVis;
|
|
62336
|
+
const MAX_LINES = 4;
|
|
62337
|
+
if (textWidth <= 0)
|
|
62338
|
+
return;
|
|
62339
|
+
let wrapped = wordWrap(text, textWidth);
|
|
62340
|
+
if (wrapped.length > MAX_LINES) {
|
|
62341
|
+
wrapped = wrapped.slice(0, MAX_LINES);
|
|
62342
|
+
const last = wrapped[wrapped.length - 1];
|
|
62343
|
+
wrapped[wrapped.length - 1] = last.length >= textWidth ? `${last.slice(0, textWidth - 1)}\u2026` : `${last}\u2026`;
|
|
62344
|
+
}
|
|
62345
|
+
const indentStr = " ".repeat(indent);
|
|
62346
|
+
for (let i = 0;i < wrapped.length; i++) {
|
|
62347
|
+
const prefix = i === 0 ? "\u2514 " : " ";
|
|
62348
|
+
const body = `${indentStr}${color}${prefix}${wrapped[i]}${pc.reset}`;
|
|
62349
|
+
w(`${renderTextLine(body, width, bg)}
|
|
62350
|
+
`);
|
|
62351
|
+
}
|
|
62352
|
+
}
|
|
61820
62353
|
function renderLegend(w) {
|
|
61821
62354
|
const net = STAGE_BG_ANSI.network;
|
|
61822
62355
|
const srv = STAGE_BG_ANSI.server;
|
|
@@ -61837,11 +62370,12 @@ function pickRepresentative(result) {
|
|
|
61837
62370
|
return { model: result.model, provider: entry.displayName, timing: entry.probe.timing };
|
|
61838
62371
|
}
|
|
61839
62372
|
}
|
|
61840
|
-
const
|
|
61841
|
-
|
|
61842
|
-
|
|
61843
|
-
|
|
61844
|
-
|
|
62373
|
+
const first = result.chain?.[0];
|
|
62374
|
+
return {
|
|
62375
|
+
model: result.model,
|
|
62376
|
+
provider: first?.displayName ?? result.routingExplanation,
|
|
62377
|
+
missing: first?.notProbed ? "not probed (native)" : first ? "no live route" : "no route"
|
|
62378
|
+
};
|
|
61845
62379
|
}
|
|
61846
62380
|
function renderLeaderboard(results, scales, maxWidth, w) {
|
|
61847
62381
|
const reps = results.map(pickRepresentative);
|
|
@@ -61935,7 +62469,7 @@ function renderLeaderboard(results, scales, maxWidth, w) {
|
|
|
61935
62469
|
const rankStr = " ".repeat(rankW);
|
|
61936
62470
|
const name = padEnd(`${pc.dim}${truncate3(row.model, nameW)}${pc.reset}`, nameW);
|
|
61937
62471
|
const prov = padEnd(`${pc.dim}${truncate3(row.provider, provW)}${pc.reset}`, provW);
|
|
61938
|
-
w(`${margin}${rankStr} ${name} ${prov} ${pc.dim}\u2014
|
|
62472
|
+
w(`${margin}${rankStr} ${name} ${prov} ${pc.dim}\u2014 ${row.missing}${pc.reset}
|
|
61939
62473
|
`);
|
|
61940
62474
|
}
|
|
61941
62475
|
const rowVis = leadW - MARGIN + LB_TIMELINE + (showBreakdown ? LB_BREAKDOWN : 0) + (showTokBar ? LB_TOKBAR : 2) + LB_TOK_VALUE;
|
|
@@ -61945,13 +62479,24 @@ function renderLeaderboard(results, scales, maxWidth, w) {
|
|
|
61945
62479
|
w(`
|
|
61946
62480
|
`);
|
|
61947
62481
|
}
|
|
62482
|
+
function renderRuleProblems(results, w) {
|
|
62483
|
+
const messages = new Set(results.flatMap((r) => (r.warnings ?? []).filter((x) => x.type === "rule-problem").map((x) => x.message)));
|
|
62484
|
+
for (const message of messages) {
|
|
62485
|
+
w(` ${pc.yellow}\u26A0 routing rule: ${message}${pc.reset}
|
|
62486
|
+
`);
|
|
62487
|
+
}
|
|
62488
|
+
if (messages.size > 0)
|
|
62489
|
+
w(`
|
|
62490
|
+
`);
|
|
62491
|
+
}
|
|
61948
62492
|
function printProbeResults(results, isLiveProbe) {
|
|
61949
62493
|
refreshPc();
|
|
61950
62494
|
const w = process.stderr.write.bind(process.stderr);
|
|
61951
62495
|
w(`
|
|
61952
62496
|
`);
|
|
61953
62497
|
const scales = computeBarScales(results);
|
|
61954
|
-
const anyTimedLive = results.some((r) =>
|
|
62498
|
+
const anyTimedLive = results.some((r) => (r.chain ?? []).some((c) => c.probe?.state === "live" && c.probe.timing !== undefined));
|
|
62499
|
+
renderRuleProblems(results, w);
|
|
61955
62500
|
if (isLiveProbe && anyTimedLive) {
|
|
61956
62501
|
renderLegend(w);
|
|
61957
62502
|
}
|
|
@@ -61975,13 +62520,16 @@ function printProbeResults(results, isLiveProbe) {
|
|
|
61975
62520
|
w(`
|
|
61976
62521
|
`);
|
|
61977
62522
|
}
|
|
61978
|
-
w(` ${pc.dim}Tip:
|
|
62523
|
+
w(` ${pc.dim}Tip: a matching user rule is used as written; otherwise the catalog orders hops by tier,${pc.reset}
|
|
62524
|
+
`);
|
|
62525
|
+
w(` ${pc.dim} subscription first, and the fallback hop comes last. Dropped candidates are never probed.${pc.reset}
|
|
61979
62526
|
`);
|
|
61980
62527
|
w(`
|
|
61981
62528
|
`);
|
|
61982
62529
|
}
|
|
61983
|
-
var pc, ANSI_RE2, PRINTER_BAR_WIDTH = 24, PRINTER_TOK_WIDTH = 14, PRINTER_TRACK = "\xB7", PRINTER_BAR_FILL = "\u2588", STAGE_NUM_W = 6, PRINTER_TOK_VALUE_W = 9, PRINTER_BARS_FULL_WIDTH, PRINTER_BARS_NOTOK_WIDTH, PRINTER_BARS_MIN_WIDTH, MIN_CARD_WIDTH = 60, CARD_PADDING_LEFT = 2, CARD_PADDING_RIGHT = 2;
|
|
62530
|
+
var pc, ANSI_RE2, PRINTER_BAR_WIDTH = 24, PRINTER_TOK_WIDTH = 14, PRINTER_TRACK = "\xB7", PRINTER_BAR_FILL = "\u2588", STAGE_NUM_W = 6, PRINTER_TOK_VALUE_W = 9, PRINTER_BARS_FULL_WIDTH, PRINTER_BARS_NOTOK_WIDTH, PRINTER_BARS_MIN_WIDTH, MIN_CARD_WIDTH = 60, CARD_PADDING_LEFT = 2, CARD_PADDING_RIGHT = 2, COLUMN_HEADERS;
|
|
61984
62531
|
var init_probe_results_printer = __esm(() => {
|
|
62532
|
+
init_native_route();
|
|
61985
62533
|
init_probe_live();
|
|
61986
62534
|
init_probe_runner();
|
|
61987
62535
|
init_ansi();
|
|
@@ -61991,6 +62539,7 @@ var init_probe_results_printer = __esm(() => {
|
|
|
61991
62539
|
PRINTER_BARS_FULL_WIDTH = 24 + 2 + 7 + 34 + 17 + 9;
|
|
61992
62540
|
PRINTER_BARS_NOTOK_WIDTH = 24 + 2 + 7 + 34 + 2 + 9;
|
|
61993
62541
|
PRINTER_BARS_MIN_WIDTH = 24 + 2 + 7 + 2 + 9;
|
|
62542
|
+
COLUMN_HEADERS = ["#", "Provider", "Tier", "Model Spec", "Status"];
|
|
61994
62543
|
});
|
|
61995
62544
|
|
|
61996
62545
|
// src/probe/probe-tui-app.tsx
|
|
@@ -62183,7 +62732,7 @@ function ProgressBar({
|
|
|
62183
62732
|
isRunFastest
|
|
62184
62733
|
}) {
|
|
62185
62734
|
const elapsedMs = link.status === "waiting" ? 0 : link.startTime ? (link.endTime ?? Date.now()) - link.startTime : 0;
|
|
62186
|
-
const elapsed = formatElapsed(elapsedMs);
|
|
62735
|
+
const elapsed = link.status === "not-probed" ? " \u2013 " : formatElapsed(elapsedMs);
|
|
62187
62736
|
const displayName = padEndSafe(link.displayName, maxNameLen);
|
|
62188
62737
|
const prefix = /* @__PURE__ */ jsxs9(Fragment6, {
|
|
62189
62738
|
children: [
|
|
@@ -62201,6 +62750,19 @@ function ProgressBar({
|
|
|
62201
62750
|
})
|
|
62202
62751
|
]
|
|
62203
62752
|
});
|
|
62753
|
+
if (link.status === "not-probed") {
|
|
62754
|
+
const used = ELAPSED_COL + maxNameLen + 2;
|
|
62755
|
+
const fg = link.tone === "native" ? C.cyan : link.tone === "ready" ? C.green : C.dim;
|
|
62756
|
+
return /* @__PURE__ */ jsxs9("text", {
|
|
62757
|
+
children: [
|
|
62758
|
+
prefix,
|
|
62759
|
+
/* @__PURE__ */ jsx12("span", {
|
|
62760
|
+
fg,
|
|
62761
|
+
children: clipReason(stripAnsi3(link.note ?? "not probed"), layout.width - used)
|
|
62762
|
+
})
|
|
62763
|
+
]
|
|
62764
|
+
});
|
|
62765
|
+
}
|
|
62204
62766
|
if (layout.pillFallback) {
|
|
62205
62767
|
if (link.status === "live") {
|
|
62206
62768
|
const latency = link.timing?.totalMs ?? elapsedMs;
|
|
@@ -62562,6 +63124,16 @@ function shortFailureReason(probe, hasCreds) {
|
|
|
62562
63124
|
return "key missing";
|
|
62563
63125
|
return stripAnsi3(describeProbeState(probe));
|
|
62564
63126
|
}
|
|
63127
|
+
function notProbedRow(link) {
|
|
63128
|
+
if (link.notProbed)
|
|
63129
|
+
return { mark: "\u25D0 ", text: `native \u2014 ${NATIVE_NOT_PROBED}`, fg: C.cyan };
|
|
63130
|
+
if (link.dropped) {
|
|
63131
|
+
return { mark: "\u2013 ", text: describeDropped(link.dropped, link.credentialHint), fg: C.dim };
|
|
63132
|
+
}
|
|
63133
|
+
if (!link.probe && link.hasCredentials)
|
|
63134
|
+
return { mark: "\u25CB ", text: "not probed", fg: C.dim };
|
|
63135
|
+
return null;
|
|
63136
|
+
}
|
|
62565
63137
|
function DetailLinkRow({
|
|
62566
63138
|
link,
|
|
62567
63139
|
isWinner,
|
|
@@ -62598,8 +63170,24 @@ function DetailLinkRow({
|
|
|
62598
63170
|
})
|
|
62599
63171
|
]
|
|
62600
63172
|
});
|
|
63173
|
+
const used = 2 + 1 + 1 + provW + 2 + 3;
|
|
63174
|
+
const idle = notProbedRow(link);
|
|
63175
|
+
if (idle) {
|
|
63176
|
+
return /* @__PURE__ */ jsxs9("text", {
|
|
63177
|
+
children: [
|
|
63178
|
+
lead,
|
|
63179
|
+
/* @__PURE__ */ jsx12("span", {
|
|
63180
|
+
fg: idle.fg,
|
|
63181
|
+
children: idle.mark
|
|
63182
|
+
}),
|
|
63183
|
+
/* @__PURE__ */ jsx12("span", {
|
|
63184
|
+
fg: idle.fg,
|
|
63185
|
+
children: clipReason(idle.text, layout.width - used)
|
|
63186
|
+
})
|
|
63187
|
+
]
|
|
63188
|
+
});
|
|
63189
|
+
}
|
|
62601
63190
|
if (!isLive || !probe?.timing) {
|
|
62602
|
-
const used = 2 + 1 + 1 + provW + 2 + 3;
|
|
62603
63191
|
return /* @__PURE__ */ jsxs9("text", {
|
|
62604
63192
|
children: [
|
|
62605
63193
|
lead,
|
|
@@ -62732,7 +63320,7 @@ function DetailModel({
|
|
|
62732
63320
|
const gap = Math.max(2, headerW - result.model.length - result.routingExplanation.length - 2);
|
|
62733
63321
|
const wiring = result.wiring;
|
|
62734
63322
|
const wireLine = winner && wiring ? `wire (${winner.displayName}): ${wiring.effectiveStreamFormat} \xB7 ${wiring.modelTranslator} \xB7 ${formatContextWindow2(wiring.contextWindow)} ctx` : "wire: \u2014";
|
|
62735
|
-
const routeChain = result.links.map((l) => l.displayName).join(" \u2192 ");
|
|
63323
|
+
const routeChain = result.links.filter((l) => !l.dropped).map((l) => l.label ? `${l.displayName} (${l.label})` : l.displayName).join(" \u2192 ");
|
|
62736
63324
|
const liveLinks = result.links.filter((l) => l.probe?.state === "live" && !!l.probe.timing);
|
|
62737
63325
|
let fastestByLatency;
|
|
62738
63326
|
let fastestByTput;
|
|
@@ -62791,6 +63379,24 @@ function DetailModel({
|
|
|
62791
63379
|
})
|
|
62792
63380
|
]
|
|
62793
63381
|
}),
|
|
63382
|
+
result.noRoute && /* @__PURE__ */ jsxs9("text", {
|
|
63383
|
+
children: [
|
|
63384
|
+
/* @__PURE__ */ jsx12("span", {
|
|
63385
|
+
fg: C.red,
|
|
63386
|
+
children: " no route "
|
|
63387
|
+
}),
|
|
63388
|
+
/* @__PURE__ */ jsx12("span", {
|
|
63389
|
+
fg: C.fg,
|
|
63390
|
+
children: clipReason(result.noRoute.reason, layout.width - 12)
|
|
63391
|
+
})
|
|
63392
|
+
]
|
|
63393
|
+
}),
|
|
63394
|
+
(result.warnings ?? []).filter((w) => w.type !== "rule-problem").map((w) => /* @__PURE__ */ jsx12("text", {
|
|
63395
|
+
children: /* @__PURE__ */ jsx12("span", {
|
|
63396
|
+
fg: C.yellow,
|
|
63397
|
+
children: ` \u26A0 ${clipReason(w.message, layout.width - 4)}`
|
|
63398
|
+
})
|
|
63399
|
+
}, `${result.model}:warn:${w.message}`)),
|
|
62794
63400
|
result.links.map((link, i) => /* @__PURE__ */ jsx12(DetailLinkRow, {
|
|
62795
63401
|
link,
|
|
62796
63402
|
isWinner: i === winnerIdx,
|
|
@@ -62874,17 +63480,28 @@ function DetailsView({
|
|
|
62874
63480
|
}) {
|
|
62875
63481
|
const provW = Math.min(22, Math.max(8, ...results.flatMap((r) => r.links.map((l) => l.displayName.length))));
|
|
62876
63482
|
const headerW = Math.max(24, Math.min(detailRowWidth(provW, layout), (termWidth || 100) - 3));
|
|
62877
|
-
|
|
63483
|
+
const ruleProblems = [
|
|
63484
|
+
...new Set(results.flatMap((r) => (r.warnings ?? []).filter((w) => w.type === "rule-problem").map((w) => w.message)))
|
|
63485
|
+
];
|
|
63486
|
+
return /* @__PURE__ */ jsxs9("box", {
|
|
62878
63487
|
flexDirection: "column",
|
|
62879
|
-
children:
|
|
62880
|
-
|
|
62881
|
-
|
|
62882
|
-
|
|
62883
|
-
|
|
62884
|
-
|
|
62885
|
-
|
|
62886
|
-
|
|
62887
|
-
|
|
63488
|
+
children: [
|
|
63489
|
+
ruleProblems.map((message) => /* @__PURE__ */ jsx12("text", {
|
|
63490
|
+
children: /* @__PURE__ */ jsx12("span", {
|
|
63491
|
+
fg: C.yellow,
|
|
63492
|
+
children: ` \u26A0 routing rule: ${clipReason(message, (termWidth || 100) - 20)}`
|
|
63493
|
+
})
|
|
63494
|
+
}, `rule-problem:${message}`)),
|
|
63495
|
+
results.map((r, idx) => /* @__PURE__ */ jsx12(DetailModel, {
|
|
63496
|
+
result: r,
|
|
63497
|
+
provW,
|
|
63498
|
+
headerW,
|
|
63499
|
+
layout,
|
|
63500
|
+
maxTotalMs,
|
|
63501
|
+
maxTokPerSec,
|
|
63502
|
+
isLast: idx === results.length - 1
|
|
63503
|
+
}, r.model))
|
|
63504
|
+
]
|
|
62888
63505
|
});
|
|
62889
63506
|
}
|
|
62890
63507
|
function pickRepresentativeLink(result) {
|
|
@@ -62893,7 +63510,12 @@ function pickRepresentativeLink(result) {
|
|
|
62893
63510
|
return { model: result.model, provider: link.displayName, timing: link.probe.timing };
|
|
62894
63511
|
}
|
|
62895
63512
|
}
|
|
62896
|
-
|
|
63513
|
+
const first = result.links.find((link) => !link.dropped);
|
|
63514
|
+
return {
|
|
63515
|
+
model: result.model,
|
|
63516
|
+
provider: first?.displayName ?? result.routingExplanation,
|
|
63517
|
+
missing: first?.notProbed ? "not probed (native)" : first ? "no live route" : "no route"
|
|
63518
|
+
};
|
|
62897
63519
|
}
|
|
62898
63520
|
function LeaderLiveRow({
|
|
62899
63521
|
row,
|
|
@@ -63167,7 +63789,7 @@ function LeaderboardView({
|
|
|
63167
63789
|
}),
|
|
63168
63790
|
/* @__PURE__ */ jsx12("span", {
|
|
63169
63791
|
fg: C.dim,
|
|
63170
|
-
children:
|
|
63792
|
+
children: ` \u2014 ${row.missing}`
|
|
63171
63793
|
})
|
|
63172
63794
|
]
|
|
63173
63795
|
}, `lb-na:${row.model}`))
|
|
@@ -63295,7 +63917,7 @@ function ProbeApp({
|
|
|
63295
63917
|
isDone ? /* @__PURE__ */ jsx12(TabBar, {
|
|
63296
63918
|
activeTab: state.activeTab
|
|
63297
63919
|
}) : null,
|
|
63298
|
-
groups.length > 0 ? /* @__PURE__ */ jsxs9(Fragment6, {
|
|
63920
|
+
groups.length > 0 || state.results.length > 0 ? /* @__PURE__ */ jsxs9(Fragment6, {
|
|
63299
63921
|
children: [
|
|
63300
63922
|
showSummary && /* @__PURE__ */ jsx12("box", {
|
|
63301
63923
|
flexDirection: "column",
|
|
@@ -63347,7 +63969,9 @@ function ProbeApp({
|
|
|
63347
63969
|
}
|
|
63348
63970
|
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;
|
|
63349
63971
|
var init_probe_tui_app = __esm(() => {
|
|
63972
|
+
init_native_route();
|
|
63350
63973
|
init_probe_live();
|
|
63974
|
+
init_probe_runner();
|
|
63351
63975
|
init_theme_mode();
|
|
63352
63976
|
init_useAnimationFrame();
|
|
63353
63977
|
init_theme2();
|
|
@@ -63677,8 +64301,7 @@ import {
|
|
|
63677
64301
|
mkdirSync as mkdirSync19,
|
|
63678
64302
|
readFileSync as readFileSync32,
|
|
63679
64303
|
readdirSync as readdirSync7,
|
|
63680
|
-
unlinkSync as unlinkSync8
|
|
63681
|
-
writeFileSync as writeFileSync20
|
|
64304
|
+
unlinkSync as unlinkSync8
|
|
63682
64305
|
} from "fs";
|
|
63683
64306
|
import { homedir as homedir36 } from "os";
|
|
63684
64307
|
import { dirname as dirname13, join as join42 } from "path";
|
|
@@ -63902,13 +64525,10 @@ async function parseArgs(args) {
|
|
|
63902
64525
|
process.exit(1);
|
|
63903
64526
|
}
|
|
63904
64527
|
config.profile = profileArg;
|
|
63905
|
-
} else if (arg === "--default-provider") {
|
|
63906
|
-
|
|
63907
|
-
|
|
63908
|
-
console.error("--default-provider requires a provider name");
|
|
63909
|
-
process.exit(1);
|
|
64528
|
+
} else if (arg === "--default-provider" || arg.startsWith("--default-provider=")) {
|
|
64529
|
+
if (arg === "--default-provider" && i + 1 < args.length && !args[i + 1].startsWith("-")) {
|
|
64530
|
+
i++;
|
|
63910
64531
|
}
|
|
63911
|
-
config.defaultProvider = dpArg;
|
|
63912
64532
|
} else if (arg === "--anthropic-api-billing") {
|
|
63913
64533
|
config.anthropicApiBilling = true;
|
|
63914
64534
|
} else if (arg === "--classifier-model") {
|
|
@@ -64165,28 +64785,6 @@ Usage: claudish --models --provider <slug>`);
|
|
|
64165
64785
|
config.modelSubagent = profileModels.subagent;
|
|
64166
64786
|
}
|
|
64167
64787
|
}
|
|
64168
|
-
try {
|
|
64169
|
-
const fileConfigForResolver = loadConfig();
|
|
64170
|
-
const resolved = resolveDefaultProvider({
|
|
64171
|
-
cliFlag: config.defaultProvider,
|
|
64172
|
-
config: fileConfigForResolver,
|
|
64173
|
-
env: process.env
|
|
64174
|
-
});
|
|
64175
|
-
config.resolvedDefaultProvider = resolved;
|
|
64176
|
-
if (resolved.legacyAutoPromoted && !config.quiet) {
|
|
64177
|
-
const markerFile = join42(homedir36(), ".claudish", ".legacy-litellm-hint-shown");
|
|
64178
|
-
if (!existsSync32(markerFile)) {
|
|
64179
|
-
const hint = buildLegacyHint(resolved);
|
|
64180
|
-
if (hint) {
|
|
64181
|
-
console.error(hint);
|
|
64182
|
-
}
|
|
64183
|
-
try {
|
|
64184
|
-
mkdirSync19(dirname13(markerFile), { recursive: true });
|
|
64185
|
-
writeFileSync20(markerFile, new Date().toISOString(), "utf-8");
|
|
64186
|
-
} catch {}
|
|
64187
|
-
}
|
|
64188
|
-
}
|
|
64189
|
-
} catch {}
|
|
64190
64788
|
if (config.proOnUltracode === undefined) {
|
|
64191
64789
|
const envVal = process.env.CLAUDISH_PRO_ON_ULTRACODE;
|
|
64192
64790
|
if (envVal !== undefined) {
|
|
@@ -64428,7 +65026,7 @@ async function printRecommendedModels(jsonOutput, forceUpdate) {
|
|
|
64428
65026
|
const { flagship, fast } = groupRecommendedModels(doc.models);
|
|
64429
65027
|
const providerByName = new Map(BUILTIN_PROVIDERS.map((p) => [p.name, p]));
|
|
64430
65028
|
const getNativePrefix = (firebaseSlug) => {
|
|
64431
|
-
const canonical =
|
|
65029
|
+
const canonical = nativeProviderForVendor(firebaseSlug);
|
|
64432
65030
|
if (!canonical)
|
|
64433
65031
|
return null;
|
|
64434
65032
|
const def = providerByName.get(canonical);
|
|
@@ -64530,204 +65128,62 @@ async function printVersion() {
|
|
|
64530
65128
|
console.log("");
|
|
64531
65129
|
}
|
|
64532
65130
|
async function probeModelRouting(models, jsonOutput, options = { live: true, timeoutMs: 40000 }) {
|
|
64533
|
-
const userRoutingKeys = new Set([
|
|
64534
|
-
...Object.keys(loadConfig().routing ?? {}),
|
|
64535
|
-
...Object.keys(loadLocalConfig()?.routing ?? {})
|
|
64536
|
-
]);
|
|
64537
65131
|
function credentialHintFrom(provenance, envVar) {
|
|
64538
65132
|
if (provenance?.effectiveLabel)
|
|
64539
65133
|
return provenance.effectiveSource;
|
|
64540
65134
|
return envVar;
|
|
64541
65135
|
}
|
|
64542
|
-
|
|
64543
|
-
|
|
64544
|
-
|
|
64545
|
-
|
|
64546
|
-
|
|
64547
|
-
|
|
64548
|
-
|
|
64549
|
-
|
|
64550
|
-
|
|
64551
|
-
|
|
64552
|
-
|
|
64553
|
-
|
|
64554
|
-
matchedPattern: undefined
|
|
64555
|
-
};
|
|
64556
|
-
}
|
|
64557
|
-
if (parsed.provider === "native-anthropic") {
|
|
64558
|
-
const tier = claudeCodeTierAlias(parsed.model);
|
|
64559
|
-
const tierEnv = {
|
|
64560
|
-
opus: process.env[ENV.CLAUDISH_MODEL_OPUS] || process.env[ENV.ANTHROPIC_DEFAULT_OPUS_MODEL],
|
|
64561
|
-
sonnet: process.env[ENV.CLAUDISH_MODEL_SONNET] || process.env[ENV.ANTHROPIC_DEFAULT_SONNET_MODEL],
|
|
64562
|
-
haiku: process.env[ENV.CLAUDISH_MODEL_HAIKU] || process.env[ENV.ANTHROPIC_DEFAULT_HAIKU_MODEL]
|
|
64563
|
-
};
|
|
64564
|
-
const opusModel = tier ? tierEnv[tier] || latestAnthropicTierModelId(tier) || "claude-opus-5" : parsed.model;
|
|
64565
|
-
return {
|
|
64566
|
-
routes: [
|
|
64567
|
-
{
|
|
64568
|
-
provider: "native-anthropic",
|
|
64569
|
-
modelSpec: opusModel,
|
|
64570
|
-
displayName: tier ? `Claude Code (${tier})` : "Claude Code"
|
|
64571
|
-
}
|
|
64572
|
-
],
|
|
64573
|
-
source: "auto-chain",
|
|
64574
|
-
matchedPattern: undefined
|
|
64575
|
-
};
|
|
64576
|
-
}
|
|
64577
|
-
const routingRules = loadRoutingRules();
|
|
64578
|
-
const matched = matchRoutingRule(parsed.model, routingRules);
|
|
64579
|
-
if (matched) {
|
|
64580
|
-
const matchedPattern = Object.keys(routingRules).find((k) => {
|
|
64581
|
-
if (k === parsed.model)
|
|
64582
|
-
return true;
|
|
64583
|
-
if (k.includes("*")) {
|
|
64584
|
-
const star = k.indexOf("*");
|
|
64585
|
-
const prefix = k.slice(0, star);
|
|
64586
|
-
const suffix = k.slice(star + 1);
|
|
64587
|
-
return parsed.model.startsWith(prefix) && parsed.model.endsWith(suffix);
|
|
64588
|
-
}
|
|
64589
|
-
return false;
|
|
64590
|
-
});
|
|
64591
|
-
const isUserKey = !!matchedPattern && userRoutingKeys.has(matchedPattern);
|
|
64592
|
-
return {
|
|
64593
|
-
routes: buildRoutingChain(matched, parsed.model),
|
|
64594
|
-
source: isUserKey ? "custom-rules" : "auto-chain",
|
|
64595
|
-
matchedPattern
|
|
64596
|
-
};
|
|
64597
|
-
}
|
|
64598
|
-
return {
|
|
64599
|
-
routes: buildCatalogChain(parsed.model, loadConfig().defaultProvider).routes,
|
|
64600
|
-
source: "auto-chain",
|
|
64601
|
-
matchedPattern: undefined
|
|
64602
|
-
};
|
|
64603
|
-
})();
|
|
64604
|
-
const chainDetails = chain.routes.map((route) => {
|
|
64605
|
-
const keyInfo = API_KEY_MAP[route.provider];
|
|
64606
|
-
const providerDef = getProviderByName(route.provider);
|
|
64607
|
-
let hasCredentials = false;
|
|
64608
|
-
let credentialHint;
|
|
64609
|
-
let provenance;
|
|
64610
|
-
if (route.provider === "native-anthropic") {
|
|
64611
|
-
hasCredentials = !!process.env.ANTHROPIC_API_KEY;
|
|
64612
|
-
if (!hasCredentials) {
|
|
64613
|
-
credentialHint = "ANTHROPIC_API_KEY (required to probe Claude Code)";
|
|
64614
|
-
}
|
|
64615
|
-
} else if (providerDef?.isLocal) {
|
|
64616
|
-
hasCredentials = isLocalProviderEnabled(route.provider);
|
|
64617
|
-
if (!hasCredentials) {
|
|
64618
|
-
credentialHint = "enable local provider in global config";
|
|
64619
|
-
}
|
|
64620
|
-
} else if (!keyInfo) {
|
|
64621
|
-
hasCredentials = true;
|
|
64622
|
-
} else if (!keyInfo.envVar) {
|
|
64623
|
-
hasCredentials = true;
|
|
64624
|
-
} else {
|
|
64625
|
-
provenance = resolveCredentialProvenance(route.provider, keyInfo.envVar, keyInfo.aliases);
|
|
64626
|
-
hasCredentials = provenance.hasValue;
|
|
64627
|
-
if (!hasCredentials && keyInfo.aliases) {
|
|
64628
|
-
hasCredentials = keyInfo.aliases.some((a) => !!process.env[a]);
|
|
64629
|
-
}
|
|
64630
|
-
if (!hasCredentials) {
|
|
64631
|
-
credentialHint = credentialHintFrom(provenance, keyInfo.envVar);
|
|
64632
|
-
}
|
|
64633
|
-
}
|
|
64634
|
-
return {
|
|
64635
|
-
provider: route.provider,
|
|
64636
|
-
displayName: route.displayName,
|
|
64637
|
-
modelSpec: route.modelSpec,
|
|
64638
|
-
hasCredentials,
|
|
64639
|
-
credentialHint,
|
|
64640
|
-
provenance,
|
|
64641
|
-
probe: undefined
|
|
64642
|
-
};
|
|
64643
|
-
});
|
|
64644
|
-
return { parsed, chain, chainDetails };
|
|
64645
|
-
}
|
|
64646
|
-
const probeCredentialReadiness = new Map;
|
|
64647
|
-
async function credentialForProbe(provider) {
|
|
64648
|
-
if (probeCredentialReadiness.has(provider))
|
|
64649
|
-
return probeCredentialReadiness.get(provider);
|
|
64650
|
-
const ready = provider === "native-anthropic" ? !!process.env.ANTHROPIC_API_KEY : await hasCredentialsForProvider(provider);
|
|
64651
|
-
probeCredentialReadiness.set(provider, ready);
|
|
64652
|
-
return ready;
|
|
64653
|
-
}
|
|
64654
|
-
async function prepareModelChain(modelInput) {
|
|
64655
|
-
const result = buildModelChain(modelInput);
|
|
64656
|
-
await Promise.all(result.chainDetails.map(async (link) => {
|
|
64657
|
-
link.hasCredentials = await credentialForProbe(link.provider);
|
|
64658
|
-
const keyInfo = API_KEY_MAP[link.provider];
|
|
64659
|
-
if (keyInfo?.envVar)
|
|
64660
|
-
link.provenance = resolveCredentialProvenance(link.provider, keyInfo.envVar, keyInfo.aliases);
|
|
64661
|
-
link.credentialHint = link.hasCredentials ? undefined : link.provider === "native-anthropic" ? "ANTHROPIC_API_KEY (required to probe Claude Code)" : getProviderByName(link.provider)?.isLocal ? "enable local provider in global config" : credentialHintFrom(link.provenance, keyInfo?.envVar);
|
|
64662
|
-
}));
|
|
64663
|
-
if (result.chain.source === "direct")
|
|
64664
|
-
await credentialForProbe(result.parsed.provider);
|
|
64665
|
-
return result;
|
|
64666
|
-
}
|
|
64667
|
-
function buildRoutingExplanation(parsed, chain) {
|
|
64668
|
-
if (parsed.provider === "native-anthropic") {
|
|
64669
|
-
return "native passthrough \xB7 default Claude Code (Opus)";
|
|
64670
|
-
}
|
|
64671
|
-
if (chain.source === "direct") {
|
|
64672
|
-
return `explicit \xB7 ${parsed.provider} (direct)`;
|
|
64673
|
-
}
|
|
64674
|
-
if (chain.source === "custom-rules" && chain.matchedPattern) {
|
|
64675
|
-
return `custom-rules \xB7 matched \`${chain.matchedPattern}\``;
|
|
64676
|
-
}
|
|
64677
|
-
if (chain.source === "auto-chain") {
|
|
64678
|
-
if (chain.matchedPattern && chain.matchedPattern !== "*") {
|
|
64679
|
-
return `auto-chain \xB7 default rule \`${chain.matchedPattern}\``;
|
|
64680
|
-
}
|
|
64681
|
-
return "auto-chain \xB7 catch-all \u2192 openrouter";
|
|
65136
|
+
const probeCredentials = {
|
|
65137
|
+
hintFor(provider) {
|
|
65138
|
+
if (getProviderByName(provider)?.isLocal)
|
|
65139
|
+
return "enable local provider in global config";
|
|
65140
|
+
const keyInfo = API_KEY_MAP[provider];
|
|
65141
|
+
if (!keyInfo?.envVar)
|
|
65142
|
+
return;
|
|
65143
|
+
return credentialHintFrom(resolveCredentialProvenance(provider, keyInfo.envVar, keyInfo.aliases), keyInfo.envVar);
|
|
65144
|
+
},
|
|
65145
|
+
provenanceFor(provider) {
|
|
65146
|
+
const keyInfo = API_KEY_MAP[provider];
|
|
65147
|
+
return keyInfo?.envVar ? resolveCredentialProvenance(provider, keyInfo.envVar, keyInfo.aliases) : undefined;
|
|
64682
65148
|
}
|
|
64683
|
-
|
|
64684
|
-
|
|
64685
|
-
|
|
64686
|
-
const
|
|
64687
|
-
const
|
|
64688
|
-
|
|
64689
|
-
return [];
|
|
64690
|
-
const hasCredentials = probeCredentialReadiness.get(parsed.provider) ?? false;
|
|
64691
|
-
const provenance = keyInfo?.envVar ? resolveCredentialProvenance(parsed.provider, keyInfo.envVar, keyInfo.aliases) : undefined;
|
|
64692
|
-
return [
|
|
64693
|
-
{
|
|
64694
|
-
provider: parsed.provider,
|
|
64695
|
-
displayName: providerDef?.displayName ?? parsed.provider,
|
|
64696
|
-
modelSpec: parsed.model,
|
|
64697
|
-
hasCredentials,
|
|
64698
|
-
credentialHint: !hasCredentials ? providerDef?.isLocal ? "enable local provider in global config" : credentialHintFrom(provenance, keyInfo?.envVar) : undefined,
|
|
64699
|
-
provenance,
|
|
64700
|
-
probe: directProbe
|
|
64701
|
-
}
|
|
64702
|
-
];
|
|
65149
|
+
};
|
|
65150
|
+
async function explainForProbe(modelInput) {
|
|
65151
|
+
const explanation = await explainRoute(modelInput);
|
|
65152
|
+
const { chain, dropped } = probeChainFrom(explanation, probeCredentials);
|
|
65153
|
+
const targets = probeTargets(explanation).map((target, i) => ({ target, link: chain[i] }));
|
|
65154
|
+
return { modelInput, explanation, chain, dropped, targets };
|
|
64703
65155
|
}
|
|
64704
|
-
function
|
|
64705
|
-
|
|
64706
|
-
|
|
64707
|
-
|
|
64708
|
-
|
|
64709
|
-
return [
|
|
64710
|
-
{
|
|
64711
|
-
provider: parsed.provider,
|
|
64712
|
-
displayName: directProviderDef?.displayName ?? parsed.provider,
|
|
64713
|
-
modelId: parsed.model,
|
|
64714
|
-
hasCredentials: directHasCreds,
|
|
64715
|
-
credentialHint: !directHasCreds ? directProviderDef?.isLocal ? "enable local provider in global config" : credentialHintFor(parsed.provider, directKeyInfo?.envVar, directKeyInfo?.aliases) : undefined,
|
|
64716
|
-
probe: directProbe
|
|
64717
|
-
}
|
|
64718
|
-
];
|
|
64719
|
-
}
|
|
64720
|
-
return chainDetails.map((c) => ({
|
|
64721
|
-
provider: c.provider,
|
|
64722
|
-
displayName: c.displayName,
|
|
64723
|
-
modelId: c.modelSpec.includes("@") ? c.modelSpec.slice(c.modelSpec.indexOf("@") + 1) : c.modelSpec,
|
|
64724
|
-
hasCredentials: c.hasCredentials,
|
|
64725
|
-
credentialHint: c.credentialHint,
|
|
64726
|
-
probe: c.probe
|
|
65156
|
+
function probeTarget(proxyUrl, target) {
|
|
65157
|
+
return probeLink(proxyUrl, { provider: target.provider, modelSpec: target.probeSpec, hasCredentials: true }, options.timeoutMs).catch((e) => ({
|
|
65158
|
+
state: "error",
|
|
65159
|
+
latencyMs: 0,
|
|
65160
|
+
errorMessage: String(e instanceof Error ? e.message : e)
|
|
64727
65161
|
}));
|
|
64728
65162
|
}
|
|
64729
|
-
|
|
64730
|
-
const
|
|
65163
|
+
function chainProbeOf(probe, wiring) {
|
|
65164
|
+
const exp = probe.explanation;
|
|
65165
|
+
const directProbe = exp.source === "explicit" ? probe.chain[0]?.probe : undefined;
|
|
65166
|
+
return {
|
|
65167
|
+
model: probe.modelInput,
|
|
65168
|
+
nativeProvider: parseModelSpec(probe.modelInput).provider,
|
|
65169
|
+
isExplicit: exp.source === "explicit",
|
|
65170
|
+
routingSource: exp.source,
|
|
65171
|
+
routingExplanation: routingFieldsFrom(exp).routingExplanation,
|
|
65172
|
+
...exp.via ? { via: exp.via } : {},
|
|
65173
|
+
...exp.matchedPattern !== undefined ? { matchedPattern: exp.matchedPattern } : {},
|
|
65174
|
+
...exp.ruleScope ? { ruleScope: exp.ruleScope } : {},
|
|
65175
|
+
...exp.catalog ? { catalog: exp.catalog } : {},
|
|
65176
|
+
...exp.fallbackWithheld ? { fallbackWithheld: exp.fallbackWithheld } : {},
|
|
65177
|
+
outcome: exp.outcome,
|
|
65178
|
+
warnings: exp.warnings,
|
|
65179
|
+
chain: probe.chain,
|
|
65180
|
+
dropped: probe.dropped,
|
|
65181
|
+
...directProbe ? { directProbe } : {},
|
|
65182
|
+
...wiring ? { wiring } : {}
|
|
65183
|
+
};
|
|
65184
|
+
}
|
|
65185
|
+
async function computeWiring(chain, parsedModel) {
|
|
65186
|
+
const firstReadyRoute = chain.find((c) => c.hasCredentials && !c.notProbed);
|
|
64731
65187
|
if (!firstReadyRoute)
|
|
64732
65188
|
return;
|
|
64733
65189
|
const providerName = firstReadyRoute.provider;
|
|
@@ -64808,52 +65264,16 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
64808
65264
|
try {
|
|
64809
65265
|
const results = [];
|
|
64810
65266
|
for (const modelInput of models) {
|
|
64811
|
-
const
|
|
64812
|
-
let directProbeResult;
|
|
64813
|
-
if (liveProxy && chain.source === "direct") {
|
|
64814
|
-
const directKeyInfo = API_KEY_MAP[parsed.provider];
|
|
64815
|
-
const directProviderDef = getProviderByName(parsed.provider);
|
|
64816
|
-
const directHasCreds = await credentialForProbe(parsed.provider);
|
|
64817
|
-
const directCredentialHint = directProviderDef?.isLocal && !directHasCreds ? "enable local provider in global config" : credentialHintFor(parsed.provider, directKeyInfo?.envVar, directKeyInfo?.aliases);
|
|
64818
|
-
directProbeResult = await probeProviderRoute(liveProxy.url, {
|
|
64819
|
-
provider: parsed.provider,
|
|
64820
|
-
modelSpec: modelInput,
|
|
64821
|
-
hasCredentials: directHasCreds,
|
|
64822
|
-
credentialHint: directCredentialHint
|
|
64823
|
-
}, options.timeoutMs).catch((e) => ({
|
|
64824
|
-
state: "error",
|
|
64825
|
-
latencyMs: 0,
|
|
64826
|
-
errorMessage: String(e instanceof Error ? e.message : e)
|
|
64827
|
-
}));
|
|
64828
|
-
}
|
|
65267
|
+
const probe = await explainForProbe(modelInput);
|
|
64829
65268
|
if (liveProxy) {
|
|
64830
|
-
const
|
|
64831
|
-
|
|
64832
|
-
|
|
64833
|
-
|
|
64834
|
-
|
|
64835
|
-
credentialHint: link.credentialHint
|
|
64836
|
-
}, options.timeoutMs).catch((e) => ({
|
|
64837
|
-
state: "error",
|
|
64838
|
-
latencyMs: 0,
|
|
64839
|
-
errorMessage: String(e instanceof Error ? e.message : e)
|
|
64840
|
-
}));
|
|
64841
|
-
}));
|
|
64842
|
-
for (let i = 0;i < chainDetails.length; i++) {
|
|
64843
|
-
chainDetails[i].probe = probes[i];
|
|
64844
|
-
}
|
|
65269
|
+
const url = liveProxy.url;
|
|
65270
|
+
const probes = await Promise.all(probe.targets.map(({ target }) => probeTarget(url, target)));
|
|
65271
|
+
probe.targets.forEach(({ link }, i) => {
|
|
65272
|
+
link.probe = probes[i];
|
|
65273
|
+
});
|
|
64845
65274
|
}
|
|
64846
|
-
const wiring = await computeWiring(
|
|
64847
|
-
results.push(
|
|
64848
|
-
model: modelInput,
|
|
64849
|
-
nativeProvider: parsed.provider,
|
|
64850
|
-
isExplicit: parsed.isExplicitProvider,
|
|
64851
|
-
routingSource: chain.source,
|
|
64852
|
-
matchedPattern: chain.matchedPattern,
|
|
64853
|
-
chain: chainDetails.length > 0 ? chainDetails : buildDirectChainEntry(parsed, directProbeResult),
|
|
64854
|
-
directProbe: directProbeResult,
|
|
64855
|
-
wiring
|
|
64856
|
-
});
|
|
65275
|
+
const wiring = await computeWiring(probe.chain, probe.explanation.routedModel);
|
|
65276
|
+
results.push(chainProbeOf(probe, wiring));
|
|
64857
65277
|
}
|
|
64858
65278
|
console.log(JSON.stringify(results, null, 2));
|
|
64859
65279
|
} finally {
|
|
@@ -64897,9 +65317,6 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
64897
65317
|
};
|
|
64898
65318
|
let liveProxy = null;
|
|
64899
65319
|
try {
|
|
64900
|
-
addStep("Loading routing rules", "running");
|
|
64901
|
-
loadRoutingRules();
|
|
64902
|
-
updateStep("Loading routing rules", "done");
|
|
64903
65320
|
if (options.live) {
|
|
64904
65321
|
addStep("Starting probe proxy", "running");
|
|
64905
65322
|
try {
|
|
@@ -64914,122 +65331,99 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
64914
65331
|
}
|
|
64915
65332
|
}
|
|
64916
65333
|
addStep("Resolving routing chains", "running");
|
|
64917
|
-
const
|
|
65334
|
+
const modelProbes = [];
|
|
64918
65335
|
for (const modelInput of models) {
|
|
64919
|
-
|
|
64920
|
-
modelChains.push({ modelInput, parsed, chain, chainDetails });
|
|
65336
|
+
modelProbes.push(await explainForProbe(modelInput));
|
|
64921
65337
|
}
|
|
64922
65338
|
updateStep("Resolving routing chains", "done");
|
|
64923
|
-
const
|
|
64924
|
-
|
|
64925
|
-
|
|
64926
|
-
|
|
64927
|
-
|
|
64928
|
-
|
|
64929
|
-
|
|
64930
|
-
|
|
64931
|
-
|
|
64932
|
-
|
|
64933
|
-
|
|
64934
|
-
displayName:
|
|
64935
|
-
modelSpec:
|
|
64936
|
-
|
|
64937
|
-
pinnedSpec: modelInput,
|
|
64938
|
-
hasCredentials: directHasCreds,
|
|
64939
|
-
credentialHint: directCredentialHint,
|
|
64940
|
-
chainDetail: null,
|
|
64941
|
-
isDirect: true,
|
|
64942
|
-
modelInput
|
|
65339
|
+
const liveRows = [];
|
|
65340
|
+
const rows = [];
|
|
65341
|
+
for (const probe of modelProbes) {
|
|
65342
|
+
const model = probe.modelInput;
|
|
65343
|
+
probe.targets.forEach(({ target, link }, i) => {
|
|
65344
|
+
const id = `${model}:${i}:${target.provider}`;
|
|
65345
|
+
if (liveProxy) {
|
|
65346
|
+
liveRows.push({ id, target, link });
|
|
65347
|
+
rows.push({
|
|
65348
|
+
id,
|
|
65349
|
+
model,
|
|
65350
|
+
displayName: target.displayName,
|
|
65351
|
+
modelSpec: target.probeSpec,
|
|
65352
|
+
status: "waiting"
|
|
64943
65353
|
});
|
|
64944
|
-
}
|
|
64945
|
-
|
|
64946
|
-
|
|
64947
|
-
|
|
64948
|
-
|
|
64949
|
-
|
|
64950
|
-
|
|
64951
|
-
|
|
64952
|
-
|
|
64953
|
-
hasCredentials: link.hasCredentials,
|
|
64954
|
-
credentialHint: link.credentialHint,
|
|
64955
|
-
chainDetail: link,
|
|
64956
|
-
isDirect: false,
|
|
64957
|
-
modelInput
|
|
65354
|
+
} else {
|
|
65355
|
+
rows.push({
|
|
65356
|
+
id,
|
|
65357
|
+
model,
|
|
65358
|
+
displayName: target.displayName,
|
|
65359
|
+
modelSpec: target.probeSpec,
|
|
65360
|
+
status: "not-probed",
|
|
65361
|
+
tone: "ready",
|
|
65362
|
+
note: `\u25CB ${link.label} \xB7 not probed (--no-probe)`
|
|
64958
65363
|
});
|
|
64959
65364
|
}
|
|
64960
|
-
}
|
|
64961
|
-
|
|
64962
|
-
|
|
64963
|
-
|
|
64964
|
-
|
|
64965
|
-
|
|
64966
|
-
|
|
64967
|
-
|
|
64968
|
-
const probePromises = allLinks.map(async (link) => {
|
|
64969
|
-
updateLink(link.id, { status: "probing", startTime: Date.now() });
|
|
64970
|
-
const result = await probeProviderRoute(liveProxy.url, {
|
|
64971
|
-
provider: link.provider,
|
|
65365
|
+
});
|
|
65366
|
+
for (const link of probe.chain) {
|
|
65367
|
+
if (!link.notProbed)
|
|
65368
|
+
continue;
|
|
65369
|
+
rows.push({
|
|
65370
|
+
id: `${model}:native`,
|
|
65371
|
+
model,
|
|
65372
|
+
displayName: link.displayName,
|
|
64972
65373
|
modelSpec: link.modelSpec,
|
|
64973
|
-
|
|
64974
|
-
|
|
64975
|
-
|
|
64976
|
-
|
|
64977
|
-
|
|
64978
|
-
|
|
64979
|
-
|
|
65374
|
+
status: "not-probed",
|
|
65375
|
+
tone: "native",
|
|
65376
|
+
note: `\u25D0 native \u2014 ${NATIVE_NOT_PROBED}`
|
|
65377
|
+
});
|
|
65378
|
+
}
|
|
65379
|
+
probe.dropped.forEach((entry, i) => {
|
|
65380
|
+
rows.push({
|
|
65381
|
+
id: `${model}:dropped:${i}:${entry.provider}`,
|
|
65382
|
+
model,
|
|
65383
|
+
displayName: entry.displayName,
|
|
65384
|
+
modelSpec: entry.wireId,
|
|
65385
|
+
status: "not-probed",
|
|
65386
|
+
tone: "dropped",
|
|
65387
|
+
note: `\u2013 ${describeDropped(entry.outcome, entry.credentialHint)}`
|
|
65388
|
+
});
|
|
65389
|
+
});
|
|
65390
|
+
}
|
|
65391
|
+
setLinks(rows);
|
|
65392
|
+
if (liveProxy) {
|
|
65393
|
+
const url = liveProxy.url;
|
|
65394
|
+
await Promise.all(liveRows.map(async ({ id, target, link }) => {
|
|
65395
|
+
updateLink(id, { status: "probing", startTime: Date.now() });
|
|
65396
|
+
const result = await probeTarget(url, target);
|
|
64980
65397
|
if (result.state === "live") {
|
|
64981
|
-
updateLink(
|
|
64982
|
-
status: "live",
|
|
64983
|
-
endTime: Date.now(),
|
|
64984
|
-
timing: result.timing
|
|
64985
|
-
});
|
|
65398
|
+
updateLink(id, { status: "live", endTime: Date.now(), timing: result.timing });
|
|
64986
65399
|
} else {
|
|
64987
|
-
updateLink(
|
|
65400
|
+
updateLink(id, {
|
|
64988
65401
|
status: "failed",
|
|
64989
65402
|
endTime: Date.now(),
|
|
64990
65403
|
error: describeProbeState(result)
|
|
64991
65404
|
});
|
|
64992
65405
|
}
|
|
64993
|
-
|
|
64994
|
-
|
|
64995
|
-
} else if (link.chainDetail) {
|
|
64996
|
-
link.chainDetail.probe = result;
|
|
64997
|
-
}
|
|
64998
|
-
});
|
|
64999
|
-
await Promise.all(probePromises);
|
|
65406
|
+
link.probe = result;
|
|
65407
|
+
}));
|
|
65000
65408
|
}
|
|
65001
65409
|
const isLiveProbe = !!liveProxy;
|
|
65002
65410
|
const printable = [];
|
|
65003
65411
|
const results = [];
|
|
65004
|
-
for (const
|
|
65005
|
-
const wiring = await computeWiring(
|
|
65006
|
-
const
|
|
65412
|
+
for (const probe of modelProbes) {
|
|
65413
|
+
const wiring = await computeWiring(probe.chain, probe.explanation.routedModel);
|
|
65414
|
+
const fields = routingFieldsFrom(probe.explanation);
|
|
65007
65415
|
printable.push({
|
|
65008
|
-
model: modelInput,
|
|
65009
|
-
|
|
65010
|
-
|
|
65011
|
-
|
|
65012
|
-
matchedPattern: chain.matchedPattern,
|
|
65013
|
-
chain: chainDetails.map((c) => ({
|
|
65014
|
-
provider: c.provider,
|
|
65015
|
-
displayName: c.displayName,
|
|
65016
|
-
modelSpec: c.modelSpec,
|
|
65017
|
-
hasCredentials: c.hasCredentials,
|
|
65018
|
-
credentialHint: c.credentialHint,
|
|
65019
|
-
provenance: c.provenance,
|
|
65020
|
-
probe: c.probe
|
|
65021
|
-
})),
|
|
65022
|
-
directProbe,
|
|
65416
|
+
model: probe.modelInput,
|
|
65417
|
+
...fields,
|
|
65418
|
+
chain: probe.chain,
|
|
65419
|
+
dropped: probe.dropped,
|
|
65023
65420
|
wiring
|
|
65024
65421
|
});
|
|
65025
65422
|
results.push({
|
|
65026
|
-
model: modelInput,
|
|
65027
|
-
|
|
65028
|
-
|
|
65029
|
-
|
|
65030
|
-
matchedPattern: chain.matchedPattern,
|
|
65031
|
-
routingExplanation: buildRoutingExplanation(parsed, chain),
|
|
65032
|
-
links: buildResultLinks(parsed, chainDetails, directProbe),
|
|
65423
|
+
model: probe.modelInput,
|
|
65424
|
+
isExplicit: probe.explanation.source === "explicit",
|
|
65425
|
+
...fields,
|
|
65426
|
+
links: resultLinksFrom(probe.chain, probe.dropped),
|
|
65033
65427
|
wiring
|
|
65034
65428
|
});
|
|
65035
65429
|
}
|
|
@@ -65064,6 +65458,18 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
65064
65458
|
setStderrQuiet(false);
|
|
65065
65459
|
}
|
|
65066
65460
|
}
|
|
65461
|
+
function providerShortcutRows(providers = BUILTIN_PROVIDERS) {
|
|
65462
|
+
const pickable = providers.filter(isPickableProvider);
|
|
65463
|
+
const ordered = [
|
|
65464
|
+
...pickable.filter((def) => !def.isLocal),
|
|
65465
|
+
...pickable.filter((def) => def.isLocal)
|
|
65466
|
+
];
|
|
65467
|
+
return ordered.map((def) => ({
|
|
65468
|
+
shortcuts: [...def.shortcuts],
|
|
65469
|
+
displayName: def.displayName,
|
|
65470
|
+
kind: def.isLocal ? "local" : def.tier ? TIER_LABEL[def.tier] : ""
|
|
65471
|
+
}));
|
|
65472
|
+
}
|
|
65067
65473
|
function printHelp2() {
|
|
65068
65474
|
const useColor = !!process.stdout.isTTY && !process.env.NO_COLOR;
|
|
65069
65475
|
const A = cliAnsi();
|
|
@@ -65076,6 +65482,12 @@ function printHelp2() {
|
|
|
65076
65482
|
const magenta = c(A.MAGENTA);
|
|
65077
65483
|
const blue = c(A.BLUE);
|
|
65078
65484
|
const h = (title) => bold(cyan(`\u258C ${title}`));
|
|
65485
|
+
const shortcutRows = providerShortcutRows();
|
|
65486
|
+
const shortcutsOf = (row) => row.shortcuts.join(", ");
|
|
65487
|
+
const shortcutWidth = Math.max(...shortcutRows.map((row) => shortcutsOf(row).length));
|
|
65488
|
+
const nameWidth = Math.max(...shortcutRows.map((row) => row.displayName.length));
|
|
65489
|
+
const shortcutTable = shortcutRows.map((row) => ` ${magenta(shortcutsOf(row).padEnd(shortcutWidth))} ${dim("->")} ${row.displayName.padEnd(nameWidth)} ${dim(row.kind)}`).join(`
|
|
65490
|
+
`);
|
|
65079
65491
|
console.log(`
|
|
65080
65492
|
${bold("claudish")} ${dim("\xB7")} Run Claude Code with any AI model
|
|
65081
65493
|
${dim("OpenRouter \xB7 Gemini \xB7 OpenAI \xB7 xAI \xB7 MiniMax \xB7 Kimi \xB7 GLM \xB7 Z.AI \xB7 Sakana \xB7 Poe \xB7 LiteLLM \xB7 Local")}
|
|
@@ -65088,60 +65500,29 @@ ${h("USAGE")}
|
|
|
65088
65500
|
|
|
65089
65501
|
${h("MODEL ROUTING")}
|
|
65090
65502
|
${bold("New syntax:")} ${yellow("provider@model[:concurrency]")}
|
|
65091
|
-
${magenta("google
|
|
65092
|
-
${magenta("openrouter
|
|
65093
|
-
${magenta("oai
|
|
65094
|
-
${magenta("ollama
|
|
65095
|
-
${magenta("ollama
|
|
65096
|
-
|
|
65097
|
-
${bold("Provider shortcuts:")}
|
|
65098
|
-
|
|
65099
|
-
|
|
65100
|
-
|
|
65101
|
-
|
|
65102
|
-
|
|
65103
|
-
|
|
65104
|
-
|
|
65105
|
-
|
|
65106
|
-
${magenta("kc")} ${dim("->")} Kimi Coding ${dim("kc@kimi-k2-thinking-turbo")}
|
|
65107
|
-
${magenta("glm, zhipu")} ${dim("->")} GLM Direct ${dim("glm@glm-4.7")}
|
|
65108
|
-
${magenta("gc")} ${dim("->")} GLM Coding ${dim("gc@glm-4.7")}
|
|
65109
|
-
${magenta("z-ai, zai")} ${dim("->")} Z.AI Direct ${dim("z-ai@glm-4.7")}
|
|
65110
|
-
${magenta("oc, llama, lc, meta")} ${dim("->")} OllamaCloud ${dim("oc@llama-3.1")}
|
|
65111
|
-
${magenta("zen")} ${dim("->")} OpenCode Zen ${dim("zen@grok-code")}
|
|
65112
|
-
${magenta("zengo, zgo")} ${dim("->")} OpenCode Zen Go ${dim("zengo@grok-code")}
|
|
65113
|
-
${magenta("v, vertex")} ${dim("->")} Vertex AI ${dim("v@gemini-2.5-flash")}
|
|
65114
|
-
${magenta("poe")} ${dim("->")} Poe ${dim("poe@GPT-4o")}
|
|
65115
|
-
${magenta("litellm, ll")} ${dim("->")} LiteLLM ${dim("ll@gpt-4o (needs LITELLM_BASE_URL)")}
|
|
65116
|
-
${magenta("ds")} ${dim("->")} DeepSeek ${dim("ds@deepseek-chat")}
|
|
65117
|
-
${magenta("sakana, fugu")} ${dim("->")} Sakana Fugu ${dim("fugu@fugu-ultra")}
|
|
65118
|
-
${magenta("sc")} ${dim("->")} Sakana Subscription ${dim("sc@fugu-ultra")}
|
|
65119
|
-
${magenta("ollama")} ${dim("->")} Ollama (local) ${dim("ollama@llama3.2")}
|
|
65120
|
-
${magenta("lms, lmstudio")} ${dim("->")} LM Studio (local) ${dim("lms@qwen")}
|
|
65121
|
-
${magenta("vllm")} ${dim("->")} vLLM (local) ${dim("vllm@model")}
|
|
65122
|
-
${magenta("mlx")} ${dim("->")} MLX (local) ${dim("mlx@model")}
|
|
65123
|
-
|
|
65124
|
-
${bold("Native auto-detection")} ${dim("(when no provider specified):")}
|
|
65125
|
-
${yellow("google/*, gemini-*")} ${dim("->")} Google API
|
|
65126
|
-
${yellow("openai/*, gpt-*, o1-*")} ${dim("->")} OpenAI API
|
|
65127
|
-
${yellow("x-ai/*, grok-*")} ${dim("->")} xAI
|
|
65128
|
-
${yellow("meta-llama/*, llama-*")} ${dim("->")} OllamaCloud
|
|
65129
|
-
${yellow("minimax/*, abab-*")} ${dim("->")} MiniMax API
|
|
65130
|
-
${yellow("moonshot/*, kimi-*")} ${dim("->")} Kimi API
|
|
65131
|
-
${yellow("zhipu/*, glm-*")} ${dim("->")} GLM API
|
|
65132
|
-
${yellow("sakana/*, fugu-*")} ${dim("->")} Sakana Fugu
|
|
65133
|
-
${yellow("poe:*")} ${dim("->")} Poe
|
|
65134
|
-
${yellow("anthropic/*, claude-*")} ${dim("->")} Native Anthropic
|
|
65135
|
-
${yellow("(unknown vendor/)")} ${dim("->")} Error (use openrouter@vendor/model)
|
|
65136
|
-
|
|
65137
|
-
${dim("A defaultProvider (config / --default-provider) catches bare names that match no rule.")}
|
|
65503
|
+
${magenta("google@<model>")} ${dim("Direct Google API (explicit)")}
|
|
65504
|
+
${magenta("openrouter@<vendor>/<model>")} ${dim("OpenRouter (explicit)")}
|
|
65505
|
+
${magenta("oai@<model>")} ${dim("Direct OpenAI API (shortcut)")}
|
|
65506
|
+
${magenta("ollama@<model>:3")} ${dim("Local Ollama, 3 concurrent requests")}
|
|
65507
|
+
${magenta("ollama@<model>:0")} ${dim("Local Ollama, no limits")}
|
|
65508
|
+
|
|
65509
|
+
${bold("Provider shortcuts:")} ${dim("(<shortcut>@<model>)")}
|
|
65510
|
+
${shortcutTable}
|
|
65511
|
+
|
|
65512
|
+
${bold("Bare names")} are routed from the cloud models catalog: subscriptions first, then the vendor's own
|
|
65513
|
+
API, then gateways, then the fallback. ${green("claudish --probe")} ${yellow("<model>")} shows the chain a request uses.
|
|
65514
|
+
|
|
65515
|
+
${dim("A defaultProvider (--default-provider / CLAUDISH_DEFAULT_PROVIDER / config) is the last hop for")}
|
|
65516
|
+
${dim('bare names that match no rule. "" disables it.')}
|
|
65517
|
+
${dim("Claude Code's own names (opus, sonnet, claude-*) are served on Claude Code's own auth.")}
|
|
65138
65518
|
|
|
65139
65519
|
${h("OPTIONS")}
|
|
65140
65520
|
${green("-i, --interactive")} Run in interactive mode (default when no prompt given)
|
|
65141
65521
|
${green("-m, --model")} ${yellow("<model>")} Model to use (required for single-shot mode)
|
|
65142
65522
|
${green("--profile")} ${yellow("<name>")} Use named profile for model mapping (default profile if omitted)
|
|
65143
|
-
${green("--default-provider")} ${yellow("<name>")} Fallback provider for bare model names (
|
|
65144
|
-
${dim("Precedence: this flag > CLAUDISH_DEFAULT_PROVIDER env > config.json
|
|
65523
|
+
${green("--default-provider")} ${yellow("<name>")} Fallback provider for bare model names (claudish provider or customEndpoints key)
|
|
65524
|
+
${dim('"" disables it. Precedence: this flag > CLAUDISH_DEFAULT_PROVIDER env > config.json')}
|
|
65525
|
+
${dim("(the global config or the --config file; a project .claudish.json is not read)")}
|
|
65145
65526
|
${green("--anthropic-api-billing")} Use your real ANTHROPIC_API_KEY for native Claude models
|
|
65146
65527
|
${dim("(metered API billing). Default: the key is hidden so Claude Code")}
|
|
65147
65528
|
${dim("uses your claude.ai subscription. Env: CLAUDISH_ANTHROPIC_API_BILLING")}
|
|
@@ -65192,9 +65573,9 @@ ${h("MODEL DISCOVERY")}
|
|
|
65192
65573
|
${green("-s, --models-search")} ${yellow("<query>")} Fuzzy search: id, brand synonyms (chatgpt,
|
|
65193
65574
|
${dim("claude, grok), gateways (zen, oc, codex), caps")}
|
|
65194
65575
|
${green("--models-top")} Curated recommended models (flagship + fast)
|
|
65195
|
-
${green("--probe")} ${yellow("<models...>")}
|
|
65576
|
+
${green("--probe")} ${yellow("<models...>")} Show each model's routing chain and send each hop
|
|
65196
65577
|
${dim("a real 1-token request (may incur tiny cost)")}
|
|
65197
|
-
${green("--no-probe")}
|
|
65578
|
+
${green("--no-probe")} Show the routing chain without the 1-token requests
|
|
65198
65579
|
${green("--probe-timeout")} ${yellow("<secs>")} Per-link timeout for live probes (default: 40)
|
|
65199
65580
|
${green("--models-refresh")} Force refresh the slim model catalog from Firebase
|
|
65200
65581
|
${green("--models-skip-update")} Skip the launcher catalog warm step (offline)
|
|
@@ -65202,7 +65583,7 @@ ${h("MODEL DISCOVERY")}
|
|
|
65202
65583
|
|
|
65203
65584
|
${h("TEAM MODE")}
|
|
65204
65585
|
${green("--team")} ${yellow("<models>")} Run multiple models in parallel (comma-separated)
|
|
65205
|
-
${dim('Example: --team
|
|
65586
|
+
${dim('Example: --team <model>,<model> "prompt"')}
|
|
65206
65587
|
${green("--mode")} ${yellow("<mode>")} Team mode: default (grid), interactive, json
|
|
65207
65588
|
${green("-f, --file")} ${yellow("<path>")} Read prompt from file (use with --team or single-shot)
|
|
65208
65589
|
|
|
@@ -65240,7 +65621,7 @@ ${h("1PASSWORD")} ${dim("(SDK-based \u2014 no op CLI needed for secrets)")}
|
|
|
65240
65621
|
${green("--op")} ${yellow("<glob> --list")} Preview which fields a glob would import (names only)
|
|
65241
65622
|
${green("--op")} ${yellow("<glob>")} ${yellow("[...args]")} Resolve a glob into env vars, then run a session
|
|
65242
65623
|
${dim("Inline op import requires a GLOB (self-names via field labels)")}
|
|
65243
|
-
${dim('Example: claudish --op "op://Jack/Keys/**" --model
|
|
65624
|
+
${dim('Example: claudish --op "op://Jack/Keys/**" --model <model> "task"')}
|
|
65244
65625
|
${green("--op-env")} ${yellow("<id>")} Load a 1Password Environment (highest-priority source)
|
|
65245
65626
|
${dim("Persistent setup (single refs, sets, environments, account): claudish config -> 1Password tab")}
|
|
65246
65627
|
|
|
@@ -65257,17 +65638,17 @@ ${h("MACOS KEYCHAIN")} ${dim("(local, encrypted at rest, no desktop-app handshak
|
|
|
65257
65638
|
|
|
65258
65639
|
${h("CLAUDE CODE FLAG PASSTHROUGH")}
|
|
65259
65640
|
${dim("Any unrecognized flag is forwarded to Claude Code. Claudish flags can appear in any order.")}
|
|
65260
|
-
${green("claudish")} --model
|
|
65261
|
-
${green("claudish")} --model
|
|
65262
|
-
${green("claudish")} --model
|
|
65641
|
+
${green("claudish")} --model ${yellow("<model>")} ${yellow("--agent test")} ${yellow('"task"')} ${dim("# --agent passes through")}
|
|
65642
|
+
${green("claudish")} --model ${yellow("<model>")} ${yellow("--effort high")} --stdin ${yellow('"task"')} ${dim("# --effort passes, --stdin stays")}
|
|
65643
|
+
${green("claudish")} --model ${yellow("<model>")} ${yellow("--permission-mode plan")} -i ${dim("# works in interactive too")}
|
|
65263
65644
|
${dim("Use -- when a Claude Code flag value starts with '-':")}
|
|
65264
|
-
${green("claudish")} --model
|
|
65645
|
+
${green("claudish")} --model ${yellow("<model>")} ${green("--")} ${yellow('--system-prompt "-verbose mode" "task"')}
|
|
65265
65646
|
|
|
65266
65647
|
${h("CUSTOM MODELS & ENDPOINTS")}
|
|
65267
|
-
${dim("
|
|
65268
|
-
${green("claudish")} --model ${yellow("openrouter
|
|
65648
|
+
${dim("An explicit provider@ takes any model id, including one --models does not list:")}
|
|
65649
|
+
${green("claudish")} --model ${yellow("openrouter@<vendor>/<model>")} ${yellow('"task"')}
|
|
65269
65650
|
${dim("Named custom endpoints live in ~/.claudish/config.json under 'customEndpoints' and route via @:")}
|
|
65270
|
-
${green("claudish")} --model ${yellow("my-vllm
|
|
65651
|
+
${green("claudish")} --model ${yellow("my-vllm@<model>")} ${yellow('"task"')}
|
|
65271
65652
|
|
|
65272
65653
|
${h("MODES")}
|
|
65273
65654
|
${green("\u2022")} ${bold("Interactive")} ${dim("(default):")} shows model selector, starts a persistent session
|
|
@@ -65330,8 +65711,8 @@ ${h("ENVIRONMENT VARIABLES")}
|
|
|
65330
65711
|
${blue("MLX_BASE_URL")} MLX server ${dim("(default: http://127.0.0.1:8080)")}
|
|
65331
65712
|
|
|
65332
65713
|
${bold("Claudish settings:")}
|
|
65333
|
-
${blue("CLAUDISH_MODEL")} Default model ${dim("(
|
|
65334
|
-
${blue("CLAUDISH_DEFAULT_PROVIDER")} Fallback provider for bare names ${dim("(see --default-provider)")}
|
|
65714
|
+
${blue("CLAUDISH_MODEL")} Default model ${dim("(--model overrides it; ANTHROPIC_MODEL is read when unset)")}
|
|
65715
|
+
${blue("CLAUDISH_DEFAULT_PROVIDER")} Fallback provider for bare names; empty disables it ${dim("(see --default-provider)")}
|
|
65335
65716
|
${blue("CLAUDISH_PORT")} Default proxy port
|
|
65336
65717
|
${blue("CLAUDISH_CONTEXT_WINDOW")} Override context window size
|
|
65337
65718
|
${blue("CLAUDISH_DIAG_MODE")} Diagnostic output: auto / logfile / off
|
|
@@ -65354,24 +65735,24 @@ ${h("EXAMPLES")}
|
|
|
65354
65735
|
${green("claudish")} --free ${dim("# only FREE models")}
|
|
65355
65736
|
|
|
65356
65737
|
${dim("# Explicit provider routing")}
|
|
65357
|
-
${green("claudish")} --model ${magenta("google
|
|
65358
|
-
${green("claudish")} --model ${magenta("oai
|
|
65359
|
-
${green("claudish")} --model ${magenta("openrouter
|
|
65738
|
+
${green("claudish")} --model ${magenta("google@<model>")} ${yellow('"implement auth"')}
|
|
65739
|
+
${green("claudish")} --model ${magenta("oai@<model>")} ${yellow('"add tests for login"')}
|
|
65740
|
+
${green("claudish")} --model ${magenta("openrouter@<vendor>/<model>")} ${yellow('"any vendor via OpenRouter"')}
|
|
65360
65741
|
|
|
65361
|
-
${dim("#
|
|
65362
|
-
${green("claudish")} --
|
|
65363
|
-
${green("claudish")} --model ${yellow("
|
|
65742
|
+
${dim("# Bare name: routed from the cloud models catalog")}
|
|
65743
|
+
${green("claudish")} --probe ${yellow("<model>")} ${dim("# show the chain it gets")}
|
|
65744
|
+
${green("claudish")} --model ${yellow("<model>")} ${yellow('"implement auth"')}
|
|
65364
65745
|
|
|
65365
65746
|
${dim("# Per-role model mapping")}
|
|
65366
|
-
${green("claudish")} --model-opus ${magenta("oai
|
|
65747
|
+
${green("claudish")} --model-opus ${magenta("oai@<model>")} --model-sonnet ${magenta("google@<model>")}
|
|
65367
65748
|
|
|
65368
65749
|
${dim("# stdin for large prompts (diffs, code review)")}
|
|
65369
|
-
${dim("git diff |")} ${green("claudish")} --stdin --model ${magenta("oai
|
|
65750
|
+
${dim("git diff |")} ${green("claudish")} --stdin --model ${magenta("oai@<model>")} ${yellow('"Review these changes"')}
|
|
65370
65751
|
|
|
65371
65752
|
${dim("# Local models with concurrency control")}
|
|
65372
|
-
${green("claudish")} --model ${magenta("ollama
|
|
65373
|
-
${green("claudish")} --model ${magenta("lms
|
|
65374
|
-
${green("claudish")} --model ${yellow('"http://localhost:8000
|
|
65753
|
+
${green("claudish")} --model ${magenta("ollama@<model>:3")} ${yellow('"3 concurrent requests"')}
|
|
65754
|
+
${green("claudish")} --model ${magenta("lms@<model>")} ${yellow('"LM Studio shortcut"')}
|
|
65755
|
+
${green("claudish")} --model ${yellow('"http://localhost:8000/<model>"')} ${yellow('"any OpenAI-compatible URL"')}
|
|
65375
65756
|
|
|
65376
65757
|
${dim("# Autonomous (no prompts, no sandbox) \u2014 use with caution")}
|
|
65377
65758
|
${green("claudish")} -y --dangerous ${yellow('"refactor entire codebase"')}
|
|
@@ -65492,19 +65873,21 @@ var init_cli = __esm(() => {
|
|
|
65492
65873
|
init_logger();
|
|
65493
65874
|
init_model_loader();
|
|
65494
65875
|
init_model_selector();
|
|
65876
|
+
init_probe_chain();
|
|
65495
65877
|
init_probe_results_printer();
|
|
65496
65878
|
init_probe_tui_runtime();
|
|
65497
65879
|
init_profile_config();
|
|
65498
65880
|
init_api_key_map();
|
|
65499
65881
|
init_api_key_provenance();
|
|
65500
|
-
init_catalog_client();
|
|
65501
65882
|
init_claude_code_aliases();
|
|
65502
65883
|
init_endpoint_registration();
|
|
65503
65884
|
init_model_parser();
|
|
65885
|
+
init_native_route();
|
|
65504
65886
|
init_probe_live();
|
|
65505
65887
|
init_probe_runner();
|
|
65506
65888
|
init_provider_definitions();
|
|
65507
65889
|
init_provider_slug_resolve();
|
|
65890
|
+
init_route_candidates();
|
|
65508
65891
|
init_routing_rules();
|
|
65509
65892
|
init_settings();
|
|
65510
65893
|
init_ansi();
|
|
@@ -67929,7 +68312,7 @@ function ProfileDetail({ config, profileIndex }) {
|
|
|
67929
68312
|
}),
|
|
67930
68313
|
/* @__PURE__ */ jsx20("span", {
|
|
67931
68314
|
fg: C.dim,
|
|
67932
|
-
children: " \u2014
|
|
68315
|
+
children: " \u2014 calculated per model \xB7 Routing \u2192 p shows the chain"
|
|
67933
68316
|
}),
|
|
67934
68317
|
/* @__PURE__ */ jsx20("span", {
|
|
67935
68318
|
fg: C.yellow,
|
|
@@ -68396,7 +68779,7 @@ function ProfilesContent({
|
|
|
68396
68779
|
}),
|
|
68397
68780
|
/* @__PURE__ */ jsx21("span", {
|
|
68398
68781
|
fg: C.fgMuted,
|
|
68399
|
-
children: "\u2014
|
|
68782
|
+
children: "\u2014 calculated per model (Routing \u2192 p) \xB7 "
|
|
68400
68783
|
}),
|
|
68401
68784
|
/* @__PURE__ */ jsxs17("span", {
|
|
68402
68785
|
fg: C.green,
|
|
@@ -69244,14 +69627,158 @@ function deriveProbeOutcome(mode, results) {
|
|
|
69244
69627
|
// src/tui/components/RoutingContent.tsx
|
|
69245
69628
|
import { useEffect as useEffect10, useRef as useRef7 } from "react";
|
|
69246
69629
|
import { jsx as jsx24, jsxs as jsxs20, Fragment as Fragment14 } from "@opentui/react/jsx-runtime";
|
|
69630
|
+
function rowStatusView(entry) {
|
|
69631
|
+
switch (entry.status) {
|
|
69632
|
+
case "unverified":
|
|
69633
|
+
return { icon: "\u25D0", color: C.cyan, text: "native \u2014 not probed" };
|
|
69634
|
+
case "success":
|
|
69635
|
+
return {
|
|
69636
|
+
icon: "\u25CF",
|
|
69637
|
+
color: C.green,
|
|
69638
|
+
text: entry.ms !== undefined ? `${entry.ms}ms` : "success"
|
|
69639
|
+
};
|
|
69640
|
+
case "failed":
|
|
69641
|
+
return { icon: "\u2717", color: C.red, text: entry.error ?? "failed" };
|
|
69642
|
+
case "testing":
|
|
69643
|
+
return { icon: "\u25CC", color: C.yellow, text: "testing..." };
|
|
69644
|
+
case "dropped":
|
|
69645
|
+
return {
|
|
69646
|
+
icon: "\u25CB",
|
|
69647
|
+
color: entry.outcome === "credential-unreadable" ? C.yellow : C.dim,
|
|
69648
|
+
text: entry.outcome ? `dropped \xB7 ${DROPPED_TEXT[entry.outcome]}` : "dropped"
|
|
69649
|
+
};
|
|
69650
|
+
case "skipped":
|
|
69651
|
+
return { icon: "\xB7", color: C.dim, text: "not reached" };
|
|
69652
|
+
case "no_key":
|
|
69653
|
+
return { icon: "\u25CB", color: C.dim, text: "not configured, skipping" };
|
|
69654
|
+
case "pending":
|
|
69655
|
+
return { icon: "\u25CB", color: C.dim, text: "waiting" };
|
|
69656
|
+
}
|
|
69657
|
+
}
|
|
69658
|
+
function hintLines(hint) {
|
|
69659
|
+
if (!hint)
|
|
69660
|
+
return [];
|
|
69661
|
+
return hint.split(`
|
|
69662
|
+
`).filter((text) => text.trim().length > 0).map((text, n) => ({ id: `hint-${n}`, text }));
|
|
69663
|
+
}
|
|
69247
69664
|
function chainStr(chain) {
|
|
69248
69665
|
return chain.join(" \u2192 ");
|
|
69249
69666
|
}
|
|
69667
|
+
function ruleChainCell(chain, selected) {
|
|
69668
|
+
if (chain.length === 0)
|
|
69669
|
+
return { text: "no route", fg: C.yellow };
|
|
69670
|
+
return { text: chainStr(chain), fg: selected ? C.cyan : C.fgMuted };
|
|
69671
|
+
}
|
|
69672
|
+
function routingHeaderLines({
|
|
69673
|
+
globalRules,
|
|
69674
|
+
localRules,
|
|
69675
|
+
resolved
|
|
69676
|
+
}) {
|
|
69677
|
+
const catchAll = { ...globalRules, ...localRules }["*"];
|
|
69678
|
+
if (Array.isArray(catchAll)) {
|
|
69679
|
+
const scope = Object.hasOwn(localRules, "*") ? "project" : "global";
|
|
69680
|
+
return [
|
|
69681
|
+
[
|
|
69682
|
+
{ text: ' "*" rule:', tone: "title" },
|
|
69683
|
+
{ text: " decides every model no other rule matches", tone: "muted" }
|
|
69684
|
+
],
|
|
69685
|
+
[
|
|
69686
|
+
{ text: " \u2192 ", tone: "dim" },
|
|
69687
|
+
catchAll.length > 0 ? { text: chainStr(catchAll), tone: "value" } : { text: "no route", tone: "warn" },
|
|
69688
|
+
{ text: ` (${scope})`, tone: "muted" }
|
|
69689
|
+
],
|
|
69690
|
+
[{ text: " The catalog and the fallback hop are not used.", tone: "dim" }]
|
|
69691
|
+
];
|
|
69692
|
+
}
|
|
69693
|
+
return fallbackHopLines(resolved);
|
|
69694
|
+
}
|
|
69695
|
+
function fallbackHopLines(resolved) {
|
|
69696
|
+
const source = ` (${FALLBACK_SOURCE_LABEL[resolved.source]})`;
|
|
69697
|
+
const note = [
|
|
69698
|
+
{
|
|
69699
|
+
text: " --default-provider overrides this for one run and the sessions it starts.",
|
|
69700
|
+
tone: "dim"
|
|
69701
|
+
}
|
|
69702
|
+
];
|
|
69703
|
+
if (resolved.provider === "") {
|
|
69704
|
+
return [
|
|
69705
|
+
[
|
|
69706
|
+
{ text: " Fallback hop:", tone: "title" },
|
|
69707
|
+
{ text: " (none \u2014 a model the catalog maps to no provider gets no route)", tone: "muted" }
|
|
69708
|
+
],
|
|
69709
|
+
[
|
|
69710
|
+
{ text: " \u2192 ", tone: "dim" },
|
|
69711
|
+
{ text: "disabled", tone: "warn" },
|
|
69712
|
+
{ text: `, set to ""${source}`, tone: "muted" }
|
|
69713
|
+
],
|
|
69714
|
+
note
|
|
69715
|
+
];
|
|
69716
|
+
}
|
|
69717
|
+
return [
|
|
69718
|
+
[
|
|
69719
|
+
{ text: " Fallback hop:", tone: "title" },
|
|
69720
|
+
{ text: " (tried last, after every provider the catalog maps)", tone: "muted" }
|
|
69721
|
+
],
|
|
69722
|
+
[
|
|
69723
|
+
{ text: " \u2192 ", tone: "dim" },
|
|
69724
|
+
{ text: resolved.provider, tone: "value" },
|
|
69725
|
+
{ text: source, tone: "muted" }
|
|
69726
|
+
],
|
|
69727
|
+
note
|
|
69728
|
+
];
|
|
69729
|
+
}
|
|
69730
|
+
function resolveFallbackHop(config, env = process.env) {
|
|
69731
|
+
return resolveDefaultProvider({ config, env });
|
|
69732
|
+
}
|
|
69733
|
+
function toneColor(tone) {
|
|
69734
|
+
switch (tone) {
|
|
69735
|
+
case "title":
|
|
69736
|
+
return C.blue;
|
|
69737
|
+
case "value":
|
|
69738
|
+
return C.cyan;
|
|
69739
|
+
case "warn":
|
|
69740
|
+
return C.yellow;
|
|
69741
|
+
case "muted":
|
|
69742
|
+
return C.fgMuted;
|
|
69743
|
+
case "dim":
|
|
69744
|
+
return C.dim;
|
|
69745
|
+
}
|
|
69746
|
+
}
|
|
69747
|
+
function rulesOfScope(mergedRules, scope) {
|
|
69748
|
+
return Object.fromEntries(mergedRules.filter((rule) => rule.kind === scope).map((rule) => [rule.pattern, rule.chain]));
|
|
69749
|
+
}
|
|
69750
|
+
function hopLabel2(entry) {
|
|
69751
|
+
if (entry.status === "unverified")
|
|
69752
|
+
return NATIVE_HOP_LABEL;
|
|
69753
|
+
return hopLabel(entry);
|
|
69754
|
+
}
|
|
69755
|
+
function hopLabelColor(entry) {
|
|
69756
|
+
if (entry.status === "dropped")
|
|
69757
|
+
return C.dim;
|
|
69758
|
+
if (entry.status === "unverified")
|
|
69759
|
+
return C.cyan;
|
|
69760
|
+
if (entry.position === "fallback")
|
|
69761
|
+
return C.yellow;
|
|
69762
|
+
switch (entry.tier) {
|
|
69763
|
+
case "subscription":
|
|
69764
|
+
case "dynamic-subscription":
|
|
69765
|
+
return C.green;
|
|
69766
|
+
case "native":
|
|
69767
|
+
return C.cyan;
|
|
69768
|
+
case "gateway":
|
|
69769
|
+
return C.blue;
|
|
69770
|
+
case "fallback":
|
|
69771
|
+
return C.yellow;
|
|
69772
|
+
default:
|
|
69773
|
+
return C.dim;
|
|
69774
|
+
}
|
|
69775
|
+
}
|
|
69250
69776
|
function RoutingContent({
|
|
69251
69777
|
config,
|
|
69252
69778
|
probeMode,
|
|
69253
69779
|
probeModel,
|
|
69254
69780
|
probeResults,
|
|
69781
|
+
probeSummary,
|
|
69255
69782
|
mode,
|
|
69256
69783
|
routingPattern,
|
|
69257
69784
|
chainSelected,
|
|
@@ -69347,23 +69874,20 @@ function RoutingContent({
|
|
|
69347
69874
|
}),
|
|
69348
69875
|
/* @__PURE__ */ jsx24("text", {
|
|
69349
69876
|
children: /* @__PURE__ */ jsx24("span", {
|
|
69350
|
-
fg: C.
|
|
69351
|
-
children: "
|
|
69877
|
+
fg: C.fgMuted,
|
|
69878
|
+
children: "The probe shows the routing chain a request would use, then tests"
|
|
69352
69879
|
})
|
|
69353
69880
|
}),
|
|
69354
|
-
/* @__PURE__ */ jsx24("text", {
|
|
69355
|
-
children: " "
|
|
69356
|
-
}),
|
|
69357
69881
|
/* @__PURE__ */ jsx24("text", {
|
|
69358
69882
|
children: /* @__PURE__ */ jsx24("span", {
|
|
69359
69883
|
fg: C.fgMuted,
|
|
69360
|
-
children: "
|
|
69884
|
+
children: "each kept hop in order, stopping at the first success. Dropped"
|
|
69361
69885
|
})
|
|
69362
69886
|
}),
|
|
69363
69887
|
/* @__PURE__ */ jsx24("text", {
|
|
69364
69888
|
children: /* @__PURE__ */ jsx24("span", {
|
|
69365
69889
|
fg: C.fgMuted,
|
|
69366
|
-
children: "
|
|
69890
|
+
children: "candidates are listed with the reason, never tested."
|
|
69367
69891
|
})
|
|
69368
69892
|
})
|
|
69369
69893
|
]
|
|
@@ -69426,21 +69950,30 @@ function RoutingContent({
|
|
|
69426
69950
|
/* @__PURE__ */ jsx24("text", {
|
|
69427
69951
|
children: /* @__PURE__ */ jsx24("span", {
|
|
69428
69952
|
fg: C.fgMuted,
|
|
69429
|
-
children:
|
|
69953
|
+
children: probeSummary?.line ?? ""
|
|
69430
69954
|
})
|
|
69431
69955
|
}),
|
|
69956
|
+
probeSummary?.warnings.map((warning) => /* @__PURE__ */ jsx24("text", {
|
|
69957
|
+
children: /* @__PURE__ */ jsx24("span", {
|
|
69958
|
+
fg: C.yellow,
|
|
69959
|
+
children: `! ${warning}`
|
|
69960
|
+
})
|
|
69961
|
+
}, `warning:${warning}`)),
|
|
69962
|
+
probeSummary?.notes.map((note) => /* @__PURE__ */ jsx24("text", {
|
|
69963
|
+
children: /* @__PURE__ */ jsx24("span", {
|
|
69964
|
+
fg: C.dim,
|
|
69965
|
+
children: note
|
|
69966
|
+
})
|
|
69967
|
+
}, `note:${note}`)),
|
|
69432
69968
|
/* @__PURE__ */ jsx24("text", {
|
|
69433
69969
|
children: " "
|
|
69434
69970
|
}),
|
|
69435
69971
|
probeResults.map((entry, idx) => {
|
|
69436
|
-
const
|
|
69972
|
+
const isDropped = entry.status === "dropped";
|
|
69437
69973
|
const isNotReached = entry.status === "skipped";
|
|
69438
69974
|
const isSelected = entry.status === "success" && probeMode === "done";
|
|
69439
|
-
const
|
|
69440
|
-
const statusColor = entry.status === "unverified" ? C.cyan : entry.status === "success" ? C.green : entry.status === "failed" ? C.red : entry.status === "testing" ? C.yellow : C.dim;
|
|
69975
|
+
const status = rowStatusView(entry);
|
|
69441
69976
|
const nameCol = entry.displayName.padEnd(18).substring(0, 18);
|
|
69442
|
-
const statusText = entry.status === "unverified" ? "native \u2014 not probed" : entry.status === "success" ? entry.ms !== undefined ? `${entry.ms}ms` : "success" : entry.status === "failed" ? entry.error ?? "failed" : entry.status === "testing" ? "testing..." : isNoKey ? "not configured, skipping" : isNotReached ? "not reached" : "waiting";
|
|
69443
|
-
const reason = PROVIDER_REASONS[entry.provider] ?? entry.provider;
|
|
69444
69977
|
return /* @__PURE__ */ jsxs20("box", {
|
|
69445
69978
|
flexDirection: "column",
|
|
69446
69979
|
children: [
|
|
@@ -69451,7 +69984,7 @@ function RoutingContent({
|
|
|
69451
69984
|
children: `${idx + 1}. `
|
|
69452
69985
|
}),
|
|
69453
69986
|
/* @__PURE__ */ jsx24("span", {
|
|
69454
|
-
fg:
|
|
69987
|
+
fg: isDropped || isNotReached ? C.dim : isSelected ? C.strong : C.fgMuted,
|
|
69455
69988
|
attributes: A.boldIf(isSelected),
|
|
69456
69989
|
children: nameCol
|
|
69457
69990
|
}),
|
|
@@ -69460,12 +69993,12 @@ function RoutingContent({
|
|
|
69460
69993
|
children: " "
|
|
69461
69994
|
}),
|
|
69462
69995
|
/* @__PURE__ */ jsxs20("span", {
|
|
69463
|
-
fg:
|
|
69996
|
+
fg: status.color,
|
|
69464
69997
|
attributes: A.boldIf(entry.status === "success"),
|
|
69465
69998
|
children: [
|
|
69466
|
-
|
|
69999
|
+
status.icon,
|
|
69467
70000
|
" ",
|
|
69468
|
-
|
|
70001
|
+
status.text
|
|
69469
70002
|
]
|
|
69470
70003
|
}),
|
|
69471
70004
|
isSelected && /* @__PURE__ */ jsx24("span", {
|
|
@@ -69482,13 +70015,21 @@ function RoutingContent({
|
|
|
69482
70015
|
children: " \u21B3 "
|
|
69483
70016
|
}),
|
|
69484
70017
|
/* @__PURE__ */ jsx24("span", {
|
|
69485
|
-
fg:
|
|
69486
|
-
children:
|
|
70018
|
+
fg: isDropped ? C.dim : C.fgMuted,
|
|
70019
|
+
children: entry.displayName
|
|
70020
|
+
}),
|
|
70021
|
+
/* @__PURE__ */ jsx24("span", {
|
|
70022
|
+
fg: C.dim,
|
|
70023
|
+
children: " \xB7 "
|
|
70024
|
+
}),
|
|
70025
|
+
/* @__PURE__ */ jsx24("span", {
|
|
70026
|
+
fg: hopLabelColor(entry),
|
|
70027
|
+
children: hopLabel2(entry)
|
|
69487
70028
|
})
|
|
69488
70029
|
]
|
|
69489
70030
|
})
|
|
69490
70031
|
]
|
|
69491
|
-
}, entry.provider);
|
|
70032
|
+
}, `${idx}:${entry.provider}`);
|
|
69492
70033
|
}),
|
|
69493
70034
|
probeMode === "done" && /* @__PURE__ */ jsxs20(Fragment14, {
|
|
69494
70035
|
children: [
|
|
@@ -69496,7 +70037,19 @@ function RoutingContent({
|
|
|
69496
70037
|
children: " "
|
|
69497
70038
|
}),
|
|
69498
70039
|
/* @__PURE__ */ jsx24("text", {
|
|
69499
|
-
children:
|
|
70040
|
+
children: probeSummary?.noRoute ? /* @__PURE__ */ jsxs20(Fragment14, {
|
|
70041
|
+
children: [
|
|
70042
|
+
/* @__PURE__ */ jsx24("span", {
|
|
70043
|
+
fg: C.red,
|
|
70044
|
+
attributes: A.bold,
|
|
70045
|
+
children: "Result: "
|
|
70046
|
+
}),
|
|
70047
|
+
/* @__PURE__ */ jsx24("span", {
|
|
70048
|
+
fg: C.red,
|
|
70049
|
+
children: `\u2717 No route \u2014 ${probeSummary.noRoute.reason}`
|
|
70050
|
+
})
|
|
70051
|
+
]
|
|
70052
|
+
}) : allFailed ? /* @__PURE__ */ jsxs20(Fragment14, {
|
|
69500
70053
|
children: [
|
|
69501
70054
|
/* @__PURE__ */ jsx24("span", {
|
|
69502
70055
|
fg: C.red,
|
|
@@ -69542,7 +70095,13 @@ function RoutingContent({
|
|
|
69542
70095
|
})
|
|
69543
70096
|
]
|
|
69544
70097
|
})
|
|
69545
|
-
})
|
|
70098
|
+
}),
|
|
70099
|
+
hintLines(probeSummary?.noRoute?.hint).map((line) => /* @__PURE__ */ jsx24("text", {
|
|
70100
|
+
children: /* @__PURE__ */ jsx24("span", {
|
|
70101
|
+
fg: C.dim,
|
|
70102
|
+
children: ` ${line.text}`
|
|
70103
|
+
})
|
|
70104
|
+
}, line.id))
|
|
69546
70105
|
]
|
|
69547
70106
|
})
|
|
69548
70107
|
]
|
|
@@ -69557,61 +70116,18 @@ function RoutingContent({
|
|
|
69557
70116
|
flexDirection: "column",
|
|
69558
70117
|
paddingX: 1,
|
|
69559
70118
|
children: [
|
|
69560
|
-
|
|
70119
|
+
routingHeaderLines({
|
|
70120
|
+
globalRules: rulesOfScope(mergedRules, "global"),
|
|
70121
|
+
localRules: rulesOfScope(mergedRules, "project"),
|
|
70122
|
+
resolved: resolveFallbackHop(config)
|
|
70123
|
+
}).map((line) => /* @__PURE__ */ jsx24("text", {
|
|
69561
70124
|
height: 1,
|
|
69562
|
-
children:
|
|
69563
|
-
|
|
69564
|
-
|
|
69565
|
-
|
|
69566
|
-
|
|
69567
|
-
|
|
69568
|
-
/* @__PURE__ */ jsx24("span", {
|
|
69569
|
-
fg: C.fgMuted,
|
|
69570
|
-
children: " (tried last, after every provider the catalog maps)"
|
|
69571
|
-
})
|
|
69572
|
-
]
|
|
69573
|
-
}),
|
|
69574
|
-
/* @__PURE__ */ jsx24("text", {
|
|
69575
|
-
height: 1,
|
|
69576
|
-
children: (() => {
|
|
69577
|
-
const configured = config.defaultProvider;
|
|
69578
|
-
if (configured !== undefined && configured.length === 0) {
|
|
69579
|
-
return /* @__PURE__ */ jsxs20(Fragment14, {
|
|
69580
|
-
children: [
|
|
69581
|
-
/* @__PURE__ */ jsx24("span", {
|
|
69582
|
-
fg: C.dim,
|
|
69583
|
-
children: " \u2192 "
|
|
69584
|
-
}),
|
|
69585
|
-
/* @__PURE__ */ jsx24("span", {
|
|
69586
|
-
fg: C.yellow,
|
|
69587
|
-
children: "disabled"
|
|
69588
|
-
}),
|
|
69589
|
-
/* @__PURE__ */ jsx24("span", {
|
|
69590
|
-
fg: C.fgMuted,
|
|
69591
|
-
children: " (defaultProvider is empty \u2014 an unroutable model errors instead)"
|
|
69592
|
-
})
|
|
69593
|
-
]
|
|
69594
|
-
});
|
|
69595
|
-
}
|
|
69596
|
-
const hasOverride = configured !== undefined && configured.length > 0;
|
|
69597
|
-
return /* @__PURE__ */ jsxs20(Fragment14, {
|
|
69598
|
-
children: [
|
|
69599
|
-
/* @__PURE__ */ jsx24("span", {
|
|
69600
|
-
fg: C.dim,
|
|
69601
|
-
children: " \u2192 "
|
|
69602
|
-
}),
|
|
69603
|
-
/* @__PURE__ */ jsx24("span", {
|
|
69604
|
-
fg: C.cyan,
|
|
69605
|
-
children: hasOverride ? configured : DEFAULT_FALLBACK_PROVIDER
|
|
69606
|
-
}),
|
|
69607
|
-
/* @__PURE__ */ jsx24("span", {
|
|
69608
|
-
fg: C.fgMuted,
|
|
69609
|
-
children: hasOverride ? " (defaultProvider)" : " (default \u2014 set defaultProvider to change)"
|
|
69610
|
-
})
|
|
69611
|
-
]
|
|
69612
|
-
});
|
|
69613
|
-
})()
|
|
69614
|
-
}),
|
|
70125
|
+
children: line.map((segment) => /* @__PURE__ */ jsx24("span", {
|
|
70126
|
+
fg: toneColor(segment.tone),
|
|
70127
|
+
attributes: A.boldIf(segment.tone === "title"),
|
|
70128
|
+
children: segment.text
|
|
70129
|
+
}, `${segment.tone}:${segment.text}`))
|
|
70130
|
+
}, line.map((segment) => segment.text).join(""))),
|
|
69615
70131
|
/* @__PURE__ */ jsx24("text", {
|
|
69616
70132
|
height: 1,
|
|
69617
70133
|
children: /* @__PURE__ */ jsx24("span", {
|
|
@@ -69726,7 +70242,7 @@ function RoutingContent({
|
|
|
69726
70242
|
const scopeText = isProject ? "project " : "global ";
|
|
69727
70243
|
const scopeFg = isProject ? C.cyan : C.green;
|
|
69728
70244
|
const patFg = sel ? C.strong : C.cyan;
|
|
69729
|
-
const
|
|
70245
|
+
const chainCell = ruleChainCell(rule.chain, sel);
|
|
69730
70246
|
return /* @__PURE__ */ jsx24("box", {
|
|
69731
70247
|
height: 1,
|
|
69732
70248
|
flexDirection: "row",
|
|
@@ -69748,8 +70264,8 @@ function RoutingContent({
|
|
|
69748
70264
|
children: scopeText
|
|
69749
70265
|
}),
|
|
69750
70266
|
/* @__PURE__ */ jsx24("span", {
|
|
69751
|
-
fg:
|
|
69752
|
-
children:
|
|
70267
|
+
fg: chainCell.fg,
|
|
70268
|
+
children: chainCell.text
|
|
69753
70269
|
})
|
|
69754
70270
|
]
|
|
69755
70271
|
})
|
|
@@ -70055,32 +70571,24 @@ function RoutingContent({
|
|
|
70055
70571
|
]
|
|
70056
70572
|
});
|
|
70057
70573
|
}
|
|
70058
|
-
var
|
|
70574
|
+
var DROPPED_TEXT, FALLBACK_SOURCE_LABEL, NATIVE_HOP_LABEL = "Claude Code's own auth";
|
|
70059
70575
|
var init_RoutingContent = __esm(() => {
|
|
70060
70576
|
init_routing_rules();
|
|
70061
70577
|
init_constants3();
|
|
70062
70578
|
init_providers();
|
|
70063
70579
|
init_theme2();
|
|
70064
|
-
|
|
70065
|
-
|
|
70066
|
-
"
|
|
70067
|
-
"
|
|
70068
|
-
|
|
70069
|
-
|
|
70070
|
-
|
|
70071
|
-
"
|
|
70072
|
-
|
|
70073
|
-
"
|
|
70074
|
-
"
|
|
70075
|
-
|
|
70076
|
-
"qwen-payg": "Alibaba PAYG",
|
|
70077
|
-
google: "Direct Gemini API",
|
|
70078
|
-
openai: "Direct OpenAI API",
|
|
70079
|
-
"openai-codex": "OpenAI Codex (Responses API)",
|
|
70080
|
-
zai: "Z.AI API",
|
|
70081
|
-
ollamacloud: "Cloud Ollama",
|
|
70082
|
-
vertex: "Vertex AI (ADC)",
|
|
70083
|
-
openrouter: "Fallback: 580+ models"
|
|
70580
|
+
DROPPED_TEXT = {
|
|
70581
|
+
"no-credential": "no credential",
|
|
70582
|
+
"credential-unreadable": "credential could not be read",
|
|
70583
|
+
"not-served": "the account does not serve it",
|
|
70584
|
+
"excluded-by-membership": "not in the plan's membership"
|
|
70585
|
+
};
|
|
70586
|
+
FALLBACK_SOURCE_LABEL = {
|
|
70587
|
+
"cli-flag": "--default-provider",
|
|
70588
|
+
"env-var": "CLAUDISH_DEFAULT_PROVIDER",
|
|
70589
|
+
"config-file": "config",
|
|
70590
|
+
"openrouter-key": "default",
|
|
70591
|
+
hardcoded: "default"
|
|
70084
70592
|
};
|
|
70085
70593
|
});
|
|
70086
70594
|
|
|
@@ -70092,6 +70600,7 @@ function RoutingDetail({ probeMode, mergedRules }) {
|
|
|
70092
70600
|
}
|
|
70093
70601
|
const globalCustom = mergedRules.filter((r) => r.kind === "global").length;
|
|
70094
70602
|
const projectRules = mergedRules.filter((r) => r.kind === "project");
|
|
70603
|
+
const hasCatchAll = mergedRules.some((r) => r.pattern === "*");
|
|
70095
70604
|
const fmtCount = (n) => String(n).padStart(2, " ");
|
|
70096
70605
|
return /* @__PURE__ */ jsxs21("box", {
|
|
70097
70606
|
height: DETAIL_H,
|
|
@@ -70157,7 +70666,7 @@ function RoutingDetail({ probeMode, mergedRules }) {
|
|
|
70157
70666
|
children: /* @__PURE__ */ jsx25("text", {
|
|
70158
70667
|
children: /* @__PURE__ */ jsx25("span", {
|
|
70159
70668
|
fg: C.fgMuted,
|
|
70160
|
-
children: " Anything with no rule here is routed from the models catalog."
|
|
70669
|
+
children: hasCatchAll ? ' The "*" rule takes every model no other rule here matches.' : " Anything with no rule here is routed from the cloud models catalog."
|
|
70161
70670
|
})
|
|
70162
70671
|
})
|
|
70163
70672
|
})
|
|
@@ -70652,20 +71161,76 @@ var probeProxy = null, probeProxyStarting = null;
|
|
|
70652
71161
|
|
|
70653
71162
|
// src/tui/hooks/useRouteProbe.ts
|
|
70654
71163
|
import { useCallback as useCallback3, useState as useState10 } from "react";
|
|
70655
|
-
|
|
71164
|
+
function probeRowsFrom(explanation) {
|
|
71165
|
+
const summary = {
|
|
71166
|
+
line: describeRouteExplanation(explanation),
|
|
71167
|
+
warnings: explanation.warnings.map((warning) => warning.message),
|
|
71168
|
+
notes: []
|
|
71169
|
+
};
|
|
71170
|
+
if (explanation.source === "native") {
|
|
71171
|
+
summary.notes.push(NATIVE_NOT_PROBED);
|
|
71172
|
+
const native = explanation.native;
|
|
71173
|
+
const rows = native ? [
|
|
71174
|
+
{
|
|
71175
|
+
provider: native.provider,
|
|
71176
|
+
displayName: native.displayName,
|
|
71177
|
+
modelSpec: native.modelSpec,
|
|
71178
|
+
status: "unverified"
|
|
71179
|
+
}
|
|
71180
|
+
] : [];
|
|
71181
|
+
return { summary, rows };
|
|
71182
|
+
}
|
|
71183
|
+
if (explanation.catalog === "found" && explanation.fallbackWithheld) {
|
|
71184
|
+
summary.notes.push(FALLBACK_WITHHELD_NOTE[explanation.fallbackWithheld]);
|
|
71185
|
+
}
|
|
71186
|
+
if (explanation.outcome.kind === "no-route") {
|
|
71187
|
+
const { reason, hint } = explanation.outcome;
|
|
71188
|
+
summary.noRoute = hint !== undefined ? { reason, hint } : { reason };
|
|
71189
|
+
}
|
|
71190
|
+
const rows = explanation.candidates.map((candidate) => {
|
|
71191
|
+
const row = {
|
|
71192
|
+
provider: candidate.provider,
|
|
71193
|
+
displayName: candidate.displayName,
|
|
71194
|
+
modelSpec: candidate.modelSpec,
|
|
71195
|
+
position: candidate.position,
|
|
71196
|
+
...candidate.tier !== undefined ? { tier: candidate.tier } : {},
|
|
71197
|
+
status: "pending"
|
|
71198
|
+
};
|
|
71199
|
+
if (candidate.outcome !== "kept") {
|
|
71200
|
+
row.status = "dropped";
|
|
71201
|
+
row.outcome = candidate.outcome;
|
|
71202
|
+
}
|
|
71203
|
+
return row;
|
|
71204
|
+
});
|
|
71205
|
+
return { summary, rows };
|
|
71206
|
+
}
|
|
71207
|
+
function probeQueue(rows) {
|
|
71208
|
+
return rows.flatMap((row, index) => row.status === "pending" && row.modelSpec !== undefined ? [{ index, provider: row.provider, modelSpec: row.modelSpec }] : []);
|
|
71209
|
+
}
|
|
71210
|
+
async function probeViewFor(model) {
|
|
70656
71211
|
try {
|
|
70657
|
-
return await
|
|
71212
|
+
return probeRowsFrom(await explainRoute(model));
|
|
70658
71213
|
} catch (err) {
|
|
70659
|
-
return {
|
|
71214
|
+
return {
|
|
71215
|
+
summary: {
|
|
71216
|
+
line: "the route could not be calculated",
|
|
71217
|
+
warnings: [],
|
|
71218
|
+
notes: [],
|
|
71219
|
+
noRoute: { reason: err instanceof Error ? err.message : String(err) }
|
|
71220
|
+
},
|
|
71221
|
+
rows: []
|
|
71222
|
+
};
|
|
70660
71223
|
}
|
|
70661
71224
|
}
|
|
70662
|
-
function useRouteProbe(
|
|
71225
|
+
function useRouteProbe() {
|
|
70663
71226
|
const [probeMode, setProbeMode] = useState10("idle");
|
|
70664
71227
|
const [probeModel, setProbeModel] = useState10("");
|
|
70665
71228
|
const [probeResults, setProbeResults] = useState10([]);
|
|
71229
|
+
const [probeSummary, setProbeSummary] = useState10(null);
|
|
70666
71230
|
const startInput = useCallback3(() => {
|
|
70667
71231
|
setProbeModel("");
|
|
70668
71232
|
setProbeResults([]);
|
|
71233
|
+
setProbeSummary(null);
|
|
70669
71234
|
setProbeMode("input");
|
|
70670
71235
|
}, []);
|
|
70671
71236
|
const typeChar = useCallback3((ch) => {
|
|
@@ -70677,11 +71242,13 @@ function useRouteProbe(config) {
|
|
|
70677
71242
|
const cancel = useCallback3(() => {
|
|
70678
71243
|
setProbeModel("");
|
|
70679
71244
|
setProbeResults([]);
|
|
71245
|
+
setProbeSummary(null);
|
|
70680
71246
|
setProbeMode("idle");
|
|
70681
71247
|
}, []);
|
|
70682
71248
|
const enterFromDone = useCallback3(() => {
|
|
70683
71249
|
setProbeModel("");
|
|
70684
71250
|
setProbeResults([]);
|
|
71251
|
+
setProbeSummary(null);
|
|
70685
71252
|
setProbeMode("input");
|
|
70686
71253
|
}, []);
|
|
70687
71254
|
const submit = useCallback3(() => {
|
|
@@ -70692,71 +71259,28 @@ function useRouteProbe(config) {
|
|
|
70692
71259
|
return;
|
|
70693
71260
|
}
|
|
70694
71261
|
(async () => {
|
|
70695
|
-
const
|
|
70696
|
-
|
|
70697
|
-
|
|
70698
|
-
|
|
70699
|
-
|
|
70700
|
-
|
|
70701
|
-
|
|
70702
|
-
setProbeResults([
|
|
70703
|
-
{
|
|
70704
|
-
provider: "none",
|
|
70705
|
-
displayName: "No routes found",
|
|
70706
|
-
status: "failed",
|
|
70707
|
-
error: plan.hint ?? plan.reason
|
|
70708
|
-
}
|
|
70709
|
-
]);
|
|
70710
|
-
setProbeMode("done");
|
|
70711
|
-
return;
|
|
70712
|
-
}
|
|
70713
|
-
chain = [plan.primary, ...plan.fallbacks];
|
|
71262
|
+
const { summary, rows } = await probeViewFor(model);
|
|
71263
|
+
setProbeSummary(summary);
|
|
71264
|
+
setProbeResults(rows);
|
|
71265
|
+
const queue = probeQueue(rows);
|
|
71266
|
+
if (queue.length === 0) {
|
|
71267
|
+
setProbeMode("done");
|
|
71268
|
+
return;
|
|
70714
71269
|
}
|
|
70715
|
-
const ruleEntries = Object.entries(config.routing ?? {});
|
|
70716
|
-
const modelLower = model.toLowerCase();
|
|
70717
|
-
const matchedRule = ruleEntries.find(([pat]) => {
|
|
70718
|
-
if (pat.toLowerCase() === modelLower)
|
|
70719
|
-
return true;
|
|
70720
|
-
if (pat.includes("*")) {
|
|
70721
|
-
const regex = new RegExp(`^${pat.replace(/\*/g, ".*")}$`, "i");
|
|
70722
|
-
return regex.test(model);
|
|
70723
|
-
}
|
|
70724
|
-
return false;
|
|
70725
|
-
});
|
|
70726
|
-
const initial = chain.map((r) => {
|
|
70727
|
-
return {
|
|
70728
|
-
provider: r.provider,
|
|
70729
|
-
displayName: r.displayName,
|
|
70730
|
-
status: "pending",
|
|
70731
|
-
hasKey: true,
|
|
70732
|
-
reason: native ? "Native Claude Code auth \u2014 served by the proxy, never routed" : matchedRule ? `Custom rule: ${matchedRule[0]}` : "Default fallback chain"
|
|
70733
|
-
};
|
|
70734
|
-
});
|
|
70735
|
-
setProbeResults(initial);
|
|
70736
71270
|
setProbeMode("running");
|
|
70737
71271
|
(async () => {
|
|
70738
|
-
if (native) {
|
|
70739
|
-
setProbeResults((prev) => prev.map((e) => ({ ...e, status: "unverified", reason: REASON_NATIVE })));
|
|
70740
|
-
setProbeMode("done");
|
|
70741
|
-
return;
|
|
70742
|
-
}
|
|
70743
71272
|
let proxyUrl;
|
|
70744
71273
|
try {
|
|
70745
71274
|
proxyUrl = await ensureProbeProxy();
|
|
70746
71275
|
} catch (err) {
|
|
70747
71276
|
const msg = err instanceof Error ? err.message : String(err);
|
|
70748
|
-
|
|
71277
|
+
const queued = new Set(queue.map((item) => item.index));
|
|
71278
|
+
setProbeResults((prev) => prev.map((e, idx) => queued.has(idx) ? { ...e, status: "failed", error: `probe proxy: ${msg}` } : e));
|
|
70749
71279
|
setProbeMode("done");
|
|
70750
71280
|
return;
|
|
70751
71281
|
}
|
|
70752
|
-
for (
|
|
70753
|
-
const
|
|
70754
|
-
const provDef = getProviderDefs().find((p) => p.catalogName === link.provider);
|
|
70755
|
-
const ready = provDef ? providerIsReady(provDef, config) : true;
|
|
70756
|
-
if (!ready) {
|
|
70757
|
-
setProbeResults((prev) => prev.map((e, idx) => idx === i ? { ...e, status: "no_key" } : e));
|
|
70758
|
-
continue;
|
|
70759
|
-
}
|
|
71282
|
+
for (const link of queue) {
|
|
71283
|
+
const i = link.index;
|
|
70760
71284
|
setProbeResults((prev) => prev.map((e, idx) => idx === i ? { ...e, status: "testing" } : e));
|
|
70761
71285
|
const startMs = Date.now();
|
|
70762
71286
|
const result = await probeProviderRoute(proxyUrl, {
|
|
@@ -70778,7 +71302,7 @@ function useRouteProbe(config) {
|
|
|
70778
71302
|
error: ok ? undefined : describeProbeState(result),
|
|
70779
71303
|
ms
|
|
70780
71304
|
};
|
|
70781
|
-
if (idx > i && ok && e.status
|
|
71305
|
+
if (idx > i && ok && e.status === "pending")
|
|
70782
71306
|
return { ...e, status: "skipped" };
|
|
70783
71307
|
return e;
|
|
70784
71308
|
}));
|
|
@@ -70788,7 +71312,7 @@ function useRouteProbe(config) {
|
|
|
70788
71312
|
setProbeMode("done");
|
|
70789
71313
|
})();
|
|
70790
71314
|
})();
|
|
70791
|
-
}, [
|
|
71315
|
+
}, [probeModel]);
|
|
70792
71316
|
let state;
|
|
70793
71317
|
if (probeMode === "idle")
|
|
70794
71318
|
state = { kind: "idle" };
|
|
@@ -70803,6 +71327,7 @@ function useRouteProbe(config) {
|
|
|
70803
71327
|
probeMode,
|
|
70804
71328
|
probeModel,
|
|
70805
71329
|
probeResults,
|
|
71330
|
+
probeSummary,
|
|
70806
71331
|
startInput,
|
|
70807
71332
|
typeChar,
|
|
70808
71333
|
backspace,
|
|
@@ -70811,13 +71336,18 @@ function useRouteProbe(config) {
|
|
|
70811
71336
|
enterFromDone
|
|
70812
71337
|
};
|
|
70813
71338
|
}
|
|
70814
|
-
var
|
|
71339
|
+
var FALLBACK_WITHHELD_NOTE;
|
|
70815
71340
|
var init_useRouteProbe = __esm(() => {
|
|
70816
71341
|
init_native_route();
|
|
70817
71342
|
init_probe_live();
|
|
70818
71343
|
init_probe_runner();
|
|
70819
71344
|
init_routing_rules();
|
|
70820
|
-
|
|
71345
|
+
FALLBACK_WITHHELD_NOTE = {
|
|
71346
|
+
disabled: 'No fallback hop: the default provider is set to "".',
|
|
71347
|
+
"catalog-unreadable": "No fallback hop: there is no cloud models catalog to check it against.",
|
|
71348
|
+
"already-gathered": "No separate fallback hop: that provider is already a catalog candidate.",
|
|
71349
|
+
"catalog-denies": "No fallback hop: the catalog maps that provider no connection to this model."
|
|
71350
|
+
};
|
|
70821
71351
|
});
|
|
70822
71352
|
|
|
70823
71353
|
// src/tui/onepassword-fields.ts
|
|
@@ -71114,8 +71644,8 @@ function App({ requestLogin } = {}) {
|
|
|
71114
71644
|
return next;
|
|
71115
71645
|
});
|
|
71116
71646
|
}, []);
|
|
71117
|
-
const probe = useRouteProbe(
|
|
71118
|
-
const { probeMode, probeModel, probeResults } = probe;
|
|
71647
|
+
const probe = useRouteProbe();
|
|
71648
|
+
const { probeMode, probeModel, probeResults, probeSummary } = probe;
|
|
71119
71649
|
const wizard = useProfileWizard({ mode, setMode, refreshConfig, setStatusMsg });
|
|
71120
71650
|
const { editProfileValue, profileScope, suggestions, suggestionIndex, providerPickerIndex } = wizard;
|
|
71121
71651
|
const hasCfgKey = !!config.apiKeys?.[selectedProvider.apiKeyEnvVar];
|
|
@@ -71139,14 +71669,10 @@ function App({ requestLogin } = {}) {
|
|
|
71139
71669
|
const out = [];
|
|
71140
71670
|
const localCfg = loadLocalConfig();
|
|
71141
71671
|
for (const [pat, chain] of Object.entries(config.routing ?? {})) {
|
|
71142
|
-
if (pat === "*")
|
|
71143
|
-
continue;
|
|
71144
71672
|
out.push({ kind: "global", pattern: pat, chain });
|
|
71145
71673
|
}
|
|
71146
71674
|
if (localCfg?.routing) {
|
|
71147
71675
|
for (const [pat, chain] of Object.entries(localCfg.routing)) {
|
|
71148
|
-
if (pat === "*")
|
|
71149
|
-
continue;
|
|
71150
71676
|
out.push({ kind: "project", pattern: pat, chain });
|
|
71151
71677
|
}
|
|
71152
71678
|
}
|
|
@@ -72634,6 +73160,7 @@ function App({ requestLogin } = {}) {
|
|
|
72634
73160
|
probeMode,
|
|
72635
73161
|
probeModel,
|
|
72636
73162
|
probeResults,
|
|
73163
|
+
probeSummary,
|
|
72637
73164
|
mode,
|
|
72638
73165
|
routingPattern,
|
|
72639
73166
|
chainSelected,
|
|
@@ -72851,7 +73378,7 @@ import {
|
|
|
72851
73378
|
mkdtempSync,
|
|
72852
73379
|
openSync as openSync8,
|
|
72853
73380
|
rmSync as rmSync2,
|
|
72854
|
-
writeFileSync as
|
|
73381
|
+
writeFileSync as writeFileSync20
|
|
72855
73382
|
} from "fs";
|
|
72856
73383
|
import { connect as netConnect2 } from "net";
|
|
72857
73384
|
import { join as join43 } from "path";
|
|
@@ -72925,7 +73452,7 @@ function planMagmuxWrap(input) {
|
|
|
72925
73452
|
const deltas = envDeltas(parentEnv, input.childEnv);
|
|
72926
73453
|
const fd = openSync8(scriptPath, "wx", 384);
|
|
72927
73454
|
try {
|
|
72928
|
-
|
|
73455
|
+
writeFileSync20(fd, buildLauncherScript(input.claudeBinary, input.claudeArgs, deltas));
|
|
72929
73456
|
} finally {
|
|
72930
73457
|
closeSync8(fd);
|
|
72931
73458
|
}
|
|
@@ -73483,7 +74010,7 @@ import {
|
|
|
73483
74010
|
readdirSync as readdirSync8,
|
|
73484
74011
|
statSync as statSync8,
|
|
73485
74012
|
unlinkSync as unlinkSync9,
|
|
73486
|
-
writeFileSync as
|
|
74013
|
+
writeFileSync as writeFileSync21
|
|
73487
74014
|
} from "fs";
|
|
73488
74015
|
import { homedir as homedir37, tmpdir as tmpdir2 } from "os";
|
|
73489
74016
|
import { dirname as dirname14, join as join44 } from "path";
|
|
@@ -73722,13 +74249,13 @@ process.stdin.on('end', () => {
|
|
|
73722
74249
|
}
|
|
73723
74250
|
});
|
|
73724
74251
|
`;
|
|
73725
|
-
|
|
74252
|
+
writeFileSync21(scriptPath, script, "utf-8");
|
|
73726
74253
|
return scriptPath;
|
|
73727
74254
|
}
|
|
73728
74255
|
function initializeTokenFile(tokenFilePath) {
|
|
73729
74256
|
try {
|
|
73730
74257
|
mkdirSync21(dirname14(tokenFilePath), { recursive: true });
|
|
73731
|
-
|
|
74258
|
+
writeFileSync21(tokenFilePath, JSON.stringify({
|
|
73732
74259
|
input_tokens: 0,
|
|
73733
74260
|
output_tokens: 0,
|
|
73734
74261
|
total_tokens: 0,
|
|
@@ -73871,7 +74398,7 @@ function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLi
|
|
|
73871
74398
|
padding: 0
|
|
73872
74399
|
};
|
|
73873
74400
|
const settings = buildClaudishSettingsOverlay(statusLine, proxyAuthMode);
|
|
73874
|
-
|
|
74401
|
+
writeFileSync21(tempPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
73875
74402
|
return { path: tempPath, statusLine, tokenFilePath };
|
|
73876
74403
|
}
|
|
73877
74404
|
function buildClaudishSettingsOverlay(statusLine, proxyAuthMode) {
|
|
@@ -73896,7 +74423,7 @@ function mergeUserSettingsIfPresent(config, tempSettingsPath, statusLine, proxyA
|
|
|
73896
74423
|
if (proxyAuthMode && !("forceLoginMethod" in userSettings)) {
|
|
73897
74424
|
userSettings.forceLoginMethod = "console";
|
|
73898
74425
|
}
|
|
73899
|
-
|
|
74426
|
+
writeFileSync21(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
|
|
73900
74427
|
} catch {
|
|
73901
74428
|
if (!config.quiet) {
|
|
73902
74429
|
console.warn(`[claudish] Warning: could not merge user settings: ${userSettingsValue}`);
|
|
@@ -74410,7 +74937,7 @@ var init_claude_runner = __esm(() => {
|
|
|
74410
74937
|
});
|
|
74411
74938
|
|
|
74412
74939
|
// src/diag-output.ts
|
|
74413
|
-
import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync22, unlinkSync as unlinkSync10, writeFileSync as
|
|
74940
|
+
import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync22, unlinkSync as unlinkSync10, writeFileSync as writeFileSync22 } from "fs";
|
|
74414
74941
|
import { homedir as homedir38 } from "os";
|
|
74415
74942
|
import { join as join45 } from "path";
|
|
74416
74943
|
function getClaudishDir() {
|
|
@@ -74430,7 +74957,7 @@ class LogFileDiagOutput {
|
|
|
74430
74957
|
constructor() {
|
|
74431
74958
|
this.logPath = getDiagLogPath();
|
|
74432
74959
|
try {
|
|
74433
|
-
|
|
74960
|
+
writeFileSync22(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
|
|
74434
74961
|
`);
|
|
74435
74962
|
} catch {}
|
|
74436
74963
|
this.stream = createWriteStream3(this.logPath, { flags: "a" });
|
|
@@ -74775,7 +75302,7 @@ function resolveMainModelFact(model) {
|
|
|
74775
75302
|
const definitionName = resolution.catalogName === "gemini" ? "google" : resolution.catalogName;
|
|
74776
75303
|
const definition = definitionName ? getProviderByName(definitionName) : undefined;
|
|
74777
75304
|
const format = definition ? pinnedFormatForTransport(definition.transport, resolution.modelName) : null;
|
|
74778
|
-
const providerName = resolution.category === "unknown" ? "unresolved (routed on the first request)" : definition?.displayName || resolution.providerName;
|
|
75305
|
+
const providerName = resolution.category === "unknown" || resolution.category === "auto-route" ? "unresolved (routed on the first request)" : definition?.displayName || resolution.providerName;
|
|
74779
75306
|
return {
|
|
74780
75307
|
model,
|
|
74781
75308
|
providerName,
|
|
@@ -77119,9 +77646,22 @@ async function applyConfigOverride() {
|
|
|
77119
77646
|
setConfigFileOverride(plan.path);
|
|
77120
77647
|
process.env.CLAUDISH_CONFIG = plan.path;
|
|
77121
77648
|
}
|
|
77649
|
+
async function applyDefaultProviderFlag() {
|
|
77650
|
+
await Promise.resolve();
|
|
77651
|
+
const plan = planDefaultProviderFlag(process.argv.slice(2));
|
|
77652
|
+
if (plan.kind === "none")
|
|
77653
|
+
return;
|
|
77654
|
+
if (plan.kind === "error") {
|
|
77655
|
+
console.error(`[claudish] ${plan.message}`);
|
|
77656
|
+
process.exit(1);
|
|
77657
|
+
}
|
|
77658
|
+
process.argv = [...process.argv.slice(0, 2), ...plan.argv];
|
|
77659
|
+
process.env.CLAUDISH_DEFAULT_PROVIDER = plan.value;
|
|
77660
|
+
}
|
|
77122
77661
|
await traceSpan("startup:config-override", () => applyConfigOverride());
|
|
77123
77662
|
await traceSpan("startup:op-env-flags", () => applyOpEnvironment());
|
|
77124
77663
|
await traceSpan("startup:op-import-flag", () => applyOpImport());
|
|
77664
|
+
await traceSpan("startup:default-provider-flag", () => applyDefaultProviderFlag());
|
|
77125
77665
|
var isMcpMode = process.argv.includes("--mcp");
|
|
77126
77666
|
function handlePromptExit(err) {
|
|
77127
77667
|
if (err instanceof PickerCancelled) {
|