claudish 14.16.2 → 14.17.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 +276 -43
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -133,6 +133,9 @@ var init_config = __esm(() => {
133
133
  CLAUDISH_PROVIDER_NAME: "CLAUDISH_PROVIDER_NAME",
134
134
  ANTHROPIC_MODEL: "ANTHROPIC_MODEL",
135
135
  ANTHROPIC_SMALL_FAST_MODEL: "ANTHROPIC_SMALL_FAST_MODEL",
136
+ CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST: "CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST",
137
+ CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL: "_CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL",
138
+ CLAUDISH_SET_HOST_ROUTING_VARS: "CLAUDISH_SET_HOST_ROUTING_VARS",
136
139
  CLAUDISH_MODEL_OPUS: "CLAUDISH_MODEL_OPUS",
137
140
  CLAUDISH_MODEL_SONNET: "CLAUDISH_MODEL_SONNET",
138
141
  CLAUDISH_MODEL_HAIKU: "CLAUDISH_MODEL_HAIKU",
@@ -5491,7 +5494,7 @@ var init_onepassword_config = __esm(() => {
5491
5494
  });
5492
5495
 
5493
5496
  // src/version.ts
5494
- var VERSION = "14.16.2";
5497
+ var VERSION = "14.17.0";
5495
5498
 
5496
5499
  // src/redact.ts
5497
5500
  function isPlaceholder(value) {
@@ -34202,6 +34205,14 @@ function toModelInfo(raw) {
34202
34205
  if (tp && typeof tp.mode === "string" && typeof tp.limit === "number") {
34203
34206
  info.truncationPolicy = { mode: tp.mode, limit: tp.limit };
34204
34207
  }
34208
+ if (Array.isArray(m.service_tiers)) {
34209
+ info.serviceTiers = m.service_tiers.flatMap((tier) => {
34210
+ const t = tier;
34211
+ return t && typeof t.id === "string" && typeof t.name === "string" ? [{ id: t.id, name: t.name }] : [];
34212
+ });
34213
+ }
34214
+ if (typeof m.default_service_tier === "string")
34215
+ info.defaultServiceTier = m.default_service_tier;
34205
34216
  return info;
34206
34217
  }
34207
34218
  function toModelTable(body) {
@@ -34298,7 +34309,7 @@ async function firstAnswer(entry, slug, binding, opts, now) {
34298
34309
  log(`[CodexDiscovery] ${slug}: /models not answered within ${waitMs} ms`);
34299
34310
  }
34300
34311
  }
34301
- return slug ? fromModelsCache(slug, opts.codexHome) : undefined;
34312
+ return slug && !opts.accountOnly ? fromModelsCache(slug, opts.codexHome) : undefined;
34302
34313
  }
34303
34314
  function fromModelsCache(slug, codexHome) {
34304
34315
  const info = toModelTable(readModelsCache(codexHome))?.get(slug.toLowerCase());
@@ -41084,6 +41095,34 @@ function parseModelParams(spec, into = {}) {
41084
41095
  return into;
41085
41096
  }
41086
41097
 
41098
+ // src/providers/codex-service-tier.ts
41099
+ function findCodexServiceTier(speed, tiers) {
41100
+ if (!tiers)
41101
+ return;
41102
+ const matches = (tier) => tier.id === speed || tier.name.toLowerCase() === speed;
41103
+ return tiers.find(matches);
41104
+ }
41105
+ function decideCodexSpeed(speed, modelInfo) {
41106
+ if (speed.value === "standard") {
41107
+ return { note: "speed standard: field omitted (connection default)" };
41108
+ }
41109
+ if (modelInfo === "unsigned") {
41110
+ const message = `speed "${speed.value}" is not available on this connection (no subscription account signed the request)`;
41111
+ return speed.explicit ? { note: message, refusal: message } : { note: message };
41112
+ }
41113
+ const tier = findCodexServiceTier(speed.value, modelInfo?.serviceTiers);
41114
+ if (tier) {
41115
+ return {
41116
+ tier: tier.id,
41117
+ note: `speed ${speed.value}: ${CODEX_SERVICE_TIER_POINTER} set to the account's ${speed.value} tier (from the account's dynamic models catalog)`
41118
+ };
41119
+ }
41120
+ const listed = modelInfo?.serviceTiers?.length ?? 0;
41121
+ const message = modelInfo ? `speed "${speed.value}" is not offered on this connection (the account lists ${listed} service tier${listed === 1 ? "" : "s"})` : `speed "${speed.value}" is not available on this connection (the account's dynamic models catalog did not answer; retry)`;
41122
+ return speed.explicit ? { note: message, refusal: message } : { note: message };
41123
+ }
41124
+ var CODEX_SERVICE_TIER_POINTER = "/service_tier";
41125
+
41087
41126
  // src/handlers/shared/call-context.ts
41088
41127
  function createSigningSecrets() {
41089
41128
  return { values: new Set, lease: acquireSigningLease() };
@@ -48151,6 +48190,34 @@ var init_authority = __esm(() => {
48151
48190
  installBillingProbes();
48152
48191
  });
48153
48192
 
48193
+ // src/providers/catalog-endpoints.ts
48194
+ function catalogUrl() {
48195
+ return process.env.CLAUDISH_CATALOG_URL ?? DEFAULT_CATALOG_URL;
48196
+ }
48197
+ function siblingEndpoint(pathname, fallback) {
48198
+ try {
48199
+ const url = new URL(catalogUrl());
48200
+ url.pathname = url.pathname.replace(/\/queryModels$/, pathname);
48201
+ url.search = "";
48202
+ return url.toString();
48203
+ } catch {
48204
+ return fallback;
48205
+ }
48206
+ }
48207
+ function plansUrl() {
48208
+ return process.env.CLAUDISH_PLANS_URL ?? siblingEndpoint("/queryPlans", `${DEFAULT_HOST}/queryPlans`);
48209
+ }
48210
+ function probeModelsUrl() {
48211
+ return process.env.CLAUDISH_PROBE_MODELS_URL ?? siblingEndpoint("/probeModels", `${DEFAULT_HOST}/probeModels`);
48212
+ }
48213
+ function modelsBaseUrl() {
48214
+ return siblingEndpoint("/queryModels", `${DEFAULT_HOST}/queryModels`);
48215
+ }
48216
+ var DEFAULT_HOST = "https://us-central1-claudish-6da10.cloudfunctions.net", DEFAULT_CATALOG_URL;
48217
+ var init_catalog_endpoints = __esm(() => {
48218
+ DEFAULT_CATALOG_URL = `${DEFAULT_HOST}/queryModels?status=all&catalog=slim&includeRouteVariants=true&limit=1000`;
48219
+ });
48220
+
48154
48221
  // src/providers/catalog-v3.ts
48155
48222
  function parseCatalogV3Envelope(value) {
48156
48223
  if (!value || typeof value !== "object")
@@ -48619,22 +48686,6 @@ var init_probe_discovery = __esm(() => {
48619
48686
  });
48620
48687
 
48621
48688
  // src/providers/catalog-client.ts
48622
- function catalogUrl() {
48623
- return process.env.CLAUDISH_CATALOG_URL ?? DEFAULT_CATALOG_URL;
48624
- }
48625
- function derivePlansUrl(modelsUrl) {
48626
- try {
48627
- const url = new URL(modelsUrl);
48628
- url.pathname = url.pathname.replace(/\/queryModels$/, "/queryPlans");
48629
- url.search = "";
48630
- return url.toString();
48631
- } catch {
48632
- return "https://us-central1-claudish-6da10.cloudfunctions.net/queryPlans";
48633
- }
48634
- }
48635
- function plansUrl() {
48636
- return process.env.CLAUDISH_PLANS_URL ?? derivePlansUrl(catalogUrl());
48637
- }
48638
48689
  function buildRoutesUrl(modelsUrl, generationId) {
48639
48690
  const url = new URL(modelsUrl);
48640
48691
  url.search = "";
@@ -48834,8 +48885,9 @@ async function refreshCatalogOnce(timeoutMs, options) {
48834
48885
  let pages = 0;
48835
48886
  const seenCursors = new Set;
48836
48887
  let expectedTotal;
48888
+ const base = catalogUrl();
48837
48889
  for (;; ) {
48838
- const result = await fetchEnvelope(buildCatalogPageUrl(catalogUrl(), cursor, CATALOG_PAGE_LIMIT, generationId), timeoutMs);
48890
+ const result = await fetchEnvelope(buildCatalogPageUrl(base, cursor, CATALOG_PAGE_LIMIT, generationId), timeoutMs);
48839
48891
  if (!result.ok) {
48840
48892
  if (result.reason === "incompatible") {
48841
48893
  return { kind: "incompatible", serverContractVersion: result.serverContractVersion };
@@ -48884,7 +48936,7 @@ async function refreshCatalogOnce(timeoutMs, options) {
48884
48936
  }
48885
48937
  return { kind: "fetch_failed", reason: planResult.reason };
48886
48938
  }
48887
- const registryResult = await fetchRouteRegistry(timeoutMs, generationId);
48939
+ const registryResult = await fetchRouteRegistry(timeoutMs, generationId, base);
48888
48940
  if (!registryResult.ok) {
48889
48941
  if (registryResult.reason === "incompatible") {
48890
48942
  return { kind: "incompatible", serverContractVersion: registryResult.serverContractVersion };
@@ -48962,8 +49014,8 @@ async function fetchSubscriptionPlans(timeoutMs, generationId) {
48962
49014
  }
48963
49015
  return { ok: true, plans };
48964
49016
  }
48965
- async function fetchRouteRegistry(timeoutMs, generationId) {
48966
- const result = await fetchEnvelope(buildRoutesUrl(catalogUrl(), generationId), timeoutMs);
49017
+ async function fetchRouteRegistry(timeoutMs, generationId, modelsUrl) {
49018
+ const result = await fetchEnvelope(buildRoutesUrl(modelsUrl, generationId), timeoutMs);
48967
49019
  if (!result.ok)
48968
49020
  return result;
48969
49021
  if (result.envelope.generationId !== generationId) {
@@ -49005,7 +49057,7 @@ async function ensureRouteRegistryReady(timeoutMs = 5000) {
49005
49057
  if (cache?.routeRegistry)
49006
49058
  return;
49007
49059
  if (cache && !catalogWarmDisabled()) {
49008
- const result = await fetchRouteRegistry(timeoutMs, cache.catalogGenerationId);
49060
+ const result = await fetchRouteRegistry(timeoutMs, cache.catalogGenerationId, catalogUrl());
49009
49061
  if (result.ok) {
49010
49062
  const routeRegistry = { generationId: cache.catalogGenerationId, registry: result.registry };
49011
49063
  if (wiresMatchRegistry(cache.entries, routeRegistry, cache.catalogGenerationId)) {
@@ -49028,10 +49080,11 @@ async function waitForCatalogWarm(timeoutMs) {
49028
49080
  if (timedOut)
49029
49081
  log(`[catalog] still refreshing after ${timeoutMs} ms; the caller goes on without it`);
49030
49082
  }
49031
- var DEFAULT_CATALOG_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/queryModels?status=all&catalog=slim&includeRouteVariants=true&limit=1000", MAX_CATALOG_PAGES = 40, CATALOG_PAGE_LIMIT = 1000, _memCache = null, _catalogEntriesForTest, _warmPromise = null;
49083
+ var MAX_CATALOG_PAGES = 40, CATALOG_PAGE_LIMIT = 1000, _memCache = null, _catalogEntriesForTest, _warmPromise = null;
49032
49084
  var init_catalog_client = __esm(() => {
49033
49085
  init_logger();
49034
49086
  init_all_models_cache();
49087
+ init_catalog_endpoints();
49035
49088
  init_catalog_route_bindings();
49036
49089
  init_connection_wire();
49037
49090
  init_probe_discovery();
@@ -50254,7 +50307,7 @@ async function discoverEveryServedModel(providerName) {
50254
50307
  detail: oneLine3(e?.message ?? "")
50255
50308
  });
50256
50309
  }
50257
- if (!hasAuthHeader(headers)) {
50310
+ if (!hasAuthHeader(headers) && def.authScheme !== "none") {
50258
50311
  return recordFailure({ kind: "no-credentials", provider: providerName, endpoint });
50259
50312
  }
50260
50313
  }
@@ -50534,6 +50587,15 @@ function setPointer(body, path, value) {
50534
50587
  }
50535
50588
  node[tokens[tokens.length - 1]] = value;
50536
50589
  }
50590
+ function readPointer(body, path) {
50591
+ let node = body;
50592
+ for (const token of pointerTokens(path)) {
50593
+ if (node === null || typeof node !== "object" || Array.isArray(node))
50594
+ return;
50595
+ node = node[token];
50596
+ }
50597
+ return node;
50598
+ }
50537
50599
  function deletePointer(body, path) {
50538
50600
  const tokens = pointerTokens(path);
50539
50601
  const trail = [body];
@@ -50610,6 +50672,18 @@ function applyControl(body, control, requested, label, explicit, result) {
50610
50672
  result.headers.push(...control.headers);
50611
50673
  result.notes.push(`${label} ${requested}: ${control.path} = ${JSON.stringify(native)}${control.access !== "open" ? ` (access: ${control.access})` : ""}`);
50612
50674
  }
50675
+ function wireSpeedOffered(control, speed) {
50676
+ return control.status === "supported" && control.values[speed] !== undefined;
50677
+ }
50678
+ function applyWireSpeed(body, wire, speed) {
50679
+ const result = { headers: [], notes: [], borrowed: [] };
50680
+ if (wire.speed.status === "supported" && readPointer(body, wire.speed.path) !== undefined) {
50681
+ result.notes.push(`speed ${speed.value}: ${wire.speed.path} already set by --model-params`);
50682
+ return result;
50683
+ }
50684
+ applyControl(body, wire.speed, speed.value, "speed", speed.explicit, result);
50685
+ return result;
50686
+ }
50613
50687
  function writeAssignments(put, assignments) {
50614
50688
  for (const assignment of assignments)
50615
50689
  put(assignment.path, assignment.value);
@@ -50695,7 +50769,8 @@ function wireChoicesFromClaudeRequest(claudeRequest, pinnedEffort) {
50695
50769
  effort: effort === "none" ? undefined : effort,
50696
50770
  reasoningOff,
50697
50771
  hasTools: Array.isArray(claudeRequest?.tools) && claudeRequest.tools.length > 0,
50698
- maxTokens: typeof claudeRequest?.max_tokens === "number" ? claudeRequest.max_tokens : undefined
50772
+ maxTokens: typeof claudeRequest?.max_tokens === "number" ? claudeRequest.max_tokens : undefined,
50773
+ ...claudeRequest?.speed === "fast" && { speed: { value: "fast", explicit: false } }
50699
50774
  };
50700
50775
  }
50701
50776
  function outputLimitToSend(wire, choices, result) {
@@ -50762,7 +50837,7 @@ function recoverBorrowedWireFields(payload, borrowed, errorText) {
50762
50837
  deletePointer(next, path);
50763
50838
  return {
50764
50839
  payload: next,
50765
- note: `dropped ${drop.join(", ")} (borrowed from the owner's connection; this connection's value is unknown)`
50840
+ note: `dropped ${drop.join(", ")} (not published by this connection's catalog wire)`
50766
50841
  };
50767
50842
  }
50768
50843
  function mergeWireHeaders(headers, extra) {
@@ -56140,6 +56215,17 @@ class ComposedHandler {
56140
56215
  subscription: CREDENTIAL_DECIDED_PROVIDERS.has(name) ? binding?.auth?.arm === "oauth" : isSubscriptionProvider(name)
56141
56216
  };
56142
56217
  }
56218
+ wireWhere() {
56219
+ const connection = this.options.connection;
56220
+ return `${connection?.route.routeId}/${connection?.route.routeProfileId} \xB7 ${connection?.externalModelId}`;
56221
+ }
56222
+ noticeFastIgnored(source) {
56223
+ if (fastIgnoredNoticed.has(this.targetModel))
56224
+ return;
56225
+ fastIgnoredNoticed.add(this.targetModel);
56226
+ const advice = source === "catalog" ? "the fast tier is billed at a higher per-token price. Add #fast to the model spec to send it anyway." : "the Codex fast tier is sent only on a request signed by a Codex subscription account.";
56227
+ logStderr(`${this.targetModel}: Claude Code /fast ignored, the request is metered and ${advice}`);
56228
+ }
56143
56229
  respondCallAborted(startTime, fallbackMeta) {
56144
56230
  log(`[${this.provider.displayName}] call stopped: its deadline passed`);
56145
56231
  try {
@@ -56583,6 +56669,8 @@ class ComposedHandler {
56583
56669
  const toolNameMap = adapter.getToolNameMap();
56584
56670
  let wireHeaders = [];
56585
56671
  let wireBorrowed = [];
56672
+ let codexSpeed;
56673
+ let fastSpeed;
56586
56674
  const wire = this.options.connection?.wire;
56587
56675
  if (wire?.status === "known") {
56588
56676
  const choices = {
@@ -56605,6 +56693,13 @@ class ComposedHandler {
56605
56693
  }
56606
56694
  if (wireSpeed)
56607
56695
  choices.speed = { value: wireSpeed, explicit: true };
56696
+ if (choices.speed && this.provider.name === "openai-codex" && wire.speed.status === "unknown") {
56697
+ codexSpeed = choices.speed;
56698
+ choices.speed = undefined;
56699
+ } else if (choices.speed && !choices.speed.explicit) {
56700
+ fastSpeed = choices.speed;
56701
+ choices.speed = undefined;
56702
+ }
56608
56703
  const shaped = shapeRequestFromWire(requestPayload, wire, choices, this.options.connection?.ownerWire);
56609
56704
  wireBorrowed = shaped.borrowed;
56610
56705
  const where = `${this.options.connection?.route.routeId}/${this.options.connection?.route.routeProfileId} \xB7 ${this.options.connection?.externalModelId}`;
@@ -56705,6 +56800,18 @@ class ComposedHandler {
56705
56800
  this.tokenTracker.setContextWindow(providerWindow);
56706
56801
  }
56707
56802
  }
56803
+ if (fastSpeed && wire?.status === "known") {
56804
+ if (!this.signedBilling(binding).subscription) {
56805
+ log(`[Wire] ${this.wireWhere()}: speed ${fastSpeed.value} (Claude Code /fast) not sent: the request is metered`);
56806
+ if (wireSpeedOffered(wire.speed, fastSpeed.value))
56807
+ this.noticeFastIgnored("catalog");
56808
+ } else {
56809
+ const applied = applyWireSpeed(requestPayload, wire, fastSpeed);
56810
+ for (const note of applied.notes)
56811
+ log(`[Wire] ${this.wireWhere()}: ${note}`);
56812
+ wireHeaders = [...wireHeaders, ...applied.headers];
56813
+ }
56814
+ }
56708
56815
  if (this.provider.name === "openai-codex") {
56709
56816
  const resume = (mayRequestModule) => resumeFromToolResults(claudeRequest, binding, peekCodeModeStores(), claudeRequest?.tool_choice, {
56710
56817
  setting: this.options.codeMode ?? DEFAULT_CODE_MODE_SETTING,
@@ -56729,6 +56836,30 @@ class ComposedHandler {
56729
56836
  if (this.provider.transformPayload) {
56730
56837
  requestPayload = this.provider.transformPayload(requestPayload, claudeRequest, binding);
56731
56838
  }
56839
+ if (codexSpeed) {
56840
+ addSigningSecrets(c, credentialValuesFromRequest(binding?.auth?.headers, this.signedEndpoint(binding)));
56841
+ const accountKey = accountKeyFromBinding(binding);
56842
+ const subscription = this.signedBilling(binding).subscription;
56843
+ const modelInfo = !subscription ? "unsigned" : binding && accountKey ? await getCodexModelInfo(String(requestPayload?.model ?? ""), binding, accountKey, {
56844
+ accountOnly: true
56845
+ }) : undefined;
56846
+ const outcome = decideCodexSpeed(codexSpeed, modelInfo);
56847
+ const where = this.wireWhere();
56848
+ log(`[Wire] ${where}: ${outcome.note}`);
56849
+ if (!subscription && !codexSpeed.explicit && codexSpeed.value !== "standard") {
56850
+ this.noticeFastIgnored("codex");
56851
+ }
56852
+ if (outcome.refusal) {
56853
+ return c.json(wrapAnthropicError(400, redactForClient(`claudish: ${outcome.refusal} (${where})`), "invalid_request_error"), 400);
56854
+ }
56855
+ if (outcome.tier && requestPayload.service_tier !== undefined) {
56856
+ log(`[Wire] ${where}: service_tier already set by --model-params; speed tier not written`);
56857
+ } else if (outcome.tier) {
56858
+ requestPayload.service_tier = outcome.tier;
56859
+ if (!codexSpeed.explicit)
56860
+ wireBorrowed = [...wireBorrowed, CODEX_SERVICE_TIER_POINTER];
56861
+ }
56862
+ }
56732
56863
  let codeModeShape;
56733
56864
  let codeModePrePayload;
56734
56865
  let codeModeContext;
@@ -58049,7 +58180,7 @@ function getRecoveryHint(status, errorText, providerName, transportTerminal429,
58049
58180
  }
58050
58181
  return `Unexpected HTTP ${status} from ${providerName}.`;
58051
58182
  }
58052
- var STREAM_RETRY_DELAYS_MS;
58183
+ var STREAM_RETRY_DELAYS_MS, fastIgnoredNoticed;
58053
58184
  var init_composed_handler = __esm(() => {
58054
58185
  init_base_api_format();
58055
58186
  init_minimax_model_dialect();
@@ -58076,6 +58207,7 @@ var init_composed_handler = __esm(() => {
58076
58207
  init_raw();
58077
58208
  init_request_stage();
58078
58209
  init_logger();
58210
+ init_codex_models_discovery();
58079
58211
  init_model_parser();
58080
58212
  init_provider_definitions();
58081
58213
  init_openai();
@@ -58114,6 +58246,7 @@ var init_composed_handler = __esm(() => {
58114
58246
  init_transient_retry();
58115
58247
  init_upstream_error_capture();
58116
58248
  STREAM_RETRY_DELAYS_MS = [3000, 15000, 30000];
58249
+ fastIgnoredNoticed = new Set;
58117
58250
  });
58118
58251
 
58119
58252
  // src/providers/api-key-provenance.ts
@@ -71096,6 +71229,14 @@ function loadCustomEndpoints(config) {
71096
71229
  }
71097
71230
  return result;
71098
71231
  }
71232
+ function openaiModelsDiscovery(wireFormat, apiPath, modelPrefix) {
71233
+ if (modelPrefix)
71234
+ return;
71235
+ const api = ["/chat/completions", "/responses"].find((suffix) => apiPath.endsWith(suffix));
71236
+ if (wireFormat !== "openai" || !api)
71237
+ return;
71238
+ return { path: `${apiPath.slice(0, -api.length)}/models`, format: "openai-models-list" };
71239
+ }
71099
71240
  function buildProviderDefinition(name, ep, ovr) {
71100
71241
  const apiKeyEnvVar = ovr?.apiKeyEnvVar ?? customEndpointKeyEnvVar(name);
71101
71242
  const apiKeyAliases = ovr?.apiKeyAliases;
@@ -71120,9 +71261,11 @@ function buildProviderDefinition(name, ep, ovr) {
71120
71261
  isDirectApi: true,
71121
71262
  shortestPrefix: name,
71122
71263
  description: ovr?.description ?? `Custom endpoint: ${name}`,
71123
- authScheme: ep.authScheme ?? "bearer"
71264
+ authScheme: ep.authScheme ?? "bearer",
71265
+ modelDiscovery: openaiModelsDiscovery(ep.format, "/chat/completions", ep.modelPrefix)
71124
71266
  };
71125
71267
  }
71268
+ const apiPath = ep.apiPath ?? "/v1/chat/completions";
71126
71269
  return {
71127
71270
  createHandler: runtimeHandler(name),
71128
71271
  tier: CUSTOM_ENDPOINT_TIER,
@@ -71131,7 +71274,7 @@ function buildProviderDefinition(name, ep, ovr) {
71131
71274
  transport: ep.transport,
71132
71275
  baseUrl: stripTrailingSlash(ep.baseUrl),
71133
71276
  baseUrlEnvVars,
71134
- apiPath: ep.apiPath ?? "/v1/chat/completions",
71277
+ apiPath,
71135
71278
  apiKeyEnvVar,
71136
71279
  apiKeyAliases,
71137
71280
  apiKeyDescription: ovr?.apiKeyDescription ?? `${ep.displayName} (custom endpoint)`,
@@ -71142,7 +71285,8 @@ function buildProviderDefinition(name, ep, ovr) {
71142
71285
  shortestPrefix: name,
71143
71286
  description: ovr?.description ?? `Custom endpoint: ${ep.displayName}`,
71144
71287
  headers: ep.headers,
71145
- authScheme: ep.authScheme ?? "bearer"
71288
+ authScheme: ep.authScheme ?? "bearer",
71289
+ modelDiscovery: openaiModelsDiscovery(ep.transport, apiPath, ep.modelPrefix)
71146
71290
  };
71147
71291
  }
71148
71292
  function buildProviderProfile(ep, ovr) {
@@ -72000,7 +72144,7 @@ function isCacheFresh(data, ttlMs = CACHE_TTL_MS4) {
72000
72144
  const generatedMs = Date.parse(data.generatedAt);
72001
72145
  return !Number.isNaN(generatedMs) && Date.now() - generatedMs < ttlMs;
72002
72146
  }
72003
- async function fetchProbeModels(url = PROBE_MODELS_URL, timeoutMs = FETCH_TIMEOUT_MS5) {
72147
+ async function fetchProbeModels(url = probeModelsUrl(), timeoutMs = FETCH_TIMEOUT_MS5) {
72004
72148
  let response;
72005
72149
  try {
72006
72150
  response = await fetch(url, {
@@ -72131,8 +72275,9 @@ function isValidResponse(raw) {
72131
72275
  const data = raw;
72132
72276
  return data.version === 3 && typeof data.generationId === "string" && data.generationId.length > 0 && typeof data.generatedAt === "string" && !!data.providers && typeof data.providers === "object" && !!data.unavailable && typeof data.unavailable === "object";
72133
72277
  }
72134
- var PROBE_MODELS_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/probeModels", CACHE_TTL_MS4, FETCH_TIMEOUT_MS5 = 15000, PROBE_MODELS_CACHE_PATH, _inFlight = null, DISCOVERY_ATTEMPTS = 3, DISCOVERY_TIMEOUT_MS = 8000;
72278
+ var CACHE_TTL_MS4, FETCH_TIMEOUT_MS5 = 15000, PROBE_MODELS_CACHE_PATH, _inFlight = null, DISCOVERY_ATTEMPTS = 3, DISCOVERY_TIMEOUT_MS = 8000;
72135
72279
  var init_probe_catalog = __esm(() => {
72280
+ init_catalog_endpoints();
72136
72281
  init_catalog_route_bindings();
72137
72282
  CACHE_TTL_MS4 = 60 * 60 * 1000;
72138
72283
  PROBE_MODELS_CACHE_PATH = join33(homedir31(), ".claudish", "probe-models.json");
@@ -73517,6 +73662,46 @@ function claudeCodeKeychainServiceCandidates(env = process.env) {
73517
73662
  var BASE_KEYCHAIN_SERVICE = "Claude Code", KEYCHAIN_SERVICE_SUFFIX = "-credentials";
73518
73663
  var init_claude_code_facts = () => {};
73519
73664
 
73665
+ // src/fast-mode-gates.ts
73666
+ function applyProxyFastModeGates(env) {
73667
+ scrubInheritedFastModeGates(env);
73668
+ if (env.CLAUDE_CODE_DISABLE_FAST_MODE)
73669
+ return;
73670
+ const opened = [];
73671
+ if (env.CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK === undefined) {
73672
+ env.CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK = "1";
73673
+ opened.push("skip");
73674
+ }
73675
+ const caps = env.CLAUDE_CODE_MODEL_CAPABILITIES;
73676
+ env.CLAUDE_CODE_MODEL_CAPABILITIES = caps ? `${FAST_MODE_CAPABILITY};${caps}` : FAST_MODE_CAPABILITY;
73677
+ opened.push("caps");
73678
+ env[CLAUDISH_FAST_MODE_GATES_VAR] = opened.join(",");
73679
+ }
73680
+ function scrubInheritedFastModeGates(env) {
73681
+ const marker = env[CLAUDISH_FAST_MODE_GATES_VAR];
73682
+ if (marker === undefined)
73683
+ return { removed: [] };
73684
+ const opened = marker.split(",");
73685
+ const removed = [];
73686
+ if (opened.includes("skip") && env.CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK === "1") {
73687
+ delete env.CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK;
73688
+ removed.push("CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK");
73689
+ }
73690
+ const caps = env.CLAUDE_CODE_MODEL_CAPABILITIES;
73691
+ if (opened.includes("caps") && caps !== undefined) {
73692
+ if (caps === FAST_MODE_CAPABILITY) {
73693
+ delete env.CLAUDE_CODE_MODEL_CAPABILITIES;
73694
+ removed.push("CLAUDE_CODE_MODEL_CAPABILITIES");
73695
+ } else if (caps.startsWith(`${FAST_MODE_CAPABILITY};`)) {
73696
+ env.CLAUDE_CODE_MODEL_CAPABILITIES = caps.slice(FAST_MODE_CAPABILITY.length + 1);
73697
+ removed.push("CLAUDE_CODE_MODEL_CAPABILITIES");
73698
+ }
73699
+ }
73700
+ delete env[CLAUDISH_FAST_MODE_GATES_VAR];
73701
+ return { removed };
73702
+ }
73703
+ var CLAUDISH_FAST_MODE_GATES_VAR = "CLAUDISH_FAST_MODE_GATES", FAST_MODE_CAPABILITY = "fast_mode";
73704
+
73520
73705
  // src/hooks/session/binding.ts
73521
73706
  function sessionHooksNeedBinding(engine) {
73522
73707
  return BINDING_EVENTS.some((e) => engine.select(e).length > 0);
@@ -77309,6 +77494,34 @@ var init_no_surface = __esm(() => {
77309
77494
  init_binding();
77310
77495
  });
77311
77496
 
77497
+ // src/host-routing-env.ts
77498
+ function applyHostRouting(env) {
77499
+ env[ENV.CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST] = "1";
77500
+ env[ENV.CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL] = "";
77501
+ env[ENV.CLAUDISH_SET_HOST_ROUTING_VARS] = "1";
77502
+ }
77503
+ function scrubInheritedHostRouting(env) {
77504
+ if (env[ENV.CLAUDISH_SET_HOST_ROUTING_VARS] !== "1")
77505
+ return { removed: [] };
77506
+ const removed = [];
77507
+ for (const name of HOST_ROUTING_VARS) {
77508
+ if (name in env) {
77509
+ delete env[name];
77510
+ removed.push(name);
77511
+ }
77512
+ }
77513
+ return { removed };
77514
+ }
77515
+ var HOST_ROUTING_VARS;
77516
+ var init_host_routing_env = __esm(() => {
77517
+ init_config();
77518
+ HOST_ROUTING_VARS = [
77519
+ ENV.CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST,
77520
+ ENV.CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL,
77521
+ ENV.CLAUDISH_SET_HOST_ROUTING_VARS
77522
+ ];
77523
+ });
77524
+
77312
77525
  // src/launcher/magmux-binary.ts
77313
77526
  import { execSync } from "child_process";
77314
77527
  import { existsSync as existsSync28 } from "fs";
@@ -78112,7 +78325,8 @@ async function getRecommendedModels(opts = {}) {
78112
78325
  const generationId = readAllModelsCache()?.catalogGenerationId;
78113
78326
  if (!generationId)
78114
78327
  throw new Error("No complete v3 model and plan snapshot");
78115
- const response = await fetchCatalogData(FIREBASE_RECOMMENDED_URL, RECOMMENDED_FETCH_TIMEOUT_MS, generationId);
78328
+ const base = modelsBaseUrl();
78329
+ const response = await fetchCatalogData(`${base}${RECOMMENDED_VIEW}`, RECOMMENDED_FETCH_TIMEOUT_MS, generationId);
78116
78330
  if (response.mode !== "recommended")
78117
78331
  throw new Error("Unexpected recommendation mode");
78118
78332
  if (response.recommendations.generationId !== generationId) {
@@ -78123,7 +78337,7 @@ async function getRecommendedModels(opts = {}) {
78123
78337
  } catch (err) {
78124
78338
  log(`[effort] sidecar write failed for generation ${generationId}: ${err instanceof Error ? err.message : String(err)}`);
78125
78339
  }
78126
- const top100 = await fetchCatalogData(`${FIREBASE_BASE_URL}?catalog=top100`, RECOMMENDED_FETCH_TIMEOUT_MS, generationId);
78340
+ const top100 = await fetchCatalogData(`${base}?catalog=top100`, RECOMMENDED_FETCH_TIMEOUT_MS, generationId);
78127
78341
  const data = recommendationProjection(response.recommendations, top100.models);
78128
78342
  if (data.models.length > 0) {
78129
78343
  _cachedRecommendedModels = data;
@@ -78167,27 +78381,27 @@ function isFreshEnough(doc) {
78167
78381
  return ageHours <= FIREBASE_CACHE_TTL_HOURS;
78168
78382
  }
78169
78383
  async function searchModels(query, limit = 50) {
78170
- const url = `${FIREBASE_BASE_URL}?search=${encodeURIComponent(query)}&limit=${limit}&status=active`;
78384
+ const url = `${modelsBaseUrl()}?search=${encodeURIComponent(query)}&limit=${limit}&status=active`;
78171
78385
  const data = await fetchCatalogData(url, SEARCH_FETCH_TIMEOUT_MS);
78172
78386
  return data.models ?? [];
78173
78387
  }
78174
78388
  async function getModelByIdFromFirebase(modelId) {
78175
- const url = `${FIREBASE_BASE_URL}?modelId=${encodeURIComponent(modelId)}`;
78389
+ const url = `${modelsBaseUrl()}?modelId=${encodeURIComponent(modelId)}`;
78176
78390
  const data = await fetchCatalogData(url, SEARCH_FETCH_TIMEOUT_MS);
78177
78391
  return data.mode === "exact" ? data.model : null;
78178
78392
  }
78179
78393
  async function getTop100Models() {
78180
- const url = `${FIREBASE_BASE_URL}?catalog=top100`;
78394
+ const url = `${modelsBaseUrl()}?catalog=top100`;
78181
78395
  const data = await fetchCatalogData(url, SEARCH_FETCH_TIMEOUT_MS);
78182
78396
  return data;
78183
78397
  }
78184
78398
  async function getProviderList() {
78185
- const url = `${FIREBASE_BASE_URL}?catalog=providers`;
78399
+ const url = `${modelsBaseUrl()}?catalog=providers`;
78186
78400
  const data = await fetchCatalogData(url, SEARCH_FETCH_TIMEOUT_MS);
78187
78401
  return data.providers ?? [];
78188
78402
  }
78189
78403
  async function getModelsByProvider(provider, pageSize = 200) {
78190
- const base = `${FIREBASE_BASE_URL}?provider=${encodeURIComponent(provider)}&status=active&limit=${pageSize}`;
78404
+ const base = `${modelsBaseUrl()}?provider=${encodeURIComponent(provider)}&status=active&limit=${pageSize}`;
78191
78405
  return fetchPinnedModelDocs(base, "provider catalog");
78192
78406
  }
78193
78407
  async function fetchPinnedModelDocs(base, label) {
@@ -78225,7 +78439,7 @@ async function fetchPinnedModelDocs(base, label) {
78225
78439
  throw new Error(`${Label} exceeded the pagination limit`);
78226
78440
  }
78227
78441
  async function getAllModelDocs(pageSize = 200) {
78228
- const base = `${FIREBASE_BASE_URL}?status=active&limit=${pageSize}`;
78442
+ const base = `${modelsBaseUrl()}?status=active&limit=${pageSize}`;
78229
78443
  return fetchPinnedModelDocs(base, "model catalog");
78230
78444
  }
78231
78445
  function loadModelInfo() {
@@ -78261,7 +78475,7 @@ function getAvailableModels() {
78261
78475
  _cachedModelIds = result;
78262
78476
  return result;
78263
78477
  }
78264
- var RECOMMENDATION_SECTIONS, RECOMMENDATION_TIER_INDEX, _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels = null, FIREBASE_BASE_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/queryModels", FIREBASE_RECOMMENDED_URL, RECOMMENDED_PROJECTION_VERSION = 2, RECOMMENDED_MODELS_CACHE_PATH, RECOMMENDED_FETCH_TIMEOUT_MS = 5000, SEARCH_FETCH_TIMEOUT_MS = 1e4, RECOMMENDED_ROUTE_TIER_ORDER;
78478
+ var RECOMMENDATION_SECTIONS, RECOMMENDATION_TIER_INDEX, _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels = null, RECOMMENDED_VIEW = "?catalog=recommended", RECOMMENDED_PROJECTION_VERSION = 2, RECOMMENDED_MODELS_CACHE_PATH, RECOMMENDED_FETCH_TIMEOUT_MS = 5000, SEARCH_FETCH_TIMEOUT_MS = 1e4, RECOMMENDED_ROUTE_TIER_ORDER;
78265
78479
  var init_model_loader = __esm(() => {
78266
78480
  init_fs_atomic();
78267
78481
  init_logger();
@@ -78269,6 +78483,7 @@ var init_model_loader = __esm(() => {
78269
78483
  init_auto_route();
78270
78484
  init_cache_ttl();
78271
78485
  init_catalog_client();
78486
+ init_catalog_endpoints();
78272
78487
  init_catalog_route_bindings();
78273
78488
  init_effort_recommendations();
78274
78489
  init_route_candidates();
@@ -78290,7 +78505,6 @@ var init_model_loader = __esm(() => {
78290
78505
  { recommendationTier: "subscription", title: "Subscription", quickPickEligible: true }
78291
78506
  ];
78292
78507
  RECOMMENDATION_TIER_INDEX = new Map(RECOMMENDATION_SECTIONS.map((section, index) => [section.recommendationTier, index]));
78293
- FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
78294
78508
  RECOMMENDED_MODELS_CACHE_PATH = join41(homedir33(), ".claudish", "recommended-models-cache-v2.json");
78295
78509
  RECOMMENDED_ROUTE_TIER_ORDER = {
78296
78510
  native: 0,
@@ -96304,6 +96518,12 @@ function scrubInheritedClaudishPlaceholders(env) {
96304
96518
  }
96305
96519
  return { removed };
96306
96520
  }
96521
+ function removeInheritedHostRouting(env) {
96522
+ const { removed } = scrubInheritedHostRouting(env);
96523
+ if (removed.length > 0) {
96524
+ log(`[claude-runner] Removed inherited host-routing variables: ${removed.join(", ")}`);
96525
+ }
96526
+ }
96307
96527
  function isClaudishPlaceholderCredential(name, value) {
96308
96528
  if (name === "ANTHROPIC_API_KEY")
96309
96529
  return value === CLAUDISH_PLACEHOLDER_API_KEY;
@@ -97072,6 +97292,8 @@ async function runClaudeWithProxy(config, proxyUrl, onCleanup) {
97072
97292
  if (config.monitor || advisorNativeSession) {
97073
97293
  delete env.ANTHROPIC_API_KEY;
97074
97294
  delete env.ANTHROPIC_AUTH_TOKEN;
97295
+ scrubInheritedFastModeGates(env);
97296
+ removeInheritedHostRouting(env);
97075
97297
  if (modelId) {
97076
97298
  env[ENV.ANTHROPIC_MODEL] = modelId;
97077
97299
  env[ENV.ANTHROPIC_SMALL_FAST_MODEL] = modelId;
@@ -97086,15 +97308,22 @@ async function runClaudeWithProxy(config, proxyUrl, onCleanup) {
97086
97308
  if (scrubbed.removed.length > 0) {
97087
97309
  log(`[claude-runner] Removed inherited claudish placeholder credentials: ${scrubbed.removed.join(", ")}`);
97088
97310
  }
97311
+ removeInheritedHostRouting(env);
97089
97312
  if (shouldHideIncidentalAnthropicKey(config, env)) {
97090
97313
  delete env.ANTHROPIC_API_KEY;
97091
97314
  hidAnthropicApiKey = true;
97092
97315
  }
97316
+ const closedGates = scrubInheritedFastModeGates(env);
97317
+ if (closedGates.removed.length > 0) {
97318
+ log(`[claude-runner] Removed inherited claudish fast-mode gates: ${closedGates.removed.join(", ")}`);
97319
+ }
97093
97320
  } else {
97094
97321
  if (classifierPassthroughEnabled(config)) {
97095
97322
  console.error("[claudish] classifier passthrough enabled but no Anthropic credentials detected \u2014 " + "classifier requests will fail to authenticate against api.anthropic.com. " + "Map a role to a native Claude model (e.g. --model-sonnet claude-sonnet-5) or set ANTHROPIC_API_KEY.");
97096
97323
  }
97097
97324
  applyProxyPlaceholderAuth(env);
97325
+ applyProxyFastModeGates(env);
97326
+ applyHostRouting(env);
97098
97327
  const realWindow = await computeMainThreadContextWindow(config);
97099
97328
  const contextEnv = resolveContextWindowEnv(realWindow, process.env);
97100
97329
  Object.assign(env, contextEnv.vars);
@@ -97429,6 +97658,7 @@ var init_claude_runner = __esm(() => {
97429
97658
  init_interactive_driver();
97430
97659
  init_interactive_launch();
97431
97660
  init_no_surface();
97661
+ init_host_routing_env();
97432
97662
  init_magmux_wrapper();
97433
97663
  init_logger();
97434
97664
  init_child_env();
@@ -106235,6 +106465,8 @@ function claudeCodePrintEnv(parent) {
106235
106465
  delete env.ANTHROPIC_API_KEY;
106236
106466
  delete env.ANTHROPIC_AUTH_TOKEN;
106237
106467
  delete env.ANTHROPIC_BASE_URL;
106468
+ scrubInheritedFastModeGates(env);
106469
+ scrubInheritedHostRouting(env);
106238
106470
  return env;
106239
106471
  }
106240
106472
  function isFrame(v) {
@@ -106425,6 +106657,7 @@ function startError(command, e) {
106425
106657
  var PRINT_FLAGS, PRINT_CHILD_DROPPED_MARKERS, inFlight4, KILL_GRACE_MS = 5000, STDERR_TAIL_CHARS = 2000;
106426
106658
  var init_run_prompt_claude_code = __esm(() => {
106427
106659
  init_config();
106660
+ init_host_routing_env();
106428
106661
  init_child_env();
106429
106662
  init_pane_launch();
106430
106663
  init_redact();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "14.16.2",
3
+ "version": "14.17.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",
@@ -71,10 +71,10 @@
71
71
  "ai"
72
72
  ],
73
73
  "optionalDependencies": {
74
- "@claudish/magmux-darwin-arm64": "14.16.2",
75
- "@claudish/magmux-darwin-x64": "14.16.2",
76
- "@claudish/magmux-linux-arm64": "14.16.2",
77
- "@claudish/magmux-linux-x64": "14.16.2"
74
+ "@claudish/magmux-darwin-arm64": "14.17.0",
75
+ "@claudish/magmux-darwin-x64": "14.17.0",
76
+ "@claudish/magmux-linux-arm64": "14.17.0",
77
+ "@claudish/magmux-linux-x64": "14.17.0"
78
78
  },
79
79
  "author": "Jack Rudenko <i@madappgang.com>",
80
80
  "license": "MIT",