claude-use 11.44.4 → 11.45.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/README.md CHANGED
@@ -196,7 +196,7 @@ agent-shim run [@<identity>] [launch flags] [claude arguments]
196
196
  # --claude-version <version> run exactly this installed Claude Code version
197
197
  # --delay <duration> wait this long after the launcher's own output before starting claude; --[no-]pause waits for a key press instead
198
198
  # --[no-]explain with @pool:<name>, list every member the pick ranked and why, not only the one picked
199
- # --[no-]route-by-name route provider-qualified model names through the models block to the provider that serves them
199
+ # --[no-]route-by-name also route bare virtual-model names through the models block (qualified names route on every session)
200
200
  # --native run the real claude with nothing from agent-shim applied; cannot be combined with the flags above
201
201
  claude @<identity> ... # the same, once `agent-shim shim enable` has run
202
202
  ```
package/dist/cli.cjs CHANGED
@@ -34701,7 +34701,7 @@ var init_package = __esm({
34701
34701
  "package.json"() {
34702
34702
  package_default = {
34703
34703
  name: "claude-use",
34704
- version: "11.44.4",
34704
+ version: "11.45.0",
34705
34705
  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.",
34706
34706
  license: "MIT",
34707
34707
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -65950,25 +65950,25 @@ function providerModelRows(provider, catalogue = []) {
65950
65950
  const taken = new Set(named.map((row) => labelOf(row.model)));
65951
65951
  return [...named, ...catalogueRows(provider, catalogue).filter((row) => !taken.has(labelOf(row.model)))];
65952
65952
  }
65953
- function routedModelRows(models, providers) {
65953
+ function routedModelRows(models, providers, bare = true) {
65954
65954
  const hidden = new Set(models.hide ?? []);
65955
65955
  const shown = models.show === void 0 ? void 0 : new Set(models.show);
65956
65956
  const visible = (model) => shown === void 0 ? !hidden.has(model) : shown.has(model);
65957
- const concrete = providers.flatMap(([name, provider]) => providerModelRows(provider).map((row) => ({ ...row, model: `${name}/${row.model}`, label: `${name} / ${row.label}`, description: `${name}: ${row.description}` })));
65957
+ const concrete = providers.flatMap(([name, provider, catalogue]) => providerModelRows(provider, catalogue).map((row) => ({ ...row, model: `${name}/${row.model}`, label: `${name} / ${row.label}`, description: `${name}: ${row.description}` })));
65958
65958
  const concreteByRef = new Map(concrete.map((row) => [row.model, row]));
65959
65959
  const families = buildFamilies([...concrete.map((row) => row.model), ...accountRefsOf(models)], models);
65960
65960
  const handlingOf = (refs) => refs.map((ref) => concreteByRef.get(ref)?.behavesAs).find((behavesAs) => behavesAs !== void 0) ?? TIER_BEHAVES_AS.sonnet;
65961
- const virtual = Object.entries(models.virtual ?? {}).flatMap(([name, definition]) => {
65961
+ const virtual = bare ? Object.entries(models.virtual ?? {}).flatMap(([name, definition]) => {
65962
65962
  if (!visible(name)) {
65963
65963
  return [];
65964
65964
  }
65965
65965
  const targets = expandFamilyMembers(safeExpand(name, models), families);
65966
65966
  return [{ model: name, label: name, description: `Virtual (${definition.mode})`, behavesAs: handlingOf(targets) }];
65967
- });
65968
- const familyRows = sharedFamilies(families).flatMap((family) => {
65967
+ }) : [];
65968
+ const familyRows = bare ? sharedFamilies(families).flatMap((family) => {
65969
65969
  const member = `${FAMILY_PREFIX}${family.key}`;
65970
65970
  return visible(member) ? [{ model: member, label: family.key, description: `Family (${familyMode(family.settings)}): ${family.refs.join(", ")}`, behavesAs: handlingOf(family.refs) }] : [];
65971
- });
65971
+ }) : [];
65972
65972
  return [...virtual, ...familyRows, ...concrete.filter((row) => visible(row.model))];
65973
65973
  }
65974
65974
  function safeExpand(name, models) {
@@ -65978,9 +65978,6 @@ function safeExpand(name, models) {
65978
65978
  return models.virtual?.[name]?.members ?? [];
65979
65979
  }
65980
65980
  }
65981
- function modelPickerSettings(provider, catalogue = []) {
65982
- return modelPickerSettingsFromRows(providerModelRows(provider, catalogue), true);
65983
- }
65984
65981
  function modelPickerSettingsFromRows(options, replaceBuiltInOptions) {
65985
65982
  return options.length === 0 ? void 0 : JSON.stringify({ modelPicker: { options, replaceBuiltInOptions } });
65986
65983
  }
@@ -66452,11 +66449,18 @@ function decideLaunch(params, readOnly) {
66452
66449
  notes.push(`${loginlessProvider.identity} has no stored login, so Remote Control is off; provider ${loginlessProvider.provider} runs without it`);
66453
66450
  }
66454
66451
  const flags = loginlessProvider === void 0 ? requestedFlags : { ...requestedFlags, remoteControl: false };
66455
- const catalogue = selectedProvider === void 0 ? void 0 : parseCatalogueCache(params.fs.readFileUtf8(catalogueCachePath(paths, selectedProvider.name)));
66456
66452
  const routesByName = flags.routeByName || selectedProvider !== void 0 && isRouterProvider(selectedProvider.definition);
66457
66453
  const globalModels = loadConfigFile(paths.globalConfigFile, GlobalConfigSchema, params.fs.readConfigFile)?.config.models;
66458
66454
  const models = launchCascade !== void 0 && params.farm !== void 0 ? cascadeModels : globalModels;
66459
- 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);
66455
+ const listedProviders = listProviderNames(fs26.readdir, paths.providersDir).flatMap((name) => {
66456
+ try {
66457
+ const definition = loadProvider(paths.providersDir, name, fs26);
66458
+ return definition === void 0 ? [] : [[name, definition, parseCatalogueCache(params.fs.readFileUtf8(catalogueCachePath(paths, name)))?.models ?? []]];
66459
+ } catch {
66460
+ return [];
66461
+ }
66462
+ });
66463
+ const pickerSettings = modelPickerSettingsFromRows(routedModelRows(models ?? {}, listedProviders, routesByName), selectedProvider !== void 0);
66460
66464
  const callerSettings = hasSettingsArgument(parsedArgv.rest);
66461
66465
  if (pickerSettings !== void 0 && callerSettings) {
66462
66466
  notes.push("--settings was passed, so /model keeps Claude Code's own model names");
@@ -131990,17 +131994,17 @@ var CHARS_PER_TOKEN2 = 4;
131990
131994
  function needsOf(scan) {
131991
131995
  return { hasImage: scan.hasImage === true, hasTools: scan.toolsPresent === true, thinking: scan.thinking === true, contextTokens: Math.ceil((scan.text?.length ?? 0) / CHARS_PER_TOKEN2) };
131992
131996
  }
131993
- function resolveRoutedModel(model, providerName, session, deps, memory, rotations, needs) {
131997
+ function resolveRoutedModel(model, providerName, session, deps, byName, memory, rotations, needs) {
131994
131998
  const models = deps.models?.(session);
131995
131999
  const qualified = model.includes("/") && !model.startsWith("acct:") ? model : void 0;
131996
132000
  if (qualified !== void 0) {
131997
132001
  const [provider2, ...rest2] = qualified.split("/");
131998
132002
  const named = rest2.join("/");
131999
- return provider2 === void 0 || named === "" ? void 0 : { provider: provider2, model: withoutContextMarker(named), ref: qualified };
132003
+ return provider2 === void 0 || named === "" || deps.definesProvider !== void 0 && !deps.definesProvider(provider2) ? void 0 : { provider: provider2, model: withoutContextMarker(named), ref: qualified };
132000
132004
  }
132001
132005
  const isFamily = model.startsWith(FAMILY_PREFIX);
132002
132006
  const virtual = isFamily ? void 0 : models?.virtual?.[model];
132003
- if (virtual === void 0 && !isFamily) {
132007
+ if (!byName || virtual === void 0 && !isFamily) {
132004
132008
  return void 0;
132005
132009
  }
132006
132010
  const declared = isFamily ? [model] : expandMembers(model, models);
@@ -132048,6 +132052,13 @@ function createProviderRouteResolver(deps) {
132048
132052
  const oauthRoute = createPassthroughRoute("anthropic", { baseUrl: `https://${CONNECT_INTERCEPT_HOST}:${String(HTTPS_PORT)}`, stripPrefix: void 0, headroomUpstream: void 0 });
