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.mjs CHANGED
@@ -4740,7 +4740,7 @@ var init_package = __esm({
4740
4740
  "package.json"() {
4741
4741
  package_default = {
4742
4742
  name: "agent-shim",
4743
- version: "11.76.0",
4743
+ version: "11.78.0",
4744
4744
  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.",
4745
4745
  license: "MIT",
4746
4746
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -5947,19 +5947,23 @@ function renderReport(rows, style) {
5947
5947
  const lines = [style(["bold"], REPORT_HEADING)];
5948
5948
  for (const row of rows) {
5949
5949
  const detail = row.detail === void 0 ? "" : ` ${style(["dim"], `(${row.detail})`)}`;
5950
- lines.push(`${indent}${style(["dim"], row.label.padEnd(labelWidth))}${COLUMN_GAP}${row.value}${detail}`);
5950
+ const label = row.label.padEnd(labelWidth);
5951
+ lines.push(
5952
+ 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}`
5953
+ );
5951
5954
  for (const note of row.notes ?? []) {
5952
5955
  lines.push(`${indent}${" ".repeat(labelWidth)}${COLUMN_GAP}${style(["dim"], note)}`);
5953
5956
  }
5954
5957
  }
5955
5958
  return lines;
5956
5959
  }
5957
- var REPORT_HEADING, COLUMN_GAP;
5960
+ var REPORT_HEADING, COLUMN_GAP, NOTICE_FORMATS;
5958
5961
  var init_report = __esm({
5959
5962
  "src/launcher/report.ts"() {
5960
5963
  "use strict";
5961
5964
  REPORT_HEADING = "agent-shim";
5962
5965
  COLUMN_GAP = " ";
5966
+ NOTICE_FORMATS = ["yellow", "bold"];
5963
5967
  }
5964
5968
  });
5965
5969
 
@@ -7008,52 +7012,6 @@ var init_account = __esm({
7008
7012
  }
7009
7013
  });
7010
7014
 
7011
- // src/usage/plan.ts
7012
- import { z as z13 } from "zod";
7013
- function planOf(account) {
7014
- const userTier = account?.userRateLimitTier;
7015
- if (userTier !== void 0 && ZERO_TIER.test(userTier)) {
7016
- return { kind: "pay-per-use", tier: userTier };
7017
- }
7018
- const tier = account?.organizationRateLimitTier ?? userTier;
7019
- const tierField = tier === void 0 ? {} : { tier };
7020
- if (tier === void 0) {
7021
- return { kind: "subscription", capacity: 1, recognised: false };
7022
- }
7023
- if (ZERO_TIER.test(tier)) {
7024
- return { kind: "pay-per-use", ...tierField };
7025
- }
7026
- const multiplier = TIER_MULTIPLIER.exec(tier)?.[1];
7027
- if (multiplier !== void 0) {
7028
- return { kind: "subscription", capacity: Number(multiplier), recognised: true, ...tierField };
7029
- }
7030
- return { kind: "subscription", capacity: 1, recognised: BASE_TIER.test(tier), ...tierField };
7031
- }
7032
- var PlanClassSchema, TIER_MULTIPLIER, ZERO_TIER, BASE_TIER;
7033
- var init_plan2 = __esm({
7034
- "src/usage/plan.ts"() {
7035
- "use strict";
7036
- PlanClassSchema = z13.union([
7037
- z13.strictObject({
7038
- kind: z13.literal("subscription"),
7039
- /** The plan's size as a multiple of the smallest subscription tier (Max is 5, Ultra is 20). */
7040
- capacity: z13.number().positive(),
7041
- /** False when the tier string named no multiplier and no tier this project knows, so `capacity` is the neutral 1 rather than a reading. */
7042
- recognised: z13.boolean(),
7043
- /** The tier string the classification rests on, when the account had one. */
7044
- tier: z13.string().optional()
7045
- }),
7046
- z13.strictObject({
7047
- kind: z13.literal("pay-per-use"),
7048
- tier: z13.string().optional()
7049
- })
7050
- ]);
7051
- TIER_MULTIPLIER = /(?:^|_)(\d+)x$/;
7052
- ZERO_TIER = /(?:^|_)zero$/;
7053
- BASE_TIER = /(?:^|_)(?:pro|free)$/;
7054
- }
7055
- });
7056
-
7057
7015
  // src/usage/rateLimit.ts
7058
7016
  function epochSecondsToIso(value) {
7059
7017
  if (value === void 0) {
@@ -7145,39 +7103,6 @@ var init_rateLimit = __esm({
7145
7103
  }
7146
7104
  });
7147
7105
 
7148
- // src/usage/scan.ts
7149
- import { z as z14 } from "zod";
7150
- var AnthropicUsageSchema, ErrorObjectSchema;
7151
- var init_scan = __esm({
7152
- "src/usage/scan.ts"() {
7153
- "use strict";
7154
- AnthropicUsageSchema = z14.looseObject({
7155
- input_tokens: z14.number().int().nonnegative().nullish(),
7156
- output_tokens: z14.number().int().nonnegative().nullish(),
7157
- cache_creation_input_tokens: z14.number().int().nonnegative().nullish(),
7158
- cache_read_input_tokens: z14.number().int().nonnegative().nullish()
7159
- });
7160
- ErrorObjectSchema = z14.looseObject({
7161
- type: z14.string().optional(),
7162
- code: z14.union([z14.string(), z14.number()]).optional(),
7163
- message: z14.string().optional()
7164
- });
7165
- }
7166
- });
7167
-
7168
- // src/usage/middleware.ts
7169
- var ANTHROPIC_PROVIDER;
7170
- var init_middleware = __esm({
7171
- "src/usage/middleware.ts"() {
7172
- "use strict";
7173
- init_route();
7174
- init_rateLimit();
7175
- init_scan();
7176
- init_schema2();
7177
- ANTHROPIC_PROVIDER = "anthropic";
7178
- }
7179
- });
7180
-
7181
7106
  // src/usage/preflight.ts
7182
7107
  function formatAge(ms) {
7183
7108
  const minutes = Math.floor(ms / (MS_PER_SECOND3 * SECONDS_PER_MINUTE));
@@ -7234,6 +7159,111 @@ var init_preflight = __esm({
7234
7159
  }
7235
7160
  });
7236
7161
 
7162
+ // src/usage/candidateText.ts
7163
+ function candidateHeading(candidate) {
7164
+ const score = candidate.score === void 0 ? "" : ` score ${candidate.score.toFixed(2)}${candidate.scoreWindow === "fiveHour" ? " by 5h reset" : " by 7d reset"}`;
7165
+ const dry = candidate.feasible ? "" : " (5h would run dry)";
7166
+ return `[${candidate.class}${score}]${dry}`;
7167
+ }
7168
+ function percent(fraction) {
7169
+ return `${String(Math.round(fraction * PERCENT))}%`;
7170
+ }
7171
+ function describeWindow(label, window, effective, nowMs) {
7172
+ if (effective.reset) {
7173
+ return `${label} window has reset`;
7174
+ }
7175
+ const used = effective.utilization === void 0 ? "usage unknown" : `${percent(effective.utilization)} used`;
7176
+ const resets = effective.resetsAtMs === void 0 ? "" : `, resets in ${formatAge(effective.resetsAtMs - nowMs)}`;
7177
+ return `${label} ${used}${resets}${window.status === "allowed_warning" ? " (nearly used)" : ""}`;
7178
+ }
7179
+ var PERCENT;
7180
+ var init_candidateText = __esm({
7181
+ "src/usage/candidateText.ts"() {
7182
+ "use strict";
7183
+ init_preflight();
7184
+ PERCENT = 100;
7185
+ }
7186
+ });
7187
+
7188
+ // src/usage/plan.ts
7189
+ import { z as z13 } from "zod";
7190
+ function planOf(account) {
7191
+ const userTier = account?.userRateLimitTier;
7192
+ if (userTier !== void 0 && ZERO_TIER.test(userTier)) {
7193
+ return { kind: "pay-per-use", tier: userTier };
7194
+ }
7195
+ const tier = account?.organizationRateLimitTier ?? userTier;
7196
+ const tierField = tier === void 0 ? {} : { tier };
7197
+ if (tier === void 0) {
7198
+ return { kind: "subscription", capacity: 1, recognised: false };
7199
+ }
7200
+ if (ZERO_TIER.test(tier)) {
7201
+ return { kind: "pay-per-use", ...tierField };
7202
+ }
7203
+ const multiplier = TIER_MULTIPLIER.exec(tier)?.[1];
7204
+ if (multiplier !== void 0) {
7205
+ return { kind: "subscription", capacity: Number(multiplier), recognised: true, ...tierField };
7206
+ }
7207
+ return { kind: "subscription", capacity: 1, recognised: BASE_TIER.test(tier), ...tierField };
7208
+ }
7209
+ var PlanClassSchema, TIER_MULTIPLIER, ZERO_TIER, BASE_TIER;
7210
+ var init_plan2 = __esm({
7211
+ "src/usage/plan.ts"() {
7212
+ "use strict";
7213
+ PlanClassSchema = z13.union([
7214
+ z13.strictObject({
7215
+ kind: z13.literal("subscription"),
7216
+ /** The plan's size as a multiple of the smallest subscription tier (Max is 5, Ultra is 20). */
7217
+ capacity: z13.number().positive(),
7218
+ /** False when the tier string named no multiplier and no tier this project knows, so `capacity` is the neutral 1 rather than a reading. */
7219
+ recognised: z13.boolean(),
7220
+ /** The tier string the classification rests on, when the account had one. */
7221
+ tier: z13.string().optional()
7222
+ }),
7223
+ z13.strictObject({
7224
+ kind: z13.literal("pay-per-use"),
7225
+ tier: z13.string().optional()
7226
+ })
7227
+ ]);
7228
+ TIER_MULTIPLIER = /(?:^|_)(\d+)x$/;
7229
+ ZERO_TIER = /(?:^|_)zero$/;
7230
+ BASE_TIER = /(?:^|_)(?:pro|free)$/;
7231
+ }
7232
+ });
7233
+
7234
+ // src/usage/scan.ts
7235
+ import { z as z14 } from "zod";
7236
+ var AnthropicUsageSchema, ErrorObjectSchema;
7237
+ var init_scan = __esm({
7238
+ "src/usage/scan.ts"() {
7239
+ "use strict";
7240
+ AnthropicUsageSchema = z14.looseObject({
7241
+ input_tokens: z14.number().int().nonnegative().nullish(),
7242
+ output_tokens: z14.number().int().nonnegative().nullish(),
7243
+ cache_creation_input_tokens: z14.number().int().nonnegative().nullish(),
7244
+ cache_read_input_tokens: z14.number().int().nonnegative().nullish()
7245
+ });
7246
+ ErrorObjectSchema = z14.looseObject({
7247
+ type: z14.string().optional(),
7248
+ code: z14.union([z14.string(), z14.number()]).optional(),
7249
+ message: z14.string().optional()
7250
+ });
7251
+ }
7252
+ });
7253
+
7254
+ // src/usage/middleware.ts
7255
+ var ANTHROPIC_PROVIDER;
7256
+ var init_middleware = __esm({
7257
+ "src/usage/middleware.ts"() {
7258
+ "use strict";
7259
+ init_route();
7260
+ init_rateLimit();
7261
+ init_scan();
7262
+ init_schema2();
7263
+ ANTHROPIC_PROVIDER = "anthropic";
7264
+ }
7265
+ });
7266
+
7237
7267
  // src/usage/quotaFacts.ts
7238
7268
  function windowFacts(window, nowMs) {
7239
7269
  if (window?.utilization === void 0 || window.resetsAt === void 0) {
@@ -7333,17 +7363,6 @@ function windowRatio(records) {
7333
7363
  }
7334
7364
  return (last.seven - first.seven) / (last.five - first.five);
7335
7365
  }
7336
- function percent(fraction) {
7337
- return `${String(Math.round(fraction * PERCENT))}%`;
7338
- }
7339
- function describeWindow(label, window, effective, nowMs) {
7340
- if (effective.reset) {
7341
- return `${label} window has reset`;
7342
- }
7343
- const used = effective.utilization === void 0 ? "usage unknown" : `${percent(effective.utilization)} used`;
7344
- const resets = effective.resetsAtMs === void 0 ? "" : `, resets in ${formatAge(effective.resetsAtMs - nowMs)}`;
7345
- return `${label} ${used}${resets}${window.status === "allowed_warning" ? " (nearly used)" : ""}`;
7346
- }
7347
7366
  function capacityOf(plan) {
7348
7367
  return plan.kind === "subscription" ? plan.capacity : 1;
7349
7368
  }
@@ -7536,11 +7555,12 @@ function rankPool(input) {
7536
7555
  ...holdForReturn === void 0 ? {} : { holdForReturn }
7537
7556
  };
7538
7557
  }
7539
- 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;
7558
+ 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;
7540
7559
  var init_pick = __esm({
7541
7560
  "src/usage/pick.ts"() {
7542
7561
  "use strict";
7543
7562
  init_conditions();
7563
+ init_candidateText();
7544
7564
  init_plan2();
7545
7565
  init_middleware();
7546
7566
  init_preflight();
@@ -7551,7 +7571,6 @@ var init_pick = __esm({
7551
7571
  HOURS_PER_DAY2 = 24;
7552
7572
  FIVE_HOURS = 5;
7553
7573
  PROMPT_CACHE_TTL_HOURS = 1;
7554
- PERCENT = 100;
7555
7574
  SEVEN_DAYS = 7;
7556
7575
  FIVE_HOUR_WINDOW_MS = FIVE_HOURS * MS_PER_HOUR2;
7557
7576
  SEVEN_DAY_WINDOW_MS = SEVEN_DAYS * HOURS_PER_DAY2 * MS_PER_HOUR2;
@@ -9610,6 +9629,62 @@ var init_guard = __esm({
9610
9629
  }
9611
9630
  });
9612
9631
 
9632
+ // src/usage/resets.ts
9633
+ function formatPeriod(window) {
9634
+ if (window.periodMs === void 0) {
9635
+ return window.period ?? "unknown period";
9636
+ }
9637
+ const hours = window.periodMs / MS_PER_HOUR3;
9638
+ return hours >= HOURS_PER_DAY3 && Number.isInteger(hours / HOURS_PER_DAY3) ? `${String(hours / HOURS_PER_DAY3)}d` : `${String(hours)}h`;
9639
+ }
9640
+ function groupOf(row) {
9641
+ return row.resetsAt === void 0 ? 2 : row.reset ? 1 : 0;
9642
+ }
9643
+ function compareRows(left, right) {
9644
+ 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);
9645
+ }
9646
+ function rowOf(snapshot, provider, window, observedAt2, recorded, nowMs) {
9647
+ const effective = effectiveWindow(recorded, nowMs);
9648
+ return {
9649
+ identity: snapshot.identity,
9650
+ provider,
9651
+ window,
9652
+ observedAt: observedAt2,
9653
+ ...recorded.resetsAt === void 0 ? {} : { resetsAt: recorded.resetsAt },
9654
+ reset: effective.reset,
9655
+ ...effective.utilization === void 0 ? {} : { utilization: effective.utilization },
9656
+ ...effective.status === void 0 ? {} : { status: effective.status }
9657
+ };
9658
+ }
9659
+ function collectResets(snapshots, nowMs) {
9660
+ const rows = snapshots.flatMap(
9661
+ (snapshot) => Object.entries(snapshot.providers).flatMap(([provider, state]) => {
9662
+ const unified = state.rateLimit?.unified;
9663
+ const observedAt2 = state.rateLimit?.observedAt;
9664
+ const overage = unified === void 0 ? void 0 : soleOverageWindow(unified);
9665
+ const headerRows = observedAt2 === void 0 || unified === void 0 ? [] : [
9666
+ ...unified.fiveHour === void 0 ? [] : [rowOf(snapshot, provider, "5h", observedAt2, unified.fiveHour, nowMs)],
9667
+ ...unified.sevenDay === void 0 ? [] : [rowOf(snapshot, provider, "7d", observedAt2, unified.sevenDay, nowMs)],
9668
+ ...overage === void 0 ? [] : [rowOf(snapshot, provider, "extra usage", observedAt2, overage, nowMs)]
9669
+ ];
9670
+ const quota = state.quota;
9671
+ const quotaRows2 = quota === void 0 ? [] : quota.windows.map((window) => rowOf(snapshot, provider, `${window.measures} ${formatPeriod(window)}`, quota.observedAt, window, nowMs));
9672
+ return [...headerRows, ...quotaRows2];
9673
+ })
9674
+ );
9675
+ return { resets: rows.sort(compareRows) };
9676
+ }
9677
+ var MS_PER_HOUR3, HOURS_PER_DAY3;
9678
+ var init_resets = __esm({
9679
+ "src/usage/resets.ts"() {
9680
+ "use strict";
9681
+ init_preflight();
9682
+ init_rateLimit();
9683
+ MS_PER_HOUR3 = 36e5;
9684
+ HOURS_PER_DAY3 = 24;
9685
+ }
9686
+ });
9687
+
9613
9688
  // src/cli/commandDeps.ts
9614
9689
  var init_commandDeps = __esm({
9615
9690
  "src/cli/commandDeps.ts"() {
@@ -11316,24 +11391,9 @@ var init_hold = __esm({
11316
11391
  }
11317
11392
  });
11318
11393
 
11319
- // src/usage/candidateText.ts
11320
- function candidateHeading(candidate) {
11321
- const score = candidate.score === void 0 ? "" : ` score ${candidate.score.toFixed(2)}${candidate.scoreWindow === "fiveHour" ? " by 5h reset" : " by 7d reset"}`;
11322
- const dry = candidate.feasible ? "" : " (5h would run dry)";
11323
- return `[${candidate.class}${score}]${dry}`;
11324
- }
11325
- var init_candidateText = __esm({
11326
- "src/usage/candidateText.ts"() {
11327
- "use strict";
11328
- }
11329
- });
11330
-
11331
11394
  // src/launcher/launchReport.ts
11332
11395
  function poolDetail(pool) {
11333
11396
  const [reason] = pool.reasons;
11334
- if (pool.movedOff !== void 0) {
11335
- return { detail: `moved off ${pool.movedOff.identity}: ${pool.movedOff.reason}`, ...reason === void 0 ? {} : { notes: [reason] } };
11336
- }
11337
11397
  return reason === void 0 ? {} : { detail: reason };
11338
11398
  }
11339
11399
  function rankingNotes(ranking, picked) {
@@ -11342,6 +11402,68 @@ function rankingNotes(ranking, picked) {
11342
11402
  ` ${candidate.reasons.join("; ")}`
11343
11403
  ]);
11344
11404
  }
11405
+ function planText(account) {
11406
+ const plan = planOf(account);
11407
+ if (plan.kind === "pay-per-use") {
11408
+ return "pay-per-use";
11409
+ }
11410
+ return plan.recognised ? `${String(plan.capacity)}x` : void 0;
11411
+ }
11412
+ function loginAccountText(account) {
11413
+ 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;
11414
+ const parts = [account.emailAddress, organisation, planText(account)].filter((part) => part !== void 0);
11415
+ return parts.length === 0 ? void 0 : parts.join(", ");
11416
+ }
11417
+ function accountRows(billing) {
11418
+ if (billing === void 0) {
11419
+ return [];
11420
+ }
11421
+ if (billing.provider !== void 0) {
11422
+ const quota = billing.snapshot?.providers[billing.provider]?.quota;
11423
+ const parts = [quota?.account?.email, quota?.level].filter((part) => part !== void 0);
11424
+ return parts.length === 0 ? [] : [{ label: "account", value: parts.join(", "), detail: `provider ${billing.provider}` }];
11425
+ }
11426
+ const account = billing.login ?? billing.snapshot?.account;
11427
+ const text = account === void 0 ? void 0 : loginAccountText(account);
11428
+ return text === void 0 ? [] : [{ label: "account", value: text }];
11429
+ }
11430
+ function isInformative(window, nowMs) {
11431
+ const effective = effectiveWindow(window, nowMs);
11432
+ return effective.reset || effective.utilization !== void 0 || effective.resetsAtMs !== void 0;
11433
+ }
11434
+ function quotaRows(billing) {
11435
+ if (billing === void 0) {
11436
+ return [];
11437
+ }
11438
+ const { nowMs } = billing;
11439
+ const state = billing.snapshot?.providers[billing.provider ?? ANTHROPIC_PROVIDER];
11440
+ const recorded = billing.provider === void 0 ? {
11441
+ observedAt: state?.rateLimit?.observedAt,
11442
+ windows: [
11443
+ { label: "5h", window: state?.rateLimit?.unified?.fiveHour },
11444
+ { label: "7d", window: state?.rateLimit?.unified?.sevenDay }
11445
+ ]
11446
+ } : { observedAt: state?.quota?.observedAt, windows: (state?.quota?.windows ?? []).map((window) => ({ label: `${formatPeriod(window)} ${window.measures}`, window })) };
11447
+ const described = recorded.windows.flatMap(({ label, window }) => window !== void 0 && isInformative(window, nowMs) ? [describeWindow(label, window, effectiveWindow(window, nowMs), nowMs)] : []);
11448
+ return recorded.observedAt === void 0 || described.length === 0 ? [] : [{ label: "quota", value: described.join("; "), detail: `recorded ${formatAge(nowMs - Date.parse(recorded.observedAt))} ago` }];
11449
+ }
11450
+ function movedRows(facts) {
11451
+ const { identity } = facts;
11452
+ if (identity === void 0) {
11453
+ return [];
11454
+ }
11455
+ const moved = (from, detail) => [{ label: "moved", value: `${from} -> ${identity}`, detail, notice: true }];
11456
+ if (facts.limitRelaunchFrom !== void 0) {
11457
+ return moved(facts.limitRelaunchFrom, `${facts.limitRelaunchFrom} ran out of quota; the session resumed here`);
11458
+ }
11459
+ if (facts.pool?.movedOff !== void 0) {
11460
+ return moved(facts.pool.movedOff.identity, `the resumed conversation could not stay: ${facts.pool.movedOff.reason}`);
11461
+ }
11462
+ if (facts.lastRanAs !== void 0 && facts.lastRanAs.identity !== identity) {
11463
+ return moved(facts.lastRanAs.identity, `this directory last ran as ${facts.lastRanAs.identity} ${formatAge(facts.lastRanAs.agoMs)} ago`);
11464
+ }
11465
+ return [];
11466
+ }
11345
11467
  function decisionRows(facts) {
11346
11468
  return [
11347
11469
  { label: "identity", value: facts.identity ?? "(none)", detail: facts.identitySource },
@@ -11353,6 +11475,9 @@ function decisionRows(facts) {
11353
11475
  ...facts.ranking === void 0 ? {} : { notes: rankingNotes(facts.ranking, facts.identity) }
11354
11476
  }
11355
11477
  ],
11478
+ ...movedRows(facts),
11479
+ ...accountRows(facts.billing),
11480
+ ...quotaRows(facts.billing),
11356
11481
  ...facts.profile === void 0 ? [] : [{ label: "profile", value: facts.profile.name, detail: facts.profile.source }],
11357
11482
  ...facts.provider === void 0 ? [] : [{ label: "provider", value: facts.provider.name, detail: `credential ${facts.provider.credential}` }],
11358
11483
  ...facts.identityCredential === void 0 ? [] : [{ label: "credential", value: facts.identityCredential, detail: "the identity's own" }]
@@ -11382,10 +11507,16 @@ function farmRow(links, builtDirectories, adopted) {
11382
11507
  function noteRow(text) {
11383
11508
  return { label: "note", value: text };
11384
11509
  }
11510
+ var NAMED_ORGANISATION_TYPES;
11385
11511
  var init_launchReport = __esm({
11386
11512
  "src/launcher/launchReport.ts"() {
11387
11513
  "use strict";
11388
11514
  init_candidateText();
11515
+ init_middleware();
11516
+ init_plan2();
11517
+ init_preflight();
11518
+ init_resets();
11519
+ NAMED_ORGANISATION_TYPES = /* @__PURE__ */ new Set(["claude_team", "claude_enterprise"]);
11389
11520
  }
11390
11521
  });
11391
11522
 
@@ -11460,7 +11591,8 @@ function resolvePoolLaunch(params) {
11460
11591
  explanation: `pool ${poolName}: ${move}${pick.reasons.slice(0, REASONS_LOGGED).join("; ")}`,
11461
11592
  reasons: pick.reasons,
11462
11593
  candidates: graph.ranking.candidates,
11463
- ...movedOff === void 0 ? {} : { movedOff }
11594
+ ...movedOff === void 0 ? {} : { movedOff },
11595
+ ...stickyRead.sticky === void 0 ? {} : { lastRanAs: stickyRead.sticky }
11464
11596
  };
11465
11597
  }
11466
11598
  if (earliestReturn === void 0) {
@@ -11638,7 +11770,8 @@ function pickFromPool(decided, params, parsedArgv, readOnly) {
11638
11770
  return {
11639
11771
  identityDecision: { ...decided, name: resolution.identity },
11640
11772
  poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } },
11641
- poolRanking: resolution.candidates
11773
+ poolRanking: resolution.candidates,
11774
+ ...resolution.lastRanAs === void 0 ? {} : { lastRanAs: { identity: resolution.lastRanAs.identity, agoMs: farmRuntime.now() - Date.parse(resolution.lastRanAs.at) } }
11642
11775
  };
11643
11776
  }
11644
11777
  function decideLaunch(params, readOnly) {
@@ -11665,7 +11798,7 @@ function decideLaunch(params, readOnly) {
11665
11798
  return trimmed === "" ? void 0 : trimmed;
11666
11799
  }
11667
11800
  });
11668
- const { identityDecision, poolPick, poolRanking } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
11801
+ const { identityDecision, poolPick, poolRanking, lastRanAs } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
11669
11802
  const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
11670
11803
  const farm = farmIdentity === void 0 ? void 0 : params.farm;
11671
11804
  if (!readOnly && farm !== void 0 && farmIdentity !== void 0) {
@@ -11742,9 +11875,11 @@ function decideLaunch(params, readOnly) {
11742
11875
  log.warn(warning);
11743
11876
  }
11744
11877
  }
11878
+ let billing;
11745
11879
  if (farm !== void 0 && farmIdentity !== void 0) {
11880
+ let snapshot;
11746
11881
  try {
11747
- const snapshot = readUsageSnapshot(farm.fs, paths.usageSnapshotsDir, farmIdentity);
11882
+ snapshot = readUsageSnapshot(farm.fs, paths.usageSnapshotsDir, farmIdentity);
11748
11883
  for (const warning of quotaWarnings(snapshot, selectedProvider?.name ?? ANTHROPIC_PROVIDER, farm.now())) {
11749
11884
  log.warn(warning);
11750
11885
  }
@@ -11754,6 +11889,16 @@ function decideLaunch(params, readOnly) {
11754
11889
  }
11755
11890
  log.warn(`agent-shim: ${error.message}`);
11756
11891
  }
11892
+ let login;
11893
+ try {
11894
+ login = readAccountMetadata(farm.fs, paths.identitiesDir, farmIdentity);
11895
+ } catch (error) {
11896
+ if (!(error instanceof AccountMetadataError)) {
11897
+ throw error;
11898
+ }
11899
+ log.warn(`agent-shim: ${error.message}`);
11900
+ }
11901
+ billing = { login, snapshot, provider: selectedProvider?.name, nowMs: farm.now() };
11757
11902
  }
11758
11903
  const identityCredentialBlock = selectedProvider === void 0 && farmIdentity !== void 0 ? loadedIdentity?.config.credential : void 0;
11759
11904
  const identityResolution = !readOnly && identityCredentialBlock !== void 0 && farmIdentity !== void 0 ? resolveIdentityCredential(farmIdentity, identityCredentialBlock, env, params.credentials) : void 0;
@@ -11852,6 +11997,8 @@ function decideLaunch(params, readOnly) {
11852
11997
  identityDecision,
11853
11998
  poolPick,
11854
11999
  poolRanking,
12000
+ lastRanAs,
12001
+ billing,
11855
12002
  notes,
11856
12003
  configDirEscapeHatch: configDirEscapeHatchApplies,
11857
12004
  farmIdentity,
@@ -11874,7 +12021,7 @@ function prepareLaunch(params) {
11874
12021
  const { paths, proc, log } = params;
11875
12022
  const { env } = proc;
11876
12023
  const decided = decideLaunch(params, false);
11877
- const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolPick, poolRanking, notes, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
12024
+ const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolPick, poolRanking, lastRanAs, billing, notes, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
11878
12025
  const rows = [
11879
12026
  ...decisionRows({
11880
12027
  identity: identityDecision.name,
@@ -11883,7 +12030,10 @@ function prepareLaunch(params) {
11883
12030
  ranking: resolvedFlags.explain ? poolRanking : void 0,
11884
12031
  profile: configProfileDecision.name === void 0 ? void 0 : { name: configProfileDecision.name, source: configProfileDecision.source },
11885
12032
  provider: resolvedProvider === void 0 ? void 0 : { name: resolvedProvider.name, credential: `${resolvedProvider.credential.target} from ${describeSource(resolvedProvider.credential.source)}` },
11886
- identityCredential: identityCredential === void 0 ? void 0 : `${identityCredential.target} from ${describeSource(identityCredential.source)}`
12033
+ identityCredential: identityCredential === void 0 ? void 0 : `${identityCredential.target} from ${describeSource(identityCredential.source)}`,
12034
+ billing,
12035
+ lastRanAs,
12036
+ limitRelaunchFrom: params.supervised?.from
11887
12037
  })
11888
12038
  ];
11889
12039
  let warnings = [];
@@ -12068,6 +12218,7 @@ var init_launcher = __esm({
12068
12218
  init_schema();
12069
12219
  init_credential();
12070
12220
  init_middleware();
12221
+ init_account();
12071
12222
  init_preflight();
12072
12223
  init_read();
12073
12224
  init_claudeVersion();
@@ -16308,56 +16459,7 @@ var CheckReportJsonSchema = z21.strictObject({
16308
16459
  // src/frontdoor/controlApi.ts
16309
16460
  init_middleware();
16310
16461
  init_preflight();
16311
-
16312
- // src/usage/resets.ts
16313
- init_preflight();
16314
- init_rateLimit();
16315
- var MS_PER_HOUR3 = 36e5;
16316
- var HOURS_PER_DAY3 = 24;
16317
- function formatPeriod(window) {
16318
- if (window.periodMs === void 0) {
16319
- return window.period ?? "unknown period";
16320
- }
16321
- const hours = window.periodMs / MS_PER_HOUR3;
16322
- return hours >= HOURS_PER_DAY3 && Number.isInteger(hours / HOURS_PER_DAY3) ? `${String(hours / HOURS_PER_DAY3)}d` : `${String(hours)}h`;
16323
- }
16324
- function groupOf(row) {
16325
- return row.resetsAt === void 0 ? 2 : row.reset ? 1 : 0;
16326
- }
16327
- function compareRows(left, right) {
16328
- 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);
16329
- }
16330
- function rowOf(snapshot, provider, window, observedAt2, recorded, nowMs) {
16331
- const effective = effectiveWindow(recorded, nowMs);
16332
- return {
16333
- identity: snapshot.identity,
16334
- provider,
16335
- window,
16336
- observedAt: observedAt2,
16337
- ...recorded.resetsAt === void 0 ? {} : { resetsAt: recorded.resetsAt },
16338
- reset: effective.reset,
16339
- ...effective.utilization === void 0 ? {} : { utilization: effective.utilization },
16340
- ...effective.status === void 0 ? {} : { status: effective.status }
16341
- };
16342
- }
16343
- function collectResets(snapshots, nowMs) {
16344
- const rows = snapshots.flatMap(
16345
- (snapshot) => Object.entries(snapshot.providers).flatMap(([provider, state]) => {
16346
- const unified = state.rateLimit?.unified;
16347
- const observedAt2 = state.rateLimit?.observedAt;
16348
- const overage = unified === void 0 ? void 0 : soleOverageWindow(unified);
16349
- const headerRows = observedAt2 === void 0 || unified === void 0 ? [] : [
16350
- ...unified.fiveHour === void 0 ? [] : [rowOf(snapshot, provider, "5h", observedAt2, unified.fiveHour, nowMs)],
16351
- ...unified.sevenDay === void 0 ? [] : [rowOf(snapshot, provider, "7d", observedAt2, unified.sevenDay, nowMs)],
16352
- ...overage === void 0 ? [] : [rowOf(snapshot, provider, "extra usage", observedAt2, overage, nowMs)]
16353
- ];
16354
- const quota = state.quota;
16355
- const quotaRows = quota === void 0 ? [] : quota.windows.map((window) => rowOf(snapshot, provider, `${window.measures} ${formatPeriod(window)}`, quota.observedAt, window, nowMs));
16356
- return [...headerRows, ...quotaRows];
16357
- })
16358
- );
16359
- return { resets: rows.sort(compareRows) };
16360
- }
16462
+ init_resets();
16361
16463
 
16362
16464
  // src/usage/resetsSchema.ts
16363
16465
  import { z as z22 } from "zod";
@@ -16567,6 +16669,65 @@ import fs11 from "node:fs";
16567
16669
  import path29 from "node:path";
16568
16670
  init_signIn();
16569
16671
 
16672
+ // src/identityAccounts.ts
16673
+ init_account();
16674
+
16675
+ // src/usage/accountDescription.ts
16676
+ function describeAccountOrganisation(account) {
16677
+ const parts = [account.organizationName, account.organizationType].filter((part) => part !== void 0);
16678
+ return parts.length === 0 ? void 0 : parts.join(", ");
16679
+ }
16680
+
16681
+ // src/identityAccounts.ts
16682
+ function readIdentityAccount(fs14, identitiesDir, identity) {
16683
+ try {
16684
+ const account = readAccountMetadata(fs14, identitiesDir, identity);
16685
+ return account === void 0 ? void 0 : { account };
16686
+ } catch (error) {
16687
+ if (error instanceof AccountMetadataError) {
16688
+ return { problem: error.message };
16689
+ }
16690
+ throw error;
16691
+ }
16692
+ }
16693
+ function summariseIdentityAccount(account) {
16694
+ const summary = {
16695
+ ...account.emailAddress === void 0 ? {} : { emailAddress: account.emailAddress },
16696
+ ...account.organizationName === void 0 ? {} : { organizationName: account.organizationName },
16697
+ ...account.organizationType === void 0 ? {} : { organizationType: account.organizationType },
16698
+ ...account.organizationRole === void 0 ? {} : { organizationRole: account.organizationRole },
16699
+ ...account.billingType === void 0 ? {} : { billingType: account.billingType },
16700
+ ...account.seatTier === void 0 ? {} : { seatTier: account.seatTier }
16701
+ };
16702
+ return Object.keys(summary).length === 0 ? void 0 : summary;
16703
+ }
16704
+ function loginKeyOf(account) {
16705
+ return account.accountUuid === void 0 ? void 0 : JSON.stringify([account.accountUuid, account.organizationUuid ?? null]);
16706
+ }
16707
+ function collectByLogin(items, loginOf) {
16708
+ const groups = /* @__PURE__ */ new Map();
16709
+ for (const item of items) {
16710
+ const key = loginOf(item) ?? /* @__PURE__ */ Symbol("no login");
16711
+ const group = groups.get(key);
16712
+ if (group === void 0) {
16713
+ groups.set(key, [item]);
16714
+ } else {
16715
+ group.push(item);
16716
+ }
16717
+ }
16718
+ return [...groups.values()];
16719
+ }
16720
+ function groupSharedLogins(items, loginOf) {
16721
+ return collectByLogin(items, loginOf).filter((group) => group.length > 1);
16722
+ }
16723
+ function describeAccountHolder(summary) {
16724
+ const organisation = describeAccountOrganisation(summary);
16725
+ if (summary.emailAddress === void 0) {
16726
+ return organisation;
16727
+ }
16728
+ return organisation === void 0 ? summary.emailAddress : `${summary.emailAddress} (${organisation})`;
16729
+ }
16730
+
16570
16731
  // src/codex/siwcStore.ts
16571
16732
  import { z as z26 } from "zod";
16572
16733
 
@@ -16941,6 +17102,10 @@ var DOCTOR_SECTIONS = [
16941
17102
  "frontdoor",
16942
17103
  "models"
16943
17104
  ];
17105
+ function joinNames(names) {
17106
+ const last = names.at(-1);
17107
+ return names.length < 2 || last === void 0 ? names.join("") : `${names.slice(0, -1).join(", ")} and ${last}`;
17108
+ }
16944
17109
  function refinePathShadow(status, ownExecutablePath, realpath) {
16945
17110
  if (status.status !== "shadowed") {
16946
17111
  return status;
@@ -17188,6 +17353,7 @@ function runDoctor(params) {
17188
17353
  const validProfileNames = new Set(profileSources.keys());
17189
17354
  const validProviderNames = /* @__PURE__ */ new Set([...params.providers.map((entry) => entry.name), ...Object.keys(params.providerAliases ?? {})]);
17190
17355
  const validIdentityNames = /* @__PURE__ */ new Set();
17356
+ const signedInAccounts = [];
17191
17357
  for (const entry of params.identities) {
17192
17358
  const validated3 = validate(IdentitySchema, entry, "identity", entry.name);
17193
17359
  if (!validated3.ok) {
@@ -17237,6 +17403,18 @@ function runDoctor(params) {
17237
17403
  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}).`,
17238
17404
  entry.name
17239
17405
  );
17406
+ if (signIn.state === "signed-in" && entry.account !== void 0) {
17407
+ signedInAccounts.push({ name: entry.name, account: entry.account });
17408
+ }
17409
+ }
17410
+ for (const group of groupSharedLogins(signedInAccounts, (entry) => loginKeyOf(entry.account))) {
17411
+ const names = group.map((entry) => entry.name);
17412
+ const holder = group.map((entry) => summariseIdentityAccount(entry.account)).map((summary) => summary === void 0 ? void 0 : describeAccountHolder(summary)).find((described) => described !== void 0);
17413
+ push(
17414
+ "sign-in",
17415
+ "warn",
17416
+ `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>\`.`
17417
+ );
17240
17418
  }
17241
17419
  const validatedGlobalConfig = params.globalConfig.raw === void 0 ? void 0 : validateJson(GlobalConfigSchema, params.globalConfig);
17242
17420
  const pools = validatedGlobalConfig?.ok === true ? validatedGlobalConfig.data.pools ?? {} : {};
@@ -17525,7 +17703,7 @@ function collectDoctorReport(params) {
17525
17703
  const identities = identityNames.map((name) => {
17526
17704
  const farmRoot = path29.join(paths.identitiesDir, name);
17527
17705
  const identityPath = path29.join(farmRoot, "identity.json");
17528
- return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot, credentialsFilePresent: fs11.existsSync(credentialsFilePath(farmRoot)) };
17706
+ return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot, credentialsFilePresent: fs11.existsSync(credentialsFilePath(farmRoot)), account: readIdentityAccount(realFsPort, paths.identitiesDir, name)?.account };
17529
17707
  });
17530
17708
  const profileNames = fs11.existsSync(paths.configProfilesDir) ? fs11.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
17531
17709
  const configProfiles = profileNames.map((name) => {
@@ -20829,6 +21007,7 @@ init_supervisor();
20829
21007
  init_read();
20830
21008
  init_schema2();
20831
21009
  init_preflight();
21010
+ init_resets();
20832
21011
  init_pick();
20833
21012
  init_plan2();
20834
21013
  init_poolPick();