claude-use 11.32.0 → 11.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -245,7 +245,7 @@ function isTimeZone(name) {
245
245
  return false;
246
246
  }
247
247
  }
248
- var import_node_path2, import_zod, import_trilean, CATEGORY_NAMES, OVERRIDABLE_CATEGORIES, CategoryMapSchema, DURATION_RE, DurationSchema, WhenConditionObjectSchema, WhenSchema, EntryValueSchema, ENTRY_KEY_RE, EntriesSchema, LaunchSchema, CREDENTIAL_TARGETS, PROVIDER_CREDENTIAL_TARGETS, CREDENTIAL_TARGET_VARS, ArgvSchema, CommandSourceOptions, EnvCredentialSourceSchema, FileCredentialSourceSchema, CommandCredentialSourceSchema, OpCredentialSourceSchema, KeychainCredentialSourceSchema, LiteralCredentialSourceSchema, CredentialSourceSchema, RemoteCredentialSourceSchema, CREDENTIAL_CACHE_STORES, CredentialCacheSchema, CredentialSchema, ProviderCredentialSchema, RESERVED_PROVIDER_ENV_KEYS, ProviderEnvSchema, PROVIDER_KINDS, ANTIGRAVITY_MODES, CLAUDE_TIERS, ANTIGRAVITY_EFFORTS, ANTIGRAVITY_DEFAULT_MODE, ANTIGRAVITY_DEFAULT_MODEL, ANTIGRAVITY_DEFAULT_TIER_MODELS, ANTIGRAVITY_DEFAULT_EFFORT, AntigravityModelTargetSchema, AntigravityProviderConfigSchema, CODEX_EFFORTS, CODEX_LOGINS, CODEX_DEFAULT_LOGIN, CODEX_DEFAULT_MODEL, CODEX_DEFAULT_TIER_MODELS, CODEX_DEFAULT_EFFORT, CodexProviderConfigSchema, ProviderRouteSchema, PickerModelSchema, PickerModelsSchema, ProviderCatalogueSchema, HttpProviderSchema, CodexProviderSchema, AntigravityProviderSchema, ProviderSchema, ConfigProfileSchema, POOL_SELECTOR_PREFIX, POOL_NAME_PATTERN, IDENTITY_NAME_PATTERN, PoolNameSchema, SELECTOR_RE, IdentitySelectorSchema, PoolMemberSchema, POOL_PREFERENCES, PoolPreferenceSchema, WHOLE_PERCENT_MAX, CompactAtUtilisationSchema, PoolSchema, WEEKDAYS, AnchorSchema, JOB_WINDOWS, JobTriggerSchema, JobTargetSchema, JobSchema, DirectoryRuleSchema, DirectoryRulesSchema, PortableConfigSchema, HEADROOM_MODES, HEADROOM_CCR_MODES, HEADROOM_ROLLOUT_CHANNELS, INTERCEPT_CHANNELS, READ_MATURATION_CHANNELS, HeadroomGlobalConfigObjectSchema, HeadroomGlobalConfigSchema, HEADROOM_DEFAULT_SOURCE, HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES, FrontDoorGlobalConfigSchema, UPDATE_MODES, UpdateGlobalConfigSchema, GlobalConfigSchema, IdentitySchema, CategoryClassificationSchema, CategoryClassificationOverlaySchema, SHIPPED_CATEGORY_DEFAULTS;
248
+ var import_node_path2, import_zod, import_trilean, CATEGORY_NAMES, OVERRIDABLE_CATEGORIES, CategoryMapSchema, DURATION_RE, DurationSchema, WhenConditionObjectSchema, WhenSchema, EntryValueSchema, ENTRY_KEY_RE, EntriesSchema, LaunchSchema, CREDENTIAL_TARGETS, PROVIDER_CREDENTIAL_TARGETS, CREDENTIAL_TARGET_VARS, ArgvSchema, CommandSourceOptions, EnvCredentialSourceSchema, FileCredentialSourceSchema, CommandCredentialSourceSchema, OpCredentialSourceSchema, KeychainCredentialSourceSchema, LiteralCredentialSourceSchema, CredentialSourceSchema, RemoteCredentialSourceSchema, CREDENTIAL_CACHE_STORES, CredentialCacheSchema, CredentialSchema, ProviderCredentialSchema, RESERVED_PROVIDER_ENV_KEYS, ProviderEnvSchema, PROVIDER_KINDS, ANTIGRAVITY_MODES, CLAUDE_TIERS, ANTIGRAVITY_EFFORTS, ANTIGRAVITY_DEFAULT_MODE, ANTIGRAVITY_DEFAULT_MODEL, ANTIGRAVITY_DEFAULT_TIER_MODELS, ANTIGRAVITY_DEFAULT_EFFORT, AntigravityModelTargetSchema, AntigravityProviderConfigSchema, CODEX_EFFORTS, CODEX_LOGINS, CODEX_DEFAULT_LOGIN, CODEX_DEFAULT_MODEL, CODEX_DEFAULT_TIER_MODELS, CODEX_DEFAULT_EFFORT, CodexProviderConfigSchema, ProviderRouteSchema, PickerModelSchema, PickerModelsSchema, ProviderCatalogueSchema, HttpProviderSchema, CodexProviderSchema, AntigravityProviderSchema, ProviderSchema, SELECTION_MODES, VirtualModelSchema, ModelPricesSchema, ModelsConfigSchema, ModelsLayerSchema, ConfigProfileSchema, POOL_SELECTOR_PREFIX, POOL_NAME_PATTERN, IDENTITY_NAME_PATTERN, PoolNameSchema, SELECTOR_RE, IdentitySelectorSchema, PoolMemberSchema, POOL_PREFERENCES, PoolPreferenceSchema, WHOLE_PERCENT_MAX, CompactAtUtilisationSchema, PoolSchema, WEEKDAYS, AnchorSchema, JOB_WINDOWS, JobTriggerSchema, JobTargetSchema, JobSchema, DirectoryRuleSchema, DirectoryRulesSchema, PortableConfigSchema, HEADROOM_MODES, HEADROOM_CCR_MODES, HEADROOM_ROLLOUT_CHANNELS, INTERCEPT_CHANNELS, READ_MATURATION_CHANNELS, HeadroomGlobalConfigObjectSchema, HeadroomGlobalConfigSchema, HEADROOM_DEFAULT_SOURCE, HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES, FrontDoorGlobalConfigSchema, UPDATE_MODES, UpdateGlobalConfigSchema, GlobalConfigSchema, IdentitySchema, CategoryClassificationSchema, CategoryClassificationOverlaySchema, SHIPPED_CATEGORY_DEFAULTS;
249
249
  var init_schema = __esm({
250
250
  "src/config/schema.ts"() {
251
251
  "use strict";
@@ -474,13 +474,54 @@ var init_schema = __esm({
474
474
  antigravity: AntigravityProviderConfigSchema.optional()
475
475
  });
476
476
  ProviderSchema = import_zod.z.discriminatedUnion("kind", [HttpProviderSchema, CodexProviderSchema, AntigravityProviderSchema]);
477
+ SELECTION_MODES = ["ordered", "most-allowance", "soonest-reset", "spread", "adaptive", "lowest-latency", "highest-success", "cheapest"];
478
+ VirtualModelSchema = import_zod.z.strictObject({
479
+ /** How the virtual model chooses its member for a request. */
480
+ mode: import_zod.z.enum(SELECTION_MODES),
481
+ /** The members to choose among, in preference order where the mode reads order. Each names a target (`z/glm-5.3`), an account model (`acct:work/opus`), another virtual model, or a family (`family:<canonical>`). */
482
+ members: import_zod.z.array(import_zod.z.string().min(1)).min(1)
483
+ });
484
+ ModelPricesSchema = import_zod.z.strictObject({
485
+ input: import_zod.z.number().positive(),
486
+ output: import_zod.z.number().positive()
487
+ });
488
+ ModelsConfigSchema = import_zod.z.strictObject({
489
+ /** Virtual models, by name. */
490
+ virtual: import_zod.z.record(import_zod.z.string().min(1), VirtualModelSchema).optional(),
491
+ /** Which model ref each Claude tier (`fable`, `opus`, `sonnet`, `haiku`) points at: a concrete target, an account model, a virtual model, or a family. */
492
+ tiers: import_zod.z.strictObject({
493
+ fable: import_zod.z.string().min(1).optional(),
494
+ opus: import_zod.z.string().min(1).optional(),
495
+ sonnet: import_zod.z.string().min(1).optional(),
496
+ haiku: import_zod.z.string().min(1).optional()
497
+ }).optional(),
498
+ /** Prices per model ref, for the `cheapest` mode. */
499
+ prices: import_zod.z.record(import_zod.z.string().min(1), ModelPricesSchema).optional(),
500
+ /** Model refs hidden from the picker and from routing, whatever else names them. */
501
+ hide: import_zod.z.array(import_zod.z.string().min(1)).optional(),
502
+ /** When set, the only model refs visible; everything else is hidden. */
503
+ show: import_zod.z.array(import_zod.z.string().min(1)).optional()
504
+ });
505
+ ModelsLayerSchema = import_zod.z.strictObject({
506
+ virtual: import_zod.z.record(import_zod.z.string().min(1), import_zod.z.union([VirtualModelSchema, import_zod.z.null()])).optional(),
507
+ tiers: import_zod.z.strictObject({
508
+ fable: import_zod.z.union([import_zod.z.string().min(1), import_zod.z.null()]).optional(),
509
+ opus: import_zod.z.union([import_zod.z.string().min(1), import_zod.z.null()]).optional(),
510
+ sonnet: import_zod.z.union([import_zod.z.string().min(1), import_zod.z.null()]).optional(),
511
+ haiku: import_zod.z.union([import_zod.z.string().min(1), import_zod.z.null()]).optional()
512
+ }).optional(),
513
+ prices: import_zod.z.record(import_zod.z.string().min(1), import_zod.z.union([ModelPricesSchema, import_zod.z.null()])).optional(),
514
+ hide: import_zod.z.array(import_zod.z.string().min(1)).optional(),
515
+ show: import_zod.z.array(import_zod.z.string().min(1)).optional()
516
+ });
477
517
  ConfigProfileSchema = import_zod.z.strictObject({
478
518
  $schema: import_zod.z.string().optional(),
479
519
  description: import_zod.z.string().optional(),
480
520
  extends: import_zod.z.array(import_zod.z.string().min(1)).optional(),
481
521
  categories: CategoryMapSchema.optional(),
482
522
  entries: EntriesSchema.optional(),
483
- launch: LaunchSchema.optional()
523
+ launch: LaunchSchema.optional(),
524
+ models: ModelsLayerSchema.optional()
484
525
  });
485
526
  POOL_SELECTOR_PREFIX = "pool:";
486
527
  POOL_NAME_PATTERN = "[A-Za-z0-9][A-Za-z0-9._-]*";
@@ -590,6 +631,7 @@ var init_schema = __esm({
590
631
  frontdoor: FrontDoorGlobalConfigSchema.optional(),
591
632
  update: UpdateGlobalConfigSchema.optional(),
592
633
  pools: import_zod.z.record(PoolNameSchema, PoolSchema).optional(),
634
+ models: ModelsConfigSchema.optional(),
593
635
  jobs: import_zod.z.record(PoolNameSchema, JobSchema).optional()
594
636
  });
595
637
  IdentitySchema = import_zod.z.strictObject({
@@ -1366,6 +1408,7 @@ function flattenLayers(layers, options) {
1366
1408
  const rules = /* @__PURE__ */ new Map();
1367
1409
  const launch = {};
1368
1410
  const diagnostics = [];
1411
+ let models;
1369
1412
  for (const layer of layers) {
1370
1413
  if (layer.categories !== void 0) {
1371
1414
  for (const [name, value] of Object.entries(layer.categories)) {
@@ -1404,6 +1447,9 @@ function flattenLayers(layers, options) {
1404
1447
  launch.explain = layer.launch.explain;
1405
1448
  }
1406
1449
  }
1450
+ if (layer.models !== void 0) {
1451
+ models = mergeModels(models, layer.models);
1452
+ }
1407
1453
  if (layer.entries === void 0) {
1408
1454
  continue;
1409
1455
  }
@@ -1466,7 +1512,7 @@ function flattenLayers(layers, options) {
1466
1512
  rules.set(pattern, rule);
1467
1513
  }
1468
1514
  }
1469
- return { categories, rules, launch, diagnostics };
1515
+ return { categories, rules, launch, ...models === void 0 ? {} : { models }, diagnostics };
1470
1516
  }
1471
1517
  function orderedKeys(layer) {
1472
1518
  const present = new Set(Object.keys(layer.entries ?? {}));
@@ -1491,6 +1537,67 @@ function matchingRules(flattened, relPath) {
1491
1537
  }
1492
1538
  return matches.sort((a, b) => compareSpecificity(b, a));
1493
1539
  }
1540
+ function mergeModels(current, layer) {
1541
+ const pieces = { ...current ?? {} };
1542
+ if (layer.virtual !== void 0) {
1543
+ const virtual = {};
1544
+ for (const [name, definition] of Object.entries(current?.virtual ?? {})) {
1545
+ if (layer.virtual[name] === void 0) {
1546
+ virtual[name] = definition;
1547
+ }
1548
+ }
1549
+ for (const [name, definition] of Object.entries(layer.virtual)) {
1550
+ if (definition !== null) {
1551
+ virtual[name] = definition;
1552
+ }
1553
+ }
1554
+ pieces.virtual = virtual;
1555
+ }
1556
+ if (layer.tiers !== void 0) {
1557
+ const tiers = {};
1558
+ for (const tier of ["fable", "opus", "sonnet", "haiku"]) {
1559
+ const ref = layer.tiers[tier];
1560
+ const inherited = current?.tiers?.[tier];
1561
+ if (ref !== null && ref !== void 0) {
1562
+ tiers[tier] = ref;
1563
+ } else if (ref === void 0 && inherited !== void 0) {
1564
+ tiers[tier] = inherited;
1565
+ }
1566
+ }
1567
+ pieces.tiers = tiers;
1568
+ }
1569
+ if (layer.prices !== void 0) {
1570
+ const priced = {};
1571
+ for (const [ref, prices] of Object.entries(current?.prices ?? {})) {
1572
+ if (layer.prices[ref] === void 0) {
1573
+ priced[ref] = prices;
1574
+ }
1575
+ }
1576
+ for (const [ref, prices] of Object.entries(layer.prices)) {
1577
+ if (prices !== null) {
1578
+ priced[ref] = prices;
1579
+ }
1580
+ }
1581
+ pieces.prices = priced;
1582
+ }
1583
+ if (layer.hide !== void 0) {
1584
+ pieces.hide = layer.hide;
1585
+ }
1586
+ if (layer.show !== void 0) {
1587
+ pieces.show = layer.show;
1588
+ }
1589
+ const merged = modelsOf(pieces);
1590
+ return Object.keys(merged).length === 0 ? void 0 : merged;
1591
+ }
1592
+ function modelsOf(pieces) {
1593
+ return {
1594
+ ...pieces.virtual === void 0 || Object.keys(pieces.virtual).length === 0 ? {} : { virtual: pieces.virtual },
1595
+ ...pieces.tiers === void 0 || Object.keys(pieces.tiers).length === 0 ? {} : { tiers: pieces.tiers },
1596
+ ...pieces.prices === void 0 || Object.keys(pieces.prices).length === 0 ? {} : { prices: pieces.prices },
1597
+ ...pieces.hide === void 0 || pieces.hide.length === 0 ? {} : { hide: [...pieces.hide] },
1598
+ ...pieces.show === void 0 || pieces.show.length === 0 ? {} : { show: [...pieces.show] }
1599
+ };
1600
+ }
1494
1601
  var init_flatten = __esm({
1495
1602
  "src/resolve/flatten.ts"() {
1496
1603
  "use strict";
@@ -1866,7 +1973,8 @@ function profileLayers(rootName, load, startId) {
1866
1973
  ...source.profile.categories === void 0 ? {} : { categories: source.profile.categories },
1867
1974
  ...source.profile.entries === void 0 ? {} : { entries: source.profile.entries },
1868
1975
  ...source.entryOrder === void 0 ? {} : { entryOrder: source.entryOrder },
1869
- ...source.profile.launch === void 0 ? {} : { launch: source.profile.launch }
1976
+ ...source.profile.launch === void 0 ? {} : { launch: source.profile.launch },
1977
+ ...source.profile.models === void 0 ? {} : { models: source.profile.models }
1870
1978
  });
1871
1979
  nextId += 1;
1872
1980
  }
@@ -1954,7 +2062,8 @@ function assembleCascade(input) {
1954
2062
  ...source.config.categories === void 0 ? {} : { categories: source.config.categories },
1955
2063
  ...source.config.entries === void 0 ? {} : { entries: source.config.entries },
1956
2064
  ...source.entryOrder === void 0 ? {} : { entryOrder: source.entryOrder },
1957
- ...source.config.launch === void 0 ? {} : { launch: source.config.launch }
2065
+ ...source.config.launch === void 0 ? {} : { launch: source.config.launch },
2066
+ ...source.config.models === void 0 ? {} : { models: source.config.models }
1958
2067
  });
1959
2068
  nextId += 1;
1960
2069
  }
@@ -2983,7 +3092,7 @@ var init_package = __esm({
2983
3092
  "package.json"() {
2984
3093
  package_default = {
2985
3094
  name: "claude-use",
2986
- version: "11.32.0",
3095
+ version: "11.33.0",
2987
3096
  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.",
2988
3097
  license: "MIT",
2989
3098
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -15085,6 +15194,107 @@ init_credentialCache();
15085
15194
  init_realCredentialCache();
15086
15195
  init_source();
15087
15196
 
15197
+ // src/modelsStore.ts
15198
+ init_store();
15199
+ init_schema();
15200
+ var VirtualModelNotFoundError = class extends Error {
15201
+ constructor(name) {
15202
+ super(`No virtual model named "${name}".`);
15203
+ this.name = "VirtualModelNotFoundError";
15204
+ }
15205
+ };
15206
+ function memberKindOf(ref, models) {
15207
+ if (ref.startsWith("acct:")) {
15208
+ return "account";
15209
+ }
15210
+ if (ref.startsWith("family:")) {
15211
+ return "family";
15212
+ }
15213
+ return models?.virtual !== void 0 && ref in models.virtual ? "virtual" : "provider";
15214
+ }
15215
+ function expandMembers(name, models) {
15216
+ const virtual = models?.virtual ?? {};
15217
+ const expanded = [];
15218
+ const walk = (current, chain) => {
15219
+ const nested = virtual[current];
15220
+ if (nested !== void 0) {
15221
+ if (chain.includes(current)) {
15222
+ throw new Error(`virtual model cycle: ${[...chain, current].join(" -> ")}`);
15223
+ }
15224
+ for (const member of nested.members) {
15225
+ walk(member, [...chain, current]);
15226
+ }
15227
+ return;
15228
+ }
15229
+ if (!expanded.includes(current)) {
15230
+ expanded.push(current);
15231
+ }
15232
+ };
15233
+ const top = virtual[name];
15234
+ if (top === void 0) {
15235
+ throw new VirtualModelNotFoundError(name);
15236
+ }
15237
+ for (const member of top.members) {
15238
+ walk(member, [name]);
15239
+ }
15240
+ return expanded;
15241
+ }
15242
+
15243
+ // src/models/doctor.ts
15244
+ function modelsFindings(input) {
15245
+ const findings = [];
15246
+ const { models } = input;
15247
+ const providers = new Set(input.providers);
15248
+ const identities = new Set(input.identities);
15249
+ const virtualNames = new Set(Object.keys(models.virtual ?? {}));
15250
+ for (const [name, model] of Object.entries(models.virtual ?? {})) {
15251
+ for (const member of model.members) {
15252
+ const kind = memberKindOf(member, models);
15253
+ if (kind === "provider" && !member.includes("/")) {
15254
+ findings.push({ severity: "fail", message: `Virtual model "${name}" names member "${member}", which is neither a defined virtual model nor a provider model (a provider model is <provider>/<model>).` });
15255
+ } else if (kind === "provider" && !providers.has(member.split("/")[0] ?? "")) {
15256
+ findings.push({ severity: "fail", message: `Virtual model "${name}" names member "${member}", but no provider "${member.split("/")[0] ?? ""}" is defined.` });
15257
+ }
15258
+ if (kind === "virtual" && !virtualNames.has(member)) {
15259
+ findings.push({ severity: "fail", message: `Virtual model "${name}" names member "${member}", but no virtual model "${member}" is defined.` });
15260
+ }
15261
+ if (kind === "account") {
15262
+ const identity = member.slice("acct:".length).split("/")[0] ?? "";
15263
+ if (!identities.has(identity)) {
15264
+ findings.push({ severity: "fail", message: `Virtual model "${name}" names member "${member}", but no identity "${identity}" is defined.` });
15265
+ }
15266
+ }
15267
+ }
15268
+ try {
15269
+ expandMembers(name, models);
15270
+ } catch (error) {
15271
+ findings.push({ severity: "fail", message: `Virtual model "${name}" cannot be expanded: ${error instanceof Error ? error.message : String(error)}` });
15272
+ }
15273
+ if (model.mode === "cheapest") {
15274
+ const expanded = expandMembers(name, models);
15275
+ const unpriced = expanded.filter((member) => models.prices?.[member] === void 0 && memberKindOf(member, models) !== "virtual");
15276
+ if (unpriced.length > 0) {
15277
+ findings.push({ severity: "warn", message: `Virtual model "${name}" chooses by price, but no prices are set for: ${unpriced.join(", ")}.` });
15278
+ }
15279
+ }
15280
+ }
15281
+ for (const [tier, ref] of Object.entries(models.tiers ?? {})) {
15282
+ const kind = memberKindOf(ref, models);
15283
+ const known = kind === "virtual" ? virtualNames.has(ref) : kind === "provider" ? providers.has(ref.split("/")[0] ?? "") : true;
15284
+ if (!known) {
15285
+ findings.push({ severity: "fail", message: `Tier ${tier} points at "${ref}", which names nothing defined.` });
15286
+ }
15287
+ }
15288
+ const hidden = new Set(models.hide ?? []);
15289
+ const shown = new Set(models.show ?? []);
15290
+ for (const ref of hidden) {
15291
+ if (shown.has(ref)) {
15292
+ findings.push({ severity: "fail", message: `Model ref "${ref}" is both hidden and in the show-only list.` });
15293
+ }
15294
+ }
15295
+ return findings;
15296
+ }
15297
+
15088
15298
  // src/headroom/allowlistDrift.ts
15089
15299
  init_earlierRelease();
15090
15300
  init_state2();
@@ -15271,7 +15481,8 @@ var DOCTOR_SECTIONS = [
15271
15481
  "categories-local",
15272
15482
  "active-identity",
15273
15483
  "headroom",
15274
- "frontdoor"
15484
+ "frontdoor",
15485
+ "models"
15275
15486
  ];
15276
15487
  function refinePathShadow(status, ownExecutablePath, realpath) {
15277
15488
  if (status.status !== "shadowed") {
@@ -15423,6 +15634,9 @@ function pushLegacyName(push, params) {
15423
15634
  );
15424
15635
  }
15425
15636
  }
15637
+ function parsedModelsOf(paths) {
15638
+ return readGlobalConfig(paths)?.models;
15639
+ }
15426
15640
  function runDoctor(params) {
15427
15641
  const findings = [];
15428
15642
  const push = (section, severity, message, subject) => {
@@ -15624,6 +15838,17 @@ function runDoctor(params) {
15624
15838
  }
15625
15839
  }
15626
15840
  }
15841
+ {
15842
+ const models = params.models;
15843
+ if (models === void 0) {
15844
+ push("models", "pass", "No models block configured.");
15845
+ } else {
15846
+ for (const finding of modelsFindings({ models, providers: params.providers.map((entry) => entry.name), identities: params.identities.map((entry) => entry.name) })) {
15847
+ push("models", finding.severity, finding.message);
15848
+ }
15849
+ push("models", "pass", "The models block is consistent.");
15850
+ }
15851
+ }
15627
15852
  if (params.categoriesLocal.raw === void 0) {
15628
15853
  push("categories-local", "pass", "No categories.local.json configured.");
15629
15854
  } else {
@@ -15718,6 +15943,7 @@ function runDoctor(params) {
15718
15943
  return { findings, ok: !findings.some((finding) => finding.severity === "fail") };
15719
15944
  }
15720
15945
  var SECTION_TITLES = {
15946
+ models: "Virtual models",
15721
15947
  "ambient-credential": "Ambient-credential exposure",
15722
15948
  "binary-discovery": "Claude Code binary discovery",
15723
15949
  "claude-shim": "`claude` command shim",
@@ -15850,6 +16076,7 @@ function collectDoctorReport(params) {
15850
16076
  providers,
15851
16077
  directoryRules: { path: paths.directoryRulesFile, raw: realFsPort.readFileUtf8(paths.directoryRulesFile) },
15852
16078
  globalConfig: { path: paths.globalConfigFile, raw: realFsPort.readFileUtf8(paths.globalConfigFile) },
16079
+ models: parsedModelsOf(paths),
15853
16080
  categoriesLocal: { path: paths.categoriesLocalFile, raw: realFsPort.readFileUtf8(paths.categoriesLocalFile) },
15854
16081
  activeIdentity: { path: paths.activeIdentityFile, raw: realFsPort.readFileUtf8(paths.activeIdentityFile) },
15855
16082
  binaryDiscovery,