132049
132053
  const antigravityQuotaSources = /* @__PURE__ */ new Map();
132050
132054
  const antigravityRoutingMemory = /* @__PURE__ */ new Map();
132055
+ const definesProvider = (name) => {
132056
+ try {
132057
+ return loadProvider(deps.providersDir, name, deps.fs) !== void 0;
132058
+ } catch {
132059
+ return false;
132060
+ }
132061
+ };
132051
132062
  const routingMemory = /* @__PURE__ */ new Map();
132052
132063
  const rotations = /* @__PURE__ */ new Map();
132053
132064
  const memoryFor = (provider) => {
@@ -132211,8 +132222,8 @@ function createProviderRouteResolver(deps) {
132211
132222
  routes = void 0;
132212
132223
  isRouter = false;
132213
132224
  }
132214
- const routesByName = !nameResolved && (isRouter || current.session.routeByName) && !isRcSelfHostPath(path65);
132215
- if (routesByName) {
132225
+ const resolvesNames = !nameResolved && !isRcSelfHostPath(path65);
132226
+ if (resolvesNames) {
132216
132227
  const scan2 = await scanRequestHead(current, true);
132217
132228
  if (scan2.replayed === void 0) {
132218
132229
  const resolution = resolve2(current);
@@ -132229,8 +132240,11 @@ function createProviderRouteResolver(deps) {
132229
132240
  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`
132230
132241
  };
132231
132242
  }
132232
- const routed = scan2.model === void 0 ? void 0 : resolveRoutedModel(scan2.model, providerName, current.session, deps, routingMemory, rotations, needsOf(scan2));
132243
+ const routed = scan2.model === void 0 ? void 0 : resolveRoutedModel(scan2.model, providerName, current.session, { ...deps, definesProvider }, isRouter || current.session.routeByName, routingMemory, rotations, needsOf(scan2));
132233
132244
  const requested = scan2.model;
132245
+ if (routed === void 0) {
132246
+ current = scan2.replayed;
132247
+ }
132234
132248
  if (routed !== void 0) {
132235
132249
  routingMemory.set(current.session.sessionId ?? "", routed.ref);
132236
132250
  if (routed.requested !== void 0) {
@@ -135075,7 +135089,7 @@ const { workerData, parentPort } = require("node:worker_threads");
135075
135089
  const fs = require("node:fs");
135076
135090
  const os = require("node:os");
135077
135091
  const inspector = require("node:inspector");
135078
- const { shared, boundMs, checkEveryMs, pauseWaitMs, stateFile, ownPid, action, logFile, respawn, respawnGeneration, respawnMaxGeneration, awaitPidEnv, respawnGenerationEnv } = workerData;
135092
+ const { shared, boundMs, checkEveryMs, pauseWaitMs, stateFile, ownPid, action, logFile, respawn, respawnGeneration, respawnMaxGeneration, startLockFile, awaitPidEnv, respawnGenerationEnv } = workerData;
135079
135093
  const counter = new Int32Array(shared);
135080
135094
  let lastValue = Atomics.load(counter, 0);
135081
135095
  let lastChangeAt = Date.now();
@@ -135139,17 +135153,59 @@ const describeMainThread = (waitMs, resume) => new Promise((resolve) => {
135139
135153
  finish("the main thread could not be inspected: " + (error instanceof Error ? error.message : String(error)));
135140
135154
  }
135141
135155
  });
135156
+ // Whether a process is alive: signal 0 only tests, and EPERM means it exists under another user.
135157
+ const isRunning = (pid) => {
135158
+ try {
135159
+ process.kill(pid, 0);
135160
+ return true;
135161
+ } catch (error) {
135162
+ return error.code === "EPERM";
135163
+ }
135164
+ };
135165
+ // The pid holding the start lock when that holder is alive, which means a door is already being started and another must not be: the launcher's ensure and this respawn are the two things that start a door, and the lock is the one protocol that keeps them from starting two. A dead holder's lock is litter and is cleared, exactly as the launcher's ensure clears it.
135166
+ const liveLockHolder = () => {
135167
+ let holder;
135168
+ try {
135169
+ holder = JSON.parse(fs.readFileSync(startLockFile, "utf8")).pid;
135170
+ } catch (error) {
135171
+ return undefined;
135172
+ }
135173
+ if (typeof holder === "number" && isRunning(holder)) return holder;
135174
+ fs.rmSync(startLockFile, { force: true });
135175
+ return undefined;
135176
+ };
135177
+ // Creates the lock naming the replacement as its holder, atomically (the wx flag), so the launcher's ensure sees a live holder while the replacement boots and waits for it instead of starting a door of its own; the replacement removes the lock once it is serving, as every door does.
135178
+ const claimStartLock = (holder) => {
135179
+ try {
135180
+ fs.writeFileSync(startLockFile, JSON.stringify({ pid: holder, at: Date.now() }) + "\\n", { flag: "wx" });
135181
+ return true;
135182
+ } catch (error) {
135183
+ if (error.code === "EEXIST") return false;
135184
+ throw error;
135185
+ }
135186
+ };
135142
135187
  const spawnReplacement = () => {
135143
135188
  if (respawn === undefined || logFile === undefined) return;
135144
135189
  if (respawnGeneration >= respawnMaxGeneration) {
135145
135190
  log("not starting another replacement: this door was replacement generation " + String(respawnGeneration) + " of " + String(respawnMaxGeneration) + ", so the stall has recurred through consecutive doors and the machine, not the door, is the one refusing to serve; leaving the next launch's ensure to start one");
135146
135191
  return;
135147
135192
  }
135193
+ const startingBy = liveLockHolder();
135194
+ if (startingBy !== undefined) {
135195
+ log("not starting a replacement: process " + String(startingBy) + " holds the start lock, so a door is already being started and a second one would race it for the sticky ports");
135196
+ return;
135197
+ }
135148
135198
  try {
135149
135199
  const out = fs.openSync(logFile, "a");
135150
135200
  const child = require("node:child_process").spawn(respawn.command, respawn.args, { detached: true, stdio: ["ignore", out, out], env: Object.assign({}, respawn.env, { [awaitPidEnv]: String(ownPid), [respawnGenerationEnv]: String(respawnGeneration + 1) }) });
135151
135201
  child.unref();
135152
135202
  fs.closeSync(out);
135203
+ if (!claimStartLock(child.pid)) {
135204
+ // A launcher took the lock between the check and the spawn, so its door is the one that is starting: this one must not also bind.
135205
+ process.kill(child.pid, "SIGKILL");
135206
+ log("withdrew replacement door " + String(child.pid) + ": a launcher took the start lock first and its door is the one starting");
135207
+ return;
135208
+ }
135153
135209
  log("started replacement door " + String(child.pid) + " of generation " + String(respawnGeneration + 1) + ", which binds once this process is gone");
135154
135210
  } catch (error) {
135155
135211
  log("could not start a replacement door: " + (error instanceof Error ? error.message : String(error)));
@@ -135198,7 +135254,7 @@ function startThreadWatchdog(params) {
135198
135254
  const counter = new Int32Array(shared);
135199
135255
  const worker = new import_node_worker_threads2.Worker(WATCHDOG_SOURCE, {
135200
135256
  eval: true,
135201
- workerData: { shared, boundMs: params.boundMs, checkEveryMs: params.checkEveryMs, pauseWaitMs: params.pauseWaitMs, stateFile: params.stateFile, ownPid: params.ownPid, action: params.action, logFile: params.logFile, respawn: params.respawn, respawnGeneration: params.respawnGeneration, respawnMaxGeneration: params.respawnMaxGeneration, awaitPidEnv: DOOR_AWAIT_PID_ENV, respawnGenerationEnv: DOOR_RESPAWN_GENERATION_ENV }
135257
+ workerData: { shared, boundMs: params.boundMs, checkEveryMs: params.checkEveryMs, pauseWaitMs: params.pauseWaitMs, stateFile: params.stateFile, ownPid: params.ownPid, action: params.action, logFile: params.logFile, respawn: params.respawn, respawnGeneration: params.respawnGeneration, respawnMaxGeneration: params.respawnMaxGeneration, startLockFile: params.startLockFile, awaitPidEnv: DOOR_AWAIT_PID_ENV, respawnGenerationEnv: DOOR_RESPAWN_GENERATION_ENV }
135202
135258
  });
135203
135259
  worker.unref();
135204
135260
  worker.on("message", (message) => {
@@ -135774,7 +135830,8 @@ function realFrontDoorSupervisorPorts(paths, respawnGeneration) {
135774
135830
  logFile: paths.frontdoorLogPath,
135775
135831
  respawn: respawnInvocation(paths),
135776
135832
  respawnGeneration,
135777
- respawnMaxGeneration: DOOR_RESPAWN_MAX_GENERATIONS
135833
+ respawnMaxGeneration: DOOR_RESPAWN_MAX_GENERATIONS,
135834
+ startLockFile: paths.frontdoorLockFile
135778
135835
  }),
135779
135836
  // The launch lifecycle publisher over the same backbone the typed API serves: the tick's registry facts go in here, and the door's own register, prune and end moments come out as source-tagged events.
135780
135837
  observeLaunchRegistry: createLaunchEventPublisher(doorEvents, () => Date.now()).observe,
package/dist/index.cjs CHANGED
@@ -3151,7 +3151,7 @@ var init_package = __esm({
3151
3151
  "package.json"() {
3152
3152
  package_default = {
3153
3153
  name: "claude-use",
3154
- version: "11.44.4",
3154
+ version: "11.45.0",
3155
3155
  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.",
3156
3156
  license: "MIT",
3157
3157
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -8162,25 +8162,25 @@ function providerModelRows(provider, catalogue = []) {
8162
8162
  const taken = new Set(named.map((row) => labelOf(row.model)));
8163
8163
  return [...named, ...catalogueRows(provider, catalogue).filter((row) => !taken.has(labelOf(row.model)))];
8164
8164
  }
8165
- function routedModelRows(models, providers) {
8165
+ function routedModelRows(models, providers, bare = true) {
8166
8166
  const hidden = new Set(models.hide ?? []);
8167
8167
  const shown = models.show === void 0 ? void 0 : new Set(models.show);
8168
8168
  const visible = (model) => shown === void 0 ? !hidden.has(model) : shown.has(model);
8169
- const concrete = providers.flatMap(([name, provider]) => providerModelRows(provider).map((row) => ({ ...row, model: `${name}/${row.model}`, label: `${name} / ${row.label}`, description: `${name}: ${row.description}` })));
8169
+ const concrete = providers.flatMap(([name, provider, catalogue]) => providerModelRows(provider, catalogue).map((row) => ({ ...row, model: `${name}/${row.model}`, label: `${name} / ${row.label}`, description: `${name}: ${row.description}` })));
8170
8170
  const concreteByRef = new Map(concrete.map((row) => [row.model, row]));
8171
8171
  const families = buildFamilies([...concrete.map((row) => row.model), ...accountRefsOf(models)], models);
8172
8172
  const handlingOf = (refs) => refs.map((ref) => concreteByRef.get(ref)?.behavesAs).find((behavesAs) => behavesAs !== void 0) ?? TIER_BEHAVES_AS.sonnet;
8173
- const virtual = Object.entries(models.virtual ?? {}).flatMap(([name, definition]) => {
8173
+ const virtual = bare ? Object.entries(models.virtual ?? {}).flatMap(([name, definition]) => {
8174
8174
  if (!visible(name)) {
8175
8175
  return [];
8176
8176
  }
8177
8177
  const targets = expandFamilyMembers(safeExpand(name, models), families);
8178
8178
  return [{ model: name, label: name, description: `Virtual (${definition.mode})`, behavesAs: handlingOf(targets) }];
8179
- });
8180
- const familyRows = sharedFamilies(families).flatMap((family) => {
8179
+ }) : [];
8180
+ const familyRows = bare ? sharedFamilies(families).flatMap((family) => {
8181
8181
  const member = `${FAMILY_PREFIX}${family.key}`;
8182
8182
  return visible(member) ? [{ model: member, label: family.key, description: `Family (${familyMode(family.settings)}): ${family.refs.join(", ")}`, behavesAs: handlingOf(family.refs) }] : [];
8183
- });
8183
+ }) : [];
8184
8184
  return [...virtual, ...familyRows, ...concrete.filter((row) => visible(row.model))];
8185
8185
  }
8186
8186
  function safeExpand(name, models) {
@@ -8190,9 +8190,6 @@ function safeExpand(name, models) {
8190
8190
  return models.virtual?.[name]?.members ?? [];
8191
8191
  }
8192
8192
  }
8193
- function modelPickerSettings(provider, catalogue = []) {
8194
- return modelPickerSettingsFromRows(providerModelRows(provider, catalogue), true);
8195
- }
8196
8193
  function modelPickerSettingsFromRows(options, replaceBuiltInOptions) {
8197
8194
  return options.length === 0 ? void 0 : JSON.stringify({ modelPicker: { options, replaceBuiltInOptions } });
8198
8195
  }
@@ -9720,11 +9717,18 @@ function decideLaunch(params, readOnly) {
9720
9717
  notes.push(`${loginlessProvider.identity} has no stored login, so Remote Control is off; provider ${loginlessProvider.provider} runs without it`);
9721
9718
  }
9722
9719
  const flags = loginlessProvider === void 0 ? requestedFlags : { ...requestedFlags, remoteControl: false };
9723
- const catalogue = selectedProvider === void 0 ? void 0 : parseCatalogueCache(params.fs.readFileUtf8(catalogueCachePath(paths, selectedProvider.name)));
9724
9720
  const routesByName = flags.routeByName || selectedProvider !== void 0 && isRouterProvider(selectedProvider.definition);
9725
9721
  const globalModels = loadConfigFile(paths.globalConfigFile, GlobalConfigSchema, params.fs.readConfigFile)?.config.models;
9726
9722
  const models = launchCascade !== void 0 && params.farm !== void 0 ? cascadeModels : globalModels;
9727
- 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);
9723
+ const listedProviders = listProviderNames(fs13.readdir, paths.providersDir).flatMap((name) => {
9724
+ try {
9725
+ const definition = loadProvider(paths.providersDir, name, fs13);
9726
+ return definition === void 0 ? [] : [[name, definition, parseCatalogueCache(params.fs.readFileUtf8(catalogueCachePath(paths, name)))?.models ?? []]];
9727
+ } catch {
9728
+ return [];
9729
+ }
9730
+ });
9731
+ const pickerSettings = modelPickerSettingsFromRows(routedModelRows(models ?? {}, listedProviders, routesByName), selectedProvider !== void 0);
9728
9732
  const callerSettings = hasSettingsArgument(parsedArgv.rest);
9729
9733
  if (pickerSettings !== void 0 && callerSettings) {
9730
9734
  notes.push("--settings was passed, so /model keeps Claude Code's own model names");
package/dist/index.mjs CHANGED
@@ -3127,7 +3127,7 @@ var init_package = __esm({
3127
3127
  "package.json"() {
3128
3128
  package_default = {
3129
3129
  name: "claude-use",
3130
- version: "11.44.4",
3130
+ version: "11.45.0",
3131
3131
  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.",
3132
3132
  license: "MIT",
3133
3133
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -8135,25 +8135,25 @@ function providerModelRows(provider, catalogue = []) {
8135
8135
  const taken = new Set(named.map((row) => labelOf(row.model)));
8136
8136
  return [...named, ...catalogueRows(provider, catalogue).filter((row) => !taken.has(labelOf(row.model)))];
8137
8137
  }
8138
- function routedModelRows(models, providers) {
8138
+ function routedModelRows(models, providers, bare = true) {
8139
8139
  const hidden = new Set(models.hide ?? []);
8140
8140
  const shown = models.show === void 0 ? void 0 : new Set(models.show);
8141
8141
  const visible = (model) => shown === void 0 ? !hidden.has(model) : shown.has(model);
8142
- const concrete = providers.flatMap(([name, provider]) => providerModelRows(provider).map((row) => ({ ...row, model: `${name}/${row.model}`, label: `${name} / ${row.label}`, description: `${name}: ${row.description}` })));
8142
+ const concrete = providers.flatMap(([name, provider, catalogue]) => providerModelRows(provider, catalogue).map((row) => ({ ...row, model: `${name}/${row.model}`, label: `${name} / ${row.label}`, description: `${name}: ${row.description}` })));
8143
8143
  const concreteByRef = new Map(concrete.map((row) => [row.model, row]));
8144
8144
  const families = buildFamilies([...concrete.map((row) => row.model), ...accountRefsOf(models)], models);
8145
8145
  const handlingOf = (refs) => refs.map((ref) => concreteByRef.get(ref)?.behavesAs).find((behavesAs) => behavesAs !== void 0) ?? TIER_BEHAVES_AS.sonnet;
8146
- const virtual = Object.entries(models.virtual ?? {}).flatMap(([name, definition]) => {
8146
+ const virtual = bare ? Object.entries(models.virtual ?? {}).flatMap(([name, definition]) => {
8147
8147
  if (!visible(name)) {
8148
8148
  return [];
8149
8149
  }
8150
8150
  const targets = expandFamilyMembers(safeExpand(name, models), families);
8151
8151
  return [{ model: name, label: name, description: `Virtual (${definition.mode})`, behavesAs: handlingOf(targets) }];
8152
- });
8153
- const familyRows = sharedFamilies(families).flatMap((family) => {
8152
+ }) : [];
8153
+ const familyRows = bare ? sharedFamilies(families).flatMap((family) => {
8154
8154
  const member = `${FAMILY_PREFIX}${family.key}`;
8155
8155
  return visible(member) ? [{ model: member, label: family.key, description: `Family (${familyMode(family.settings)}): ${family.refs.join(", ")}`, behavesAs: handlingOf(family.refs) }] : [];
8156
- });
8156
+ }) : [];
8157
8157
  return [...virtual, ...familyRows, ...concrete.filter((row) => visible(row.model))];
8158
8158
  }
8159
8159
  function safeExpand(name, models) {
@@ -8163,9 +8163,6 @@ function safeExpand(name, models) {
8163
8163
  return models.virtual?.[name]?.members ?? [];
8164
8164
  }
8165
8165
  }
8166
- function modelPickerSettings(provider, catalogue = []) {
8167
- return modelPickerSettingsFromRows(providerModelRows(provider, catalogue), true);
8168
- }
8169
8166
  function modelPickerSettingsFromRows(options, replaceBuiltInOptions) {
8170
8167
  return options.length === 0 ? void 0 : JSON.stringify({ modelPicker: { options, replaceBuiltInOptions } });
8171
8168
  }
@@ -9695,11 +9692,18 @@ function decideLaunch(params, readOnly) {
9695
9692
  notes.push(`${loginlessProvider.identity} has no stored login, so Remote Control is off; provider ${loginlessProvider.provider} runs without it`);
9696
9693
  }
9697
9694
  const flags = loginlessProvider === void 0 ? requestedFlags : { ...requestedFlags, remoteControl: false };
9698
- const catalogue = selectedProvider === void 0 ? void 0 : parseCatalogueCache(params.fs.readFileUtf8(catalogueCachePath(paths, selectedProvider.name)));
9699
9695
  const routesByName = flags.routeByName || selectedProvider !== void 0 && isRouterProvider(selectedProvider.definition);
9700
9696
  const globalModels = loadConfigFile(paths.globalConfigFile, GlobalConfigSchema, params.fs.readConfigFile)?.config.models;
9701
9697
  const models = launchCascade !== void 0 && params.farm !== void 0 ? cascadeModels : globalModels;
9702
- 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);
9698
+ const listedProviders = listProviderNames(fs13.readdir, paths.providersDir).flatMap((name) => {
9699
+ try {
9700
+ const definition = loadProvider(paths.providersDir, name, fs13);
9701
+ return definition === void 0 ? [] : [[name, definition, parseCatalogueCache(params.fs.readFileUtf8(catalogueCachePath(paths, name)))?.models ?? []]];
9702
+ } catch {
9703
+ return [];
9704
+ }
9705
+ });
9706
+ const pickerSettings = modelPickerSettingsFromRows(routedModelRows(models ?? {}, listedProviders, routesByName), selectedProvider !== void 0);
9703
9707
  const callerSettings = hasSettingsArgument(parsedArgv.rest);
9704
9708
  if (pickerSettings !== void 0 && callerSettings) {
9705
9709
  notes.push("--settings was passed, so /model keeps Claude Code's own model names");