claude-use 11.41.0 → 11.42.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/cli.cjs CHANGED
@@ -27528,6 +27528,9 @@ function pruneDeadFrontDoorDirectRecords(fs26, recordsDir, records, liveness) {
27528
27528
  }
27529
27529
  }
27530
27530
  }
27531
+ function recordOf(details) {
27532
+ return details === void 0 ? {} : { sessionId: details.sessionId, ...details.models === void 0 ? {} : { models: details.models } };
27533
+ }
27531
27534
  function writeFrontDoorSession(fs26, sessionsDir, session) {
27532
27535
  fs26.mkdirPrivate(sessionsDir);
27533
27536
  fs26.writeFilePrivate(import_node_path5.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
@@ -27580,14 +27583,31 @@ function liveSessionTokens(fs26, sessionsDir) {
27580
27583
  }
27581
27584
  return tokens;
27582
27585
  }
27586
+ function readFrontDoorSessionModels(fs26, sessionsDir, sessionId) {
27587
+ for (const name of fs26.readdir(sessionsDir)) {
27588
+ if (!name.endsWith(".json")) {
27589
+ continue;
27590
+ }
27591
+ try {
27592
+ const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs26.readFileUtf8(import_node_path5.default.join(sessionsDir, name)) ?? ""));
27593
+ if (parsed.success && parsed.data.sessionId === sessionId) {
27594
+ return parsed.data.models;
27595
+ }
27596
+ } catch {
27597
+ continue;
27598
+ }
27599
+ }
27600
+ return void 0;
27601
+ }
27583
27602
  var import_node_path5, FRONT_DOOR_PROTOCOL, FrontDoorSessionSchema, FrontDoorStateSchema, MAX_TCP_PORT, FrontDoorDirectRecordSchema, RECORD_TEMPORARY_FILE;
