claudish 7.62.0 → 7.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +209 -92
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -729,7 +729,7 @@ var init_onepassword_config = __esm(() => {
729
729
  });
730
730
 
731
731
  // src/version.ts
732
- var VERSION = "7.62.0";
732
+ var VERSION = "7.64.0";
733
733
 
734
734
  // src/logger.ts
735
735
  var exports_logger = {};
@@ -35087,7 +35087,7 @@ class OpenAIProviderTransport {
35087
35087
  }
35088
35088
  async getHeaders() {
35089
35089
  const headers = {};
35090
- if (this.apiKey) {
35090
+ if (this.provider.authScheme !== "none" && this.apiKey) {
35091
35091
  if (this.provider.authScheme === "x-api-key") {
35092
35092
  headers["x-api-key"] = this.apiKey;
35093
35093
  } else {
@@ -36505,6 +36505,17 @@ function wrapAnthropicError(status, message, errorType, upstreamStatus) {
36505
36505
  error46.upstream_status = upstreamStatus;
36506
36506
  return { type: "error", error: error46 };
36507
36507
  }
36508
+ function extractUpstreamStatus(body) {
36509
+ if (!body)
36510
+ return;
36511
+ try {
36512
+ const parsed = JSON.parse(body);
36513
+ const status = parsed?.error?.upstream_status;
36514
+ return typeof status === "number" ? status : undefined;
36515
+ } catch {
36516
+ return;
36517
+ }
36518
+ }
36508
36519
  function extractProviderMessage(body) {
36509
36520
  if (body == null)
36510
36521
  return "";
@@ -40894,6 +40905,8 @@ class ApiKeyCredentialProvider {
40894
40905
  }
40895
40906
  }
40896
40907
  async isAvailable(opts) {
40908
+ if (this.authScheme === "none")
40909
+ return true;
40897
40910
  if (this.publicKeyFallback)
40898
40911
  return true;
40899
40912
  if (this.resolveFromEnvConfig())
@@ -40908,6 +40921,9 @@ class ApiKeyCredentialProvider {
40908
40921
  this.resolving = undefined;
40909
40922
  }
40910
40923
  async getRequestAuth(ctx) {
40924
+ if (this.authScheme === "none") {
40925
+ return { headers: { ...this.staticHeaders } };
40926
+ }
40911
40927
  const key = await this.resolveKey({ allowOpPrompt: ctx.allowOpPrompt }) || this.publicKeyFallback || "";
40912
40928
  let headers;
40913
40929
  if (this.authScheme === "x-api-key") {
@@ -42077,6 +42093,13 @@ __export(exports_authority, {
42077
42093
  credentials: () => credentials,
42078
42094
  CredentialAuthority: () => CredentialAuthority
42079
42095
  });
42096
+ function normalizeAuthScheme(scheme) {
42097
+ if (scheme === "x-api-key")
42098
+ return "x-api-key";
42099
+ if (scheme === "none")
42100
+ return "none";
42101
+ return "bearer";
42102
+ }
42080
42103
 
42081
42104
  class CredentialAuthority {
42082
42105
  registry = new Map;
@@ -42093,7 +42116,7 @@ class CredentialAuthority {
42093
42116
  catalogName: descriptor.name,
42094
42117
  envVar: descriptor.envVar,
42095
42118
  aliases: descriptor.aliases,
42096
- authScheme: descriptor.authScheme === "x-api-key" ? "x-api-key" : "bearer",
42119
+ authScheme: normalizeAuthScheme(descriptor.authScheme),
42097
42120
  declaredKey: descriptor.declaredKey
42098
42121
  }), [descriptor.name]);
42099
42122
  }
@@ -42166,7 +42189,7 @@ class CredentialAuthority {
42166
42189
  catalogName: def.name,
42167
42190
  envVar: def.apiKeyEnvVar,
42168
42191
  aliases: def.apiKeyAliases,
42169
- authScheme: def.authScheme === "x-api-key" ? "x-api-key" : "bearer",
42192
+ authScheme: normalizeAuthScheme(def.authScheme),
42170
42193
  publicKeyFallback: def.publicKeyFallback,
42171
42194
  oauthFallback: def.oauthFallback
42172
42195
  }), [def.name, ...RUNTIME_NAME_ALIASES[def.name] ?? []]);
@@ -43333,7 +43356,7 @@ class AnthropicProviderTransport {
43333
43356
  const headers = {
43334
43357
  "anthropic-version": "2023-06-01"
43335
43358
  };
43336
- if (this.provider.authScheme === "bearer") {
43359
+ if (this.provider.authScheme === "none") {} else if (this.provider.authScheme === "bearer") {
43337
43360
  headers.Authorization = `Bearer ${this.apiKey}`;
43338
43361
  } else {
43339
43362
  headers["x-api-key"] = this.apiKey;
@@ -45239,7 +45262,27 @@ var init_catalog_client = __esm(() => {
45239
45262
  });
45240
45263
 
45241
45264
  // src/config-schema.ts
45242
- var BuiltinDefaultProviderSchema, CustomEndpointSimpleSchema, CustomEndpointComplexSchema, CustomEndpointSchema, PredefinedEndpointsConfigSchema, DefaultProviderSchema;
45265
+ function requireKeyUnlessNoAuth(ep, ctx) {
45266
+ const declared = ep.apiKey?.trim() ?? "";
45267
+ if (ep.authScheme === "none") {
45268
+ if (declared !== "") {
45269
+ ctx.addIssue({
45270
+ code: "custom",
45271
+ path: ["apiKey"],
45272
+ message: 'authScheme "none" sends no auth header, so apiKey must be omitted. ' + "Remove apiKey, or drop authScheme to send it as a bearer token."
45273
+ });
45274
+ }
45275
+ return;
45276
+ }
45277
+ if (declared === "") {
45278
+ ctx.addIssue({
45279
+ code: "custom",
45280
+ path: ["apiKey"],
45281
+ message: "apiKey is required. If this endpoint needs no credential, set " + '"authScheme": "none" and omit apiKey entirely.'
45282
+ });
45283
+ }
45284
+ }
45285
+ var BuiltinDefaultProviderSchema, CustomEndpointAuthSchemeSchema, CustomEndpointSimpleSchema, CustomEndpointComplexSchema, CustomEndpointSchema, PredefinedEndpointsConfigSchema, DefaultProviderSchema;
45243
45286
  var init_config_schema = __esm(() => {
45244
45287
  init_zod();
45245
45288
  BuiltinDefaultProviderSchema = exports_external.enum([
@@ -45249,27 +45292,29 @@ var init_config_schema = __esm(() => {
45249
45292
  "anthropic",
45250
45293
  "google"
45251
45294
  ]);
45295
+ CustomEndpointAuthSchemeSchema = exports_external.enum(["bearer", "x-api-key", "none"]);
45252
45296
  CustomEndpointSimpleSchema = exports_external.object({
45253
45297
  kind: exports_external.literal("simple"),
45254
45298
  url: exports_external.url(),
45255
45299
  format: exports_external.enum(["openai", "anthropic"]),
45256
- apiKey: exports_external.string().min(1),
45300
+ apiKey: exports_external.string().optional(),
45301
+ authScheme: CustomEndpointAuthSchemeSchema.optional(),
45257
45302
  modelPrefix: exports_external.string().optional(),
45258
45303
  models: exports_external.array(exports_external.string()).optional()
45259
- });
45304
+ }).superRefine(requireKeyUnlessNoAuth);
45260
45305
  CustomEndpointComplexSchema = exports_external.object({
45261
45306
  kind: exports_external.literal("complex"),
45262
45307
  displayName: exports_external.string(),
45263
45308
  transport: exports_external.enum(["openai", "anthropic", "gemini", "ollamacloud", "litellm"]),
45264
45309
  baseUrl: exports_external.url(),
45265
45310
  apiPath: exports_external.string().optional(),
45266
- apiKey: exports_external.string().min(1),
45267
- authScheme: exports_external.enum(["bearer", "x-api-key"]).optional(),
45311
+ apiKey: exports_external.string().optional(),
45312
+ authScheme: CustomEndpointAuthSchemeSchema.optional(),
45268
45313
  headers: exports_external.record(exports_external.string(), exports_external.string()).optional(),
45269
45314
  streamFormat: exports_external.enum(["openai-sse", "openai-responses-sse", "gemini-sse", "anthropic-sse", "ollama-jsonl"]).optional(),
45270
45315
  modelPrefix: exports_external.string().optional(),
45271
45316
  models: exports_external.array(exports_external.string()).optional()
45272
- });
45317
+ }).superRefine(requireKeyUnlessNoAuth);
45273
45318
  CustomEndpointSchema = exports_external.discriminatedUnion("kind", [
45274
45319
  CustomEndpointSimpleSchema,
45275
45320
  CustomEndpointComplexSchema
@@ -45297,6 +45342,40 @@ var init_endpoint_diagnostics = __esm(() => {
45297
45342
  reasons = new Map;
45298
45343
  });
45299
45344
 
45345
+ // src/providers/picker-alias-extra.ts
45346
+ var PROVIDER_FILTER_ALIAS_EXTRA;
45347
+ var init_picker_alias_extra = __esm(() => {
45348
+ PROVIDER_FILTER_ALIAS_EXTRA = {
45349
+ gem: "google",
45350
+ zen: "opencode-zen"
45351
+ };
45352
+ });
45353
+
45354
+ // src/providers/reserved-namespace.ts
45355
+ function reservedNamespace() {
45356
+ const reserved = new Map;
45357
+ for (const def of BUILTIN_PROVIDERS) {
45358
+ reserved.set(def.name.toLowerCase(), def.name);
45359
+ for (const shortcut of def.shortcuts) {
45360
+ reserved.set(shortcut.toLowerCase(), def.name);
45361
+ }
45362
+ for (const legacy of def.legacyPrefixes) {
45363
+ reserved.set(legacy.prefix.replace(/[/:]+$/, "").toLowerCase(), def.name);
45364
+ }
45365
+ }
45366
+ for (const [alias, owner] of Object.entries(PROVIDER_FILTER_ALIAS_EXTRA)) {
45367
+ reserved.set(alias.toLowerCase(), owner);
45368
+ }
45369
+ return reserved;
45370
+ }
45371
+ function reservedNamespaceOwner(name) {
45372
+ return reservedNamespace().get(name.toLowerCase());
45373
+ }
45374
+ var init_reserved_namespace = __esm(() => {
45375
+ init_picker_alias_extra();
45376
+ init_provider_definitions();
45377
+ });
45378
+
45300
45379
  // src/providers/custom-endpoints-loader.ts
45301
45380
  function registerEndpoint(name, entry, ovr) {
45302
45381
  const validated = CustomEndpointSchema.parse(entry);
@@ -45308,17 +45387,24 @@ function registerEndpoint(name, entry, ovr) {
45308
45387
  name: def.name,
45309
45388
  envVar: def.apiKeyEnvVar,
45310
45389
  aliases: def.apiKeyAliases,
45311
- authScheme: def.authScheme === "x-api-key" ? "x-api-key" : "bearer",
45390
+ authScheme: def.authScheme,
45312
45391
  declaredKey: () => resolveDeclaredEndpointKey(validated)
45313
45392
  });
45314
45393
  clearEndpointUnavailable(name);
45315
45394
  }
45316
45395
  function loadCustomEndpoints(config2) {
45317
- const result = { registered: 0, errors: [] };
45396
+ const result = { registered: 0, errors: [], refused: [] };
45318
45397
  const raw = config2.customEndpoints;
45319
45398
  if (!raw || typeof raw !== "object")
45320
45399
  return result;
45321
45400
  for (const [name, entry] of Object.entries(raw)) {
45401
+ const owner = reservedNamespaceOwner(name);
45402
+ if (owner) {
45403
+ const reason = `'${name}' is already claimed by builtin provider '${owner}' ` + "(as its name, a shortcut, or a legacy prefix)";
45404
+ result.refused.push({ name, reason });
45405
+ recordEndpointUnavailable(name, `custom endpoint was skipped because ${reason}`);
45406
+ continue;
45407
+ }
45322
45408
  try {
45323
45409
  registerEndpoint(name, entry);
45324
45410
  result.registered++;
@@ -45352,7 +45438,7 @@ function buildProviderDefinition(name, ep, ovr) {
45352
45438
  isDirectApi: true,
45353
45439
  shortestPrefix: name,
45354
45440
  description: ovr?.description ?? `Custom endpoint: ${name}`,
45355
- authScheme: "bearer"
45441
+ authScheme: ep.authScheme ?? "bearer"
45356
45442
  };
45357
45443
  }
45358
45444
  return {
@@ -45514,7 +45600,7 @@ function buildComplexHandler(ep, ctx, apiKey, baseUrl) {
45514
45600
  }
45515
45601
  }
45516
45602
  function resolveCustomEndpointApiKey(ep) {
45517
- const literal3 = ep.apiKey;
45603
+ const literal3 = ep.apiKey ?? "";
45518
45604
  const match = literal3.match(/^\$\{([A-Z_][A-Z0-9_]*)\}$/i);
45519
45605
  if (match) {
45520
45606
  return process.env[match[1]] ?? "";
@@ -45549,21 +45635,13 @@ var init_custom_endpoints_loader = __esm(() => {
45549
45635
  init_composed_handler();
45550
45636
  init_endpoint_diagnostics();
45551
45637
  init_provider_definitions();
45638
+ init_reserved_namespace();
45552
45639
  init_runtime_providers();
45553
45640
  init_anthropic_compat();
45554
45641
  init_litellm();
45555
45642
  init_openai();
45556
45643
  });
45557
45644
 
45558
- // src/providers/picker-alias-extra.ts
45559
- var PROVIDER_FILTER_ALIAS_EXTRA;
45560
- var init_picker_alias_extra = __esm(() => {
45561
- PROVIDER_FILTER_ALIAS_EXTRA = {
45562
- gem: "google",
45563
- zen: "opencode-zen"
45564
- };
45565
- });
45566
-
45567
45645
  // src/providers/predefined-catalog.ts
45568
45646
  var PREDEFINED_ENDPOINTS;
45569
45647
  var init_predefined_catalog = __esm(() => {
@@ -45872,22 +45950,6 @@ function warnOnce2(message) {
45872
45950
  function activeCatalog() {
45873
45951
  return catalogOverride ?? PREDEFINED_ENDPOINTS;
45874
45952
  }
45875
- function reservedNamespace() {
45876
- const reserved = new Map;
45877
- for (const def of BUILTIN_PROVIDERS) {
45878
- reserved.set(def.name.toLowerCase(), def.name);
45879
- for (const shortcut of def.shortcuts) {
45880
- reserved.set(shortcut.toLowerCase(), def.name);
45881
- }
45882
- for (const legacy of def.legacyPrefixes) {
45883
- reserved.set(legacy.prefix.replace(/[/:]+$/, "").toLowerCase(), def.name);
45884
- }
45885
- }
45886
- for (const [alias, owner] of Object.entries(PROVIDER_FILTER_ALIAS_EXTRA)) {
45887
- reserved.set(alias.toLowerCase(), owner);
45888
- }
45889
- return reserved;
45890
- }
45891
45953
  function readOptOut(config2) {
45892
45954
  const off = { disabled: true, disable: new Set, enable: new Set };
45893
45955
  if (process.env[KILL_SWITCH_ENV] === "1")
@@ -46026,9 +46088,8 @@ var init_predefined_endpoints = __esm(() => {
46026
46088
  init_config_schema();
46027
46089
  init_custom_endpoints_loader();
46028
46090
  init_endpoint_diagnostics();
46029
- init_picker_alias_extra();
46030
46091
  init_predefined_catalog();
46031
- init_provider_definitions();
46092
+ init_reserved_namespace();
46032
46093
  init_runtime_providers();
46033
46094
  warnedMessages2 = new Set;
46034
46095
  ownRegistrations = new Set;
@@ -46038,23 +46099,67 @@ var init_predefined_endpoints = __esm(() => {
46038
46099
  var exports_endpoint_registration = {};
46039
46100
  __export(exports_endpoint_registration, {
46040
46101
  invalidateEndpointRegistration: () => invalidateEndpointRegistration,
46102
+ getCustomEndpointResult: () => getCustomEndpointResult,
46041
46103
  ensureEndpointsRegistered: () => ensureEndpointsRegistered
46042
46104
  });
46105
+ function getCustomEndpointResult() {
46106
+ return lastCustomResult;
46107
+ }
46043
46108
  function ensureEndpointsRegistered(opts = {}) {
46044
46109
  if (registered && !opts.force)
46045
46110
  return;
46111
+ let config2;
46112
+ try {
46113
+ config2 = opts.config ?? loadConfig();
46114
+ } catch {
46115
+ return;
46116
+ }
46046
46117
  registered = true;
46047
46118
  try {
46048
- loadPredefinedEndpoints(opts.config ?? loadConfig());
46119
+ loadPredefinedEndpoints(config2);
46120
+ } catch {}
46121
+ try {
46122
+ lastCustomResult = loadCustomEndpoints(config2);
46123
+ reportCustomEndpoints(lastCustomResult);
46124
+ } catch {}
46125
+ try {
46126
+ warnOnProjectScopedEndpoints();
46127
+ } catch {}
46128
+ }
46129
+ function reportCustomEndpoints(result) {
46130
+ for (const { name, message } of result.errors) {
46131
+ logStderr(`customEndpoints['${name}'] failed validation: ${message}`);
46132
+ }
46133
+ for (const { name, reason } of result.refused) {
46134
+ warnOnce3(`customEndpoints['${name}'] skipped: ${reason}. The builtin wins. ` + `Rename your entry (e.g. '${name}-custom') to use it.`);
46135
+ }
46136
+ }
46137
+ function warnOnProjectScopedEndpoints() {
46138
+ try {
46139
+ const local = loadLocalConfig();
46140
+ const names = Object.keys(local?.customEndpoints ?? {});
46141
+ if (names.length === 0)
46142
+ return;
46143
+ warnOnce3(`.claudish.json declares customEndpoints (${names.join(", ")}) but they are ` + "read from the GLOBAL config only, so they are being ignored. Move them to " + "~/.claudish/config.json.");
46049
46144
  } catch {}
46050
46145
  }
46146
+ function warnOnce3(message) {
46147
+ if (warnedMessages3.has(message))
46148
+ return;
46149
+ warnedMessages3.add(message);
46150
+ logStderr(message);
46151
+ }
46051
46152
  function invalidateEndpointRegistration() {
46052
46153
  registered = false;
46053
46154
  }
46054
- var registered = false;
46155
+ var registered = false, lastCustomResult, warnedMessages3;
46055
46156
  var init_endpoint_registration = __esm(() => {
46157
+ init_logger();
46056
46158
  init_profile_config();
46159
+ init_custom_endpoints_loader();
46057
46160
  init_predefined_endpoints();
46161
+ lastCustomResult = { registered: 0, errors: [], refused: [] };
46162
+ warnedMessages3 = new Set;
46058
46163
  });
46059
46164
 
46060
46165
  // src/providers/provider-registry.ts
@@ -46911,7 +47016,6 @@ async function prepareParentRoutingContext() {
46911
47016
  try {
46912
47017
  const config2 = loadConfig();
46913
47018
  ensureEndpointsRegistered({ config: config2 });
46914
- loadCustomEndpoints(config2);
46915
47019
  } catch {}
46916
47020
  }
46917
47021
  try {
@@ -46960,7 +47064,6 @@ var init_prehydrate = __esm(() => {
46960
47064
  init_profile_config();
46961
47065
  init_auto_route();
46962
47066
  init_catalog_client();
46963
- init_custom_endpoints_loader();
46964
47067
  init_endpoint_registration();
46965
47068
  init_model_parser();
46966
47069
  init_onepassword();
@@ -48113,17 +48216,6 @@ async function safeReadBody(response) {
48113
48216
  return "";
48114
48217
  }
48115
48218
  }
48116
- function extractUpstreamStatus(body) {
48117
- if (!body)
48118
- return;
48119
- try {
48120
- const parsed = JSON.parse(body);
48121
- const status = parsed?.error?.upstream_status;
48122
- return typeof status === "number" ? status : undefined;
48123
- } catch {
48124
- return;
48125
- }
48126
- }
48127
48219
  function extractErrorType(body) {
48128
48220
  if (!body)
48129
48221
  return;
@@ -48447,6 +48539,7 @@ function isFailureState(state) {
48447
48539
  }
48448
48540
  var STREAM_MS_FLOOR = 50, OAUTH_PROVIDERS2, PROBE_PROMPT = "Count from one to twenty in words, one per line.", PROBE_MAX_TOKENS = 512, MINIMAL_EFFORT_UNSUPPORTED;
48449
48541
  var init_probe_live = __esm(() => {
48542
+ init_anthropic_error();
48450
48543
  init_model_unsupported();
48451
48544
  OAUTH_PROVIDERS2 = new Set(["vertex", "antigravity", "devin"]);
48452
48545
  MINIMAL_EFFORT_UNSUPPORTED = new Set(["native-anthropic", "anthropic"]);
@@ -50491,6 +50584,10 @@ ${summary}`);
50491
50584
  function isRetryableError(status, errorBody, provider) {
50492
50585
  if (hasQuotaExhaustionWording(errorBody))
50493
50586
  return true;
50587
+ const upstream = status === 400 ? extractUpstreamStatus(errorBody) : undefined;
50588
+ if (upstream === 401 || upstream === 403 || upstream === 402 || upstream === 429) {
50589
+ return true;
50590
+ }
50494
50591
  if (status === 401 || status === 403)
50495
50592
  return true;
50496
50593
  if (status === 402)
@@ -50526,8 +50623,15 @@ function isRetryableError(status, errorBody, provider) {
50526
50623
  function exhaustedChainStatus(errors3) {
50527
50624
  if (errors3.length === 0)
50528
50625
  return 400;
50529
- const allTransient = errors3.every((e) => e.status === 429 || e.status === 503 || hasQuotaExhaustionWording(e.message));
50530
- return allTransient ? 503 : 400;
50626
+ const isTransient = (e) => {
50627
+ if (e.status === 429 || e.status === 503)
50628
+ return true;
50629
+ if (hasQuotaExhaustionWording(e.message))
50630
+ return true;
50631
+ const upstream = e.status === 400 ? extractUpstreamStatus(e.message) : undefined;
50632
+ return upstream === 429 || upstream === 503;
50633
+ };
50634
+ return errors3.every(isTransient) ? 503 : 400;
50531
50635
  }
50532
50636
  function isProvider(provider, needle) {
50533
50637
  if (!provider)
@@ -50552,6 +50656,7 @@ function truncate(s, max) {
50552
50656
  var init_fallback_handler = __esm(() => {
50553
50657
  init_logger();
50554
50658
  init_composed_handler();
50659
+ init_anthropic_error();
50555
50660
  init_quota_exhaustion();
50556
50661
  });
50557
50662
 
@@ -52034,14 +52139,11 @@ function maybeCaptureClassifierRequest(c, body) {
52034
52139
  async function createProxyServer(port, _openrouterApiKey, model, monitorMode = false, anthropicApiKey, modelMap, options = {}) {
52035
52140
  try {
52036
52141
  const config2 = loadConfig();
52037
- ensureEndpointsRegistered({ config: config2 });
52038
- const customEpResult = loadCustomEndpoints(config2);
52142
+ ensureEndpointsRegistered({ config: config2, force: true });
52143
+ const customEpResult = getCustomEndpointResult();
52039
52144
  if (customEpResult.registered > 0) {
52040
52145
  log(`[Proxy] Registered ${customEpResult.registered} custom endpoint(s) from config`);
52041
52146
  }
52042
- for (const err of customEpResult.errors) {
52043
- logStderr(`customEndpoints['${err.name}'] failed validation: ${err.message}`);
52044
- }
52045
52147
  } catch (err) {
52046
52148
  log(`[Proxy] customEndpoints load skipped: ${err instanceof Error ? err.message : String(err)}`);
52047
52149
  }
@@ -52155,7 +52257,8 @@ async function createProxyServer(port, _openrouterApiKey, model, monitorMode = f
52155
52257
  return null;
52156
52258
  }
52157
52259
  let apiKey = "";
52158
- if (resolved.provider.apiKeyEnvVar) {
52260
+ const needsNoAuth = resolved.provider.authScheme === "none";
52261
+ if (resolved.provider.apiKeyEnvVar && !needsNoAuth) {
52159
52262
  if (!credentials.get(resolved.provider.name)) {
52160
52263
  logStderr(`[Proxy] No credential provider registered for "${resolved.provider.name}" \u2014 treating as missing credential (authority registration gap)`);
52161
52264
  log(`[Proxy] Credential authority has no provider registered under "${resolved.provider.name}"`);
@@ -52511,7 +52614,6 @@ var init_proxy_server = __esm(() => {
52511
52614
  init_profile_config();
52512
52615
  init_auto_route();
52513
52616
  init_catalog_client();
52514
- init_custom_endpoints_loader();
52515
52617
  init_endpoint_diagnostics();
52516
52618
  init_endpoint_registration();
52517
52619
  init_model_parser();
@@ -54106,6 +54208,7 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
54106
54208
  const doProbe = args.probe !== false;
54107
54209
  const timeoutMs = typeof args.timeout_ms === "number" ? args.timeout_ms : 20000;
54108
54210
  const proxy = doProbe ? await getProxy() : null;
54211
+ ensureEndpointsRegistered();
54109
54212
  const rows = [];
54110
54213
  const readyModels = [];
54111
54214
  const failedModels = [];
@@ -54775,6 +54878,7 @@ var init_mcp_server = __esm(() => {
54775
54878
  init_progress_heartbeat();
54776
54879
  init_model_loader();
54777
54880
  init_port_manager();
54881
+ init_endpoint_registration();
54778
54882
  init_model_parser();
54779
54883
  init_onepassword();
54780
54884
  init_probe_live();
@@ -55806,7 +55910,7 @@ __export(exports_providers, {
55806
55910
  providerAuthSource: () => providerAuthSource,
55807
55911
  providerAuthCapabilities: () => providerAuthCapabilities,
55808
55912
  maskKey: () => maskKey2,
55809
- PROVIDERS: () => PROVIDERS
55913
+ getProviderDefs: () => getProviderDefs
55810
55914
  });
55811
55915
  function toProviderDef(def) {
55812
55916
  return {
@@ -55846,6 +55950,9 @@ function providerAuthCapabilities(p, config3) {
55846
55950
  oauth: { supported: oauthSupported, set: oauthSet }
55847
55951
  };
55848
55952
  }
55953
+ function getProviderDefs() {
55954
+ return getAllProviders().filter((d) => !SKIP.has(d.name)).map(toProviderDef);
55955
+ }
55849
55956
  function maskKey2(key) {
55850
55957
  if (!key)
55851
55958
  return "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500";
@@ -55853,7 +55960,7 @@ function maskKey2(key) {
55853
55960
  return "**** ";
55854
55961
  return `${key.slice(0, 3)}\u2022\u2022${key.slice(-3)}`;
55855
55962
  }
55856
- var SKIP, PROVIDERS;
55963
+ var SKIP;
55857
55964
  var init_providers = __esm(() => {
55858
55965
  init_antigravity_token();
55859
55966
  init_source();
@@ -55861,7 +55968,6 @@ var init_providers = __esm(() => {
55861
55968
  init_devin_credentials();
55862
55969
  init_provider_definitions();
55863
55970
  SKIP = new Set(["qwen", "native-anthropic"]);
55864
- PROVIDERS = getAllProviders().filter((d) => !SKIP.has(d.name)).map(toProviderDef);
55865
55971
  });
55866
55972
 
55867
55973
  // src/providers-command.ts
@@ -55871,7 +55977,8 @@ __export(exports_providers_command, {
55871
55977
  collectProviderStatuses: () => collectProviderStatuses
55872
55978
  });
55873
55979
  async function collectProviderStatuses(config3 = loadConfig()) {
55874
- return Promise.all(PROVIDERS.map(async (p) => {
55980
+ ensureEndpointsRegistered();
55981
+ return Promise.all(getProviderDefs().map(async (p) => {
55875
55982
  const authSource = await describeSource(p, config3);
55876
55983
  return {
55877
55984
  slug: p.catalogName,
@@ -55895,6 +56002,7 @@ async function providersCommand(opts) {
55895
56002
  var init_providers_command = __esm(() => {
55896
56003
  init_source();
55897
56004
  init_profile_config();
56005
+ init_endpoint_registration();
55898
56006
  init_providers();
55899
56007
  });
55900
56008
 
@@ -75055,7 +75163,17 @@ var init_probe_catalog = __esm(() => {
75055
75163
  });
75056
75164
 
75057
75165
  // src/tui/constants.ts
75058
- var COMMON_MODELS, PROVIDER_PREFIXES, CHAIN_PROVIDERS, HEADER_H = 2, TABS_H = 3, FOOTER_H = 1, DETAIL_H = 7;
75166
+ function getProviderPrefixes() {
75167
+ return getProviderDefs().map((p) => ({
75168
+ prefix: p.aliases?.[0] ? `${p.aliases[0]}@` : `${p.name}@`,
75169
+ displayName: p.displayName,
75170
+ name: p.name
75171
+ }));
75172
+ }
75173
+ function getChainProviders() {
75174
+ return getProviderDefs();
75175
+ }
75176
+ var COMMON_MODELS, HEADER_H = 2, TABS_H = 3, FOOTER_H = 1, DETAIL_H = 7;
75059
75177
  var init_constants3 = __esm(() => {
75060
75178
  init_providers();
75061
75179
  COMMON_MODELS = [
@@ -75077,12 +75195,6 @@ var init_constants3 = __esm(() => {
75077
75195
  "or@x-ai/grok-code-fast-1",
75078
75196
  "or@deepseek/deepseek-r1"
75079
75197
  ];
75080
- PROVIDER_PREFIXES = PROVIDERS.map((p) => ({
75081
- prefix: p.aliases?.[0] ? `${p.aliases[0]}@` : `${p.name}@`,
75082
- displayName: p.displayName,
75083
- name: p.name
75084
- }));
75085
- CHAIN_PROVIDERS = PROVIDERS;
75086
75198
  });
75087
75199
 
75088
75200
  // src/tui/components/Footer.tsx
@@ -76863,8 +76975,9 @@ function ProfilesContent({
76863
76975
  { name: "global ~/.claudish/config.json", description: "", value: "global" },
76864
76976
  { name: "project ./.claudish.json", description: "", value: "project" }
76865
76977
  ];
76866
- const prefixColW = PROVIDER_PREFIXES.reduce((max, p) => Math.max(max, p.prefix.length), 0) + 2;
76867
- const prefixOptions = PROVIDER_PREFIXES.map((p) => ({
76978
+ const prefixes = getProviderPrefixes();
76979
+ const prefixColW = prefixes.reduce((max, p) => Math.max(max, p.prefix.length), 0) + 2;
76980
+ const prefixOptions = prefixes.map((p) => ({
76868
76981
  name: `${p.prefix.padEnd(prefixColW)}${p.displayName}`,
76869
76982
  description: "",
76870
76983
  value: p.prefix
@@ -78750,7 +78863,7 @@ function RoutingContent({
78750
78863
  scrollY: true,
78751
78864
  focused: false,
78752
78865
  style: { flexGrow: 1 },
78753
- children: CHAIN_PROVIDERS.map((prov, idx) => {
78866
+ children: getChainProviders().map((prov, idx) => {
78754
78867
  const isCursor = idx === chainCursor;
78755
78868
  const isOn = chainSelected.has(prov.name);
78756
78869
  const pos = isOn ? chainOrder.indexOf(prov.name) + 1 : 0;
@@ -79192,10 +79305,10 @@ function useProfileWizard(args) {
79192
79305
  setProviderPickerIndex((i) => Math.max(0, i - 1));
79193
79306
  }, []);
79194
79307
  const prefixPickerDown = useCallback(() => {
79195
- setProviderPickerIndex((i) => Math.min(PROVIDER_PREFIXES.length - 1, i + 1));
79308
+ setProviderPickerIndex((i) => Math.min(getProviderPrefixes().length - 1, i + 1));
79196
79309
  }, []);
79197
79310
  const prefixPickerSubmit = useCallback(() => {
79198
- const prefix = PROVIDER_PREFIXES[providerPickerIndex]?.prefix ?? "";
79311
+ const prefix = getProviderPrefixes()[providerPickerIndex]?.prefix ?? "";
79199
79312
  setEditProfileValue(prefix);
79200
79313
  setSuggestions(computeSuggestions(prefix));
79201
79314
  setSuggestionIndex(-1);
@@ -79505,7 +79618,7 @@ function useRouteProbe(config3) {
79505
79618
  }
79506
79619
  for (let i = 0;i < chain.length; i++) {
79507
79620
  const link = chain[i];
79508
- const provDef = PROVIDERS.find((p) => p.catalogName === link.provider);
79621
+ const provDef = getProviderDefs().find((p) => p.catalogName === link.provider);
79509
79622
  const ready = provDef ? providerIsReady(provDef, config3) : true;
79510
79623
  if (!ready) {
79511
79624
  setProbeResults((prev) => prev.map((e, idx) => idx === i ? { ...e, status: "no_key" } : e));
@@ -79609,7 +79722,7 @@ function App({ requestLogin } = {}) {
79609
79722
  if (activeTab !== "providers")
79610
79723
  return;
79611
79724
  let cancelled = false;
79612
- const localNames = PROVIDERS.filter((p) => p.isLocal).map((p) => p.catalogName);
79725
+ const localNames = getProviderDefs().filter((p) => p.isLocal).map((p) => p.catalogName);
79613
79726
  if (localNames.length === 0)
79614
79727
  return;
79615
79728
  const sweep = async () => {
@@ -79653,11 +79766,12 @@ function App({ requestLogin } = {}) {
79653
79766
  const opPickerResolver = useRef4(null);
79654
79767
  const quit = useCallback3(() => renderer.destroy(), [renderer]);
79655
79768
  const displayProviders = useMemo2(() => {
79656
- return [...PROVIDERS].sort((a, b) => {
79769
+ const roster = getProviderDefs();
79770
+ return [...roster].sort((a, b) => {
79657
79771
  const aReady = providerIsReadyForDisplay(a, config3, localLiveness);
79658
79772
  const bReady = providerIsReadyForDisplay(b, config3, localLiveness);
79659
79773
  if (aReady === bReady)
79660
- return PROVIDERS.indexOf(a) - PROVIDERS.indexOf(b);
79774
+ return roster.indexOf(a) - roster.indexOf(b);
79661
79775
  return aReady ? -1 : 1;
79662
79776
  });
79663
79777
  }, [config3, localLiveness]);
@@ -80269,9 +80383,9 @@ function App({ requestLogin } = {}) {
80269
80383
  if (key.name === "up" || key.name === "k") {
80270
80384
  setChainCursor((i) => Math.max(0, i - 1));
80271
80385
  } else if (key.name === "down" || key.name === "j") {
80272
- setChainCursor((i) => Math.min(CHAIN_PROVIDERS.length - 1, i + 1));
80386
+ setChainCursor((i) => Math.min(getChainProviders().length - 1, i + 1));
80273
80387
  } else if (key.name === "space" || key.raw === " ") {
80274
- const prov = CHAIN_PROVIDERS[chainCursor];
80388
+ const prov = getChainProviders()[chainCursor];
80275
80389
  if (prov.isLocal && !providerIsReady(prov, config3)) {
80276
80390
  setStatusMsg(`${prov.displayName} is disabled. Enable it in Providers first.`);
80277
80391
  return;
@@ -80289,7 +80403,7 @@ function App({ requestLogin } = {}) {
80289
80403
  return next;
80290
80404
  });
80291
80405
  } else if (key.raw && key.raw >= "1" && key.raw <= "9") {
80292
- const prov = CHAIN_PROVIDERS[chainCursor];
80406
+ const prov = getChainProviders()[chainCursor];
80293
80407
  if (prov.isLocal && !providerIsReady(prov, config3)) {
80294
80408
  setStatusMsg(`${prov.displayName} is disabled. Enable it in Providers first.`);
80295
80409
  return;
@@ -80745,7 +80859,7 @@ function App({ requestLogin } = {}) {
80745
80859
  }
80746
80860
  } else if (key.raw === "T") {
80747
80861
  const fired = [];
80748
- for (const prov of PROVIDERS) {
80862
+ for (const prov of getProviderDefs()) {
80749
80863
  const localRunning = prov.isLocal && localLiveness[prov.catalogName] === "running";
80750
80864
  if (!providerIsReady(prov, config3) && !localRunning)
80751
80865
  continue;
@@ -85530,8 +85644,11 @@ if (isMcpMode) {
85530
85644
  } else if (isConfigCommand) {
85531
85645
  traceSpan("startup:tui-import", () => Promise.resolve().then(() => (init_tui(), exports_tui))).then(async (m) => {
85532
85646
  const { credentials: credentials2 } = await Promise.resolve().then(() => (init_authority(), exports_authority));
85533
- const { PROVIDERS: PROVIDERS2 } = await Promise.resolve().then(() => (init_providers(), exports_providers));
85534
- await traceSpan("startup:credential-resolution", () => Promise.all(PROVIDERS2.map((p) => credentials2.isAvailable(p.catalogName, { allowOpPrompt: true }))), { providers: PROVIDERS2.length });
85647
+ const { ensureEndpointsRegistered: ensureEndpointsRegistered2 } = await Promise.resolve().then(() => (init_endpoint_registration(), exports_endpoint_registration));
85648
+ ensureEndpointsRegistered2();
85649
+ const { getProviderDefs: getProviderDefs2 } = await Promise.resolve().then(() => (init_providers(), exports_providers));
85650
+ const tuiProviders = getProviderDefs2();
85651
+ await traceSpan("startup:credential-resolution", () => Promise.all(tuiProviders.map((p) => credentials2.isAvailable(p.catalogName, { allowOpPrompt: true }))), { providers: tuiProviders.length });
85535
85652
  finalizeStartupTrace("config");
85536
85653
  suppressStartupTraceTerminalOutput();
85537
85654
  return m.startConfigTui().catch(handlePromptExit);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "7.62.0",
3
+ "version": "7.64.0",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,10 +60,10 @@
60
60
  "ai"
61
61
  ],
62
62
  "optionalDependencies": {
63
- "@claudish/magmux-darwin-arm64": "7.62.0",
64
- "@claudish/magmux-darwin-x64": "7.62.0",
65
- "@claudish/magmux-linux-arm64": "7.62.0",
66
- "@claudish/magmux-linux-x64": "7.62.0"
63
+ "@claudish/magmux-darwin-arm64": "7.64.0",
64
+ "@claudish/magmux-darwin-x64": "7.64.0",
65
+ "@claudish/magmux-linux-arm64": "7.64.0",
66
+ "@claudish/magmux-linux-x64": "7.64.0"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",