agent-shim 11.76.0 → 11.78.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
@@ -4764,7 +4764,7 @@ var init_package = __esm({
4764
4764
  "package.json"() {
4765
4765
  package_default = {
4766
4766
  name: "agent-shim",
4767
- version: "11.76.0",
4767
+ version: "11.78.0",
4768
4768
  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.",
4769
4769
  license: "MIT",
4770
4770
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -5971,19 +5971,23 @@ function renderReport(rows, style) {
5971
5971
  const lines = [style(["bold"], REPORT_HEADING)];
5972
5972
  for (const row of rows) {
5973
5973
  const detail = row.detail === void 0 ? "" : ` ${style(["dim"], `(${row.detail})`)}`;
5974
- lines.push(`${indent}${style(["dim"], row.label.padEnd(labelWidth))}${COLUMN_GAP}${row.value}${detail}`);
5974
+ const label = row.label.padEnd(labelWidth);
5975
+ lines.push(
5976
+ row.notice === true ? `${indent}${style(NOTICE_FORMATS, label)}${COLUMN_GAP}${style(NOTICE_FORMATS, row.value)}${detail}` : `${indent}${style(["dim"], label)}${COLUMN_GAP}${row.value}${detail}`
5977
+ );
5975
5978
  for (const note of row.notes ?? []) {
5976
5979
  lines.push(`${indent}${" ".repeat(labelWidth)}${COLUMN_GAP}${style(["dim"], note)}`);
5977
5980
  }
5978
5981
  }
5979
5982
  return lines;
5980
5983
  }
5981
- var REPORT_HEADING, COLUMN_GAP;
5984
+ var REPORT_HEADING, COLUMN_GAP, NOTICE_FORMATS;
5982
5985
  var init_report = __esm({
5983
5986
  "src/launcher/report.ts"() {
5984
5987
  "use strict";
5985
5988
  REPORT_HEADING = "agent-shim";
5986
5989
  COLUMN_GAP = " ";
5990
+ NOTICE_FORMATS = ["yellow", "bold"];
5987
5991
  }
5988
5992
  });
5989
5993
 
@@ -7033,52 +7037,6 @@ var init_account = __esm({
7033
7037
  }
7034
7038
  });
7035
7039
 
7036
- // src/usage/plan.ts
7037
- function planOf(account) {
7038
- const userTier = account?.userRateLimitTier;
7039
- if (userTier !== void 0 && ZERO_TIER.test(userTier)) {
7040
- return { kind: "pay-per-use", tier: userTier };
7041
- }
7042
- const tier = account?.organizationRateLimitTier ?? userTier;
7043
- const tierField = tier === void 0 ? {} : { tier };
7044
- if (tier === void 0) {
7045
- return { kind: "subscription", capacity: 1, recognised: false };
7046
- }
7047
- if (ZERO_TIER.test(tier)) {
7048
- return { kind: "pay-per-use", ...tierField };
7049
- }
7050
- const multiplier = TIER_MULTIPLIER.exec(tier)?.[1];
7051
- if (multiplier !== void 0) {
7052
- return { kind: "subscription", capacity: Number(multiplier), recognised: true, ...tierField };
7053
- }
7054
- return { kind: "subscription", capacity: 1, recognised: BASE_TIER.test(tier), ...tierField };
7055
- }
7056
- var import_zod13, PlanClassSchema, TIER_MULTIPLIER, ZERO_TIER, BASE_TIER;
7057
- var init_plan2 = __esm({
7058
- "src/usage/plan.ts"() {
7059
- "use strict";
7060
- import_zod13 = require("zod");
7061
- PlanClassSchema = import_zod13.z.union([
7062
- import_zod13.z.strictObject({
7063
- kind: import_zod13.z.literal("subscription"),
7064
- /** The plan's size as a multiple of the smallest subscription tier (Max is 5, Ultra is 20). */
7065
- capacity: import_zod13.z.number().positive(),
7066
- /** False when the tier string named no multiplier and no tier this project knows, so `capacity` is the neutral 1 rather than a reading. */
7067
- recognised: import_zod13.z.boolean(),
7068
- /** The tier string the classification rests on, when the account had one. */
7069
- tier: import_zod13.z.string().optional()
7070
- }),
7071
- import_zod13.z.strictObject({
7072
- kind: import_zod13.z.literal("pay-per-use"),
7073
- tier: import_zod13.z.string().optional()
7074
- })
7075
- ]);
7076
- TIER_MULTIPLIER = /(?:^|_)(\d+)x$/;
7077
- ZERO_TIER = /(?:^|_)zero$/;
7078
- BASE_TIER = /(?:^|_)(?:pro|free)$/;
7079
- }
7080
- });
7081
-
7082
7040
  // src/usage/rateLimit.ts
7083
7041
  function epochSecondsToIso(value) {
7084
7042
  if (value === void 0) {
@@ -7170,39 +7128,6 @@ var init_rateLimit = __esm({
7170
7128
  }
7171
7129
  });
7172
7130
 
7173
- // src/usage/scan.ts
7174
- var import_zod14, AnthropicUsageSchema, ErrorObjectSchema;
7175
- var init_scan = __esm({
7176
- "src/usage/scan.ts"() {
7177
- "use strict";
7178
- import_zod14 = require("zod");
7179
- AnthropicUsageSchema = import_zod14.z.looseObject({
7180
- input_tokens: import_zod14.z.number().int().nonnegative().nullish(),
7181
- output_tokens: import_zod14.z.number().int().nonnegative().nullish(),
7182
- cache_creation_input_tokens: import_zod14.z.number().int().nonnegative().nullish(),
7183
- cache_read_input_tokens: import_zod14.z.number().int().nonnegative().nullish()
7184
- });
7185
- ErrorObjectSchema = import_zod14.z.looseObject({
7186
- type: import_zod14.z.string().optional(),
7187
- code: import_zod14.z.union([import_zod14.z.string(), import_zod14.z.number()]).optional(),
7188
- message: import_zod14.z.string().optional()
7189
- });
7190
- }
7191
- });
7192
-
7193
- // src/usage/middleware.ts
7194
- var ANTHROPIC_PROVIDER;
7195
- var init_middleware = __esm({
7196
- "src/usage/middleware.ts"() {
7197
- "use strict";
7198
- init_route();
7199
- init_rateLimit();
7200
- init_scan();
7201
- init_schema2();
7202
- ANTHROPIC_PROVIDER = "anthropic";
7203
- }
7204
- });
7205
-
7206
7131
  // src/usage/preflight.ts
7207
7132
  function formatAge(ms) {
7208
7133
  const minutes = Math.floor(ms / (MS_PER_SECOND3 * SECONDS_PER_MINUTE));
@@ -7259,6 +7184,111 @@ var init_preflight = __esm({
7259
7184
  }
7260
7185
  });
7261
7186
 
7187
+ // src/usage/candidateText.ts
7188
+ function candidateHeading(candidate) {
7189
+ const score = candidate.score === void 0 ? "" : ` score ${candidate.score.toFixed(2)}${candidate.scoreWindow === "fiveHour" ? " by 5h reset" : " by 7d reset"}`;
7190
+ const dry = candidate.feasible ? "" : " (5h would run dry)";
7191
+ return `[${candidate.class}${score}]${dry}`;
7192
+ }
7193
+ function percent(fraction) {
7194
+ return `${String(Math.round(fraction * PERCENT))}%`;
7195
+ }
7196
+ function describeWindow(label, window, effective, nowMs) {
7197
+ if (effective.reset) {
7198
+ return `${label} window has reset`;
7199
+ }
7200
+ const used = effective.utilization === void 0 ? "usage unknown" : `${percent(effective.utilization)} used`;
7201
+ const resets = effective.resetsAtMs === void 0 ? "" : `, resets in ${formatAge(effective.resetsAtMs - nowMs)}`;
7202
+ return `${label} ${used}${resets}${window.status === "allowed_warning" ? " (nearly used)" : ""}`;
7203
+ }
7204
+ var PERCENT;
7205
+ var init_candidateText = __esm({
7206
+ "src/usage/candidateText.ts"() {
7207
+ "use strict";
7208
+ init_preflight();
7209
+ PERCENT = 100;
7210
+ }
7211
+ });
7212
+
7213
+ // src/usage/plan.ts
7214
+ function planOf(account) {
7215
+ const userTier = account?.userRateLimitTier;
7216
+ if (userTier !== void 0 && ZERO_TIER.test(userTier)) {
7217
+ return { kind: "pay-per-use", tier: userTier };
7218
+ }
7219
+ const tier = account?.organizationRateLimitTier ?? userTier;
7220
+ const tierField = tier === void 0 ? {} : { tier };
7221
+ if (tier === void 0) {
7222
+ return { kind: "subscription", capacity: 1, recognised: false };
7223
+ }
7224
+ if (ZERO_TIER.test(tier)) {
7225
+ return { kind: "pay-per-use", ...tierField };
7226
+ }
7227
+ const multiplier = TIER_MULTIPLIER.exec(tier)?.[1];
7228
+ if (multiplier !== void 0) {
7229
+ return { kind: "subscription", capacity: Number(multiplier), recognised: true, ...tierField };
7230
+ }
7231
+ return { kind: "subscription", capacity: 1, recognised: BASE_TIER.test(tier), ...tierField };
7232
+ }
7233
+ var import_zod13, PlanClassSchema, TIER_MULTIPLIER, ZERO_TIER, BASE_TIER;
7234
+ var init_plan2 = __esm({
7235
+ "src/usage/plan.ts"() {
7236
+ "use strict";
7237
+ import_zod13 = require("zod");
7238
+ PlanClassSchema = import_zod13.z.union([
7239
+ import_zod13.z.strictObject({
7240
+ kind: import_zod13.z.literal("subscription"),
7241
+ /** The plan's size as a multiple of the smallest subscription tier (Max is 5, Ultra is 20). */
7242
+ capacity: import_zod13.z.number().positive(),
7243
+ /** False when the tier string named no multiplier and no tier this project knows, so `capacity` is the neutral 1 rather than a reading. */
7244
+ recognised: import_zod13.z.boolean(),
7245
+ /** The tier string the classification rests on, when the account had one. */
7246
+ tier: import_zod13.z.string().optional()
7247
+ }),
7248
+ import_zod13.z.strictObject({
7249
+ kind: import_zod13.z.literal("pay-per-use"),
7250
+ tier: import_zod13.z.string().optional()
7251
+ })
7252
+ ]);
7253
+ TIER_MULTIPLIER = /(?:^|_)(\d+)x$/;
7254
+ ZERO_TIER = /(?:^|_)zero$/;
7255
+ BASE_TIER = /(?:^|_)(?:pro|free)$/;
7256
+ }
7257
+ });
7258
+
7259
+ // src/usage/scan.ts
7260
+ var import_zod14, AnthropicUsageSchema, ErrorObjectSchema;
7261
+ var init_scan = __esm({
7262
+ "src/usage/scan.ts"() {
7263
+ "use strict";
7264
+ import_zod14 = require("zod");
7265
+ AnthropicUsageSchema = import_zod14.z.looseObject({
7266
+ input_tokens: import_zod14.z.number().int().nonnegative().nullish(),
7267
+ output_tokens: import_zod14.z.number().int().nonnegative().nullish(),
7268
+ cache_creation_input_tokens: import_zod14.z.number().int().nonnegative().nullish(),
7269
+ cache_read_input_tokens: import_zod14.z.number().int().nonnegative().nullish()
7270
+ });
7271
+ ErrorObjectSchema = import_zod14.z.looseObject({
7272
+ type: import_zod14.z.string().optional(),
7273
+ code: import_zod14.z.union([import_zod14.z.string(), import_zod14.z.number()]).optional(),
7274
+ message: import_zod14.z.string().optional()
7275
+ });
7276
+ }
7277
+ });
7278
+
7279
+ // src/usage/middleware.ts
7280
+ var ANTHROPIC_PROVIDER;
7281
+ var init_middleware = __esm({
7282
+ "src/usage/middleware.ts"() {
7283
+ "use strict";
7284
+ init_route();
7285
+ init_rateLimit();
7286
+ init_scan();
7287
+ init_schema2();
7288
+ ANTHROPIC_PROVIDER = "anthropic";
7289
+ }
7290
+ });
7291
+
7262
7292
  // src/usage/quotaFacts.ts
7263
7293
  function windowFacts(window, nowMs) {
7264
7294
  if (window?.utilization === void 0 || window.resetsAt === void 0) {
@@ -7358,17 +7388,6 @@ function windowRatio(records) {
7358
7388
  }
7359
7389
  return (last.seven - first.seven) / (last.five - first.five);
7360
7390
  }
7361
- function percent(fraction) {
7362
- return `${String(Math.round(fraction * PERCENT))}%`;
7363
- }
7364
- function describeWindow(label, window, effective, nowMs) {
7365
- if (effective.reset) {
7366
- return `${label} window has reset`;
7367
- }
7368
- const used = effective.utilization === void 0 ? "usage unknown" : `${percent(effective.utilization)} used`;
7369
- const resets = effective.resetsAtMs === void 0 ? "" : `, resets in ${formatAge(effective.resetsAtMs - nowMs)}`;
7370
- return `${label} ${used}${resets}${window.status === "allowed_warning" ? " (nearly used)" : ""}`;
7371
- }
7372
7391
  function capacityOf(plan) {
7373
7392
  return plan.kind === "subscription" ? plan.capacity : 1;
7374
7393
  }
@@ -7561,11 +7580,12 @@ function rankPool(input) {
7561
7580
  ...holdForReturn === void 0 ? {} : { holdForReturn }
7562
7581
  };
7563
7582
  }
7564
- var MS_PER_SECOND4, MS_PER_HOUR2, HOURS_PER_DAY2, FIVE_HOURS, PROMPT_CACHE_TTL_HOURS, PERCENT, SEVEN_DAYS, FIVE_HOUR_WINDOW_MS, SEVEN_DAY_WINDOW_MS, PROMPT_CACHE_TTL_MS, CLASS_ORDER;
7583
+ var MS_PER_SECOND4, MS_PER_HOUR2, HOURS_PER_DAY2, FIVE_HOURS, PROMPT_CACHE_TTL_HOURS, SEVEN_DAYS, FIVE_HOUR_WINDOW_MS, SEVEN_DAY_WINDOW_MS, PROMPT_CACHE_TTL_MS, CLASS_ORDER;
7565
7584
  var init_pick = __esm({
7566
7585
  "src/usage/pick.ts"() {
7567
7586
  "use strict";
7568
7587
  init_conditions();
7588
+ init_candidateText();
7569
7589
  init_plan2();
7570
7590
  init_middleware();
7571
7591
  init_preflight();
@@ -7576,7 +7596,6 @@ var init_pick = __esm({
7576
7596
  HOURS_PER_DAY2 = 24;
7577
7597
  FIVE_HOURS = 5;
7578
7598
  PROMPT_CACHE_TTL_HOURS = 1;
7579
- PERCENT = 100;
7580
7599
  SEVEN_DAYS = 7;
7581
7600
  FIVE_HOUR_WINDOW_MS = FIVE_HOURS * MS_PER_HOUR2;
7582
7601
  SEVEN_DAY_WINDOW_MS = SEVEN_DAYS * HOURS_PER_DAY2 * MS_PER_HOUR2;
@@ -9637,6 +9656,62 @@ var init_guard = __esm({
9637
9656
  }
9638
9657
  });
9639
9658
 
9659
+ // src/usage/resets.ts
9660
+ function formatPeriod(window) {
9661
+ if (window.periodMs === void 0) {
9662
+ return window.period ?? "unknown period";
9663
+ }
9664
+ const hours = window.periodMs / MS_PER_HOUR3;
9665
+ return hours >= HOURS_PER_DAY3 && Number.isInteger(hours / HOURS_PER_DAY3) ? `${String(hours / HOURS_PER_DAY3)}d` : `${String(hours)}h`;
9666
+ }
9667
+ function groupOf(row) {
9668
+ return row.resetsAt === void 0 ? 2 : row.reset ? 1 : 0;
9669
+ }
9670
+ function compareRows(left, right) {
9671
+ return groupOf(left) - groupOf(right) || (left.resetsAt ?? "").localeCompare(right.resetsAt ?? "") || left.identity.localeCompare(right.identity) || left.provider.localeCompare(right.provider) || left.window.localeCompare(right.window);
9672
+ }
9673
+ function rowOf(snapshot, provider, window, observedAt2, recorded, nowMs) {
9674
+ const effective = effectiveWindow(recorded, nowMs);
9675
+ return {
9676
+ identity: snapshot.identity,
9677
+ provider,
9678
+ window,
9679
+ observedAt: observedAt2,
9680
+ ...recorded.resetsAt === void 0 ? {} : { resetsAt: recorded.resetsAt },
9681
+ reset: effective.reset,
9682
+ ...effective.utilization === void 0 ? {} : { utilization: effective.utilization },
9683
+ ...effective.status === void 0 ? {} : { status: effective.status }
9684
+ };
9685
+ }
9686
+ function collectResets(snapshots, nowMs) {
9687
+ const rows = snapshots.flatMap(
9688
+ (snapshot) => Object.entries(snapshot.providers).flatMap(([provider, state]) => {
9689
+ const unified = state.rateLimit?.unified;
9690
+ const observedAt2 = state.rateLimit?.observedAt;
9691
+ const overage = unified === void 0 ? void 0 : soleOverageWindow(unified);
9692
+ const headerRows = observedAt2 === void 0 || unified === void 0 ? [] : [
9693
+ ...unified.fiveHour === void 0 ? [] : [rowOf(snapshot, provider, "5h", observedAt2, unified.fiveHour, nowMs)],
9694
+ ...unified.sevenDay === void 0 ? [] : [rowOf(snapshot, provider, "7d", observedAt2, unified.sevenDay, nowMs)],
9695
+ ...overage === void 0 ? [] : [rowOf(snapshot, provider, "extra usage", observedAt2, overage, nowMs)]
9696
+ ];
9697
+ const quota = state.quota;
9698
+ const quotaRows2 = quota === void 0 ? [] : quota.windows.map((window) => rowOf(snapshot, provider, `${window.measures} ${formatPeriod(window)}`, quota.observedAt, window, nowMs));
9699
+ return [...headerRows, ...quotaRows2];
9700
+ })
9701
+ );
9702
+ return { resets: rows.sort(compareRows) };
9703
+ }
9704
+ var MS_PER_HOUR3, HOURS_PER_DAY3;
9705
+ var init_resets = __esm({
9706
+ "src/usage/resets.ts"() {
9707
+ "use strict";
9708
+ init_preflight();
9709
+ init_rateLimit();
9710
+ MS_PER_HOUR3 = 36e5;
9711
+ HOURS_PER_DAY3 = 24;
9712
+ }
9713
+ });
9714
+
9640
9715
  // src/cli/commandDeps.ts
9641
9716
  var init_commandDeps = __esm({
9642
9717
  "src/cli/commandDeps.ts"() {
@@ -11344,24 +11419,9 @@ var init_hold = __esm({
11344
11419
  }
11345
11420
  });
11346
11421
 
11347
- // src/usage/candidateText.ts
11348
- function candidateHeading(candidate) {
11349
- const score = candidate.score === void 0 ? "" : ` score ${candidate.score.toFixed(2)}${candidate.scoreWindow === "fiveHour" ? " by 5h reset" : " by 7d reset"}`;
11350
- const dry = candidate.feasible ? "" : " (5h would run dry)";
11351
- return `[${candidate.class}${score}]${dry}`;
11352
- }
11353
- var init_candidateText = __esm({
11354
- "src/usage/candidateText.ts"() {
11355
- "use strict";
11356
- }
11357
- });
11358
-
11359
11422
  // src/launcher/launchReport.ts
11360
11423
  function poolDetail(pool) {
11361
11424
  const [reason] = pool.reasons;
11362
- if (pool.movedOff !== void 0) {
11363
- return { detail: `moved off ${pool.movedOff.identity}: ${pool.movedOff.reason}`, ...reason === void 0 ? {} : { notes: [reason] } };
11364
- }
11365
11425
  return reason === void 0 ? {} : { detail: reason };
11366
11426
  }
11367
11427
  function rankingNotes(ranking, picked) {
@@ -11370,6 +11430,68 @@ function rankingNotes(ranking, picked) {
11370
11430
  ` ${candidate.reasons.join("; ")}`
11371
11431
  ]);
11372
11432
  }
11433
+ function planText(account) {
11434
+ const plan = planOf(account);
11435
+ if (plan.kind === "pay-per-use") {
11436
+ return "pay-per-use";
11437
+ }
11438
+ return plan.recognised ? `${String(plan.capacity)}x` : void 0;
11439
+ }
11440
+ function loginAccountText(account) {
11441
+ const organisation = account.organizationName !== void 0 && account.organizationType !== void 0 && NAMED_ORGANISATION_TYPES.has(account.organizationType) ? account.organizationRole === void 0 ? account.organizationName : `${account.organizationName} (${account.organizationRole})` : void 0;
11442
+ const parts = [account.emailAddress, organisation, planText(account)].filter((part) => part !== void 0);
11443
+ return parts.length === 0 ? void 0 : parts.join(", ");
11444
+ }
11445
+ function accountRows(billing) {
11446
+ if (billing === void 0) {
11447
+ return [];
11448
+ }
11449
+ if (billing.provider !== void 0) {
11450
+ const quota = billing.snapshot?.providers[billing.provider]?.quota;
11451
+ const parts = [quota?.account?.email, quota?.level].filter((part) => part !== void 0);
11452
+ return parts.length === 0 ? [] : [{ label: "account", value: parts.join(", "), detail: `provider ${billing.provider}` }];
11453
+ }
11454
+ const account = billing.login ?? billing.snapshot?.account;
11455
+ const text = account === void 0 ? void 0 : loginAccountText(account);
11456
+ return text === void 0 ? [] : [{ label: "account", value: text }];
11457
+ }
11458
+ function isInformative(window, nowMs) {
11459
+ const effective = effectiveWindow(window, nowMs);
11460
+ return effective.reset || effective.utilization !== void 0 || effective.resetsAtMs !== void 0;
11461
+ }
11462
+ function quotaRows(billing) {
11463
+ if (billing === void 0) {
11464
+ return [];
11465
+ }
11466
+ const { nowMs } = billing;
11467
+ const state = billing.snapshot?.providers[billing.provider ?? ANTHROPIC_PROVIDER];
11468
+ const recorded = billing.provider === void 0 ? {
11469
+ observedAt: state?.rateLimit?.observedAt,
11470
+ windows: [
11471
+ { label: "5h", window: state?.rateLimit?.unified?.fiveHour },
11472
+ { label: "7d", window: state?.rateLimit?.unified?.sevenDay }
11473
+ ]
11474
+ } : { observedAt: state?.quota?.observedAt, windows: (state?.quota?.windows ?? []).map((window) => ({ label: `${formatPeriod(window)} ${window.measures}`, window })) };
11475
+ const described = recorded.windows.flatMap(({ label, window }) => window !== void 0 && isInformative(window, nowMs) ? [describeWindow(label, window, effectiveWindow(window, nowMs), nowMs)] : []);
11476
+ return recorded.observedAt === void 0 || described.length === 0 ? [] : [{ label: "quota", value: described.join("; "), detail: `recorded ${formatAge(nowMs - Date.parse(recorded.observedAt))} ago` }];
11477
+ }
11478
+ function movedRows(facts) {
11479
+ const { identity } = facts;
11480
+ if (identity === void 0) {
11481
+ return [];
11482
+ }
11483
+ const moved = (from, detail) => [{ label: "moved", value: `${from} -> ${identity}`, detail, notice: true }];
11484
+ if (facts.limitRelaunchFrom !== void 0) {
11485
+ return moved(facts.limitRelaunchFrom, `${facts.limitRelaunchFrom} ran out of quota; the session resumed here`);
11486
+ }
11487
+ if (facts.pool?.movedOff !== void 0) {
11488
+ return moved(facts.pool.movedOff.identity, `the resumed conversation could not stay: ${facts.pool.movedOff.reason}`);
11489
+ }
11490
+ if (facts.lastRanAs !== void 0 && facts.lastRanAs.identity !== identity) {
11491
+ return moved(facts.lastRanAs.identity, `this directory last ran as ${facts.lastRanAs.identity} ${formatAge(facts.lastRanAs.agoMs)} ago`);
11492
+ }
11493
+ return [];
11494
+ }
11373
11495
  function decisionRows(facts) {
11374
11496
  return [
11375
11497
  { label: "identity", value: facts.identity ?? "(none)", detail: facts.identitySource },
@@ -11381,6 +11503,9 @@ function decisionRows(facts) {
11381
11503
  ...facts.ranking === void 0 ? {} : { notes: rankingNotes(facts.ranking, facts.identity) }
11382
11504
  }
11383
11505
  ],
11506
+ ...movedRows(facts),
11507
+ ...accountRows(facts.billing),
11508
+ ...quotaRows(facts.billing),
11384
11509
  ...facts.profile === void 0 ? [] : [{ label: "profile", value: facts.profile.name, detail: facts.profile.source }],
11385
11510
  ...facts.provider === void 0 ? [] : [{ label: "provider", value: facts.provider.name, detail: `credential ${facts.provider.credential}` }],
11386
11511
  ...facts.identityCredential === void 0 ? [] : [{ label: "credential", value: facts.identityCredential, detail: "the identity's own" }]
@@ -11410,10 +11535,16 @@ function farmRow(links, builtDirectories, adopted) {
11410
11535
  function noteRow(text) {
11411
11536
  return { label: "note", value: text };
11412
11537
  }
11538
+ var NAMED_ORGANISATION_TYPES;
11413
11539
  var init_launchReport = __esm({
11414
11540
  "src/launcher/launchReport.ts"() {
11415
11541
  "use strict";
11416
11542
  init_candidateText();
11543
+ init_middleware();
11544
+ init_plan2();
11545
+ init_preflight();
11546
+ init_resets();
11547
+ NAMED_ORGANISATION_TYPES = /* @__PURE__ */ new Set(["claude_team", "claude_enterprise"]);
11417
11548
  }
11418
11549
  });
11419
11550
 
@@ -11488,7 +11619,8 @@ function resolvePoolLaunch(params) {
11488
11619
  explanation: `pool ${poolName}: ${move}${pick.reasons.slice(0, REASONS_LOGGED).join("; ")}`,
11489
11620
  reasons: pick.reasons,
11490
11621
  candidates: graph.ranking.candidates,
11491
- ...movedOff === void 0 ? {} : { movedOff }
11622
+ ...movedOff === void 0 ? {} : { movedOff },
11623
+ ...stickyRead.sticky === void 0 ? {} : { lastRanAs: stickyRead.sticky }
11492
11624
  };
11493
11625
  }
11494
11626
  if (earliestReturn === void 0) {
@@ -11663,7 +11795,8 @@ function pickFromPool(decided, params, parsedArgv, readOnly) {
11663
11795
  return {
11664
11796
  identityDecision: { ...decided, name: resolution.identity },
11665
11797
  poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } },
11666
- poolRanking: resolution.candidates
11798
+ poolRanking: resolution.candidates,
11799
+ ...resolution.lastRanAs === void 0 ? {} : { lastRanAs: { identity: resolution.lastRanAs.identity, agoMs: farmRuntime.now() - Date.parse(resolution.lastRanAs.at) } }
11667
11800
  };
11668
11801
  }
11669
11802
  function decideLaunch(params, readOnly) {
@@ -11690,7 +11823,7 @@ function decideLaunch(params, readOnly) {
11690
11823
  return trimmed === "" ? void 0 : trimmed;
11691
11824
  }
11692
11825
  });
11693
- const { identityDecision, poolPick, poolRanking } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
11826
+ const { identityDecision, poolPick, poolRanking, lastRanAs } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
11694
11827
  const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
11695
11828
  const farm = farmIdentity === void 0 ? void 0 : params.farm;
11696
11829
  if (!readOnly && farm !== void 0 && farmIdentity !== void 0) {
@@ -11767,9 +11900,11 @@ function decideLaunch(params, readOnly) {
11767
11900
  log.warn(warning);
11768
11901
  }
11769
11902
  }
11903
+ let billing;
11770
11904
  if (farm !== void 0 && farmIdentity !== void 0) {
11905
+ let snapshot;
11771
11906
  try {
11772
- const snapshot = readUsageSnapshot(farm.fs, paths.usageSnapshotsDir, farmIdentity);
11907
+ snapshot = readUsageSnapshot(farm.fs, paths.usageSnapshotsDir, farmIdentity);
11773
11908
  for (const warning of quotaWarnings(snapshot, selectedProvider?.name ?? ANTHROPIC_PROVIDER, farm.now())) {
11774
11909
  log.warn(warning);
11775
11910
  }
@@ -11779,6 +11914,16 @@ function decideLaunch(params, readOnly) {
11779
11914
  }
11780
11915
  log.warn(`agent-shim: ${error.message}`);
11781
11916
  }
11917
+ let login;
11918
+ try {
11919
+ login = readAccountMetadata(farm.fs, paths.identitiesDir, farmIdentity);
11920
+ } catch (error) {
11921
+ if (!(error instanceof AccountMetadataError)) {
11922
+ throw error;
11923
+ }
11924
+ log.warn(`agent-shim: ${error.message}`);
11925
+ }
11926
+ billing = { login, snapshot, provider: selectedProvider?.name, nowMs: farm.now() };
11782
11927
  }
11783
11928
  const identityCredentialBlock = selectedProvider === void 0 && farmIdentity !== void 0 ? loadedIdentity?.config.credential : void 0;
11784
11929
  const identityResolution = !readOnly && identityCredentialBlock !== void 0 && farmIdentity !== void 0 ? resolveIdentityCredential(farmIdentity, identityCredentialBlock, env, params.credentials) : void 0;
@@ -11877,6 +12022,8 @@ function decideLaunch(params, readOnly) {
11877
12022
  identityDecision,
11878
12023
  poolPick,
11879
12024
  poolRanking,
12025
+ lastRanAs,
12026
+ billing,
11880
12027
  notes,
11881
12028
  configDirEscapeHatch: configDirEscapeHatchApplies,
11882
12029
  farmIdentity,
@@ -11899,7 +12046,7 @@ function prepareLaunch(params) {
11899
12046
  const { paths, proc, log } = params;
11900
12047
  const { env } = proc;
11901
12048
  const decided = decideLaunch(params, false);
11902
- const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolPick, poolRanking, notes, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
12049
+ const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolPick, poolRanking, lastRanAs, billing, notes, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
11903
12050
  const rows = [
11904
12051
  ...decisionRows({
11905
12052
  identity: identityDecision.name,
@@ -11908,7 +12055,10 @@ function prepareLaunch(params) {
11908
12055
  ranking: resolvedFlags.explain ? poolRanking : void 0,
11909
12056
  profile: configProfileDecision.name === void 0 ? void 0 : { name: configProfileDecision.name, source: configProfileDecision.source },
11910
12057
  provider: resolvedProvider === void 0 ? void 0 : { name: resolvedProvider.name, credential: `${resolvedProvider.credential.target} from ${describeSource(resolvedProvider.credential.source)}` },
11911
- identityCredential: identityCredential === void 0 ? void 0 : `${identityCredential.target} from ${describeSource(identityCredential.source)}`
12058
+ identityCredential: identityCredential === void 0 ? void 0 : `${identityCredential.target} from ${describeSource(identityCredential.source)}`,
12059
+ billing,
12060
+ lastRanAs,
12061
+ limitRelaunchFrom: params.supervised?.from
11912
12062
  })
11913
12063
  ];
11914
12064
  let warnings = [];
@@ -12097,6 +12247,7 @@ var init_launcher = __esm({
12097
12247
  init_schema();
12098
12248
  init_credential();
12099
12249
  init_middleware();
12250
+ init_account();
12100
12251
  init_preflight();
12101
12252
  init_read();
12102
12253
  init_claudeVersion();
@@ -16723,56 +16874,7 @@ var CheckReportJsonSchema = import_zod21.z.strictObject({
16723
16874
  // src/frontdoor/controlApi.ts
16724
16875
  init_middleware();
16725
16876
  init_preflight();
16726
-
16727
- // src/usage/resets.ts
16728
- init_preflight();
16729
- init_rateLimit();
16730
- var MS_PER_HOUR3 = 36e5;
16731
- var HOURS_PER_DAY3 = 24;
16732
- function formatPeriod(window) {
16733
- if (window.periodMs === void 0) {
16734
- return window.period ?? "unknown period";
16735
- }
16736
- const hours = window.periodMs / MS_PER_HOUR3;
16737
- return hours >= HOURS_PER_DAY3 && Number.isInteger(hours / HOURS_PER_DAY3) ? `${String(hours / HOURS_PER_DAY3)}d` : `${String(hours)}h`;
16738
- }
16739
- function groupOf(row) {
16740
- return row.resetsAt === void 0 ? 2 : row.reset ? 1 : 0;
16741
- }
16742
- function compareRows(left, right) {
16743
- return groupOf(left) - groupOf(right) || (left.resetsAt ?? "").localeCompare(right.resetsAt ?? "") || left.identity.localeCompare(right.identity) || left.provider.localeCompare(right.provider) || left.window.localeCompare(right.window);
16744
- }
16745
- function rowOf(snapshot, provider, window, observedAt2, recorded, nowMs) {
16746
- const effective = effectiveWindow(recorded, nowMs);
16747
- return {
16748
- identity: snapshot.identity,
16749
- provider,
16750
- window,
16751
- observedAt: observedAt2,
16752
- ...recorded.resetsAt === void 0 ? {} : { resetsAt: recorded.resetsAt },
16753
- reset: effective.reset,
16754
- ...effective.utilization === void 0 ? {} : { utilization: effective.utilization },
16755
- ...effective.status === void 0 ? {} : { status: effective.status }
16756
- };
16757
- }
16758
- function collectResets(snapshots, nowMs) {
16759
- const rows = snapshots.flatMap(
16760
- (snapshot) => Object.entries(snapshot.providers).flatMap(([provider, state]) => {
16761
- const unified = state.rateLimit?.unified;
16762
- const observedAt2 = state.rateLimit?.observedAt;
16763
- const overage = unified === void 0 ? void 0 : soleOverageWindow(unified);
16764
- const headerRows = observedAt2 === void 0 || unified === void 0 ? [] : [
16765
- ...unified.fiveHour === void 0 ? [] : [rowOf(snapshot, provider, "5h", observedAt2, unified.fiveHour, nowMs)],
16766
- ...unified.sevenDay === void 0 ? [] : [rowOf(snapshot, provider, "7d", observedAt2, unified.sevenDay, nowMs)],
16767
- ...overage === void 0 ? [] : [rowOf(snapshot, provider, "extra usage", observedAt2, overage, nowMs)]
16768
- ];
16769
- const quota = state.quota;
16770
- const quotaRows = quota === void 0 ? [] : quota.windows.map((window) => rowOf(snapshot, provider, `${window.measures} ${formatPeriod(window)}`, quota.observedAt, window, nowMs));
16771
- return [...headerRows, ...quotaRows];
16772
- })
16773
- );
16774
- return { resets: rows.sort(compareRows) };
16775
- }
16877
+ init_resets();
16776
16878
 
16777
16879
  // src/usage/resetsSchema.ts
16778
16880
  var import_zod22 = require("zod");
@@ -16982,6 +17084,65 @@ var import_node_fs10 = __toESM(require("node:fs"), 1);
16982
17084
  var import_node_path29 = __toESM(require("node:path"), 1);
16983
17085
  init_signIn();
16984
17086
 
17087
+ // src/identityAccounts.ts
17088
+ init_account();
17089
+
17090
+ // src/usage/accountDescription.ts
17091
+ function describeAccountOrganisation(account) {
17092
+ const parts = [account.organizationName, account.organizationType].filter((part) => part !== void 0);
17093
+ return parts.length === 0 ? void 0 : parts.join(", ");
17094
+ }
17095
+
17096
+ // src/identityAccounts.ts
17097
+ function readIdentityAccount(fs14, identitiesDir, identity) {
17098
+ try {
17099
+ const account = readAccountMetadata(fs14, identitiesDir, identity);
17100
+ return account === void 0 ? void 0 : { account };
17101
+ } catch (error) {
17102
+ if (error instanceof AccountMetadataError) {
17103
+ return { problem: error.message };
17104
+ }
17105
+ throw error;
17106
+ }
17107
+ }
17108
+ function summariseIdentityAccount(account) {
17109
+ const summary = {
17110
+ ...account.emailAddress === void 0 ? {} : { emailAddress: account.emailAddress },
17111
+ ...account.organizationName === void 0 ? {} : { organizationName: account.organizationName },
17112
+ ...account.organizationType === void 0 ? {} : { organizationType: account.organizationType },
17113
+ ...account.organizationRole === void 0 ? {} : { organizationRole: account.organizationRole },
17114
+ ...account.billingType === void 0 ? {} : { billingType: account.billingType },
17115
+ ...account.seatTier === void 0 ? {} : { seatTier: account.seatTier }
17116
+ };
17117
+ return Object.keys(summary).length === 0 ? void 0 : summary;
17118
+ }
17119
+ function loginKeyOf(account) {
17120
+ return account.accountUuid === void 0 ? void 0 : JSON.stringify([account.accountUuid, account.organizationUuid ?? null]);
17121
+ }
17122
+ function collectByLogin(items, loginOf) {
17123
+ const groups = /* @__PURE__ */ new Map();
17124
+ for (const item of items) {
17125
+ const key = loginOf(item) ?? /* @__PURE__ */ Symbol("no login");
17126
+ const group = groups.get(key);
17127
+ if (group === void 0) {
17128
+ groups.set(key, [item]);
17129
+ } else {
17130
+ group.push(item);
17131
+ }
17132
+ }
17133
+ return [...groups.values()];
17134
+ }
17135
+ function groupSharedLogins(items, loginOf) {
17136
+ return collectByLogin(items, loginOf).filter((group) => group.length > 1);
17137
+ }
17138
+ function describeAccountHolder(summary) {
17139
+ const organisation = describeAccountOrganisation(summary);
17140
+ if (summary.emailAddress === void 0) {
17141
+ return organisation;
17142
+ }
17143
+ return organisation === void 0 ? summary.emailAddress : `${summary.emailAddress} (${organisation})`;
17144
+ }
17145
+
16985
17146
  // src/codex/siwcStore.ts
16986
17147
  var import_zod26 = require("zod");
16987
17148
 
@@ -17356,6 +17517,10 @@ var DOCTOR_SECTIONS = [
17356
17517
  "frontdoor",
17357
17518
  "models"
17358
17519
  ];
17520
+ function joinNames(names) {
17521
+ const last = names.at(-1);
17522
+ return names.length < 2 || last === void 0 ? names.join("") : `${names.slice(0, -1).join(", ")} and ${last}`;
17523
+ }
17359
17524
  function refinePathShadow(status, ownExecutablePath, realpath) {
17360
17525
  if (status.status !== "shadowed") {
17361
17526
  return status;
@@ -17603,6 +17768,7 @@ function runDoctor(params) {
17603
17768
  const validProfileNames = new Set(profileSources.keys());
17604
17769
  const validProviderNames = /* @__PURE__ */ new Set([...params.providers.map((entry) => entry.name), ...Object.keys(params.providerAliases ?? {})]);
17605
17770
  const validIdentityNames = /* @__PURE__ */ new Set();
17771
+ const signedInAccounts = [];
17606
17772
  for (const entry of params.identities) {
17607
17773
  const validated3 = validate(IdentitySchema, entry, "identity", entry.name);
17608
17774
  if (!validated3.ok) {
@@ -17652,6 +17818,18 @@ function runDoctor(params) {
17652
17818
  signIn.state === "signed-out" ? `${entry.name} is signed out (${signIn.detail}). Run \`agent-shim run @${entry.name}\` and sign in.` : `${entry.name} ${standing} (${signIn.detail}).`,
17653
17819
  entry.name
17654
17820
  );
17821
+ if (signIn.state === "signed-in" && entry.account !== void 0) {
17822
+ signedInAccounts.push({ name: entry.name, account: entry.account });
17823
+ }
17824
+ }
17825
+ for (const group of groupSharedLogins(signedInAccounts, (entry) => loginKeyOf(entry.account))) {
17826
+ const names = group.map((entry) => entry.name);
17827
+ const holder = group.map((entry) => summariseIdentityAccount(entry.account)).map((summary) => summary === void 0 ? void 0 : describeAccountHolder(summary)).find((described) => described !== void 0);
17828
+ push(
17829
+ "sign-in",
17830
+ "warn",
17831
+ `Identities ${joinNames(names)} hold the same login${holder === void 0 ? "" : ` (${holder})`}, so they share one quota window and all but one are redundant. Remove the redundant ones with \`agent-shim identity remove <name>\`.`
17832
+ );
17655
17833
  }
17656
17834
  const validatedGlobalConfig = params.globalConfig.raw === void 0 ? void 0 : validateJson(GlobalConfigSchema, params.globalConfig);
17657
17835
  const pools = validatedGlobalConfig?.ok === true ? validatedGlobalConfig.data.pools ?? {} : {};
@@ -17940,7 +18118,7 @@ function collectDoctorReport(params) {
17940
18118
  const identities = identityNames.map((name) => {
17941
18119
  const farmRoot = import_node_path29.default.join(paths.identitiesDir, name);
17942
18120
  const identityPath = import_node_path29.default.join(farmRoot, "identity.json");
17943
- return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot, credentialsFilePresent: import_node_fs10.default.existsSync(credentialsFilePath(farmRoot)) };
18121
+ return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot, credentialsFilePresent: import_node_fs10.default.existsSync(credentialsFilePath(farmRoot)), account: readIdentityAccount(realFsPort, paths.identitiesDir, name)?.account };
17944
18122
  });
17945
18123
  const profileNames = import_node_fs10.default.existsSync(paths.configProfilesDir) ? import_node_fs10.default.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
17946
18124
  const configProfiles = profileNames.map((name) => {
@@ -21244,6 +21422,7 @@ init_supervisor();
21244
21422
  init_read();
21245
21423
  init_schema2();
21246
21424
  init_preflight();
21425
+ init_resets();
21247
21426
  init_pick();
21248
21427
  init_plan2();
21249
21428
  init_poolPick();