27584
27603
  var init_state = __esm({
27585
27604
  "src/frontdoor/state.ts"() {
27586
27605
  "use strict";
27587
27606
  import_node_path5 = __toESM(require("node:path"), 1);
27588
27607
  init_zod();
27608
+ init_schema();
27589
27609
  FRONT_DOOR_PROTOCOL = 4;
27590
- FrontDoorSessionSchema = external_exports.strictObject({ pid: external_exports.number().int().positive(), startedAt: external_exports.number(), token: external_exports.string().min(1), supervisorPid: external_exports.number().int().positive().optional() });
27610
+ FrontDoorSessionSchema = external_exports.strictObject({ pid: external_exports.number().int().positive(), startedAt: external_exports.number(), token: external_exports.string().min(1), supervisorPid: external_exports.number().int().positive().optional(), sessionId: external_exports.string().min(1).optional(), models: ModelsConfigSchema.optional() });
27591
27611
  FrontDoorStateSchema = external_exports.strictObject({
27592
27612
  /**
27593
27613
  * The launcher-to-door wire protocol this supervisor speaks, written once it is serving; absent in state written by a release that predates the field, which `ensureFrontDoor` reads as protocol 0. A launcher replaces a door whose protocol is lower than its own (see `FRONT_DOOR_PROTOCOL`).
@@ -32142,7 +32162,8 @@ function assembleCascade(input2) {
32142
32162
  ...config2.categories === void 0 ? {} : { categories: config2.categories },
32143
32163
  ...config2.entries === void 0 ? {} : { entries: config2.entries },
32144
32164
  ...entryOrder === void 0 ? {} : { entryOrder },
32145
- ...config2.launch === void 0 ? {} : { launch: config2.launch }
32165
+ ...config2.launch === void 0 ? {} : { launch: config2.launch },
32166
+ ...config2.models === void 0 ? {} : { models: config2.models }
32146
32167
  });
32147
32168
  nextId += 1;
32148
32169
  }
@@ -34676,7 +34697,7 @@ var init_package = __esm({
34676
34697
  "package.json"() {
34677
34698
  package_default = {
34678
34699
  name: "claude-use",
34679
- version: "11.41.0",
34700
+ version: "11.42.0",
34680
34701
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
34681
34702
  license: "MIT",
34682
34703
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -36251,6 +36272,219 @@ var init_realCredentialCache = __esm({
36251
36272
  }
36252
36273
  });
36253
36274
 
36275
+ // src/models/identity.ts
36276
+ function withoutContextMarker(model) {
36277
+ return model.toLowerCase().endsWith(CONTEXT_MARKER_1M) ? model.slice(0, -CONTEXT_MARKER_1M.length) : model;
36278
+ }
36279
+ function canonicalText(name) {
36280
+ return name.trim().toLowerCase().replace(NON_IDENTITY_BRACKET_RE, "").replace(/[\s_]+/g, "-").replace(/([a-z])(\d+(?:\.\d+)+)/g, "$1-$2").replace(/-+/g, "-").replace(/^-|-$/g, "");
36281
+ }
36282
+ function splitVariants(tokens) {
36283
+ const variants = [];
36284
+ let end = tokens.length;
36285
+ for (; ; ) {
36286
+ const token = tokens[end - 1];
36287
+ if (token === void 0 || !KNOWN_VARIANTS.has(token)) {
36288
+ return { familyTokens: tokens.slice(0, end), variants };
36289
+ }
36290
+ variants.unshift(token);
36291
+ end -= 1;
36292
+ }
36293
+ }
36294
+ function versionOf(tokens) {
36295
+ for (let index = 0; index < tokens.length; index += 1) {
36296
+ const token = tokens[index];
36297
+ const next = tokens[index + 1];
36298
+ if (token === void 0) {
36299
+ return "";
36300
+ }
36301
+ if (/^\d+$/.test(token) && next !== void 0 && /^\d+$/.test(next)) {
36302
+ return `${token}.${next}`;
36303
+ }
36304
+ const dotted = /^\d+(?:\.\d+)+$/.exec(token);
36305
+ if (dotted !== null) {
36306
+ return dotted[0];
36307
+ }
36308
+ }
36309
+ return "";
36310
+ }
36311
+ function modelIdentity(rawName) {
36312
+ const segments = rawName.trim().toLowerCase().split("/");
36313
+ const stripped = canonicalText(segments[segments.length - 1] ?? "").split(":")[0] ?? "";
36314
+ const withoutDate = stripped.replace(DATE_STAMP_RE, "");
36315
+ const tokens = withoutDate.split("-").filter((token) => token !== "");
36316
+ const { familyTokens, variants } = splitVariants(tokens);
36317
+ const version2 = versionOf(familyTokens);
36318
+ const versionless = familyTokens.filter((token, index) => {
36319
+ if (version2 === "") {
36320
+ return true;
36321
+ }
36322
+ const dotted = /^\d+(?:\.\d+)+$/.test(token);
36323
+ const previous = familyTokens[index - 1];
36324
+ const next = familyTokens[index + 1];
36325
+ const insideVersionRun = dotted || /^\d+$/.test(token) && (previous !== void 0 && /^\d+$/.test(previous) || next !== void 0 && /^\d+$/.test(next));
36326
+ return !insideVersionRun;
36327
+ });
36328
+ const family = versionless.join("-");
36329
+ const tokenVendor = familyTokens.find((token) => Object.keys(VENDOR_BY_TOKEN).some((key) => token === key || token.startsWith(key)));
36330
+ const namespace = segments.length >= 2 ? (segments[0] ?? "").split(":").pop() ?? "" : "";
36331
+ const namespaceVendor = VENDOR_BY_NAMESPACE[namespace] ?? "";
36332
+ const tokenVendorName = tokenVendor === void 0 ? "" : VENDOR_BY_TOKEN[Object.keys(VENDOR_BY_TOKEN).find((key) => tokenVendor === key || tokenVendor.startsWith(key)) ?? ""] ?? "";
36333
+ return {
36334
+ vendor: tokenVendorName === "" ? namespaceVendor : tokenVendorName,
36335
+ vendorConflict: tokenVendorName !== "" && namespaceVendor !== "" && tokenVendorName !== namespaceVendor,
36336
+ family,
36337
+ version: version2,
36338
+ variant: variants.join("-"),
36339
+ familyAndVersion: version2 === "" ? family : `${family}-${version2.replace(/\./g, "-")}`
36340
+ };
36341
+ }
36342
+ function relateModels(left, right) {
36343
+ const a10 = modelIdentity(left);
36344
+ const b = modelIdentity(right);
36345
+ if (a10.familyAndVersion !== b.familyAndVersion) {
36346
+ return sameFamilyOtherVersion(a10, b) ? "similar" : "distinct";
36347
+ }
36348
+ if (a10.variant !== b.variant || a10.vendorConflict || b.vendorConflict || a10.vendor !== "" && b.vendor !== "" && a10.vendor !== b.vendor) {
36349
+ return "similar";
36350
+ }
36351
+ return "same";
36352
+ }
36353
+ function sameFamilyOtherVersion(a10, b) {
36354
+ if (a10.family !== b.family) {
36355
+ return false;
36356
+ }
36357
+ if (a10.vendor !== "" && b.vendor !== "" && a10.vendor !== b.vendor) {
36358
+ return false;
36359
+ }
36360
+ return true;
36361
+ }
36362
+ var NON_IDENTITY_BRACKET_RE, CONTEXT_MARKER_1M, DATE_STAMP_RE, KNOWN_VARIANTS, VENDOR_BY_NAMESPACE, VENDOR_BY_TOKEN;
36363
+ var init_identity2 = __esm({
36364
+ "src/models/identity.ts"() {
36365
+ "use strict";
36366
+ NON_IDENTITY_BRACKET_RE = /\[[^\]]*\]/g;
36367
+ CONTEXT_MARKER_1M = "[1m]";
36368
+ DATE_STAMP_RE = /-(?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])$/;
36369
+ KNOWN_VARIANTS = /* @__PURE__ */ new Set(["high", "medium", "low", "thinking", "xhigh", "max", "highspeed", "sol", "terra", "luna", "mini", "flash-lite", "turbo"]);
36370
+ VENDOR_BY_NAMESPACE = Object.freeze({
36371
+ anthropic: "anthropic",
36372
+ google: "google",
36373
+ openai: "openai",
36374
+ zai: "zai",
36375
+ "z-ai": "zai",
36376
+ minimax: "minimax",
36377
+ qwen: "qwen",
36378
+ deepseek: "deepseek",
36379
+ moonshot: "moonshot",
36380
+ meta: "meta",
36381
+ mistral: "mistral"
36382
+ });
36383
+ VENDOR_BY_TOKEN = Object.freeze({
36384
+ claude: "anthropic",
36385
+ gemini: "google",
36386
+ antigravity: "google",
36387
+ gpt: "openai",
36388
+ glm: "zai",
36389
+ minimax: "minimax",
36390
+ qwen: "qwen",
36391
+ deepseek: "deepseek",
36392
+ kimi: "moonshot",
36393
+ llama: "meta",
36394
+ mistral: "mistral",
36395
+ mixtral: "mistral"
36396
+ });
36397
+ }
36398
+ });
36399
+
36400
+ // src/models/families.ts
36401
+ function modelOf(ref) {
36402
+ const slash = ref.indexOf("/");
36403
+ return slash === -1 ? ref : ref.slice(slash + 1);
36404
+ }
36405
+ function familyKeyOf(rawModel) {
36406
+ const identity = modelIdentity(rawModel);
36407
+ return identity.variant === "" ? identity.familyAndVersion : `${identity.familyAndVersion}${VARIANT_SEPARATOR}${identity.variant}`;
36408
+ }
36409
+ function assertionsOf(models) {
36410
+ return { same: models?.same ?? [], distinct: models?.distinct ?? [] };
36411
+ }
36412
+ function sameModel(left, right, assertions) {
36413
+ if (assertions.distinct.some(([a10, b]) => a10 === left && b === right || a10 === right && b === left)) {
36414
+ return false;
36415
+ }
36416
+ const leftGroup = assertions.same.find((group) => group.includes(left));
36417
+ const rightGroup = assertions.same.find((group) => group.includes(right));
36418
+ if (leftGroup !== void 0 && leftGroup === rightGroup) {
36419
+ return true;
36420
+ }
36421
+ if (leftGroup !== void 0 && !leftGroup.includes(right) || rightGroup !== void 0 && !rightGroup.includes(left)) {
36422
+ return false;
36423
+ }
36424
+ return relateModels(modelOf(left), modelOf(right)) === "same";
36425
+ }
36426
+ function pinnedTo(settings2, ref) {
36427
+ return settings2?.names?.some((name) => name === ref || name === modelOf(ref)) === true;
36428
+ }
36429
+ function buildFamilies(refs, models) {
36430
+ const assertions = assertionsOf(models);
36431
+ const settingsByKey = models?.families ?? {};
36432
+ const groups = [];
36433
+ for (const ref of refs) {
36434
+ const pinnedKey = Object.entries(settingsByKey).find(([, settings2]) => pinnedTo(settings2, ref))?.[0];
36435
+ const joined2 = groups.find((group) => pinnedKey === void 0 ? group.refs.some((first) => sameModel(first, ref, assertions)) : group.key === pinnedKey);
36436
+ if (joined2 !== void 0) {
36437
+ joined2.refs.push(ref);
36438
+ } else {
36439
+ groups.push({ key: pinnedKey ?? familyKeyOf(modelOf(ref)), refs: [ref] });
36440
+ }
36441
+ }
36442
+ return groups.map((group) => ({ key: group.key, refs: group.refs, settings: settingsByKey[group.key] ?? {} }));
36443
+ }
36444
+ function familyNamed(families, member) {
36445
+ if (!member.startsWith(FAMILY_PREFIX)) {
36446
+ return void 0;
36447
+ }
36448
+ const key = member.slice(FAMILY_PREFIX.length);
36449
+ return families.find((family) => family.key === key);
36450
+ }
36451
+ function familyCapabilities(settings2) {
36452
+ return { vision: settings2.vision ?? true, tools: settings2.tools ?? true, thinking: settings2.thinking ?? true };
36453
+ }
36454
+ function familyMode(settings2) {
36455
+ return settings2.mode ?? "ordered";
36456
+ }
36457
+ function sharedFamilies(families) {
36458
+ return families.filter((family) => family.refs.length > 1);
36459
+ }
36460
+ function expandFamilyMembers(members2, families) {
36461
+ const expanded = [];
36462
+ for (const member of members2) {
36463
+ for (const ref of member.startsWith(FAMILY_PREFIX) ? familyNamed(families, member)?.refs ?? [] : [member]) {
36464
+ if (!expanded.includes(ref)) {
36465
+ expanded.push(ref);
36466
+ }
36467
+ }
36468
+ }
36469
+ return expanded;
36470
+ }
36471
+ function familyOfRef(families, ref) {
36472
+ return families.find((family) => family.refs.includes(ref));
36473
+ }
36474
+ function accountRefsOf(models) {
36475
+ const named = [...(models?.same ?? []).flat(), ...Object.values(models?.families ?? {}).flatMap((settings2) => settings2.names ?? [])];
36476
+ return [...new Set(named.filter((ref) => ref.startsWith("acct:")))];
36477
+ }
36478
+ var FAMILY_PREFIX, VARIANT_SEPARATOR;
36479
+ var init_families = __esm({
36480
+ "src/models/families.ts"() {
36481
+ "use strict";
36482
+ init_identity2();
36483
+ FAMILY_PREFIX = "family:";
36484
+ VARIANT_SEPARATOR = "+";
36485
+ }
36486
+ });
36487
+
36254
36488
  // src/providersStore.ts
36255
36489
  function providerJsonPath(paths, name) {
36256
36490
  return import_node_path29.default.join(paths.providersDir, `${name}.json`);
@@ -36545,8 +36779,15 @@ function resolveRoutedProviderCredentials(params) {
36545
36779
  }
36546
36780
  const virtualNames = new Set(Object.keys(models.virtual ?? {}));
36547
36781
  const providerNames = /* @__PURE__ */ new Set();
36782
+ const families = () => buildFamilies(params.targets?.() ?? [], models);
36548
36783
  const collect = (ref) => {
36549
- if (ref.startsWith("acct:") || ref.startsWith("family:") || virtualNames.has(ref)) {
36784
+ if (ref.startsWith(FAMILY_PREFIX)) {
36785
+ for (const target of expandFamilyMembers([ref], families())) {
36786
+ collect(target);
36787
+ }
36788
+ return;
36789
+ }
36790
+ if (ref.startsWith("acct:") || virtualNames.has(ref)) {
36550
36791
  return;
36551
36792
  }
36552
36793
  const [provider] = ref.split("/", 1);
@@ -36603,6 +36844,7 @@ var init_providersStore = __esm({
36603
36844
  init_cliError();
36604
36845
  init_credential();
36605
36846
  init_walk();
36847
+ init_families();
36606
36848
  ProviderNotFoundError = class extends CliError {
36607
36849
  constructor(name) {
36608
36850
  super(`No provider named "${name}". Run \`agent-shim provider add ${name}\` first.`);
@@ -62713,7 +62955,7 @@ function ensureFrontDoor(params) {
62713
62955
  if (state?.port !== void 0 && state.connectPort !== void 0) {
62714
62956
  if (supervisorPid === params.launcherPid && params.replace !== true && ports.isFrontDoorSupervisor(supervisorPid)) {
62715
62957
  const token = (0, import_node_crypto11.randomUUID)();
62716
- writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token, supervisorPid });
62958
+ writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token, supervisorPid, ...recordOf(params.session) });
62717
62959
  return { port: state.port, connectPort: state.connectPort, token };
62718
62960
  }
62719
62961
  const verdict = verifyWithRetry(state.port);
@@ -62727,7 +62969,7 @@ function ensureFrontDoor(params) {
62727
62969
  }
62728
62970
  if (verdict.ok) {
62729
62971
  const token = (0, import_node_crypto11.randomUUID)();
62730
- writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token, supervisorPid });
62972
+ writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token, supervisorPid, ...recordOf(params.session) });
62731
62973
  return { port: state.port, connectPort: state.connectPort, token };
62732
62974
  }
62733
62975
  lastRejection = `the listener on 127.0.0.1:${String(state.port)} (recorded for pid ${String(supervisorPid)}) failed authentication: ${verdict.reason}`;
@@ -62993,8 +63235,8 @@ function realRestartFrontDoor(paths, spawnDaemon) {
62993
63235
  }
62994
63236
  function realFrontDoorPort(paths, spawnDaemon) {
62995
63237
  return {
62996
- ensure: (inheritedExtraCaCerts) => {
62997
- const up2 = ensureFrontDoor({ paths, launcherPid: process.pid, ports: realEnsurePorts(paths, spawnDaemon) });
63238
+ ensure: (inheritedExtraCaCerts, session) => {
63239
+ const up2 = ensureFrontDoor({ paths, launcherPid: process.pid, ports: realEnsurePorts(paths, spawnDaemon), ...session === void 0 ? {} : { session } });
62998
63240
  const trust = resolveTrustBundle({ caCertFile: paths.frontdoorCaCertFile, bundlesDir: paths.frontdoorCaBundlesDir, variable: "NODE_EXTRA_CA_CERTS", inherited: inheritedExtraCaCerts, fs: realTrustBundleFs });
62999
63241
  return {
63000
63242
  port: up2.port,
@@ -63796,6 +64038,14 @@ function buildEnv(params) {
63796
64038
  env[key] = value2;
63797
64039
  }
63798
64040
  }
64041
+ if (params.routeByName) {
64042
+ for (const tier of CLAUDE_TIERS) {
64043
+ const ref = params.tierModels?.[tier];
64044
+ if (ref !== void 0) {
64045
+ env[`ANTHROPIC_DEFAULT_${tier.toUpperCase()}_MODEL`] = ref;
64046
+ }
64047
+ }
64048
+ }
63799
64049
  if (params.provider !== void 0) {
63800
64050
  env.ANTHROPIC_AUTH_TOKEN = params.remoteControl ? void 0 : PROVIDER_SESSION_PLACEHOLDER;
63801
64051
  env.ANTHROPIC_API_KEY = void 0;
@@ -63838,6 +64088,7 @@ var init_flags = __esm({
63838
64088
  init_envBool();
63839
64089
  init_cliError();
63840
64090
  init_conditions();
64091
+ init_schema();
63841
64092
  init_credential();
63842
64093
  init_headers();
63843
64094
  init_capability();
@@ -64216,131 +64467,6 @@ var init_launchReport = __esm({
64216
64467
  }
64217
64468
  });
64218
64469
 
64219
- // src/models/identity.ts
64220
- function withoutContextMarker(model) {
64221
- return model.toLowerCase().endsWith(CONTEXT_MARKER_1M) ? model.slice(0, -CONTEXT_MARKER_1M.length) : model;
64222
- }
64223
- function canonicalText(name) {
64224
- return name.trim().toLowerCase().replace(NON_IDENTITY_BRACKET_RE, "").replace(/[\s_]+/g, "-").replace(/([a-z])(\d+(?:\.\d+)+)/g, "$1-$2").replace(/-+/g, "-").replace(/^-|-$/g, "");
64225
- }
64226
- function splitVariants(tokens) {
64227
- const variants = [];
64228
- let end = tokens.length;
64229
- for (; ; ) {
64230
- const token = tokens[end - 1];
64231
- if (token === void 0 || !KNOWN_VARIANTS.has(token)) {
64232
- return { familyTokens: tokens.slice(0, end), variants };
64233
- }
64234
- variants.unshift(token);
64235
- end -= 1;
64236
- }
64237
- }
64238
- function versionOf(tokens) {
64239
- for (let index = 0; index < tokens.length; index += 1) {
64240
- const token = tokens[index];
64241
- const next = tokens[index + 1];
64242
- if (token === void 0) {
64243
- return "";
64244
- }
64245
- if (/^\d+$/.test(token) && next !== void 0 && /^\d+$/.test(next)) {
64246
- return `${token}.${next}`;
64247
- }
64248
- const dotted = /^\d+(?:\.\d+)+$/.exec(token);
64249
- if (dotted !== null) {
64250
- return dotted[0];
64251
- }
64252
- }
64253
- return "";
64254
- }
64255
- function modelIdentity(rawName) {
64256
- const segments = rawName.trim().toLowerCase().split("/");
64257
- const stripped = canonicalText(segments[segments.length - 1] ?? "").split(":")[0] ?? "";
64258
- const withoutDate = stripped.replace(DATE_STAMP_RE, "");
64259
- const tokens = withoutDate.split("-").filter((token) => token !== "");
64260
- const { familyTokens, variants } = splitVariants(tokens);
64261
- const version2 = versionOf(familyTokens);
64262
- const versionless = familyTokens.filter((token, index) => {
64263
- if (version2 === "") {
64264
- return true;
64265
- }
64266
- const dotted = /^\d+(?:\.\d+)+$/.test(token);
64267
- const previous = familyTokens[index - 1];
64268
- const next = familyTokens[index + 1];
64269
- const insideVersionRun = dotted || /^\d+$/.test(token) && (previous !== void 0 && /^\d+$/.test(previous) || next !== void 0 && /^\d+$/.test(next));
64270
- return !insideVersionRun;
64271
- });
64272
- const family = versionless.join("-");
64273
- const tokenVendor = familyTokens.find((token) => Object.keys(VENDOR_BY_TOKEN).some((key) => token === key || token.startsWith(key)));
64274
- const namespace = segments.length >= 2 ? (segments[0] ?? "").split(":").pop() ?? "" : "";
64275
- const namespaceVendor = VENDOR_BY_NAMESPACE[namespace] ?? "";
64276
- const tokenVendorName = tokenVendor === void 0 ? "" : VENDOR_BY_TOKEN[Object.keys(VENDOR_BY_TOKEN).find((key) => tokenVendor === key || tokenVendor.startsWith(key)) ?? ""] ?? "";
64277
- return {
64278
- vendor: tokenVendorName === "" ? namespaceVendor : tokenVendorName,
64279
- vendorConflict: tokenVendorName !== "" && namespaceVendor !== "" && tokenVendorName !== namespaceVendor,
64280
- family,
64281
- version: version2,
64282
- variant: variants.join("-"),
64283
- familyAndVersion: version2 === "" ? family : `${family}-${version2.replace(/\./g, "-")}`
64284
- };
64285
- }
64286
- function relateModels(left, right) {
64287
- const a10 = modelIdentity(left);
64288
- const b = modelIdentity(right);
64289
- if (a10.familyAndVersion !== b.familyAndVersion) {
64290
- return sameFamilyOtherVersion(a10, b) ? "similar" : "distinct";
64291
- }
64292
- if (a10.variant !== b.variant || a10.vendorConflict || b.vendorConflict || a10.vendor !== "" && b.vendor !== "" && a10.vendor !== b.vendor) {
64293
- return "similar";
64294
- }
64295
- return "same";
64296
- }
64297
- function sameFamilyOtherVersion(a10, b) {
64298
- if (a10.family !== b.family) {
64299
- return false;
64300
- }
64301
- if (a10.vendor !== "" && b.vendor !== "" && a10.vendor !== b.vendor) {
64302
- return false;
64303
- }
64304
- return true;
64305
- }
64306
- var NON_IDENTITY_BRACKET_RE, CONTEXT_MARKER_1M, DATE_STAMP_RE, KNOWN_VARIANTS, VENDOR_BY_NAMESPACE, VENDOR_BY_TOKEN;
64307
- var init_identity2 = __esm({
64308
- "src/models/identity.ts"() {
64309
- "use strict";
64310
- NON_IDENTITY_BRACKET_RE = /\[[^\]]*\]/g;
64311
- CONTEXT_MARKER_1M = "[1m]";
64312
- DATE_STAMP_RE = /-(?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])$/;
64313
- KNOWN_VARIANTS = /* @__PURE__ */ new Set(["high", "medium", "low", "thinking", "xhigh", "max", "highspeed", "sol", "terra", "luna", "mini", "flash-lite", "turbo"]);
64314
- VENDOR_BY_NAMESPACE = Object.freeze({
64315
- anthropic: "anthropic",
64316
- google: "google",
64317
- openai: "openai",
64318
- zai: "zai",
64319
- "z-ai": "zai",
64320
- minimax: "minimax",
64321
- qwen: "qwen",
64322
- deepseek: "deepseek",
64323
- moonshot: "moonshot",
64324
- meta: "meta",
64325
- mistral: "mistral"
64326
- });
64327
- VENDOR_BY_TOKEN = Object.freeze({
64328
- claude: "anthropic",
64329
- gemini: "google",
64330
- antigravity: "google",
64331
- gpt: "openai",
64332
- glm: "zai",
64333
- minimax: "minimax",
64334
- qwen: "qwen",
64335
- deepseek: "deepseek",
64336
- kimi: "moonshot",
64337
- llama: "meta",
64338
- mistral: "mistral",
64339
- mixtral: "mistral"
64340
- });
64341
- }
64342
- });
64343
-
64344
64470
  // src/selection/engine.ts
64345
64471
  function compareMaybe(left, right, preferHigh) {
64346
64472
  if (left === void 0 && right === void 0) {
@@ -65483,7 +65609,7 @@ function catalogueUrls(provider, catalogue) {
65483
65609
  function isRecord9(value2) {
65484
65610
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
65485
65611
  }
65486
- function modelOf(entry) {
65612
+ function modelOf2(entry) {
65487
65613
  if (typeof entry === "string") {
65488
65614
  return entry.trim() === "" ? void 0 : { id: entry.trim() };
65489
65615
  }
@@ -65499,7 +65625,7 @@ function parseCatalogueBody(body) {
65499
65625
  const seen = /* @__PURE__ */ new Set();
65500
65626
  const models = [];
65501
65627
  for (const entry of list) {
65502
- const model = modelOf(entry);
65628
+ const model = modelOf2(entry);
65503
65629
  if (model !== void 0 && !seen.has(model.id)) {
65504
65630
  seen.add(model.id);
65505
65631
  models.push(model);
@@ -65564,147 +65690,6 @@ var init_providerCatalogue = __esm({
65564
65690
  }
65565
65691
  });
65566
65692
 
65567
- // src/launcher/modelPicker.ts
65568
- function labelOf(model) {
65569
- return withoutContextMarker(model);
65570
- }
65571
- function describedAs(model, description) {
65572
- return model.toLowerCase().endsWith(CONTEXT_MARKER_1M) ? `${description}; 1M context` : description;
65573
- }
65574
- function joined(parts) {
65575
- const last = parts[parts.length - 1];
65576
- return last === void 0 || parts.length === 1 ? last ?? "" : `${parts.slice(0, -1).join(", ")} and ${last}`;
65577
- }
65578
- function rowOf(model, reaches) {
65579
- const lead = reaches.find((reach) => reach.standing === "first") ?? reaches[0];
65580
- if (lead === void 0) {
65581
- throw new Error(`model ${model} is reached by no tier`);
65582
- }
65583
- const firsts = reaches.filter((reach) => reach.standing === "first").map((reach) => reach.tier);
65584
- const fallbacks = reaches.filter((reach) => reach.standing === "fallback").map((reach) => reach.tier);
65585
- const serves = firsts.length === 0 ? [] : [`Serves the ${joined(firsts)} tier${firsts.length === 1 ? "" : "s"}`];
65586
- const falls = fallbacks.length === 0 ? [] : [`${serves.length === 0 ? "Fallback" : "fallback"} for ${joined(fallbacks)}`];
65587
- return { model, label: labelOf(model), description: describedAs(model, [...serves, ...falls].join("; ")), behavesAs: TIER_BEHAVES_AS[lead.tier] };
65588
- }
65589
- function rowsOfTable(table) {
65590
- const reachesByModel = /* @__PURE__ */ new Map();
65591
- for (const [tier, candidates] of table) {
65592
- candidates.forEach((model, index) => {
65593
- const reaches = reachesByModel.get(model) ?? [];
65594
- if (!reaches.some((reach) => reach.tier === tier)) {
65595
- reaches.push({ tier, standing: index === 0 ? "first" : "fallback" });
65596
- }
65597
- reachesByModel.set(model, reaches);
65598
- });
65599
- }
65600
- return [...reachesByModel].map(([model, reaches]) => rowOf(model, reaches));
65601
- }
65602
- function antigravityRows(provider) {
65603
- const config2 = resolveAntigravityConfig(provider.antigravity);
65604
- const tiers = rowsOfTable(CLAUDE_TIERS.map((tier) => [tier, config2.models[tier]]));
65605
- const behavesAsOf = new Map(tiers.map((row) => [row.model, row.behavesAs]));
65606
- const aliases = [...config2.aliases].flatMap(([alias, candidates]) => {
65607
- const [first] = candidates;
65608
- const behavesAs = first === void 0 ? void 0 : behavesAsOf.get(first);
65609
- const description = alias === AUTO_ALIAS ? `Routes each request to a backend model with quota left, best first (${String(candidates.length)} models)` : `Alias for ${candidates.join(", then ")}`;
65610
- return behavesAs === void 0 ? [] : [{ model: alias, label: labelOf(alias), description, behavesAs }];
65611
- });
65612
- return [...aliases.filter((row) => row.model === AUTO_ALIAS), ...tiers, ...aliases.filter((row) => row.model !== AUTO_ALIAS)];
65613
- }
65614
- function codexRows(provider) {
65615
- const config2 = resolveCodexConfig(provider.codex);
65616
- return rowsOfTable(CLAUDE_TIERS.map((tier) => [tier, [config2.models[tier]]]));
65617
- }
65618
- function httpRows(provider) {
65619
- const env = provider.env ?? {};
65620
- const table = CLAUDE_TIERS.flatMap((tier) => {
65621
- const model = env[TIER_ENV_VARIABLES[tier]];
65622
- return model === void 0 || model === "" ? [] : [[tier, [model]]];
65623
- });
65624
- return rowsOfTable(table);
65625
- }
65626
- function declaredRow(entry) {
65627
- return {
65628
- model: entry.model,
65629
- label: entry.label ?? labelOf(entry.model),
65630
- description: entry.description ?? describedAs(entry.model, `Declared by the provider for the ${entry.tier} tier`),
65631
- behavesAs: TIER_BEHAVES_AS[entry.tier]
65632
- };
65633
- }
65634
- function catalogueRows(provider, models) {
65635
- if (provider.kind !== void 0 && provider.kind !== "http" || provider.catalogue === void 0) {
65636
- return [];
65637
- }
65638
- const { tier } = provider.catalogue;
65639
- return filterCatalogue(models, provider.catalogue).map((model) => ({ model: model.id, label: labelOf(model.id), description: describedAs(model.id, model.name === void 0 ? "Listed by the provider" : `Listed by the provider as ${model.name}`), behavesAs: TIER_BEHAVES_AS[tier] })).sort((left, right) => left.model.localeCompare(right.model));
65640
- }
65641
- function providerModelRows(provider, catalogue = []) {
65642
- const derived2 = provider.kind === "codex" ? codexRows(provider) : provider.kind === "antigravity" ? antigravityRows(provider) : provider.kind === "router" ? [] : httpRows(provider);
65643
- const declared = provider.kind === "router" ? [] : (provider.pickerModels ?? []).map(declaredRow);
65644
- const declaredModels = new Set(declared.map((row) => row.model));
65645
- const named = [...derived2.filter((row) => !declaredModels.has(row.model)), ...declared];
65646
- const taken = new Set(named.map((row) => labelOf(row.model)));
65647
- return [...named, ...catalogueRows(provider, catalogue).filter((row) => !taken.has(labelOf(row.model)))];
65648
- }
65649
- function routedModelRows(models, providers) {
65650
- const hidden = new Set(models.hide ?? []);
65651
- const shown = models.show === void 0 ? void 0 : new Set(models.show);
65652
- const visible = (model) => shown === void 0 ? !hidden.has(model) : shown.has(model);
65653
- const tierOf = (model) => {
65654
- for (const [, provider] of providers) {
65655
- if (provider.kind !== void 0 && provider.kind !== "http") {
65656
- continue;
65657
- }
65658
- const match = Object.entries(provider.env ?? {}).find(([key, value2]) => value2 === model && key.startsWith("ANTHROPIC_DEFAULT_") && key.endsWith("_MODEL"));
65659
- if (match !== void 0) {
65660
- const tier = match[0].replace("ANTHROPIC_DEFAULT_", "").replace("_MODEL", "").toLowerCase();
65661
- return tier === "fable" || tier === "opus" || tier === "sonnet" || tier === "haiku" ? tier : void 0;
65662
- }
65663
- }
65664
- return void 0;
65665
- };
65666
- const virtual = Object.entries(models.virtual ?? {}).flatMap(([name, definition]) => {
65667
- if (!visible(name)) {
65668
- return [];
65669
- }
65670
- const first = definition.members.find((member) => member.includes("/"));
65671
- const tier = first === void 0 ? void 0 : tierOf(first.split("/").slice(1).join("/"));
65672
- const behavesAs = tier === void 0 ? void 0 : TIER_BEHAVES_AS[tier];
65673
- return behavesAs === void 0 ? [] : [{ model: name, label: name, description: `Virtual (${definition.mode})`, behavesAs }];
65674
- });
65675
- const concrete = providers.flatMap(([name, provider]) => providerModelRows(provider).map((row) => ({ ...row, model: `${name}/${row.model}`, label: `${name} / ${row.label}`, description: `${name}: ${row.description}` })));
65676
- return [...virtual, ...concrete.filter((row) => visible(row.model))];
65677
- }
65678
- function modelPickerSettings(provider, catalogue = []) {
65679
- return modelPickerSettingsFromRows(providerModelRows(provider, catalogue), true);
65680
- }
65681
- function modelPickerSettingsFromRows(options, replaceBuiltInOptions) {
65682
- return options.length === 0 ? void 0 : JSON.stringify({ modelPicker: { options, replaceBuiltInOptions } });
65683
- }
65684
- var TIER_BEHAVES_AS, TIER_ENV_VARIABLES;
65685
- var init_modelPicker = __esm({
65686
- "src/launcher/modelPicker.ts"() {
65687
- "use strict";
65688
- init_translate();
65689
- init_translate2();
65690
- init_providerCatalogue();
65691
- init_schema();
65692
- init_identity2();
65693
- TIER_BEHAVES_AS = Object.freeze({
65694
- fable: "claude-fable-5-1",
65695
- opus: "claude-opus-5-5",
65696
- sonnet: "claude-sonnet-5-5",
65697
- haiku: "claude-haiku-5-5"
65698
- });
65699
- TIER_ENV_VARIABLES = Object.freeze({
65700
- fable: "ANTHROPIC_DEFAULT_FABLE_MODEL",
65701
- opus: "ANTHROPIC_DEFAULT_OPUS_MODEL",
65702
- sonnet: "ANTHROPIC_DEFAULT_SONNET_MODEL",
65703
- haiku: "ANTHROPIC_DEFAULT_HAIKU_MODEL"
65704
- });
65705
- }
65706
- });
65707
-
65708
65693
  // src/modelsStore.ts
65709
65694
  function readModels(paths) {
65710
65695
  return readGlobalConfig(paths)?.models;
@@ -65855,6 +65840,148 @@ var init_modelsStore = __esm({
65855
65840
  }
65856
65841
  });
65857
65842
 
65843
+ // src/launcher/modelPicker.ts
65844
+ function labelOf(model) {
65845
+ return withoutContextMarker(model);
65846
+ }
65847
+ function describedAs(model, description) {
65848
+ return model.toLowerCase().endsWith(CONTEXT_MARKER_1M) ? `${description}; 1M context` : description;
65849
+ }
65850
+ function joined(parts) {
65851
+ const last = parts[parts.length - 1];
65852
+ return last === void 0 || parts.length === 1 ? last ?? "" : `${parts.slice(0, -1).join(", ")} and ${last}`;
65853
+ }
65854
+ function rowOf(model, reaches) {
65855
+ const lead = reaches.find((reach) => reach.standing === "first") ?? reaches[0];
65856
+ if (lead === void 0) {
65857
+ throw new Error(`model ${model} is reached by no tier`);
65858
+ }
65859
+ const firsts = reaches.filter((reach) => reach.standing === "first").map((reach) => reach.tier);
65860
+ const fallbacks = reaches.filter((reach) => reach.standing === "fallback").map((reach) => reach.tier);
65861
+ const serves = firsts.length === 0 ? [] : [`Serves the ${joined(firsts)} tier${firsts.length === 1 ? "" : "s"}`];
65862
+ const falls = fallbacks.length === 0 ? [] : [`${serves.length === 0 ? "Fallback" : "fallback"} for ${joined(fallbacks)}`];
65863
+ return { model, label: labelOf(model), description: describedAs(model, [...serves, ...falls].join("; ")), behavesAs: TIER_BEHAVES_AS[lead.tier] };
65864
+ }
65865
+ function rowsOfTable(table) {
65866
+ const reachesByModel = /* @__PURE__ */ new Map();
65867
+ for (const [tier, candidates] of table) {
65868
+ candidates.forEach((model, index) => {
65869
+ const reaches = reachesByModel.get(model) ?? [];
65870
+ if (!reaches.some((reach) => reach.tier === tier)) {
65871
+ reaches.push({ tier, standing: index === 0 ? "first" : "fallback" });
65872
+ }
65873
+ reachesByModel.set(model, reaches);
65874
+ });
65875
+ }
65876
+ return [...reachesByModel].map(([model, reaches]) => rowOf(model, reaches));
65877
+ }
65878
+ function antigravityRows(provider) {
65879
+ const config2 = resolveAntigravityConfig(provider.antigravity);
65880
+ const tiers = rowsOfTable(CLAUDE_TIERS.map((tier) => [tier, config2.models[tier]]));
65881
+ const behavesAsOf = new Map(tiers.map((row) => [row.model, row.behavesAs]));
65882
+ const aliases = [...config2.aliases].flatMap(([alias, candidates]) => {
65883
+ const [first] = candidates;
65884
+ const behavesAs = first === void 0 ? void 0 : behavesAsOf.get(first);
65885
+ const description = alias === AUTO_ALIAS ? `Routes each request to a backend model with quota left, best first (${String(candidates.length)} models)` : `Alias for ${candidates.join(", then ")}`;
65886
+ return behavesAs === void 0 ? [] : [{ model: alias, label: labelOf(alias), description, behavesAs }];
65887
+ });
65888
+ return [...aliases.filter((row) => row.model === AUTO_ALIAS), ...tiers, ...aliases.filter((row) => row.model !== AUTO_ALIAS)];
65889
+ }
65890
+ function codexRows(provider) {
65891
+ const config2 = resolveCodexConfig(provider.codex);
65892
+ return rowsOfTable(CLAUDE_TIERS.map((tier) => [tier, [config2.models[tier]]]));
65893
+ }
65894
+ function httpRows(provider) {
65895
+ const env = provider.env ?? {};
65896
+ const table = CLAUDE_TIERS.flatMap((tier) => {
65897
+ const model = env[TIER_ENV_VARIABLES[tier]];
65898
+ return model === void 0 || model === "" ? [] : [[tier, [model]]];
65899
+ });
65900
+ return rowsOfTable(table);
65901
+ }
65902
+ function declaredRow(entry) {
65903
+ return {
65904
+ model: entry.model,
65905
+ label: entry.label ?? labelOf(entry.model),
65906
+ description: entry.description ?? describedAs(entry.model, `Declared by the provider for the ${entry.tier} tier`),
65907
+ behavesAs: TIER_BEHAVES_AS[entry.tier]
65908
+ };
65909
+ }
65910
+ function catalogueRows(provider, models) {
65911
+ if (provider.kind !== void 0 && provider.kind !== "http" || provider.catalogue === void 0) {
65912
+ return [];
65913
+ }
65914
+ const { tier } = provider.catalogue;
65915
+ return filterCatalogue(models, provider.catalogue).map((model) => ({ model: model.id, label: labelOf(model.id), description: describedAs(model.id, model.name === void 0 ? "Listed by the provider" : `Listed by the provider as ${model.name}`), behavesAs: TIER_BEHAVES_AS[tier] })).sort((left, right) => left.model.localeCompare(right.model));
65916
+ }
65917
+ function providerModelRows(provider, catalogue = []) {
65918
+ const derived2 = provider.kind === "codex" ? codexRows(provider) : provider.kind === "antigravity" ? antigravityRows(provider) : provider.kind === "router" ? [] : httpRows(provider);
65919
+ const declared = provider.kind === "router" ? [] : (provider.pickerModels ?? []).map(declaredRow);
65920
+ const declaredModels = new Set(declared.map((row) => row.model));
65921
+ const named = [...derived2.filter((row) => !declaredModels.has(row.model)), ...declared];
65922
+ const taken = new Set(named.map((row) => labelOf(row.model)));
65923
+ return [...named, ...catalogueRows(provider, catalogue).filter((row) => !taken.has(labelOf(row.model)))];
65924
+ }
65925
+ function routedModelRows(models, providers) {
65926
+ const hidden = new Set(models.hide ?? []);
65927
+ const shown = models.show === void 0 ? void 0 : new Set(models.show);
65928
+ const visible = (model) => shown === void 0 ? !hidden.has(model) : shown.has(model);
65929
+ const concrete = providers.flatMap(([name, provider]) => providerModelRows(provider).map((row) => ({ ...row, model: `${name}/${row.model}`, label: `${name} / ${row.label}`, description: `${name}: ${row.description}` })));
65930
+ const concreteByRef = new Map(concrete.map((row) => [row.model, row]));
65931
+ const families = buildFamilies([...concrete.map((row) => row.model), ...accountRefsOf(models)], models);
65932
+ const handlingOf = (refs) => refs.map((ref) => concreteByRef.get(ref)?.behavesAs).find((behavesAs) => behavesAs !== void 0) ?? TIER_BEHAVES_AS.sonnet;
65933
+ const virtual = Object.entries(models.virtual ?? {}).flatMap(([name, definition]) => {
65934
+ if (!visible(name)) {
65935
+ return [];
65936
+ }
65937
+ const targets = expandFamilyMembers(safeExpand(name, models), families);
65938
+ return [{ model: name, label: name, description: `Virtual (${definition.mode})`, behavesAs: handlingOf(targets) }];
65939
+ });
65940
+ const familyRows = sharedFamilies(families).flatMap((family) => {
65941
+ const member = `${FAMILY_PREFIX}${family.key}`;
65942
+ return visible(member) ? [{ model: member, label: family.key, description: `Family (${familyMode(family.settings)}): ${family.refs.join(", ")}`, behavesAs: handlingOf(family.refs) }] : [];
65943
+ });
65944
+ return [...virtual, ...familyRows, ...concrete.filter((row) => visible(row.model))];
65945
+ }
65946
+ function safeExpand(name, models) {
65947
+ try {
65948
+ return expandMembers(name, models);
65949
+ } catch {
65950
+ return models.virtual?.[name]?.members ?? [];
65951
+ }
65952
+ }
65953
+ function modelPickerSettings(provider, catalogue = []) {
65954
+ return modelPickerSettingsFromRows(providerModelRows(provider, catalogue), true);
65955
+ }
65956
+ function modelPickerSettingsFromRows(options, replaceBuiltInOptions) {
65957
+ return options.length === 0 ? void 0 : JSON.stringify({ modelPicker: { options, replaceBuiltInOptions } });
65958
+ }
65959
+ var TIER_BEHAVES_AS, TIER_ENV_VARIABLES;
65960
+ var init_modelPicker = __esm({
65961
+ "src/launcher/modelPicker.ts"() {
65962
+ "use strict";
65963
+ init_translate();
65964
+ init_translate2();
65965
+ init_providerCatalogue();
65966
+ init_schema();
65967
+ init_identity2();
65968
+ init_families();
65969
+ init_modelsStore();
65970
+ TIER_BEHAVES_AS = Object.freeze({
65971
+ fable: "claude-fable-5-1",
65972
+ opus: "claude-opus-5-5",
65973
+ sonnet: "claude-sonnet-5-5",
65974
+ haiku: "claude-haiku-5-5"
65975
+ });
65976
+ TIER_ENV_VARIABLES = Object.freeze({
65977
+ fable: "ANTHROPIC_DEFAULT_FABLE_MODEL",
65978
+ opus: "ANTHROPIC_DEFAULT_OPUS_MODEL",
65979
+ sonnet: "ANTHROPIC_DEFAULT_SONNET_MODEL",
65980
+ haiku: "ANTHROPIC_DEFAULT_HAIKU_MODEL"
65981
+ });
65982
+ }
65983
+ });
65984
+
65858
65985
  // src/launcher/pool.ts
65859
65986
  function isResuming(passthrough) {
65860
65987
  const end = passthrough.indexOf(TERMINATOR3);
@@ -66054,6 +66181,26 @@ var init_launchHook = __esm({
66054
66181
  }
66055
66182
  });
66056
66183
 
66184
+ // src/models/targets.ts
66185
+ function providerModels(paths) {
66186
+ return listProviders(paths).flatMap((entry) => {
66187
+ const catalogue = parseCatalogueCache(realFsPort.readFileUtf8(catalogueCachePath(paths, entry.name)));
66188
+ return providerModelRows(entry.provider, catalogue?.models).map((row) => ({ provider: entry.name, model: row.model }));
66189
+ });
66190
+ }
66191
+ function targetRefs(paths) {
66192
+ return providerModels(paths).map((entry) => `${entry.provider}/${entry.model}`);
66193
+ }
66194
+ var init_targets = __esm({
66195
+ "src/models/targets.ts"() {
66196
+ "use strict";
66197
+ init_modelPicker();
66198
+ init_providerCatalogue();
66199
+ init_providersStore();
66200
+ init_realPorts();
66201
+ }
66202
+ });
66203
+
66057
66204
  // src/launcher.ts
66058
66205
  function resolveIdentityCredential(identity, credential, env, port) {
66059
66206
  if (port === void 0) {
@@ -66245,10 +66392,12 @@ function decideLaunch(params, readOnly) {
66245
66392
  }
66246
66393
  const launchCascade = farmContext?.cascade ?? (params.farm === void 0 ? void 0 : params.farm.loadCascade(configProfileDecision.name, cliOverride));
66247
66394
  let cascadeLaunch;
66395
+ let cascadeModels;
66248
66396
  if (launchCascade !== void 0 && params.farm !== void 0) {
66249
66397
  const assembled = assembleCascade(launchCascade);
66250
66398
  const flattened = flattenLayers(assembled.layers, { home: params.farm.home });
66251
66399
  cascadeLaunch = flattened.launch;
66400
+ cascadeModels = flattened.models;
66252
66401
  if (readOnly || farmContext === void 0) {
66253
66402
  reportDiagnostics(log, [...assembled.diagnostics, ...flattened.diagnostics], { errorsAsWarnings: readOnly });
66254
66403
  }
@@ -66277,7 +66426,9 @@ function decideLaunch(params, readOnly) {
66277
66426
  const flags = loginlessProvider === void 0 ? requestedFlags : { ...requestedFlags, remoteControl: false };
66278
66427
  const catalogue = selectedProvider === void 0 ? void 0 : parseCatalogueCache(params.fs.readFileUtf8(catalogueCachePath(paths, selectedProvider.name)));
66279
66428
  const routesByName = flags.routeByName || selectedProvider !== void 0 && isRouterProvider(selectedProvider.definition);
66280
- const pickerSettings = routesByName ? modelPickerSettingsFromRows(routedModelRows(readModels(paths) ?? {}, listProviders(paths).map((entry) => [entry.name, entry.provider])), selectedProvider !== void 0) : selectedProvider === void 0 ? void 0 : modelPickerSettings(selectedProvider.definition, catalogue?.models);
66429
+ const globalModels = loadConfigFile(paths.globalConfigFile, GlobalConfigSchema, params.fs.readConfigFile)?.config.models;
66430
+ const models = launchCascade !== void 0 && params.farm !== void 0 ? cascadeModels : globalModels;
66431
+ const pickerSettings = routesByName ? modelPickerSettingsFromRows(routedModelRows(models ?? {}, listProviders(paths).map((entry) => [entry.name, entry.provider])), selectedProvider !== void 0) : selectedProvider === void 0 ? void 0 : modelPickerSettings(selectedProvider.definition, catalogue?.models);
66281
66432
  const callerSettings = hasSettingsArgument(parsedArgv.rest);
66282
66433
  if (pickerSettings !== void 0 && callerSettings) {
66283
66434
  notes.push("--settings was passed, so /model keeps Claude Code's own model names");
@@ -66315,6 +66466,8 @@ function decideLaunch(params, readOnly) {
66315
66466
  identityCredential,
66316
66467
  pinnedVersion,
66317
66468
  flags,
66469
+ models,
66470
+ globalModels,
66318
66471
  bin: discovered.path,
66319
66472
  args,
66320
66473
  decision
@@ -66381,7 +66534,7 @@ function prepareLaunch(params) {
66381
66534
  }
66382
66535
  const routesByName = resolvedFlags.routeByName || resolvedProvider !== void 0 && isRouterProvider(resolvedProvider.definition);
66383
66536
  if (routesByName) {
66384
- const check2 = resolveRoutedProviderCredentials({ paths, port: params.fs, env, ...params.credentials === void 0 ? {} : { credentials: params.credentials }, models: loadConfigFile(paths.globalConfigFile, GlobalConfigSchema, params.fs.readConfigFile)?.config.models });
66537
+ const check2 = resolveRoutedProviderCredentials({ paths, port: params.fs, env, ...params.credentials === void 0 ? {} : { credentials: params.credentials }, models: decided.models, targets: () => targetRefs(paths) });
66385
66538
  if (!check2.ok) {
66386
66539
  log.error(check2.message);
66387
66540
  proc.exit(check2.status);
@@ -66393,7 +66546,10 @@ function prepareLaunch(params) {
66393
66546
  log.error("agent-shim: this launch routes through the front-door daemon, but this launcher has no front-door port wired; refusing to launch without it.");
66394
66547
  proc.exit(1);
66395
66548
  }
66396
- const frontDoor = frontDoorEngaged && frontDoorPort !== void 0 ? frontDoorPort.ensure(env.NODE_EXTRA_CA_CERTS) : void 0;
66549
+ const sessionId = params.supervised?.sessionId ?? (0, import_node_crypto18.randomUUID)();
66550
+ const resolvedModels = decided.models ?? (decided.globalModels === void 0 ? void 0 : {});
66551
+ const sessionModels = (0, import_node_util6.isDeepStrictEqual)(resolvedModels, decided.globalModels) ? void 0 : resolvedModels;
66552
+ const frontDoor = frontDoorEngaged && frontDoorPort !== void 0 ? frontDoorPort.ensure(env.NODE_EXTRA_CA_CERTS, { sessionId, ...sessionModels === void 0 ? {} : { models: sessionModels } }) : void 0;
66397
66553
  if (frontDoor?.trustWarning !== void 0) {
66398
66554
  log.warn(frontDoor.trustWarning);
66399
66555
  }
@@ -66407,7 +66563,6 @@ function prepareLaunch(params) {
66407
66563
  }
66408
66564
  rows.push(...routingRows({ frontDoor, headroom, provider: resolvedProvider !== void 0 }));
66409
66565
  const frontDoorRelease = frontDoor === void 0 ? void 0 : frontDoorPort?.release;
66410
- const sessionId = params.supervised?.sessionId ?? (0, import_node_crypto18.randomUUID)();
66411
66566
  const finalEnv = buildEnv({
66412
66567
  baseEnv: env,
66413
66568
  configDirEscapeHatch: configDirEscapeHatchApplies,
@@ -66419,7 +66574,8 @@ function prepareLaunch(params) {
66419
66574
  ...headroom === void 0 ? {} : { headroom },
66420
66575
  sessionId,
66421
66576
  remoteControl: resolvedFlags.remoteControl,
66422
- routeByName: routesByName
66577
+ routeByName: routesByName,
66578
+ ...decided.models?.tiers === void 0 ? {} : { tierModels: decided.models.tiers }
66423
66579
  });
66424
66580
  const releases = [...headroom === void 0 || headroomPort === void 0 ? [] : [headroomPort.release], ...frontDoorRelease === void 0 ? [] : [frontDoorRelease]];
66425
66581
  const release = () => {
@@ -66481,11 +66637,12 @@ function runLaunchPlan(plan, spawn8) {
66481
66637
  function runLauncher(params) {
66482
66638
  params.proc.exit(runLaunchPlan(prepareLaunch(params), params.spawn));
66483
66639
  }
66484
- var import_node_crypto18, import_node_path44;
66640
+ var import_node_crypto18, import_node_util6, import_node_path44;
66485
66641
  var init_launcher = __esm({
66486
66642
  "src/launcher.ts"() {
66487
66643
  "use strict";
66488
66644
  import_node_crypto18 = require("node:crypto");
66645
+ import_node_util6 = require("node:util");
66489
66646
  import_node_path44 = __toESM(require("node:path"), 1);
66490
66647
  init_package();
66491
66648
  init_envBool();
@@ -66502,7 +66659,6 @@ var init_launcher = __esm({
66502
66659
  init_launchReport();
66503
66660
  init_modelPicker();
66504
66661
  init_providerCatalogue();
66505
- init_modelsStore();
66506
66662
  init_providersStore();
66507
66663
  init_pool();
66508
66664
  init_resumeContext();
@@ -66520,6 +66676,7 @@ var init_launcher = __esm({
66520
66676
  init_read();
66521
66677
  init_claudeVersion();
66522
66678
  init_launchHook();
66679
+ init_targets();
66523
66680
  }
66524
66681
  });
66525
66682
 
@@ -119819,56 +119976,7 @@ init_source();
119819
119976
 
119820
119977
  // src/models/doctor.ts
119821
119978
  init_modelsStore();
119822
-
119823
- // src/models/families.ts
119824
- init_identity2();
119825
- var FAMILY_PREFIX = "family:";
119826
- var VARIANT_SEPARATOR = "+";
119827
- function modelOf2(ref) {
119828
- const slash = ref.indexOf("/");
119829
- return slash === -1 ? ref : ref.slice(slash + 1);
119830
- }
119831
- function familyKeyOf(rawModel) {
119832
- const identity = modelIdentity(rawModel);
119833
- return identity.variant === "" ? identity.familyAndVersion : `${identity.familyAndVersion}${VARIANT_SEPARATOR}${identity.variant}`;
119834
- }
119835
- function assertionsOf(models) {
119836
- return { same: models?.same ?? [], distinct: models?.distinct ?? [] };
119837
- }
119838
- function sameModel(left, right, assertions) {
119839
- if (assertions.distinct.some(([a10, b]) => a10 === left && b === right || a10 === right && b === left)) {
119840
- return false;
119841
- }
119842
- const leftGroup = assertions.same.find((group) => group.includes(left));
119843
- const rightGroup = assertions.same.find((group) => group.includes(right));
119844
- if (leftGroup !== void 0 && leftGroup === rightGroup) {
119845
- return true;
119846
- }
119847
- if (leftGroup !== void 0 && !leftGroup.includes(right) || rightGroup !== void 0 && !rightGroup.includes(left)) {
119848
- return false;
119849
- }
119850
- return relateModels(modelOf2(left), modelOf2(right)) === "same";
119851
- }
119852
- function pinnedTo(settings2, ref) {
119853
- return settings2?.names?.some((name) => name === ref || name === modelOf2(ref)) === true;
119854
- }
119855
- function buildFamilies(refs, models) {
119856
- const assertions = assertionsOf(models);
119857
- const settingsByKey = models?.families ?? {};
119858
- const groups = [];
119859
- for (const ref of refs) {
119860
- const pinnedKey = Object.entries(settingsByKey).find(([, settings2]) => pinnedTo(settings2, ref))?.[0];
119861
- const joined2 = groups.find((group) => pinnedKey === void 0 ? group.refs.some((first) => sameModel(first, ref, assertions)) : group.key === pinnedKey);
119862
- if (joined2 !== void 0) {
119863
- joined2.refs.push(ref);
119864
- } else {
119865
- groups.push({ key: pinnedKey ?? familyKeyOf(modelOf2(ref)), refs: [ref] });
119866
- }
119867
- }
119868
- return groups.map((group) => ({ key: group.key, refs: group.refs, settings: settingsByKey[group.key] ?? {} }));
119869
- }
119870
-
119871
- // src/models/doctor.ts
119979
+ init_families();
119872
119980
  init_identity2();
119873
119981
  function modelsFindings(input2) {
119874
119982
  const findings = [];
@@ -119956,22 +120064,8 @@ function modelsFindings(input2) {
119956
120064
  return findings;
119957
120065
  }
119958
120066
 
119959
- // src/models/targets.ts
119960
- init_modelPicker();
119961
- init_providerCatalogue();
119962
- init_providersStore();
119963
- init_realPorts();
119964
- function providerModels(paths) {
119965
- return listProviders(paths).flatMap((entry) => {
119966
- const catalogue = parseCatalogueCache(realFsPort.readFileUtf8(catalogueCachePath(paths, entry.name)));
119967
- return providerModelRows(entry.provider, catalogue?.models).map((row) => ({ provider: entry.name, model: row.model }));
119968
- });
119969
- }
119970
- function targetRefs(paths) {
119971
- return providerModels(paths).map((entry) => `${entry.provider}/${entry.model}`);
119972
- }
119973
-
119974
120067
  // src/doctorReport.ts
120068
+ init_targets();
119975
120069
  init_configProfilesStore();
119976
120070
 
119977
120071
  // src/headroom/allowlistDrift.ts
@@ -131728,6 +131822,7 @@ function candidateOf(ref, order, facts, isCurrent) {
131728
131822
 
131729
131823
  // src/frontdoor/providerRoute.ts
131730
131824
  init_engine();
131825
+ init_families();
131731
131826
  init_identity2();
131732
131827
  init_route();
131733
131828
  var import_node_stream3 = require("node:stream");
@@ -131818,37 +131913,45 @@ function scopeSessionProviderPath(request7) {
131818
131913
  }
131819
131914
  return { ...request7, url: `${PROVIDER_PATH_PREFIX}${encodeURIComponent(request7.session.provider)}${request7.url}` };
131820
131915
  }
131821
- function resolveRoutedModel(model, providerName, session, includeUnqualified, deps, memory, rotations) {
131822
- const models = deps.models?.();
131916
+ var CHARS_PER_TOKEN2 = 4;
131917
+ function needsOf(scan) {
131918
+ return { hasImage: scan.hasImage === true, hasTools: scan.toolsPresent === true, thinking: scan.thinking === true, contextTokens: Math.ceil((scan.text?.length ?? 0) / CHARS_PER_TOKEN2) };
131919
+ }
131920
+ function resolveRoutedModel(model, providerName, session, includeUnqualified, deps, memory, rotations, needs) {
131921
+ const models = deps.models?.(session);
131823
131922
  const qualified = model.includes("/") && !model.startsWith("acct:") ? model : void 0;
131824
131923
  if (qualified !== void 0) {
131825
131924
  const [provider2, ...rest2] = qualified.split("/");
131826
131925
  const named = rest2.join("/");
131827
131926
  return provider2 === void 0 || named === "" ? void 0 : { provider: provider2, model: withoutContextMarker(named), ref: qualified };
131828
131927
  }
131829
- const virtual = models?.virtual?.[model];
131830
- if (virtual === void 0 || !includeUnqualified) {
131928
+ const isFamily = model.startsWith(FAMILY_PREFIX);
131929
+ const virtual = isFamily ? void 0 : models?.virtual?.[model];
131930
+ if (virtual === void 0 && !isFamily || !includeUnqualified) {
131831
131931
  return void 0;
131832
131932
  }
131833
- const members2 = expandMembers(model, models).filter((member) => !member.startsWith("acct:") && !member.startsWith("family:"));
131933
+ const declared = isFamily ? [model] : expandMembers(model, models);
131934
+ const families = isFamily || declared.some((member) => member.startsWith(FAMILY_PREFIX)) || models?.families !== void 0 ? buildFamilies(deps.targets?.() ?? [], models) : [];
131935
+ const mode = virtual?.mode ?? familyMode(familyNamed(families, model)?.settings ?? {});
131936
+ const members2 = expandFamilyMembers(declared, families).filter((member) => !member.startsWith("acct:"));
131834
131937
  if (members2.length === 0) {
131835
131938
  return void 0;
131836
131939
  }
131837
131940
  const snapshot = deps.usageSnapshotOf?.(session.identity);
131838
131941
  const current = memory.get(session.sessionId ?? "");
131839
- const candidates = members2.map((ref, order) => {
131942
+ const evaluated = members2.map((ref, order) => {
131840
131943
  const [provider2] = ref.split("/");
131841
131944
  const facts = quotaFactsOf(snapshot?.providers[provider2 ?? ""]?.rateLimit?.unified, Date.now());
131842
- return candidateOf(ref, order, {
131945
+ const candidate = candidateOf(ref, order, {
131843
131946
  quota: facts,
131844
131947
  ...deps.observations?.(ref) === void 0 ? {} : { observation: deps.observations(ref) },
131845
131948
  ...models?.prices?.[ref] === void 0 ? {} : { price: models.prices[ref] }
131846
131949
  }, ref === current);
131950
+ return { candidate, capabilities: familyCapabilities(familyOfRef(families, ref)?.settings ?? {}) };
131847
131951
  });
131848
- const evaluated = candidates.map((candidate) => ({ candidate, capabilities: { vision: true, tools: true, thinking: true } }));
131849
131952
  const rotation = rotations.get(model) ?? 0;
131850
131953
  rotations.set(model, rotation + 1);
131851
- const selection = selectMember(virtual.mode, evaluated, { rotation });
131954
+ const selection = selectMember(mode, evaluated, { rotation, ...needs === void 0 ? {} : { needs } });
131852
131955
  if (selection.ref === void 0) {
131853
131956
  return void 0;
131854
131957
  }
@@ -132011,6 +132114,7 @@ function createProviderRouteResolver(deps) {
132011
132114
  const serveScoped = (resolution) => scopedRequest === request7 ? resolution : { ok: true, route: servingRewritten(resolution.route, scopedRequest) };
132012
132115
  let current = scopedRequest;
132013
132116
  let replay;
132117
+ let nameResolved = false;
132014
132118
  const visited = /* @__PURE__ */ new Set();
132015
132119
  for (; ; ) {
132016
132120
  const path65 = new URL(current.url, "http://127.0.0.1").pathname;
@@ -132032,7 +132136,7 @@ function createProviderRouteResolver(deps) {
132032
132136
  routes = void 0;
132033
132137
  isRouter = false;
132034
132138
  }
132035
- const routesByName = (isRouter || current.session.routeByName) && !isRcSelfHostPath(path65);
132139
+ const routesByName = !nameResolved && (isRouter || current.session.routeByName) && !isRcSelfHostPath(path65);
132036
132140
  if (routesByName) {
132037
132141
  const scan2 = await scanRequestHead(current, true);
132038
132142
  if (scan2.replayed === void 0) {
@@ -132040,7 +132144,7 @@ function createProviderRouteResolver(deps) {
132040
132144
  return resolution.ok && replay !== void 0 ? { ok: true, route: servingRewritten(resolution.route, { ...replay, url: current.url }), request: { ...replay, url: current.url } } : resolution.ok ? serveScoped(resolution) : resolution;
132041
132145
  }
132042
132146
  replay = scan2.replayed;
132043
- const account = scan2.model === void 0 ? void 0 : resolveAccountTarget(scan2.model, deps.models?.());
132147
+ const account = scan2.model === void 0 ? void 0 : resolveAccountTarget(scan2.model, deps.models?.(current.session));
132044
132148
  if (account !== void 0) {
132045
132149
  const sessionId = current.session.sessionId ?? "";
132046
132150
  const moved = sessionId !== "" && (deps.accountMoves?.(sessionId, account.identity, account.model) ?? false);
@@ -132050,7 +132154,7 @@ function createProviderRouteResolver(deps) {
132050
132154
  message: moved ? `model "${account.model}" runs under identity "${account.identity}"; this session is being moved there and will resume with it` : `model "${account.model}" runs under identity "${account.identity}", which needs a relaunch this session cannot make; start it there with: claude @${account.identity} --resume`
132051
132155
  };
132052
132156
  }
132053
- const routed = scan2.model === void 0 ? void 0 : resolveRoutedModel(scan2.model, providerName, current.session, isRouter || providerName !== void 0, deps, routingMemory, rotations);
132157
+ const routed = scan2.model === void 0 ? void 0 : resolveRoutedModel(scan2.model, providerName, current.session, isRouter || providerName !== void 0, deps, routingMemory, rotations, needsOf(scan2));
132054
132158
  const requested = scan2.model;
132055
132159
  if (routed !== void 0) {
132056
132160
  routingMemory.set(current.session.sessionId ?? "", routed.ref);
@@ -132069,6 +132173,7 @@ function createProviderRouteResolver(deps) {
132069
132173
  const query2 = current.url.includes("?") ? current.url.slice(current.url.indexOf("?")) : "";
132070
132174
  const carried = replay;
132071
132175
  current = { ...current, url: `${PROVIDER_PATH_PREFIX}${encodeURIComponent(routed.provider)}${rest2}${query2}`, body: carried.body, headers: carried.headers };
132176
+ nameResolved = true;
132072
132177
  continue;
132073
132178
  }
132074
132179
  const resolution = resolve2(current);
@@ -134555,6 +134660,9 @@ data: ${JSON.stringify(envelope)}
134555
134660
  };
134556
134661
  }
134557
134662
 
134663
+ // src/frontdoor/commands.ts
134664
+ init_targets();
134665
+
134558
134666
  // src/frontdoor/rcStream.ts
134559
134667
  var RC_STREAM_EVENT_NAME2 = "client_event";
134560
134668
  var SSE_BYTE_ORDER_MARK = 65279;
@@ -135233,7 +135341,9 @@ function realFrontDoorSupervisorPorts(paths) {
135233
135341
  const resolveRoute = rcObservingResolver(
135234
135342
  createProviderRouteResolver({
135235
135343
  // Read live so a models-block edit reaches the next request without a door restart.
135236
- models: () => readModels(paths),
135344
+ // The block this session launched with when its directory, profile or committed file added definitions of its own; otherwise the global block, read live so an edit applies to the next request with no relaunch.
135345
+ models: (session) => (session.sessionId === void 0 ? void 0 : readFrontDoorSessionModels(realFarmFs, paths.frontdoorSessionsDir, session.sessionId)) ?? readModels(paths),
135346
+ targets: () => targetRefs(paths),
135237
135347
  fs: realFsPort,
135238
135348
  providersDir: paths.providersDir,
135239
135349
  codexPorts,
@@ -147821,8 +147931,10 @@ function registerProviderCommand(program2, deps) {
147821
147931
 
147822
147932
  // src/models.ts
147823
147933
  init_commandDeps();
147934
+ init_targets();
147824
147935
  init_schema();
147825
147936
  init_cliError();
147937
+ init_families();
147826
147938
  init_identity2();
147827
147939
  init_modelsStore();
147828
147940
  init_realPorts();
@@ -147852,32 +147964,35 @@ function providerQuotaOf(paths) {
147852
147964
  return snapshot === void 0 ? {} : quotaFactsOf(snapshot.providers[provider]?.rateLimit?.unified, Date.now());
147853
147965
  };
147854
147966
  }
147855
- function describeUnroutedMembers(members2) {
147967
+ function describeUnroutedMembers(members2, families) {
147856
147968
  return members2.flatMap((member) => {
147857
147969
  if (member.startsWith("acct:")) {
147858
147970
  const [identity] = member.slice("acct:".length).split("/");
147859
147971
  return [`${member} is served by relaunching the session under identity "${identity ?? ""}", so no quota signal ranks it`];
147860
147972
  }
147861
- return member.startsWith("family:") ? [`${member} is resolved from the live catalogues, which the door does not read yet, so it is not a candidate`] : [];
147973
+ return member.startsWith(FAMILY_PREFIX) && familyNamed(families, member) === void 0 ? [`no target the providers offer belongs to ${member}, so it has nothing to choose among`] : [];
147862
147974
  });
147863
147975
  }
147864
147976
  function explainVirtualModel(paths, name) {
147865
147977
  const models = readModels(paths);
147866
- const definition = models?.virtual?.[name];
147867
- if (definition === void 0) {
147978
+ const virtual = models?.virtual?.[name];
147979
+ const families = buildFamilies(targetRefs(paths), models);
147980
+ const isFamily = name.startsWith(FAMILY_PREFIX);
147981
+ if (virtual === void 0 && !isFamily) {
147868
147982
  throw new UsageError(`No virtual model named "${name}".`);
147869
147983
  }
147984
+ const mode = virtual?.mode ?? familyMode(familyNamed(families, name)?.settings ?? {});
147870
147985
  const quotaOf = providerQuotaOf(paths);
147871
147986
  const observations = createTargetObservationStore(realFarmFs, paths);
147872
- const members2 = expandMembers(name, models);
147873
- const candidates = members2.filter((member) => !member.startsWith("acct:") && !member.startsWith("family:")).map((ref, order) => {
147987
+ const members2 = isFamily ? [name] : expandMembers(name, models);
147988
+ const candidates = expandFamilyMembers(members2, families).filter((member) => !member.startsWith("acct:")).map((ref, order) => {
147874
147989
  const [provider] = ref.split("/");
147875
147990
  return candidateOf(ref, order, { quota: quotaOf(provider ?? ""), ...observations.observation(ref) === void 0 ? {} : { observation: observations.observation(ref) }, ...models?.prices?.[ref] === void 0 ? {} : { price: models.prices[ref] } }, false);
147876
147991
  });
147877
- const evaluated = candidates.map((candidate) => ({ candidate, capabilities: { vision: true, tools: true, thinking: true } }));
147878
- const selection = selectMember(definition.mode, evaluated, {});
147879
- const unrouted = describeUnroutedMembers(members2);
147880
- console.log(`${name} (${definition.mode}) chooses ${selection.ref ?? (candidates.length === 0 ? "nothing by quota" : "nothing")}:`);
147992
+ const evaluated = candidates.map((candidate) => ({ candidate, capabilities: familyCapabilities(familyOfRef(families, candidate.ref)?.settings ?? {}) }));
147993
+ const selection = selectMember(mode, evaluated, {});
147994
+ const unrouted = describeUnroutedMembers(members2, families);
147995
+ console.log(`${name} (${mode}) chooses ${selection.ref ?? (candidates.length === 0 ? "nothing by quota" : "nothing")}:`);
147881
147996
  for (const line of candidates.length === 0 ? unrouted : [...selection.reasons, ...unrouted]) {
147882
147997
  console.log(` ${line}`);
147883
147998
  }
@@ -147909,7 +148024,7 @@ function registerModelsCommand(program2, deps) {
147909
148024
  const { paths } = deps;
147910
148025
  const modelsCommand = program2.command("model").description("Define and inspect the models the providers offer and the virtual models chosen among them.");
147911
148026
  withExamples(
147912
- modelsCommand.command("explain <name>").description("Show which member a virtual model's mode picks over the live signals, and why each candidate stands where it does.").action((name) => {
148027
+ modelsCommand.command("explain <name>").description("Show which member a virtual model's (or a family row's) mode picks over the live signals, and why each candidate stands where it does.").action((name) => {
147913
148028
  explainVirtualModel(paths, name);
147914
148029
  }),
147915
148030
  ["agent-shim model explain fast"]