claude-use 11.39.0 → 11.40.1

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
@@ -132,6 +132,7 @@ agent-shim model remove <name> [--yes]
132
132
  agent-shim model tier <tier> --ref <ref> | --clear
133
133
  agent-shim model price <ref> --input <usd> --output <usd> | --clear
134
134
  agent-shim model list [--json]
135
+ agent-shim model explain <name> # which member the virtual model's mode picks now, and why
135
136
  agent-shim provider remove <name> [--yes] [--json]
136
137
 
137
138
  agent-shim rule add <path> [--config-profile <profile>] [--identity <identity>] [--json]
package/dist/cli.cjs CHANGED
@@ -34636,7 +34636,7 @@ var init_package = __esm({
34636
34636
  "package.json"() {
34637
34637
  package_default = {
34638
34638
  name: "claude-use",
34639
- version: "11.39.0",
34639
+ version: "11.40.1",
34640
34640
  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.",
34641
34641
  license: "MIT",
34642
34642
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -35948,6 +35948,7 @@ function createUsageStore(deps) {
35948
35948
  }
35949
35949
  fs26.appendFilePrivate(import_node_path26.default.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record2)}
35950
35950
  `);
35951
+ deps.onRecord?.(record2);
35951
35952
  if (record2.identity !== void 0) {
35952
35953
  rewriteSnapshot(record2.identity, (current) => ({ ...current?.providers, [record2.provider]: foldProviderState(current?.providers[record2.provider], record2) }));
35953
35954
  }
@@ -65489,9 +65490,8 @@ function routedModelRows(models, providers) {
65489
65490
  if (provider.kind !== void 0 && provider.kind !== "http") {
65490
65491
  continue;
65491
65492
  }
65492
- const env = provider.env ?? {};
65493
- const match = Object.entries(env).find(([, value2]) => value2 === model);
65494
- if (match?.[0].endsWith("_MODEL") === true) {
65493
+ const match = Object.entries(provider.env ?? {}).find(([key, value2]) => value2 === model && key.startsWith("ANTHROPIC_DEFAULT_") && key.endsWith("_MODEL"));
65494
+ if (match !== void 0) {
65495
65495
  const tier = match[0].replace("ANTHROPIC_DEFAULT_", "").replace("_MODEL", "").toLowerCase();
65496
65496
  return tier === "fable" || tier === "opus" || tier === "sonnet" || tier === "haiku" ? tier : void 0;
65497
65497
  }
@@ -115764,6 +115764,72 @@ function supervisedSessionOf(fs26, paths, sessionId, isRunning) {
115764
115764
  return void 0;
115765
115765
  }
115766
115766
 
115767
+ // src/selection/targetStore.ts
115768
+ init_read();
115769
+
115770
+ // src/selection/signals.ts
115771
+ function targetOf(record2) {
115772
+ return record2.model === void 0 ? void 0 : `${record2.provider}/${record2.model}`;
115773
+ }
115774
+ function median(values) {
115775
+ if (values.length === 0) {
115776
+ return void 0;
115777
+ }
115778
+ const sorted = [...values].sort((left, right) => left - right);
115779
+ const middle = Math.floor(sorted.length / 2);
115780
+ const above = sorted[middle];
115781
+ const below = sorted[middle - 1];
115782
+ return sorted.length % 2 === 0 && above !== void 0 && below !== void 0 ? (above + below) / 2 : sorted[middle];
115783
+ }
115784
+ var OBSERVATION_WINDOW = 20;
115785
+ function observeRecord(observations, record2) {
115786
+ const target = targetOf(record2);
115787
+ if (target === void 0) {
115788
+ return new Map(observations);
115789
+ }
115790
+ const kept = [...observations.get(target) ?? [], record2].slice(-OBSERVATION_WINDOW);
115791
+ return new Map(observations).set(target, kept);
115792
+ }
115793
+ function observationOf(records) {
115794
+ const completed = records.filter((record2) => record2.outcome === "completed");
115795
+ const latencies = completed.map((record2) => record2.latencyMs);
115796
+ const usage = records.flatMap((record2) => record2.usage === void 0 ? [] : [record2.usage]);
115797
+ const input2 = usage.reduce((sum, entry) => sum + (entry.inputTokens ?? 0), 0);
115798
+ const output2 = usage.reduce((sum, entry) => sum + (entry.outputTokens ?? 0), 0);
115799
+ const cacheRead = usage.reduce((sum, entry) => sum + (entry.cacheReadInputTokens ?? 0), 0);
115800
+ return {
115801
+ latencyMs: median(latencies),
115802
+ successRate: records.length === 0 ? void 0 : completed.length / records.length,
115803
+ tokenMix: input2 + output2 + cacheRead === 0 ? void 0 : { input: input2, output: output2, cacheRead }
115804
+ };
115805
+ }
115806
+ function blendedPricePerMTok(prices, mix) {
115807
+ const total = mix.input + mix.output + mix.cacheRead;
115808
+ if (total === 0) {
115809
+ return void 0;
115810
+ }
115811
+ return (prices.input * mix.input + prices.output * mix.output) / total;
115812
+ }
115813
+
115814
+ // src/selection/targetStore.ts
115815
+ var SEED_LOOKBACK_RECORDS = 500;
115816
+ function createTargetObservationStore(fs26, paths) {
115817
+ let observations = /* @__PURE__ */ new Map();
115818
+ const seeded = readUsageLog(fs26, paths.usageLogDir, {}).records.slice(-SEED_LOOKBACK_RECORDS);
115819
+ for (const record2 of seeded) {
115820
+ observations = observeRecord(observations, record2);
115821
+ }
115822
+ return {
115823
+ observe: (record2) => {
115824
+ observations = observeRecord(observations, record2);
115825
+ },
115826
+ observation: (target) => {
115827
+ const records = observations.get(target);
115828
+ return records === void 0 ? void 0 : observationOf(records);
115829
+ }
115830
+ };
115831
+ }
115832
+
115767
115833
  // src/update/commands.ts
115768
115834
  var import_node_fs14 = __toESM(require("node:fs"), 1);
115769
115835
  var import_node_os7 = __toESM(require("node:os"), 1);
@@ -131323,6 +131389,39 @@ function createPassthroughRoute(name, target) {
131323
131389
  // src/frontdoor/providerRoute.ts
131324
131390
  init_conditions();
131325
131391
  init_quotaFacts();
131392
+ init_modelsStore();
131393
+
131394
+ // src/selection/candidates.ts
131395
+ var WINDOW_PERIOD_HOURS = { fiveHour: 5, sevenDay: 168, extraUsage: 168 };
131396
+ function candidateOf(ref, order, facts, isCurrent) {
131397
+ const present = Object.entries(facts.quota ?? {}).map(([name, window]) => ({ name, ...window }));
131398
+ const available = present.every((window) => window.remaining > 0);
131399
+ const remainingAllowance = present.length === 0 ? void 0 : Math.min(...present.map((window) => window.remaining));
131400
+ const hoursToReset = present.length === 0 ? void 0 : Math.min(...present.map((window) => window.hoursUntilReset));
131401
+ const pressure = present.length === 0 ? void 0 : Math.max(
131402
+ ...present.map((window) => {
131403
+ const period = WINDOW_PERIOD_HOURS[window.name] ?? Number.NaN;
131404
+ return period > 0 && window.hoursUntilReset > 0 ? window.remaining / (window.hoursUntilReset / period) : Number.NaN;
131405
+ })
131406
+ );
131407
+ return {
131408
+ ref,
131409
+ order,
131410
+ available,
131411
+ ...remainingAllowance === void 0 ? {} : { remainingAllowance },
131412
+ ...hoursToReset === void 0 ? {} : { hoursToReset },
131413
+ ...pressure === void 0 || Number.isNaN(pressure) ? {} : { pressure },
131414
+ // Feasibility at the observed burn needs a burn rate no signal yet carries, so an available candidate counts as feasible and the run-dry projection waits on one.
131415
+ feasible: available,
131416
+ ...facts.observation?.latencyMs === void 0 ? {} : { latencyMs: facts.observation.latencyMs },
131417
+ ...facts.observation?.successRate === void 0 ? {} : { successRate: facts.observation.successRate },
131418
+ ...facts.price === void 0 || facts.observation?.tokenMix === void 0 ? {} : { pricePerMTok: blendedPricePerMTok(facts.price, facts.observation.tokenMix) },
131419
+ isCurrent
131420
+ };
131421
+ }
131422
+
131423
+ // src/frontdoor/providerRoute.ts
131424
+ init_engine();
131326
131425
  init_route();
131327
131426
  var import_node_stream3 = require("node:stream");
131328
131427
 
@@ -131412,22 +131511,43 @@ function scopeSessionProviderPath(request7) {
131412
131511
  }
131413
131512
  return { ...request7, url: `${PROVIDER_PATH_PREFIX}${encodeURIComponent(request7.session.provider)}${request7.url}` };
131414
131513
  }
131415
- function resolveModelTarget(model, models, includeUnqualified) {
131416
- if (models === void 0) {
131417
- return model.includes("/") && !model.startsWith("acct:") ? model.split("/")[0] : void 0;
131514
+ function resolveRoutedModel(model, providerName, session, includeUnqualified, deps, memory, rotations) {
131515
+ const models = deps.models?.();
131516
+ const qualified = model.includes("/") && !model.startsWith("acct:") ? model : void 0;
131517
+ if (qualified !== void 0) {
131518
+ const [provider2, ...rest2] = qualified.split("/");
131519
+ const named = rest2.join("/");
131520
+ return provider2 === void 0 || named === "" ? void 0 : { provider: provider2, model: named, ref: qualified };
131418
131521
  }
131419
- if (model.includes("/") && !model.startsWith("acct:")) {
131420
- return model.split("/")[0];
131522
+ const virtual = models?.virtual?.[model];
131523
+ if (virtual === void 0 || !includeUnqualified) {
131524
+ return void 0;
131421
131525
  }
131422
- if (!includeUnqualified) {
131526
+ const members2 = expandMembers(model, models).filter((member) => !member.startsWith("acct:") && !member.startsWith("family:"));
131527
+ if (members2.length === 0) {
131423
131528
  return void 0;
131424
131529
  }
131425
- const virtual = models.virtual?.[model];
131426
- const first = virtual?.members.find((member) => !member.startsWith("acct:") && !member.startsWith("family:"));
131427
- if (first === void 0) {
131530
+ const snapshot = deps.usageSnapshotOf?.(session.identity);
131531
+ const current = memory.get(session.sessionId ?? "");
131532
+ const candidates = members2.map((ref, order) => {
131533
+ const [provider2] = ref.split("/");
131534
+ const facts = quotaFactsOf(snapshot?.providers[provider2 ?? ""]?.rateLimit?.unified, Date.now());
131535
+ return candidateOf(ref, order, {
131536
+ quota: facts,
131537
+ ...deps.observations?.(ref) === void 0 ? {} : { observation: deps.observations(ref) },
131538
+ ...models?.prices?.[ref] === void 0 ? {} : { price: models.prices[ref] }
131539
+ }, ref === current);
131540
+ });
131541
+ const evaluated = candidates.map((candidate) => ({ candidate, capabilities: { vision: true, tools: true, thinking: true } }));
131542
+ const rotation = rotations.get(model) ?? 0;
131543
+ rotations.set(model, rotation + 1);
131544
+ const selection = selectMember(virtual.mode, evaluated, { rotation });
131545
+ if (selection.ref === void 0) {
131428
131546
  return void 0;
131429
131547
  }
131430
- return first.includes("/") ? first.split("/")[0] : resolveModelTarget(first, models, true);
131548
+ const [provider, ...rest] = selection.ref.split("/");
131549
+ const chosen = rest.join("/");
131550
+ return provider === void 0 || chosen === "" ? void 0 : { provider, model: chosen, ref: selection.ref };
131431
131551
  }
131432
131552
  function resolveAccountTarget(model, models) {
131433
131553
  if (model.startsWith("acct:")) {
@@ -131444,6 +131564,8 @@ function createProviderRouteResolver(deps) {
131444
131564
  const oauthRoute = createPassthroughRoute("anthropic", { baseUrl: `https://${CONNECT_INTERCEPT_HOST}:${String(HTTPS_PORT)}`, stripPrefix: void 0, headroomUpstream: void 0 });
131445
131565
  const antigravityQuotaSources = /* @__PURE__ */ new Map();
131446
131566
  const antigravityRoutingMemory = /* @__PURE__ */ new Map();
131567
+ const routingMemory = /* @__PURE__ */ new Map();
131568
+ const rotations = /* @__PURE__ */ new Map();
131447
131569
  const memoryFor = (provider) => {
131448
131570
  const existing = antigravityRoutingMemory.get(provider);
131449
131571
  if (existing !== void 0) {
@@ -131605,10 +131727,12 @@ function createProviderRouteResolver(deps) {
131605
131727
  }
131606
131728
  const routesByName = (isRouter || current.session.routeByName) && !isRcSelfHostPath(path65);
131607
131729
  if (routesByName) {
131608
- const scan2 = await scanRequestHead(current, false);
131609
- if (scan2.replayed !== void 0) {
131610
- replay = scan2.replayed;
131730
+ const scan2 = await scanRequestHead(current, true);
131731
+ if (scan2.replayed === void 0) {
131732
+ const resolution = resolve2(current);
131733
+ 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;
131611
131734
  }
131735
+ replay = scan2.replayed;
131612
131736
  const account = scan2.model === void 0 ? void 0 : resolveAccountTarget(scan2.model, deps.models?.());
131613
131737
  if (account !== void 0) {
131614
131738
  const sessionId = current.session.sessionId ?? "";
@@ -131619,18 +131743,29 @@ function createProviderRouteResolver(deps) {
131619
131743
  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`
131620
131744
  };
131621
131745
  }
131622
- const target = scan2.model === void 0 ? void 0 : resolveModelTarget(scan2.model, deps.models?.(), isRouter || current.session.routeByName && providerName !== void 0);
131623
- if (target === providerName) {
131746
+ const routed = scan2.model === void 0 ? void 0 : resolveRoutedModel(scan2.model, providerName, current.session, isRouter || providerName !== void 0, deps, routingMemory, rotations);
131747
+ const requested = scan2.model;
131748
+ if (routed !== void 0) {
131749
+ routingMemory.set(current.session.sessionId ?? "", routed.ref);
131750
+ if (requested !== void 0 && routed.provider === providerName && routed.model === requested) {
131751
+ const resolution2 = resolve2(current);
131752
+ return resolution2.ok ? { ok: true, route: servingRewritten(resolution2.route, { ...replay, url: current.url }), request: { ...replay, url: current.url } } : resolution2;
131753
+ }
131754
+ if (requested !== void 0 && routed.model !== requested) {
131755
+ const rewritten = (scan2.text ?? "").replace(new RegExp('"model":\\s*"' + requested.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + '"'), '"model":"' + routed.model + '"');
131756
+ const headers = Object.fromEntries(Object.entries(replay.headers).filter(([name]) => name.toLowerCase() !== "content-length"));
131757
+ replay = { ...replay, headers, body: import_node_stream3.Readable.from([Buffer.from(rewritten, "utf8")]) };
131758
+ }
131759
+ if (routed.provider !== providerName) {
131760
+ const scopedPrefix = providerName === void 0 ? void 0 : `${PROVIDER_PATH_PREFIX}${encodeURIComponent(providerName)}`;
131761
+ const rest2 = scopedPrefix !== void 0 && path65.startsWith(scopedPrefix) ? path65.slice(scopedPrefix.length) : path65;
131762
+ const query2 = current.url.includes("?") ? current.url.slice(current.url.indexOf("?")) : "";
131763
+ const carried = replay;
131764
+ current = { ...current, url: `${PROVIDER_PATH_PREFIX}${encodeURIComponent(routed.provider)}${rest2}${query2}`, body: carried.body, headers: carried.headers };
131765
+ continue;
131766
+ }
131624
131767
  const resolution = resolve2(current);
131625
- 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;
131626
- }
131627
- if (target !== void 0) {
131628
- const scopedPrefix = providerName === void 0 ? void 0 : `${PROVIDER_PATH_PREFIX}${encodeURIComponent(providerName)}`;
131629
- const rest2 = scopedPrefix !== void 0 && path65.startsWith(scopedPrefix) ? path65.slice(scopedPrefix.length) : path65;
131630
- const query2 = current.url.includes("?") ? current.url.slice(current.url.indexOf("?")) : "";
131631
- const carried = scan2.replayed ?? current;
131632
- current = { ...current, url: `${PROVIDER_PATH_PREFIX}${encodeURIComponent(target)}${rest2}${query2}`, body: carried.body, headers: carried.headers };
131633
- continue;
131768
+ return resolution.ok ? { ok: true, route: servingRewritten(resolution.route, { ...replay, url: current.url }), request: { ...replay, url: current.url } } : resolution;
131634
131769
  }
131635
131770
  }
131636
131771
  if (routes === void 0 || routes.length === 0) {
@@ -134701,67 +134836,6 @@ function createRealQuotaRefresher(params) {
134701
134836
 
134702
134837
  // src/frontdoor/commands.ts
134703
134838
  init_store2();
134704
-
134705
- // src/selection/targetStore.ts
134706
- init_read();
134707
-
134708
- // src/selection/signals.ts
134709
- function targetOf(record2) {
134710
- return record2.model === void 0 ? void 0 : `${record2.provider}/${record2.model}`;
134711
- }
134712
- function median(values) {
134713
- if (values.length === 0) {
134714
- return void 0;
134715
- }
134716
- const sorted = [...values].sort((left, right) => left - right);
134717
- const middle = Math.floor(sorted.length / 2);
134718
- const above = sorted[middle];
134719
- const below = sorted[middle - 1];
134720
- return sorted.length % 2 === 0 && above !== void 0 && below !== void 0 ? (above + below) / 2 : sorted[middle];
134721
- }
134722
- var OBSERVATION_WINDOW = 20;
134723
- function observeRecord(observations, record2) {
134724
- const target = targetOf(record2);
134725
- if (target === void 0) {
134726
- return new Map(observations);
134727
- }
134728
- const kept = [...observations.get(target) ?? [], record2].slice(-OBSERVATION_WINDOW);
134729
- return new Map(observations).set(target, kept);
134730
- }
134731
- function observationOf(records) {
134732
- const completed = records.filter((record2) => record2.outcome === "completed");
134733
- const latencies = completed.map((record2) => record2.latencyMs);
134734
- const usage = records.flatMap((record2) => record2.usage === void 0 ? [] : [record2.usage]);
134735
- const input2 = usage.reduce((sum, entry) => sum + (entry.inputTokens ?? 0), 0);
134736
- const output2 = usage.reduce((sum, entry) => sum + (entry.outputTokens ?? 0), 0);
134737
- const cacheRead = usage.reduce((sum, entry) => sum + (entry.cacheReadInputTokens ?? 0), 0);
134738
- return {
134739
- latencyMs: median(latencies),
134740
- successRate: records.length === 0 ? void 0 : completed.length / records.length,
134741
- tokenMix: input2 + output2 + cacheRead === 0 ? void 0 : { input: input2, output: output2, cacheRead }
134742
- };
134743
- }
134744
-
134745
- // src/selection/targetStore.ts
134746
- var SEED_LOOKBACK_RECORDS = 500;
134747
- function createTargetObservationStore(fs26, paths) {
134748
- let observations = /* @__PURE__ */ new Map();
134749
- const seeded = readUsageLog(fs26, paths.usageLogDir, {}).records.slice(-SEED_LOOKBACK_RECORDS);
134750
- for (const record2 of seeded) {
134751
- observations = observeRecord(observations, record2);
134752
- }
134753
- return {
134754
- observe: (record2) => {
134755
- observations = observeRecord(observations, record2);
134756
- },
134757
- observation: (target) => {
134758
- const records = observations.get(target);
134759
- return records === void 0 ? void 0 : observationOf(records);
134760
- }
134761
- };
134762
- }
134763
-
134764
- // src/frontdoor/commands.ts
134765
134839
  function respawnInvocation(paths) {
134766
134840
  const env = {};
134767
134841
  for (const [name, value2] of Object.entries({ ...process.env, AGENT_SHIM_HOME: paths.root })) {
@@ -134846,6 +134920,7 @@ function realFrontDoorSupervisorPorts(paths) {
134846
134920
  appendLog(paths, `frontdoor ${String(process.pid)}: ${line}`);
134847
134921
  }
134848
134922
  });
134923
+ const observations = createTargetObservationStore(realFarmFs, paths);
134849
134924
  const routingSnapshots = /* @__PURE__ */ new Map();
134850
134925
  const rcControlToken = (0, import_node_crypto25.randomUUID)();
134851
134926
  const resolveRoute = rcObservingResolver(
@@ -134861,6 +134936,7 @@ function realFrontDoorSupervisorPorts(paths) {
134861
134936
  credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
134862
134937
  usageSnapshotOf: (identity) => identity === void 0 ? void 0 : routingSnapshots.get(identity) ?? readUsageSnapshot(realFarmFs, paths.usageSnapshotsDir, identity),
134863
134938
  // An `acct:` model member is served by relaunch: the door leaves a move request for the session's supervisor (found across every pool's registry, since the door does not know which pool launched the session) and answers the request with what is happening. A session nothing supervises gets the message naming the command to run instead.
134939
+ observations: (target) => observations.observation(target),
134864
134940
  accountMoves: (sessionId, to2, model) => {
134865
134941
  if (supervisedSessionOf(realFarmFs, paths, sessionId, realIsProcessRunning) === void 0) {
134866
134942
  return false;
@@ -134884,6 +134960,9 @@ function realFrontDoorSupervisorPorts(paths) {
134884
134960
  publish: (snapshot) => {
134885
134961
  routingSnapshots.set(snapshot.identity, snapshot);
134886
134962
  usagePublisher.publish(snapshot);
134963
+ },
134964
+ onRecord: (record2) => {
134965
+ observations.observe(record2);
134887
134966
  }
134888
134967
  });
134889
134968
  const quotaRefresher = createRealQuotaRefresher({ paths, store: usageStore, log });
@@ -135501,7 +135580,8 @@ function enrichStatuslinePayload(params) {
135501
135580
  sevenDayResetAt: void 0,
135502
135581
  providerQuotaWindows: [],
135503
135582
  quotaFamilies: [],
135504
- headroom: params.headroom
135583
+ headroom: params.headroom,
135584
+ routedTarget: params.routedTarget
135505
135585
  };
135506
135586
  if (params.snapshot !== void 0) {
135507
135587
  const scopedName = providerScopedState(params.snapshot, params.providerName, params.env.AGENT_SHIM_PROVIDER);
@@ -135575,6 +135655,9 @@ function providerScopedState(snapshot, providerName, providerDisplayName) {
135575
135655
  return void 0;
135576
135656
  }
135577
135657
 
135658
+ // src/statusline/commands.ts
135659
+ init_read();
135660
+
135578
135661
  // src/statusline/ansi.ts
135579
135662
  var ESCAPE_CHAR_CODE = 27;
135580
135663
  var ESCAPE = String.fromCharCode(ESCAPE_CHAR_CODE);
@@ -135866,6 +135949,9 @@ function renderStatuslineBlock(summary, view, terminalWidth, nowMs) {
135866
135949
  const account = [summary.providerAccountEmail, summary.providerPlan].filter((part) => part !== void 0);
135867
135950
  header.push(account.length > 0 ? `${summary.provider} \xB7 ${account.join(" \xB7 ")}` : summary.provider);
135868
135951
  }
135952
+ if (summary.routedTarget !== void 0) {
135953
+ header.push(`via ${summary.routedTarget}`);
135954
+ }
135869
135955
  const loginPlan = summary.provider === void 0 ? summary.loginPlan ?? accountPlanLabel(summary) : void 0;
135870
135956
  const loginOrgName = summary.loginOrganizationType === "claude_team" || summary.loginOrganizationType === "claude_enterprise" ? summary.loginOrganizationName : void 0;
135871
135957
  const loginParts = [summary.loginAccountEmail, loginOrgName, loginPlan].filter((part) => part !== void 0);
@@ -135969,6 +136055,7 @@ async function readAllStdin() {
135969
136055
  process.stdin.resume();
135970
136056
  });
135971
136057
  }
136058
+ var ROUTED_TARGET_LOOKBACK_MS = 36e5;
135972
136059
  function registerStatuslineCommand(program2, deps) {
135973
136060
  withExamples(
135974
136061
  program2.command("statusline").description("Serve as a statusline entrypoint: read the client's stdin payload, add the identity's live provider, account and usage windows under an agent_shim key, then run the renderer named in AGENT_SHIM_STATUSLINE_CMD or print the built-in line.").action(async () => {
@@ -136015,7 +136102,19 @@ function registerStatuslineCommand(program2, deps) {
136015
136102
  const target = headroomTargetOf(process.env, socketTarget === void 0 || socketTarget.refused !== void 0 ? void 0 : socketTarget.socketPath);
136016
136103
  const sessionId = headroomSessionIdOf(payload, process.env);
136017
136104
  const headroom = target === void 0 || sessionId === void 0 ? void 0 : await fetchHeadroomSessionStats(realHeadroomGet, target, sessionId);
136018
- const { payload: enriched, summary } = enrichStatuslinePayload({ payload, env: process.env, snapshot, account, providerName, nowMs, headroom });
136105
+ const sessionHeader = /x-agent-shim-session:\s*([A-Za-z0-9@._-]+)/i.exec(process.env.ANTHROPIC_CUSTOM_HEADERS ?? "")?.[1];
136106
+ let routedTarget;
136107
+ if (sessionHeader !== void 0) {
136108
+ try {
136109
+ const last = readUsageLog(realFarmFs, deps.paths.usageLogDir, { sinceMs: nowMs - ROUTED_TARGET_LOOKBACK_MS }).records.filter((record2) => record2.sessionId === sessionHeader).at(-1);
136110
+ if (last?.model !== void 0 && last.provider !== providerName) {
136111
+ routedTarget = `${last.provider}/${last.model}`;
136112
+ }
136113
+ } catch {
136114
+ routedTarget = void 0;
136115
+ }
136116
+ }
136117
+ const { payload: enriched, summary } = enrichStatuslinePayload({ payload, env: process.env, snapshot, account, providerName, nowMs, headroom, routedTarget });
136019
136118
  const renderer = process.env.AGENT_SHIM_STATUSLINE_CMD;
136020
136119
  if (renderer !== void 0 && renderer !== "") {
136021
136120
  const child = (0, import_node_child_process7.spawn)("/bin/sh", ["-c", renderer], { stdio: ["pipe", "inherit", "inherit"] });
@@ -147539,6 +147638,52 @@ function sameFamilyOtherVersion(a10, b) {
147539
147638
 
147540
147639
  // src/models.ts
147541
147640
  init_modelsStore();
147641
+ init_realPorts();
147642
+ init_read();
147643
+ init_quotaFacts();
147644
+ init_engine();
147645
+ function providerQuotaOf(paths) {
147646
+ const newest = /* @__PURE__ */ new Map();
147647
+ for (const name of realFarmFs.readdir(paths.usageSnapshotsDir)) {
147648
+ if (!name.endsWith(".json")) {
147649
+ continue;
147650
+ }
147651
+ const identity = name.slice(0, -".json".length);
147652
+ const snapshot = readUsageSnapshot(realFarmFs, paths.usageSnapshotsDir, identity);
147653
+ if (snapshot === void 0) {
147654
+ continue;
147655
+ }
147656
+ for (const provider of Object.keys(snapshot.providers)) {
147657
+ const known = newest.get(provider);
147658
+ if (known === void 0 || snapshot.updatedAt.localeCompare(known.updatedAt) > 0) {
147659
+ newest.set(provider, snapshot);
147660
+ }
147661
+ }
147662
+ }
147663
+ return (provider) => {
147664
+ const snapshot = newest.get(provider);
147665
+ return snapshot === void 0 ? {} : quotaFactsOf(snapshot.providers[provider]?.rateLimit?.unified, Date.now());
147666
+ };
147667
+ }
147668
+ function explainVirtualModel(paths, name) {
147669
+ const models = readModels(paths);
147670
+ const definition = models?.virtual?.[name];
147671
+ if (definition === void 0) {
147672
+ throw new UsageError(`No virtual model named "${name}".`);
147673
+ }
147674
+ const quotaOf = providerQuotaOf(paths);
147675
+ const observations = createTargetObservationStore(realFarmFs, paths);
147676
+ const candidates = expandMembers(name, models).filter((member) => !member.startsWith("acct:") && !member.startsWith("family:")).map((ref, order) => {
147677
+ const [provider] = ref.split("/");
147678
+ 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);
147679
+ });
147680
+ const evaluated = candidates.map((candidate) => ({ candidate, capabilities: { vision: true, tools: true, thinking: true } }));
147681
+ const selection = selectMember(definition.mode, evaluated, {});
147682
+ console.log(`${name} (${definition.mode}) chooses ${selection.ref ?? "nothing"}:`);
147683
+ for (const line of selection.reasons) {
147684
+ console.log(` ${line}`);
147685
+ }
147686
+ }
147542
147687
  function providerModels(paths) {
147543
147688
  return listProviders(paths).flatMap((entry) => {
147544
147689
  const catalogue = parseCatalogueCache(realFsPort.readFileUtf8(catalogueCachePath(paths, entry.name)));
@@ -147573,6 +147718,12 @@ function matchModels(models) {
147573
147718
  function registerModelsCommand(program2, deps) {
147574
147719
  const { paths } = deps;
147575
147720
  const modelsCommand = program2.command("model").description("Define and inspect the models the providers offer and the virtual models chosen among them.");
147721
+ withExamples(
147722
+ 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) => {
147723
+ explainVirtualModel(paths, name);
147724
+ }),
147725
+ ["agent-shim model explain fast"]
147726
+ );
147576
147727
  withExamples(modelsCommand, ["agent-shim model match", "agent-shim model add fast --mode soonest-reset --member z/glm-5.3 --member m/MiniMax-M3"]);
147577
147728
  withExamples(
147578
147729
  modelsCommand.command("match").description("List every model every provider offers, grouped into the ones that are the same model across providers, with the pairs that are merely similar named beside them.").option("--json", "Print the match as JSON."),
package/dist/index.cjs CHANGED
@@ -3106,7 +3106,7 @@ var init_package = __esm({
3106
3106
  "package.json"() {
3107
3107
  package_default = {
3108
3108
  name: "claude-use",
3109
- version: "11.39.0",
3109
+ version: "11.40.1",
3110
3110
  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.",
3111
3111
  license: "MIT",
3112
3112
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -6063,6 +6063,7 @@ function createUsageStore(deps) {
6063
6063
  }
6064
6064
  fs13.appendFilePrivate(import_node_path20.default.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record)}
6065
6065
  `);
6066
+ deps.onRecord?.(record);
6066
6067
  if (record.identity !== void 0) {
6067
6068
  rewriteSnapshot(record.identity, (current) => ({ ...current?.providers, [record.provider]: foldProviderState(current?.providers[record.provider], record) }));
6068
6069
  }
@@ -8955,9 +8956,8 @@ function routedModelRows(models, providers) {
8955
8956
  if (provider.kind !== void 0 && provider.kind !== "http") {
8956
8957
  continue;
8957
8958
  }
8958
- const env = provider.env ?? {};
8959
- const match = Object.entries(env).find(([, value]) => value === model);
8960
- if (match?.[0].endsWith("_MODEL") === true) {
8959
+ const match = Object.entries(provider.env ?? {}).find(([key, value]) => value === model && key.startsWith("ANTHROPIC_DEFAULT_") && key.endsWith("_MODEL"));
8960
+ if (match !== void 0) {
8961
8961
  const tier = match[0].replace("ANTHROPIC_DEFAULT_", "").replace("_MODEL", "").toLowerCase();
8962
8962
  return tier === "fable" || tier === "opus" || tier === "sonnet" || tier === "haiku" ? tier : void 0;
8963
8963
  }
package/dist/index.mjs CHANGED
@@ -3082,7 +3082,7 @@ var init_package = __esm({
3082
3082
  "package.json"() {
3083
3083
  package_default = {
3084
3084
  name: "claude-use",
3085
- version: "11.39.0",
3085
+ version: "11.40.1",
3086
3086
  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.",
3087
3087
  license: "MIT",
3088
3088
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -6038,6 +6038,7 @@ function createUsageStore(deps) {
6038
6038
  }
6039
6039
  fs13.appendFilePrivate(path20.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record)}
6040
6040
  `);
6041
+ deps.onRecord?.(record);
6041
6042
  if (record.identity !== void 0) {
6042
6043
  rewriteSnapshot(record.identity, (current) => ({ ...current?.providers, [record.provider]: foldProviderState(current?.providers[record.provider], record) }));
6043
6044
  }
@@ -8927,9 +8928,8 @@ function routedModelRows(models, providers) {
8927
8928
  if (provider.kind !== void 0 && provider.kind !== "http") {
8928
8929
  continue;
8929
8930
  }
8930
- const env = provider.env ?? {};
8931
- const match = Object.entries(env).find(([, value]) => value === model);
8932
- if (match?.[0].endsWith("_MODEL") === true) {
8931
+ const match = Object.entries(provider.env ?? {}).find(([key, value]) => value === model && key.startsWith("ANTHROPIC_DEFAULT_") && key.endsWith("_MODEL"));
8932
+ if (match !== void 0) {
8933
8933
  const tier = match[0].replace("ANTHROPIC_DEFAULT_", "").replace("_MODEL", "").toLowerCase();
8934
8934
  return tier === "fable" || tier === "opus" || tier === "sonnet" || tier === "haiku" ? tier : void 0;
8935
8935
  }