agent-shim 8.30.0 → 8.31.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/cli.cjs CHANGED
@@ -61796,7 +61796,7 @@ function registerIdentityCommand(program2, deps) {
61796
61796
  // package.json
61797
61797
  var package_default = {
61798
61798
  name: "agent-shim",
61799
- version: "8.30.0",
61799
+ version: "8.31.0",
61800
61800
  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.",
61801
61801
  license: "MIT",
61802
61802
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -63150,6 +63150,7 @@ function createUsageStore(deps) {
63150
63150
  fs20.mkdirPrivate(paths.usageSnapshotsDir);
63151
63151
  fs20.writeFilePrivate(snapshotPath(paths.usageSnapshotsDir, identity), `${JSON.stringify(snapshot, null, 2)}
63152
63152
  `);
63153
+ deps.publish?.(snapshot);
63153
63154
  return true;
63154
63155
  };
63155
63156
  return {
@@ -65682,6 +65683,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
65682
65683
  try {
65683
65684
  http8 = await ports.startProviderListener(lastPort);
65684
65685
  } catch (error62) {
65686
+ ports.doorHealth.listenerFailed("provider", error62 instanceof Error ? error62.message : String(error62));
65685
65687
  return fail(`could not start the provider listener: ${error62 instanceof Error ? error62.message : String(error62)}`);
65686
65688
  }
65687
65689
  if (previousSticky !== void 0 && http8.port !== previousSticky) {
@@ -65694,6 +65696,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
65694
65696
  connect3 = await ports.startConnectListener(lastConnectPort);
65695
65697
  } catch (error62) {
65696
65698
  await http8.close();
65699
+ ports.doorHealth.listenerFailed("connect", error62 instanceof Error ? error62.message : String(error62));
65697
65700
  return fail(`could not start the CONNECT surface: ${error62 instanceof Error ? error62.message : String(error62)}`);
65698
65701
  }
65699
65702
  if (previousStickyConnect !== void 0 && connect3.port !== previousStickyConnect) {
@@ -65707,6 +65710,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
65707
65710
  } catch (error62) {
65708
65711
  await connect3.close();
65709
65712
  await http8.close();
65713
+ ports.doorHealth.listenerFailed("direct", error62 instanceof Error ? error62.message : String(error62));
65710
65714
  return fail(`could not start the direct listener: ${error62 instanceof Error ? error62.message : String(error62)}`);
65711
65715
  }
65712
65716
  if (previousStickyDirect !== void 0 && direct.port !== previousStickyDirect) {
@@ -65714,6 +65718,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
65714
65718
  }
65715
65719
  lastDirectPort = direct.port;
65716
65720
  writeFrontDoorState(fs20, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http8.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
65721
+ ports.doorHealth.generation({ providerPort: http8.port, connectPort: connect3.port, directPort: direct.port });
65717
65722
  fs20.removeRecursive(paths.frontdoorLockFile);
65718
65723
  ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http8.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
65719
65724
  let idleSince;
@@ -65726,11 +65731,13 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
65726
65731
  const listed = listFrontDoorSessions(fs20, paths.frontdoorSessionsDir);
65727
65732
  const pruned = pruneDeadFrontDoorSessions(fs20, paths.frontdoorSessionsDir, ports.isRunning);
65728
65733
  ports.observeLaunchRegistry(listed, pruned);
65734
+ ports.checkQuotaExpiry();
65729
65735
  const prunedPids = new Set(pruned);
65730
65736
  if (listed.filter((session) => !prunedPids.has(session.pid)).length === 0) {
65731
65737
  idleSince ??= ports.now();
65732
65738
  if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE2) {
65733
65739
  ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
65740
+ ports.doorHealth.idleShutdown();
65734
65741
  await direct.close();
65735
65742
  await connect3.close();
65736
65743
  await http8.close();
@@ -73910,6 +73917,9 @@ function frontDoorRcApiClient(port, ca, token) {
73910
73917
  // src/frontdoor/eventSchemas.ts
73911
73918
  var DOOR_EVENT_SOURCE_RC = "rc";
73912
73919
  var LAUNCH_EVENT_SOURCE = "launch";
73920
+ var USAGE_EVENT_SOURCE = "usage";
73921
+ var DOOR_HEALTH_EVENT_SOURCE = "door";
73922
+ var QUOTA_EXPIRING_EVENT_SOURCE = "quota-expiring";
73913
73923
  var DoorEventSchema = external_exports.strictObject({
73914
73924
  source: external_exports.string().min(1),
73915
73925
  /** A positive integer because the backbone's counters start at one and only ever increase. */
@@ -73925,6 +73935,20 @@ var LaunchLifecycleEventSchema = external_exports.strictObject({
73925
73935
  startedAt: external_exports.number(),
73926
73936
  observedAt: external_exports.number()
73927
73937
  });
73938
+ var DoorHealthEventSchema = external_exports.discriminatedUnion("kind", [
73939
+ external_exports.strictObject({ kind: external_exports.literal("generation"), pid: external_exports.number().int().positive(), providerPort: external_exports.number().int().positive(), connectPort: external_exports.number().int().positive(), directPort: external_exports.number().int().positive(), observedAt: external_exports.number() }),
73940
+ external_exports.strictObject({ kind: external_exports.literal("listenerFailed"), pid: external_exports.number().int().positive(), listener: external_exports.enum(["provider", "connect", "direct"]), message: external_exports.string(), observedAt: external_exports.number() }),
73941
+ external_exports.strictObject({ kind: external_exports.literal("idleShutdown"), pid: external_exports.number().int().positive(), observedAt: external_exports.number() })
73942
+ ]);
73943
+ var QuotaExpiringEventSchema = external_exports.strictObject({
73944
+ identity: external_exports.string().min(1),
73945
+ provider: external_exports.string().min(1),
73946
+ window: external_exports.enum(["fiveHour", "sevenDay"]),
73947
+ /** The fraction of the window already used when it was seen expiring, always below one because a fully used window has nothing left to spend. */
73948
+ utilization: external_exports.number().min(0).max(1),
73949
+ resetsAt: external_exports.iso.datetime(),
73950
+ observedAt: external_exports.number()
73951
+ });
73928
73952
 
73929
73953
  // src/frontdoor/eventsApi.ts
73930
73954
  var EVENTS_API_TAG = "events";
@@ -74035,6 +74059,22 @@ function createDoorApiNodeHandler(deps) {
74035
74059
  return doorApiNodeHandlerOf(createDoorApiRouter(deps), deps.expectedToken);
74036
74060
  }
74037
74061
 
74062
+ // src/frontdoor/doorHealthEvents.ts
74063
+ function createDoorHealthPublisher(hub, now, pid) {
74064
+ const publisher = hub.publisher(DOOR_HEALTH_EVENT_SOURCE);
74065
+ return {
74066
+ generation: (ports) => {
74067
+ publisher.publish({ kind: "generation", pid, providerPort: ports.providerPort, connectPort: ports.connectPort, directPort: ports.directPort, observedAt: now() });
74068
+ },
74069
+ listenerFailed: (listener, message) => {
74070
+ publisher.publish({ kind: "listenerFailed", pid, listener, message, observedAt: now() });
74071
+ },
74072
+ idleShutdown: () => {
74073
+ publisher.publish({ kind: "idleShutdown", pid, observedAt: now() });
74074
+ }
74075
+ };
74076
+ }
74077
+
74038
74078
  // src/frontdoor/eventHub.ts
74039
74079
  var DOOR_EVENT_BUFFER_EVENTS = 100;
74040
74080
  function createDoorEventHub() {
@@ -74141,6 +74181,65 @@ function rcFanoutOnDoorHub(fanout, hub) {
74141
74181
  };
74142
74182
  }
74143
74183
 
74184
+ // src/frontdoor/quotaExpiringEvents.ts
74185
+ var MS_PER_HOUR2 = 36e5;
74186
+ var MS_PER_DAY2 = 864e5;
74187
+ var FIVE_HOUR_WINDOW_HOURS = 5;
74188
+ var SEVEN_DAY_WINDOW_DAYS = 7;
74189
+ var FIVE_HOUR_WINDOW_MS2 = FIVE_HOUR_WINDOW_HOURS * MS_PER_HOUR2;
74190
+ var SEVEN_DAY_WINDOW_MS2 = SEVEN_DAY_WINDOW_DAYS * MS_PER_DAY2;
74191
+ var FINAL_SPAN_DENOMINATOR = 30;
74192
+ var QUOTA_EXPIRING_WINDOW_FRACTION = 1 / FINAL_SPAN_DENOMINATOR;
74193
+ function createQuotaExpiringPublisher(hub, deps) {
74194
+ const publisher = hub.publisher(QUOTA_EXPIRING_EVENT_SOURCE);
74195
+ const latest = /* @__PURE__ */ new Map();
74196
+ for (const snapshot of deps.seed) {
74197
+ latest.set(snapshot.identity, snapshot);
74198
+ }
74199
+ hub.subscribe([USAGE_EVENT_SOURCE], (event) => {
74200
+ const snapshot = UsageSnapshotSchema.parse(event.payload);
74201
+ latest.set(snapshot.identity, snapshot);
74202
+ });
74203
+ const announced = /* @__PURE__ */ new Set();
74204
+ const windowsOf = (snapshot) => {
74205
+ const views = [];
74206
+ for (const provider of Object.keys(snapshot.providers).sort()) {
74207
+ const unified = snapshot.providers[provider]?.rateLimit?.unified;
74208
+ const fiveHour = unified?.fiveHour;
74209
+ if (fiveHour?.utilization !== void 0 && fiveHour.resetsAt !== void 0) {
74210
+ views.push({ provider, view: { window: "fiveHour", spanMs: FIVE_HOUR_WINDOW_MS2, utilization: fiveHour.utilization, resetsAtMs: Date.parse(fiveHour.resetsAt) } });
74211
+ }
74212
+ const sevenDay = unified?.sevenDay;
74213
+ if (sevenDay?.utilization !== void 0 && sevenDay.resetsAt !== void 0) {
74214
+ views.push({ provider, view: { window: "sevenDay", spanMs: SEVEN_DAY_WINDOW_MS2, utilization: sevenDay.utilization, resetsAtMs: Date.parse(sevenDay.resetsAt) } });
74215
+ }
74216
+ }
74217
+ return views;
74218
+ };
74219
+ return {
74220
+ check: () => {
74221
+ const now = deps.now();
74222
+ for (const identity of [...latest.keys()].sort()) {
74223
+ const snapshot = latest.get(identity);
74224
+ if (snapshot === void 0) {
74225
+ continue;
74226
+ }
74227
+ for (const { provider, view } of windowsOf(snapshot)) {
74228
+ if (view.utilization >= 1 || view.resetsAtMs <= now || view.resetsAtMs - now >= view.spanMs * QUOTA_EXPIRING_WINDOW_FRACTION) {
74229
+ continue;
74230
+ }
74231
+ const key = `${identity}:${provider}:${view.window}:${String(view.resetsAtMs)}`;
74232
+ if (announced.has(key)) {
74233
+ continue;
74234
+ }
74235
+ announced.add(key);
74236
+ publisher.publish({ identity, provider, window: view.window, utilization: view.utilization, resetsAt: new Date(view.resetsAtMs).toISOString(), observedAt: now });
74237
+ }
74238
+ }
74239
+ }
74240
+ };
74241
+ }
74242
+
74144
74243
  // src/frontdoor/launchEvents.ts
74145
74244
  function createLaunchEventPublisher(hub, now) {
74146
74245
  const publisher = hub.publisher(LAUNCH_EVENT_SOURCE);
@@ -78277,7 +78376,7 @@ var OPENROUTER_HOST = "openrouter.ai";
78277
78376
  var OPENROUTER_KEY_URL = `https://${OPENROUTER_HOST}/api/v1/key`;
78278
78377
  var OPENROUTER_CREDITS_URL = `https://${OPENROUTER_HOST}/api/v1/credits`;
78279
78378
  var HTTP_FORBIDDEN = 403;
78280
- var MS_PER_DAY2 = HOURS_PER_DAY3 * SECONDS_PER_HOUR * MS_PER_SECOND10;
78379
+ var MS_PER_DAY3 = HOURS_PER_DAY3 * SECONDS_PER_HOUR * MS_PER_SECOND10;
78281
78380
  var OpenRouterKeySchema = external_exports.object({
78282
78381
  data: external_exports.object({
78283
78382
  limit: external_exports.number().nonnegative().nullable(),
@@ -78309,7 +78408,7 @@ async function openRouterGet(url2, schema, apiKey, http8, signal) {
78309
78408
  return parsed.data;
78310
78409
  }
78311
78410
  function nextUtcMidnight(nowMs) {
78312
- return new Date((Math.floor(nowMs / MS_PER_DAY2) + 1) * MS_PER_DAY2).toISOString();
78411
+ return new Date((Math.floor(nowMs / MS_PER_DAY3) + 1) * MS_PER_DAY3).toISOString();
78313
78412
  }
78314
78413
  var openRouterQuotaAdapter = {
78315
78414
  source: OPENROUTER_SOURCE,
@@ -78331,7 +78430,7 @@ var openRouterQuotaAdapter = {
78331
78430
  windows.push({ measures: "account-credits", period: "prepaid", utilization: used / total, limit: total, used, remaining: Math.max(total - used, 0) });
78332
78431
  }
78333
78432
  if (free !== void 0 && free.limit > 0) {
78334
- windows.push({ measures: "free-model-requests", periodMs: MS_PER_DAY2, utilization: free.used / free.limit, resetsAt: nextUtcMidnight(nowMs), limit: free.limit, used: free.used, remaining: Math.max(free.remaining, 0) });
78433
+ windows.push({ measures: "free-model-requests", periodMs: MS_PER_DAY3, utilization: free.used / free.limit, resetsAt: nextUtcMidnight(nowMs), limit: free.limit, used: free.used, remaining: Math.max(free.remaining, 0) });
78335
78434
  }
78336
78435
  return ProviderQuotaSchema.parse({
78337
78436
  observedAt: new Date(nowMs).toISOString(),
@@ -78520,6 +78619,9 @@ function realFrontDoorSupervisorPorts(paths) {
78520
78619
  const rcCredentialStore = createRcCredentialStore(realFarmFs, paths.frontdoorRcCredentialsDir);
78521
78620
  const rcTracker = createRcSessionTracker({ now: () => Date.now(), idleMs: RC_IDLE_EXPIRY_MS, credentialStore: rcCredentialStore });
78522
78621
  const doorEvents = createDoorEventHub();
78622
+ const usagePublisher = doorEvents.publisher(USAGE_EVENT_SOURCE);
78623
+ const quotaExpiring = createQuotaExpiringPublisher(doorEvents, { seed: listUsageSnapshots(realFarmFs, paths.usageSnapshotsDir), now: () => Date.now() });
78624
+ const doorHealth = createDoorHealthPublisher(doorEvents, () => Date.now(), process.pid);
78523
78625
  const rcLiveUsage = createRcLiveUsage({ now: () => Date.now(), hub: doorEvents });
78524
78626
  const rcFanout = rcFanoutOnDoorHub(createRcEventFanout(), doorEvents);
78525
78627
  const rcHub = createRcStreamHub({
@@ -78565,7 +78667,10 @@ function realFrontDoorSupervisorPorts(paths) {
78565
78667
  pid: process.pid,
78566
78668
  now: () => Date.now(),
78567
78669
  readAccount: createAccountReader(realFarmFs, paths.identitiesDir),
78568
- log
78670
+ log,
78671
+ publish: (snapshot) => {
78672
+ usagePublisher.publish(snapshot);
78673
+ }
78569
78674
  });
78570
78675
  const quotaRefresher = createRealQuotaRefresher({ paths, store: usageStore, log });
78571
78676
  const usageMiddleware = createUsageMiddleware({
@@ -78764,6 +78869,8 @@ function realFrontDoorSupervisorPorts(paths) {
78764
78869
  closeRcStreamHub: rcHub.close,
78765
78870
  // The launch lifecycle publisher over the same backbone the typed API serves: the tick's registry facts go in here, and the door's own register, prune and end moments come out as source-tagged events.
78766
78871
  observeLaunchRegistry: createLaunchEventPublisher(doorEvents, () => Date.now()).observe,
78872
+ doorHealth,
78873
+ checkQuotaExpiry: quotaExpiring.check,
78767
78874
  log: (line) => {
78768
78875
  appendLog(paths, line);
78769
78876
  }
@@ -80582,13 +80689,13 @@ function formatLimit(limit) {
80582
80689
  return `last limit: ${limit.kind} (${String(limit.status)}) at ${limit.observedAt}${limit.window === void 0 ? "" : ` on the ${limit.window} window`}${wait.length === 0 ? "" : `, ${wait.join(", ")}`}`;
80583
80690
  }
80584
80691
  var MONEY_DECIMALS = 2;
80585
- var MS_PER_HOUR2 = 36e5;
80692
+ var MS_PER_HOUR3 = 36e5;
80586
80693
  var HOURS_PER_DAY4 = 24;
80587
80694
  function formatPeriod(window) {
80588
80695
  if (window.periodMs === void 0) {
80589
80696
  return window.period ?? "unknown period";
80590
80697
  }
80591
- const hours = window.periodMs / MS_PER_HOUR2;
80698
+ const hours = window.periodMs / MS_PER_HOUR3;
80592
80699
  return hours >= HOURS_PER_DAY4 && Number.isInteger(hours / HOURS_PER_DAY4) ? `${String(hours / HOURS_PER_DAY4)}d` : `${String(hours)}h`;
80593
80700
  }
80594
80701
  function formatCount(value2) {
package/dist/index.cjs CHANGED
@@ -48,6 +48,7 @@ __export(index_exports, {
48
48
  CredentialSourceSchema: () => CredentialSourceSchema,
49
49
  DOOR_EVENT_BUFFER_EVENTS: () => DOOR_EVENT_BUFFER_EVENTS,
50
50
  DOOR_EVENT_SOURCE_RC: () => DOOR_EVENT_SOURCE_RC,
51
+ DOOR_HEALTH_EVENT_SOURCE: () => DOOR_HEALTH_EVENT_SOURCE,
51
52
  DirectoryRuleAlreadyExistsError: () => DirectoryRuleAlreadyExistsError,
52
53
  DirectoryRuleMissingTargetError: () => DirectoryRuleMissingTargetError,
53
54
  DirectoryRuleNotFoundError: () => DirectoryRuleNotFoundError,
@@ -57,6 +58,7 @@ __export(index_exports, {
57
58
  DoctorRunOutputSchema: () => DoctorRunOutputSchema,
58
59
  DoorEventSchema: () => DoorEventSchema,
59
60
  DoorEventSourceQuerySchema: () => DoorEventSourceQuerySchema,
61
+ DoorHealthEventSchema: () => DoorHealthEventSchema,
60
62
  EXIT_FAILURE: () => EXIT_FAILURE,
61
63
  EXIT_USAGE: () => EXIT_USAGE,
62
64
  EffectiveWindowSchema: () => EffectiveWindowSchema,
@@ -93,6 +95,8 @@ __export(index_exports, {
93
95
  ProviderKindMismatchError: () => ProviderKindMismatchError,
94
96
  ProviderNotFoundError: () => ProviderNotFoundError,
95
97
  ProviderSchema: () => ProviderSchema,
98
+ QUOTA_EXPIRING_EVENT_SOURCE: () => QUOTA_EXPIRING_EVENT_SOURCE,
99
+ QuotaExpiringEventSchema: () => QuotaExpiringEventSchema,
96
100
  RC_CONTEXT_USAGE_DETAILS: () => RC_CONTEXT_USAGE_DETAILS,
97
101
  RC_IDLE_EXPIRY_MS: () => RC_IDLE_EXPIRY_MS,
98
102
  RC_ORPC_PATH_PREFIX: () => RC_ORPC_PATH_PREFIX,
@@ -120,6 +124,7 @@ __export(index_exports, {
120
124
  RcRateLimitWindowSchema: () => RcRateLimitWindowSchema,
121
125
  RcStreamEnvelopeSchema: () => RcStreamEnvelopeSchema,
122
126
  RcStreamEventSchema: () => RcStreamEventSchema,
127
+ USAGE_EVENT_SOURCE: () => USAGE_EVENT_SOURCE,
123
128
  UsageError: () => UsageError,
124
129
  UsageListOutputSchema: () => UsageListOutputSchema,
125
130
  UsageLiveOutputSchema: () => UsageLiveOutputSchema,
@@ -165,10 +170,12 @@ __export(index_exports, {
165
170
  createDoorApiNodeHandler: () => createDoorApiNodeHandler,
166
171
  createDoorApiRouter: () => createDoorApiRouter,
167
172
  createDoorEventHub: () => createDoorEventHub,
173
+ createDoorHealthPublisher: () => createDoorHealthPublisher,
168
174
  createEventsApiRouter: () => createEventsApiRouter,
169
175
  createLaunchEventPublisher: () => createLaunchEventPublisher,
170
176
  createLeafCache: () => createLeafCache,
171
177
  createProfile: () => createProfile,
178
+ createQuotaExpiringPublisher: () => createQuotaExpiringPublisher,
172
179
  createRcApiNodeHandler: () => createRcApiNodeHandler,
173
180
  createRcApiRouter: () => createRcApiRouter,
174
181
  createRcControlHandler: () => createRcControlHandler,
@@ -3034,6 +3041,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
3034
3041
  try {
3035
3042
  http3 = await ports.startProviderListener(lastPort);
3036
3043
  } catch (error) {
3044
+ ports.doorHealth.listenerFailed("provider", error instanceof Error ? error.message : String(error));
3037
3045
  return fail(`could not start the provider listener: ${error instanceof Error ? error.message : String(error)}`);
3038
3046
  }
3039
3047
  if (previousSticky !== void 0 && http3.port !== previousSticky) {
@@ -3046,6 +3054,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
3046
3054
  connect3 = await ports.startConnectListener(lastConnectPort);
3047
3055
  } catch (error) {
3048
3056
  await http3.close();
3057
+ ports.doorHealth.listenerFailed("connect", error instanceof Error ? error.message : String(error));
3049
3058
  return fail(`could not start the CONNECT surface: ${error instanceof Error ? error.message : String(error)}`);
3050
3059
  }
3051
3060
  if (previousStickyConnect !== void 0 && connect3.port !== previousStickyConnect) {
@@ -3059,6 +3068,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
3059
3068
  } catch (error) {
3060
3069
  await connect3.close();
3061
3070
  await http3.close();
3071
+ ports.doorHealth.listenerFailed("direct", error instanceof Error ? error.message : String(error));
3062
3072
  return fail(`could not start the direct listener: ${error instanceof Error ? error.message : String(error)}`);
3063
3073
  }
3064
3074
  if (previousStickyDirect !== void 0 && direct.port !== previousStickyDirect) {
@@ -3066,6 +3076,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
3066
3076
  }
3067
3077
  lastDirectPort = direct.port;
3068
3078
  writeFrontDoorState(fs12, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http3.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
3079
+ ports.doorHealth.generation({ providerPort: http3.port, connectPort: connect3.port, directPort: direct.port });
3069
3080
  fs12.removeRecursive(paths.frontdoorLockFile);
3070
3081
  ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http3.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
3071
3082
  let idleSince;
@@ -3078,11 +3089,13 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
3078
3089
  const listed = listFrontDoorSessions(fs12, paths.frontdoorSessionsDir);
3079
3090
  const pruned = pruneDeadFrontDoorSessions(fs12, paths.frontdoorSessionsDir, ports.isRunning);
3080
3091
  ports.observeLaunchRegistry(listed, pruned);
3092
+ ports.checkQuotaExpiry();
3081
3093
  const prunedPids = new Set(pruned);
3082
3094
  if (listed.filter((session) => !prunedPids.has(session.pid)).length === 0) {
3083
3095
  idleSince ??= ports.now();
3084
3096
  if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
3085
3097
  ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
3098
+ ports.doorHealth.idleShutdown();
3086
3099
  await direct.close();
3087
3100
  await connect3.close();
3088
3101
  await http3.close();
@@ -5342,7 +5355,7 @@ var import_undici = require("undici");
5342
5355
  // package.json
5343
5356
  var package_default = {
5344
5357
  name: "agent-shim",
5345
- version: "8.30.0",
5358
+ version: "8.31.0",
5346
5359
  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.",
5347
5360
  license: "MIT",
5348
5361
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -10204,6 +10217,9 @@ var import_server3 = require("@orpc/server");
10204
10217
  var import_zod20 = require("zod");
10205
10218
  var DOOR_EVENT_SOURCE_RC = "rc";
10206
10219
  var LAUNCH_EVENT_SOURCE = "launch";
10220
+ var USAGE_EVENT_SOURCE = "usage";
10221
+ var DOOR_HEALTH_EVENT_SOURCE = "door";
10222
+ var QUOTA_EXPIRING_EVENT_SOURCE = "quota-expiring";
10207
10223
  var DoorEventSchema = import_zod20.z.strictObject({
10208
10224
  source: import_zod20.z.string().min(1),
10209
10225
  /** A positive integer because the backbone's counters start at one and only ever increase. */
@@ -10219,6 +10235,20 @@ var LaunchLifecycleEventSchema = import_zod20.z.strictObject({
10219
10235
  startedAt: import_zod20.z.number(),
10220
10236
  observedAt: import_zod20.z.number()
10221
10237
  });
10238
+ var DoorHealthEventSchema = import_zod20.z.discriminatedUnion("kind", [
10239
+ import_zod20.z.strictObject({ kind: import_zod20.z.literal("generation"), pid: import_zod20.z.number().int().positive(), providerPort: import_zod20.z.number().int().positive(), connectPort: import_zod20.z.number().int().positive(), directPort: import_zod20.z.number().int().positive(), observedAt: import_zod20.z.number() }),
10240
+ import_zod20.z.strictObject({ kind: import_zod20.z.literal("listenerFailed"), pid: import_zod20.z.number().int().positive(), listener: import_zod20.z.enum(["provider", "connect", "direct"]), message: import_zod20.z.string(), observedAt: import_zod20.z.number() }),
10241
+ import_zod20.z.strictObject({ kind: import_zod20.z.literal("idleShutdown"), pid: import_zod20.z.number().int().positive(), observedAt: import_zod20.z.number() })
10242
+ ]);
10243
+ var QuotaExpiringEventSchema = import_zod20.z.strictObject({
10244
+ identity: import_zod20.z.string().min(1),
10245
+ provider: import_zod20.z.string().min(1),
10246
+ window: import_zod20.z.enum(["fiveHour", "sevenDay"]),
10247
+ /** The fraction of the window already used when it was seen expiring, always below one because a fully used window has nothing left to spend. */
10248
+ utilization: import_zod20.z.number().min(0).max(1),
10249
+ resetsAt: import_zod20.z.iso.datetime(),
10250
+ observedAt: import_zod20.z.number()
10251
+ });
10222
10252
 
10223
10253
  // src/frontdoor/eventsApi.ts
10224
10254
  var EVENTS_API_TAG = "events";
@@ -10527,6 +10557,81 @@ function createLaunchEventPublisher(hub, now) {
10527
10557
  };
10528
10558
  }
10529
10559
 
10560
+ // src/frontdoor/doorHealthEvents.ts
10561
+ function createDoorHealthPublisher(hub, now, pid) {
10562
+ const publisher = hub.publisher(DOOR_HEALTH_EVENT_SOURCE);
10563
+ return {
10564
+ generation: (ports) => {
10565
+ publisher.publish({ kind: "generation", pid, providerPort: ports.providerPort, connectPort: ports.connectPort, directPort: ports.directPort, observedAt: now() });
10566
+ },
10567
+ listenerFailed: (listener, message) => {
10568
+ publisher.publish({ kind: "listenerFailed", pid, listener, message, observedAt: now() });
10569
+ },
10570
+ idleShutdown: () => {
10571
+ publisher.publish({ kind: "idleShutdown", pid, observedAt: now() });
10572
+ }
10573
+ };
10574
+ }
10575
+
10576
+ // src/frontdoor/quotaExpiringEvents.ts
10577
+ var MS_PER_HOUR2 = 36e5;
10578
+ var MS_PER_DAY2 = 864e5;
10579
+ var FIVE_HOUR_WINDOW_HOURS = 5;
10580
+ var SEVEN_DAY_WINDOW_DAYS = 7;
10581
+ var FIVE_HOUR_WINDOW_MS2 = FIVE_HOUR_WINDOW_HOURS * MS_PER_HOUR2;
10582
+ var SEVEN_DAY_WINDOW_MS2 = SEVEN_DAY_WINDOW_DAYS * MS_PER_DAY2;
10583
+ var FINAL_SPAN_DENOMINATOR = 30;
10584
+ var QUOTA_EXPIRING_WINDOW_FRACTION = 1 / FINAL_SPAN_DENOMINATOR;
10585
+ function createQuotaExpiringPublisher(hub, deps) {
10586
+ const publisher = hub.publisher(QUOTA_EXPIRING_EVENT_SOURCE);
10587
+ const latest = /* @__PURE__ */ new Map();
10588
+ for (const snapshot of deps.seed) {
10589
+ latest.set(snapshot.identity, snapshot);
10590
+ }
10591
+ hub.subscribe([USAGE_EVENT_SOURCE], (event) => {
10592
+ const snapshot = UsageSnapshotSchema.parse(event.payload);
10593
+ latest.set(snapshot.identity, snapshot);
10594
+ });
10595
+ const announced = /* @__PURE__ */ new Set();
10596
+ const windowsOf = (snapshot) => {
10597
+ const views = [];
10598
+ for (const provider of Object.keys(snapshot.providers).sort()) {
10599
+ const unified = snapshot.providers[provider]?.rateLimit?.unified;
10600
+ const fiveHour = unified?.fiveHour;
10601
+ if (fiveHour?.utilization !== void 0 && fiveHour.resetsAt !== void 0) {
10602
+ views.push({ provider, view: { window: "fiveHour", spanMs: FIVE_HOUR_WINDOW_MS2, utilization: fiveHour.utilization, resetsAtMs: Date.parse(fiveHour.resetsAt) } });
10603
+ }
10604
+ const sevenDay = unified?.sevenDay;
10605
+ if (sevenDay?.utilization !== void 0 && sevenDay.resetsAt !== void 0) {
10606
+ views.push({ provider, view: { window: "sevenDay", spanMs: SEVEN_DAY_WINDOW_MS2, utilization: sevenDay.utilization, resetsAtMs: Date.parse(sevenDay.resetsAt) } });
10607
+ }
10608
+ }
10609
+ return views;
10610
+ };
10611
+ return {
10612
+ check: () => {
10613
+ const now = deps.now();
10614
+ for (const identity of [...latest.keys()].sort()) {
10615
+ const snapshot = latest.get(identity);
10616
+ if (snapshot === void 0) {
10617
+ continue;
10618
+ }
10619
+ for (const { provider, view } of windowsOf(snapshot)) {
10620
+ if (view.utilization >= 1 || view.resetsAtMs <= now || view.resetsAtMs - now >= view.spanMs * QUOTA_EXPIRING_WINDOW_FRACTION) {
10621
+ continue;
10622
+ }
10623
+ const key = `${identity}:${provider}:${view.window}:${String(view.resetsAtMs)}`;
10624
+ if (announced.has(key)) {
10625
+ continue;
10626
+ }
10627
+ announced.add(key);
10628
+ publisher.publish({ identity, provider, window: view.window, utilization: view.utilization, resetsAt: new Date(view.resetsAtMs).toISOString(), observedAt: now });
10629
+ }
10630
+ }
10631
+ }
10632
+ };
10633
+ }
10634
+
10530
10635
  // src/frontdoor/rcLiveUsage.ts
10531
10636
  var RC_RATE_LIMIT_EVENT_TYPE = "rate_limit_event";
10532
10637
  function isRecord5(value) {
@@ -13520,6 +13625,7 @@ function prepareClaudeLaunch(options) {
13520
13625
  CredentialSourceSchema,
13521
13626
  DOOR_EVENT_BUFFER_EVENTS,
13522
13627
  DOOR_EVENT_SOURCE_RC,
13628
+ DOOR_HEALTH_EVENT_SOURCE,
13523
13629
  DirectoryRuleAlreadyExistsError,
13524
13630
  DirectoryRuleMissingTargetError,
13525
13631
  DirectoryRuleNotFoundError,
@@ -13529,6 +13635,7 @@ function prepareClaudeLaunch(options) {
13529
13635
  DoctorRunOutputSchema,
13530
13636
  DoorEventSchema,
13531
13637
  DoorEventSourceQuerySchema,
13638
+ DoorHealthEventSchema,
13532
13639
  EXIT_FAILURE,
13533
13640
  EXIT_USAGE,
13534
13641
  EffectiveWindowSchema,
@@ -13565,6 +13672,8 @@ function prepareClaudeLaunch(options) {
13565
13672
  ProviderKindMismatchError,
13566
13673
  ProviderNotFoundError,
13567
13674
  ProviderSchema,
13675
+ QUOTA_EXPIRING_EVENT_SOURCE,
13676
+ QuotaExpiringEventSchema,
13568
13677
  RC_CONTEXT_USAGE_DETAILS,
13569
13678
  RC_IDLE_EXPIRY_MS,
13570
13679
  RC_ORPC_PATH_PREFIX,
@@ -13592,6 +13701,7 @@ function prepareClaudeLaunch(options) {
13592
13701
  RcRateLimitWindowSchema,
13593
13702
  RcStreamEnvelopeSchema,
13594
13703
  RcStreamEventSchema,
13704
+ USAGE_EVENT_SOURCE,
13595
13705
  UsageError,
13596
13706
  UsageListOutputSchema,
13597
13707
  UsageLiveOutputSchema,
@@ -13637,10 +13747,12 @@ function prepareClaudeLaunch(options) {
13637
13747
  createDoorApiNodeHandler,
13638
13748
  createDoorApiRouter,
13639
13749
  createDoorEventHub,
13750
+ createDoorHealthPublisher,
13640
13751
  createEventsApiRouter,
13641
13752
  createLaunchEventPublisher,
13642
13753
  createLeafCache,
13643
13754
  createProfile,
13755
+ createQuotaExpiringPublisher,
13644
13756
  createRcApiNodeHandler,
13645
13757
  createRcApiRouter,
13646
13758
  createRcControlHandler,
package/dist/index.mjs CHANGED
@@ -2729,6 +2729,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2729
2729
  try {
2730
2730
  http3 = await ports.startProviderListener(lastPort);
2731
2731
  } catch (error) {
2732
+ ports.doorHealth.listenerFailed("provider", error instanceof Error ? error.message : String(error));
2732
2733
  return fail(`could not start the provider listener: ${error instanceof Error ? error.message : String(error)}`);
2733
2734
  }
2734
2735
  if (previousSticky !== void 0 && http3.port !== previousSticky) {
@@ -2741,6 +2742,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2741
2742
  connect3 = await ports.startConnectListener(lastConnectPort);
2742
2743
  } catch (error) {
2743
2744
  await http3.close();
2745
+ ports.doorHealth.listenerFailed("connect", error instanceof Error ? error.message : String(error));
2744
2746
  return fail(`could not start the CONNECT surface: ${error instanceof Error ? error.message : String(error)}`);
2745
2747
  }
2746
2748
  if (previousStickyConnect !== void 0 && connect3.port !== previousStickyConnect) {
@@ -2754,6 +2756,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2754
2756
  } catch (error) {
2755
2757
  await connect3.close();
2756
2758
  await http3.close();
2759
+ ports.doorHealth.listenerFailed("direct", error instanceof Error ? error.message : String(error));
2757
2760
  return fail(`could not start the direct listener: ${error instanceof Error ? error.message : String(error)}`);
2758
2761
  }
2759
2762
  if (previousStickyDirect !== void 0 && direct.port !== previousStickyDirect) {
@@ -2761,6 +2764,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2761
2764
  }
2762
2765
  lastDirectPort = direct.port;
2763
2766
  writeFrontDoorState(fs12, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http3.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
2767
+ ports.doorHealth.generation({ providerPort: http3.port, connectPort: connect3.port, directPort: direct.port });
2764
2768
  fs12.removeRecursive(paths.frontdoorLockFile);
2765
2769
  ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http3.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
2766
2770
  let idleSince;
@@ -2773,11 +2777,13 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2773
2777
  const listed = listFrontDoorSessions(fs12, paths.frontdoorSessionsDir);
2774
2778
  const pruned = pruneDeadFrontDoorSessions(fs12, paths.frontdoorSessionsDir, ports.isRunning);
2775
2779
  ports.observeLaunchRegistry(listed, pruned);
2780
+ ports.checkQuotaExpiry();
2776
2781
  const prunedPids = new Set(pruned);
2777
2782
  if (listed.filter((session) => !prunedPids.has(session.pid)).length === 0) {
2778
2783
  idleSince ??= ports.now();
2779
2784
  if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
2780
2785
  ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
2786
+ ports.doorHealth.idleShutdown();
2781
2787
  await direct.close();
2782
2788
  await connect3.close();
2783
2789
  await http3.close();
@@ -5037,7 +5043,7 @@ import { Agent as Agent3, fetch as undiciFetch } from "undici";
5037
5043
  // package.json
5038
5044
  var package_default = {
5039
5045
  name: "agent-shim",
5040
- version: "8.30.0",
5046
+ version: "8.31.0",
5041
5047
  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.",
5042
5048
  license: "MIT",
5043
5049
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -9899,6 +9905,9 @@ import { eventIterator as eventIterator2, withEventMeta as withEventMeta2 } from
9899
9905
  import { z as z20 } from "zod";
9900
9906
  var DOOR_EVENT_SOURCE_RC = "rc";
9901
9907
  var LAUNCH_EVENT_SOURCE = "launch";
9908
+ var USAGE_EVENT_SOURCE = "usage";
9909
+ var DOOR_HEALTH_EVENT_SOURCE = "door";
9910
+ var QUOTA_EXPIRING_EVENT_SOURCE = "quota-expiring";
9902
9911
  var DoorEventSchema = z20.strictObject({
9903
9912
  source: z20.string().min(1),
9904
9913
  /** A positive integer because the backbone's counters start at one and only ever increase. */
@@ -9914,6 +9923,20 @@ var LaunchLifecycleEventSchema = z20.strictObject({
9914
9923
  startedAt: z20.number(),
9915
9924
  observedAt: z20.number()
9916
9925
  });
9926
+ var DoorHealthEventSchema = z20.discriminatedUnion("kind", [
9927
+ z20.strictObject({ kind: z20.literal("generation"), pid: z20.number().int().positive(), providerPort: z20.number().int().positive(), connectPort: z20.number().int().positive(), directPort: z20.number().int().positive(), observedAt: z20.number() }),
9928
+ z20.strictObject({ kind: z20.literal("listenerFailed"), pid: z20.number().int().positive(), listener: z20.enum(["provider", "connect", "direct"]), message: z20.string(), observedAt: z20.number() }),
9929
+ z20.strictObject({ kind: z20.literal("idleShutdown"), pid: z20.number().int().positive(), observedAt: z20.number() })
9930
+ ]);
9931
+ var QuotaExpiringEventSchema = z20.strictObject({
9932
+ identity: z20.string().min(1),
9933
+ provider: z20.string().min(1),
9934
+ window: z20.enum(["fiveHour", "sevenDay"]),
9935
+ /** The fraction of the window already used when it was seen expiring, always below one because a fully used window has nothing left to spend. */
9936
+ utilization: z20.number().min(0).max(1),
9937
+ resetsAt: z20.iso.datetime(),
9938
+ observedAt: z20.number()
9939
+ });
9917
9940
 
9918
9941
  // src/frontdoor/eventsApi.ts
9919
9942
  var EVENTS_API_TAG = "events";
@@ -10222,6 +10245,81 @@ function createLaunchEventPublisher(hub, now) {
10222
10245
  };
10223
10246
  }
10224
10247
 
10248
+ // src/frontdoor/doorHealthEvents.ts
10249
+ function createDoorHealthPublisher(hub, now, pid) {
10250
+ const publisher = hub.publisher(DOOR_HEALTH_EVENT_SOURCE);
10251
+ return {
10252
+ generation: (ports) => {
10253
+ publisher.publish({ kind: "generation", pid, providerPort: ports.providerPort, connectPort: ports.connectPort, directPort: ports.directPort, observedAt: now() });
10254
+ },
10255
+ listenerFailed: (listener, message) => {
10256
+ publisher.publish({ kind: "listenerFailed", pid, listener, message, observedAt: now() });
10257
+ },
10258
+ idleShutdown: () => {
10259
+ publisher.publish({ kind: "idleShutdown", pid, observedAt: now() });
10260
+ }
10261
+ };
10262
+ }
10263
+
10264
+ // src/frontdoor/quotaExpiringEvents.ts
10265
+ var MS_PER_HOUR2 = 36e5;
10266
+ var MS_PER_DAY2 = 864e5;
10267
+ var FIVE_HOUR_WINDOW_HOURS = 5;
10268
+ var SEVEN_DAY_WINDOW_DAYS = 7;
10269
+ var FIVE_HOUR_WINDOW_MS2 = FIVE_HOUR_WINDOW_HOURS * MS_PER_HOUR2;
10270
+ var SEVEN_DAY_WINDOW_MS2 = SEVEN_DAY_WINDOW_DAYS * MS_PER_DAY2;
10271
+ var FINAL_SPAN_DENOMINATOR = 30;
10272
+ var QUOTA_EXPIRING_WINDOW_FRACTION = 1 / FINAL_SPAN_DENOMINATOR;
10273
+ function createQuotaExpiringPublisher(hub, deps) {
10274
+ const publisher = hub.publisher(QUOTA_EXPIRING_EVENT_SOURCE);
10275
+ const latest = /* @__PURE__ */ new Map();
10276
+ for (const snapshot of deps.seed) {
10277
+ latest.set(snapshot.identity, snapshot);
10278
+ }
10279
+ hub.subscribe([USAGE_EVENT_SOURCE], (event) => {
10280
+ const snapshot = UsageSnapshotSchema.parse(event.payload);
10281
+ latest.set(snapshot.identity, snapshot);
10282
+ });
10283
+ const announced = /* @__PURE__ */ new Set();
10284
+ const windowsOf = (snapshot) => {
10285
+ const views = [];
10286
+ for (const provider of Object.keys(snapshot.providers).sort()) {
10287
+ const unified = snapshot.providers[provider]?.rateLimit?.unified;
10288
+ const fiveHour = unified?.fiveHour;
10289
+ if (fiveHour?.utilization !== void 0 && fiveHour.resetsAt !== void 0) {
10290
+ views.push({ provider, view: { window: "fiveHour", spanMs: FIVE_HOUR_WINDOW_MS2, utilization: fiveHour.utilization, resetsAtMs: Date.parse(fiveHour.resetsAt) } });
10291
+ }
10292
+ const sevenDay = unified?.sevenDay;
10293
+ if (sevenDay?.utilization !== void 0 && sevenDay.resetsAt !== void 0) {
10294
+ views.push({ provider, view: { window: "sevenDay", spanMs: SEVEN_DAY_WINDOW_MS2, utilization: sevenDay.utilization, resetsAtMs: Date.parse(sevenDay.resetsAt) } });
10295
+ }
10296
+ }
10297
+ return views;
10298
+ };
10299
+ return {
10300
+ check: () => {
10301
+ const now = deps.now();
10302
+ for (const identity of [...latest.keys()].sort()) {
10303
+ const snapshot = latest.get(identity);
10304
+ if (snapshot === void 0) {
10305
+ continue;
10306
+ }
10307
+ for (const { provider, view } of windowsOf(snapshot)) {
10308
+ if (view.utilization >= 1 || view.resetsAtMs <= now || view.resetsAtMs - now >= view.spanMs * QUOTA_EXPIRING_WINDOW_FRACTION) {
10309
+ continue;
10310
+ }
10311
+ const key = `${identity}:${provider}:${view.window}:${String(view.resetsAtMs)}`;
10312
+ if (announced.has(key)) {
10313
+ continue;
10314
+ }
10315
+ announced.add(key);
10316
+ publisher.publish({ identity, provider, window: view.window, utilization: view.utilization, resetsAt: new Date(view.resetsAtMs).toISOString(), observedAt: now });
10317
+ }
10318
+ }
10319
+ }
10320
+ };
10321
+ }
10322
+
10225
10323
  // src/frontdoor/rcLiveUsage.ts
10226
10324
  var RC_RATE_LIMIT_EVENT_TYPE = "rate_limit_event";
10227
10325
  function isRecord5(value) {
@@ -13214,6 +13312,7 @@ export {
13214
13312
  CredentialSourceSchema,
13215
13313
  DOOR_EVENT_BUFFER_EVENTS,
13216
13314
  DOOR_EVENT_SOURCE_RC,
13315
+ DOOR_HEALTH_EVENT_SOURCE,
13217
13316
  DirectoryRuleAlreadyExistsError,
13218
13317
  DirectoryRuleMissingTargetError,
13219
13318
  DirectoryRuleNotFoundError,
@@ -13223,6 +13322,7 @@ export {
13223
13322
  DoctorRunOutputSchema,
13224
13323
  DoorEventSchema,
13225
13324
  DoorEventSourceQuerySchema,
13325
+ DoorHealthEventSchema,
13226
13326
  EXIT_FAILURE,
13227
13327
  EXIT_USAGE,
13228
13328
  EffectiveWindowSchema,
@@ -13259,6 +13359,8 @@ export {
13259
13359
  ProviderKindMismatchError,
13260
13360
  ProviderNotFoundError,
13261
13361
  ProviderSchema,
13362
+ QUOTA_EXPIRING_EVENT_SOURCE,
13363
+ QuotaExpiringEventSchema,
13262
13364
  RC_CONTEXT_USAGE_DETAILS,
13263
13365
  RC_IDLE_EXPIRY_MS,
13264
13366
  RC_ORPC_PATH_PREFIX,
@@ -13286,6 +13388,7 @@ export {
13286
13388
  RcRateLimitWindowSchema,
13287
13389
  RcStreamEnvelopeSchema,
13288
13390
  RcStreamEventSchema,
13391
+ USAGE_EVENT_SOURCE,
13289
13392
  UsageError,
13290
13393
  UsageListOutputSchema,
13291
13394
  UsageLiveOutputSchema,
@@ -13331,10 +13434,12 @@ export {
13331
13434
  createDoorApiNodeHandler,
13332
13435
  createDoorApiRouter,
13333
13436
  createDoorEventHub,
13437
+ createDoorHealthPublisher,
13334
13438
  createEventsApiRouter,
13335
13439
  createLaunchEventPublisher,
13336
13440
  createLeafCache,
13337
13441
  createProfile,
13442
+ createQuotaExpiringPublisher,
13338
13443
  createRcApiNodeHandler,
13339
13444
  createRcApiRouter,
13340
13445
  createRcControlHandler,
@@ -3760,6 +3760,12 @@ type UsageSnapshot = z.infer<typeof UsageSnapshotSchema>;
3760
3760
  declare const DOOR_EVENT_SOURCE_RC = "rc";
3761
3761
  /** The source tag every launch lifecycle event carries: the registry's own register, prune and end moments, the first publisher the door itself owns. */
3762
3762
  declare const LAUNCH_EVENT_SOURCE = "launch";
3763
+ /** The source tag every usage change event carries: one event per usage snapshot the door writes, the durable fact a quota consumer diffs or reads windows from. */
3764
+ declare const USAGE_EVENT_SOURCE = "usage";
3765
+ /** The source tag every door health event carries: the supervisor's own state transitions, the moments a consumer of the door needs to know the door itself changed. */
3766
+ declare const DOOR_HEALTH_EVENT_SOURCE = "door";
3767
+ /** The source tag every expiring-quota event carries: an identity whose unused window allowance is about to reset, computed from the same snapshots the usage source keeps fresh. */
3768
+ declare const QUOTA_EXPIRING_EVENT_SOURCE = "quota-expiring";
3763
3769
  /** One event on the door's backbone, exactly as the subscription yields it: the source that published it, the sequence the backbone assigned that source, and the publisher's own payload carried verbatim for the consumer to narrow. */
3764
3770
  declare const DoorEventSchema: z.ZodObject<{
3765
3771
  source: z.ZodString;
@@ -3789,6 +3795,54 @@ declare const LaunchLifecycleEventSchema: z.ZodObject<{
3789
3795
  }, z.core.$strict>;
3790
3796
  /** One launch lifecycle event, as the TypeScript the publisher emits and its consumers handle. */
3791
3797
  type LaunchLifecycleEvent = z.output<typeof LaunchLifecycleEventSchema>;
3798
+ /**
3799
+ * One door health event: the supervisor's own state transitions, observed at the moment they happened in this process. `generation` is the door fully serving (every listener bound and the state file naming it); `listenerFailed` is a start failure that ends the generation, naming which listener and why; `idleShutdown` is the door closing itself with an empty session registry.
3800
+ */
3801
+ declare const DoorHealthEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3802
+ kind: z.ZodLiteral<"generation">;
3803
+ pid: z.ZodNumber;
3804
+ providerPort: z.ZodNumber;
3805
+ connectPort: z.ZodNumber;
3806
+ directPort: z.ZodNumber;
3807
+ observedAt: z.ZodNumber;
3808
+ }, z.core.$strict>, z.ZodObject<{
3809
+ kind: z.ZodLiteral<"listenerFailed">;
3810
+ pid: z.ZodNumber;
3811
+ listener: z.ZodEnum<{
3812
+ provider: "provider";
3813
+ connect: "connect";
3814
+ direct: "direct";
3815
+ }>;
3816
+ message: z.ZodString;
3817
+ observedAt: z.ZodNumber;
3818
+ }, z.core.$strict>, z.ZodObject<{
3819
+ kind: z.ZodLiteral<"idleShutdown">;
3820
+ pid: z.ZodNumber;
3821
+ observedAt: z.ZodNumber;
3822
+ }, z.core.$strict>], "kind">;
3823
+ /** One door health event, as the TypeScript the publisher emits and its consumers handle. */
3824
+ type DoorHealthEvent = z.output<typeof DoorHealthEventSchema>;
3825
+ /**
3826
+ * One expiring-quota event: an identity's window with allowance still unspent that is about to reset, published once when the window enters its final span (so a scheduler can spend what would otherwise be lost, the moment spending it is still possible). `resetsAt` is the window's own reset instant; `observedAt` is when the door's tick saw it cross.
3827
+ */
3828
+ declare const QuotaExpiringEventSchema: z.ZodObject<{
3829
+ identity: z.ZodString;
3830
+ provider: z.ZodString;
3831
+ window: z.ZodEnum<{
3832
+ fiveHour: "fiveHour";
3833
+ sevenDay: "sevenDay";
3834
+ }>;
3835
+ utilization: z.ZodNumber;
3836
+ resetsAt: z.ZodISODateTime;
3837
+ observedAt: z.ZodNumber;
3838
+ }, z.core.$strict>;
3839
+ /** One expiring-quota event, as the TypeScript the publisher emits and its consumers handle. */
3840
+ type QuotaExpiringEvent = z.output<typeof QuotaExpiringEventSchema>;
3841
+ /**
3842
+ * The usage source's payload: the snapshot the door just wrote, verbatim, so a consumer sees the quota change or reset in the payload itself rather than the door guessing which of the two a write was. The snapshot schema is the payload schema (identity, observed instant, every provider's state with its windows), the one definition `usage --json` readers already share.
3843
+ */
3844
+ /** One usage change event, as the TypeScript the publisher emits and its consumers handle: the written snapshot itself, so the snapshot's own schema (`UsageSnapshotSchema`) is this payload's schema rather than a renamed copy. */
3845
+ type UsageChangeEvent = UsageSnapshot;
3792
3846
 
3793
3847
  /**
3794
3848
  * The door's event backbone: the publisher/subscriber machinery the Remote Control client stream's fan-out first proved, generalised so any door-wide source can publish and any consumer can subscribe once instead of each source growing its own channel. A publisher registers under a source tag and publishes payloads; the backbone stamps each event with its source's own monotonic sequence and delivers to every matching subscriber synchronously, in publication order. A source that carries its own ordering on the wire (the Remote Control envelope's per-session `sequence_num`, the number its resume rule resumes after) keeps it inside the payload, verbatim: the backbone's sequence is deliberately not any protocol's number.
@@ -5571,6 +5625,36 @@ interface LaunchEventPublisher {
5571
5625
  /** Creates the launch lifecycle publisher. One per door process, fed by the supervisor's tick. */
5572
5626
  declare function createLaunchEventPublisher(hub: DoorEventHub, now: () => number): LaunchEventPublisher;
5573
5627
 
5628
+ /**
5629
+ * The door health publisher: the supervisor's own state transitions as backbone events, so a consumer of the door learns the door itself changed and not only its sessions. The publisher emits nothing of its own: the supervisor tells it the moments it already lives through (every listener bound, a start failure that ends the generation, the idle shutdown), each published the moment it happens rather than at a tick, because these are process facts, not registry facts diffed between observations.
5630
+ */
5631
+ /** Everything the door health publisher needs: the backbone it publishes on and the clock its events are observed at. */
5632
+ interface DoorHealthPublisher {
5633
+ /** Publishes the generation event: every listener bound, the state file naming this supervisor, the door fully serving. */
5634
+ readonly generation: (ports: {
5635
+ readonly providerPort: number;
5636
+ readonly connectPort: number;
5637
+ readonly directPort: number;
5638
+ }) => void;
5639
+ /** Publishes the start failure that ends the generation, naming which listener and why. */
5640
+ readonly listenerFailed: (listener: "provider" | "connect" | "direct", message: string) => void;
5641
+ /** Publishes the idle shutdown: the door closing itself with an empty session registry. */
5642
+ readonly idleShutdown: () => void;
5643
+ }
5644
+ /** Creates the door health publisher. One per door process, fed by the supervisor. */
5645
+ declare function createDoorHealthPublisher(hub: DoorEventHub, now: () => number, pid: number): DoorHealthPublisher;
5646
+
5647
+ /** Everything the expiring-quota publisher needs: the backbone (its usage source keeps the snapshots fresh), the snapshots as they stand at assembly, and the clock the tick reads. */
5648
+ interface QuotaExpiringPublisher {
5649
+ /** Checks every held window against the clock and publishes each one newly inside its final span. Idempotent within one span; cheap enough for the supervisor's every tick. */
5650
+ readonly check: () => void;
5651
+ }
5652
+ /** Creates the expiring-quota publisher. One per door process, checked on the supervisor's tick. */
5653
+ declare function createQuotaExpiringPublisher(hub: DoorEventHub, deps: {
5654
+ readonly seed: readonly UsageSnapshot[];
5655
+ readonly now: () => number;
5656
+ }): QuotaExpiringPublisher;
5657
+
5574
5658
  /**
5575
5659
  * The rate-limit facts one client read stream event carries, or undefined when the event is not a `rate_limit_event` this module can read: a payload of another type, a payload without the family's own one required field, or one whose `rate_limit_info` does not parse. An envelope the door cannot read is one it knows nothing about, never a failure, exactly as the stream's own parser treats an envelope it cannot read. Exported because the renderers (`frontdoor rc watch`, the web client's twin) narrow the same payload through the same one definition.
5576
5660
  */
@@ -5859,6 +5943,14 @@ interface FrontDoorSupervisorPorts {
5859
5943
  * Reports one tick's session-registry facts to the door's event backbone: the sessions the tick's listing saw (taken before the prune, so a pruned launch's record is still there to name its start time) and the pids the tick's prune removed. The launch lifecycle publisher turns the diff between ticks into source-tagged events; the listing is also this loop's own idle input, so the two read one fact instead of two.
5860
5944
  */
5861
5945
  readonly observeLaunchRegistry: (sessions: readonly FrontDoorSessionSummary[], pruned: readonly number[]) => void;
5946
+ /**
5947
+ * Publishes the supervisor's own state transitions to the door's event backbone: the generation serving, a start failure that ends it, the idle shutdown. Fed the moments the supervisor already lives through, published as they happen rather than at a tick, because these are process facts.
5948
+ */
5949
+ readonly doorHealth: DoorHealthPublisher;
5950
+ /**
5951
+ * Checks the expiring-quota windows against the clock, once per tick: the publisher holds the snapshots the usage source keeps fresh, so this costs arithmetic, never a file read.
5952
+ */
5953
+ readonly checkQuotaExpiry: () => void;
5862
5954
  readonly log: (line: string) => void;
5863
5955
  }
5864
5956
  /** Options for `runFrontDoorSupervisor`. */
@@ -6597,5 +6689,5 @@ interface PrepareClaudeLaunchOptions {
6597
6689
  */
6598
6690
  declare function prepareClaudeLaunch(options: PrepareClaudeLaunchOptions): LaunchPlan;
6599
6691
 
6600
- export { AMBIENT_CREDENTIAL_VARS, CHECK_CREDENTIAL_APPLIES, CONNECT_INTERCEPT_HOST, CONNECT_INTERCEPT_HOSTS, CONNECT_LIMITS, CONTROL_PATH_PREFIX, CategoryClassificationOverlaySchema, CategoryClassificationSchema, CategoryMapSchema, CheckReportJsonSchema, CheckRunInputSchema, CliError, ConfigProfileSchema, CredentialCacheSchema, CredentialSchema, CredentialSourceSchema, DOOR_EVENT_BUFFER_EVENTS, DOOR_EVENT_SOURCE_RC, DirectoryRuleAlreadyExistsError, DirectoryRuleMissingTargetError, DirectoryRuleNotFoundError, DirectoryRuleSchema, DirectoryRulesSchema, DoctorFindingSchema, DoctorRunOutputSchema, DoorEventSchema, DoorEventSourceQuerySchema, EXIT_FAILURE, EXIT_USAGE, EffectiveWindowSchema, EntryValueSchema, FARM_MANIFEST_FILENAME, FrontDoorSessionStatusSchema, FrontDoorSessionsOutputSchema, FrontDoorStartError, FrontDoorStateSchema, FrontDoorStatusOutputSchema, GlobalConfigSchema, HeadroomSocketTargetSchema, HeadroomStartError, IdentityAlreadyExistsError, IdentityNotFoundError, IdentitySchema, InvalidCategoryNameError, InvalidIdentityNameError, InvalidProviderNameError, LAUNCH_EVENT_SOURCE, LaunchLifecycleEventSchema, LaunchRefusedError, LegacyProviderFileError, PROMPT_CACHE_TTL_MS, PlanClassSchema, PoolNameSchema, PoolNotFoundError, PoolPickReportSchema, PoolSchema, PortableConfigSchema, ProfileAlreadyExistsError, ProfileNotFoundError, ProviderAlreadyExistsError, ProviderKindMismatchError, ProviderNotFoundError, ProviderSchema, RC_CONTEXT_USAGE_DETAILS, RC_IDLE_EXPIRY_MS, RC_ORPC_PATH_PREFIX, RC_PENDING_DEADLINE_MS, RC_PERMISSION_MODES, RC_READ_FILE_ENCODINGS, RC_REQUEST_PARSE_CAP_BYTES, RC_SELF_HOST_ENV, RC_SELF_HOST_KEEPALIVE_MS, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE, RC_SELF_HOST_RETENTION_MS, RC_SELF_HOST_SCOPE_LIST, RC_SELF_HOST_WORKER_JWT_TTL_SECONDS, RC_SESSIONS_PATH_PREFIX, RC_STREAM_BACKOFF_MS, RC_WEB_FETCH_ALLOW_PRIVATE_ENV, RC_WEB_FETCH_DEADLINE_MS, RC_WEB_FETCH_MAX_BYTES, RC_WEB_FETCH_MAX_REDIRECTS, ROUTED_PATH_PREFIX, RcLiveRateLimitSchema, RcPermissionModeSchema, RcRateLimitInfoSchema, RcRateLimitWindowSchema, RcStreamEnvelopeSchema, RcStreamEventSchema, UsageError, UsageListOutputSchema, UsageLiveOutputSchema, UsageSnapshotError, UsageSnapshotSchema, UsageWindowsInputSchema, UsageWindowsOutputSchema, WhenSchema, addDirectoryRule, addIdentity, addPool, addProvider, answerRcControlRequest, authenticateRcSessionMcpServer, buildEntryFacts, buildLayoutPaths, buildRcControlRequestPayload, buildRcControlResponsePayload, buildRcEndSessionPayload, buildRcEventWriteBody, buildRcFileSuggestionsPayload, buildRcGetContextUsagePayload, buildRcGetUsagePayload, buildRcInterruptPayload, buildRcKeepAlivePayload, buildRcMarkReadBody, buildRcMcpAuthenticatePayload, buildRcMcpOAuthCallbackUrlPayload, buildRcMcpReconnectPayload, buildRcMcpStatusPayload, buildRcReadFilePayload, buildRcSetModelPayload, buildRcSetPermissionModePayload, buildRcUserMessagePayload, carryOver, checkReportHasWarnings, checkReportToJson, collectCheckReport, collectDoctorReport, collectFrontDoorStatus, collectPoolPick, createControlApiRouter, createDoorApiNodeHandler, createDoorApiRouter, createDoorEventHub, createEventsApiRouter, createLaunchEventPublisher, createLeafCache, createProfile, createRcApiNodeHandler, createRcApiRouter, createRcControlHandler, createRcCredentialStore, createRcEventFanout, createRcLiveUsage, createRcSelfHostSurface, createRcSessionTracker, createRcStreamHub, createSseParser, describeProviderEndpoint, detectAmbientCredential, doorApiAuth, doorApiNodeHandlerOf, effectiveWindow, endRcSession, ensureCa, ensureFrontDoor, ensureHeadroom, evaluateAmbientCredentialGuard, evaluateWhen, fetchThroughWebProxy, formatAmbientCredentialGuardMessage, formatCheckReport, formatDoctorReport, formatFrontDoorStatus, forwardableHeaders, frontDoorApiClient, frontDoorApiLink, frontDoorRcApiClient, frontDoorRcControl, generateCa, getRcSessionContextUsage, getRcSessionMcpStatus, getRcSessionUsage, headroomSocketTarget, identityExists, injectRcUserMessage, interruptRcSession, isIdentityDirectoryName, isInterceptedHost, isPrivateAddress, isRcContextUsageDetail, isRcPermissionMode, isRcReadFileEncoding, lateRcEventDial, lateRcStreamDial, listDirectoryRules, listIdentities, listProfiles, listProviders, listUsageSnapshots, matchBranch, mintLeaf, mintRcSelfHostCredential, observingRoutedRoute, parseConnectTarget, parseRcStreamEnvelope, planOf, prepareClaudeLaunch, prepareLaunch, profileExists, providerExists, rankPool, rcEventWriteResultFromAnswer, rcFanoutOnDoorHub, rcObserverAsPassthrough, rcRateLimitInfoOf, rcSelfHostFromEnv, rcWebFetchAllowsPrivateFromEnv, readActiveIdentity, readDirectoryRules, readFarmManifest, readGlobalConfig, readIdentity, readPools, readProfile, readProvider, readRcSelfHostRecord, readRcSessionFile, readUsageSnapshot, realConnectCertStore, realConnectEffects, realRcControlTransport, realRcEventDial, realRcStreamDial, realRcWebFetch, reconnectRcSessionMcpServer, recoverFarm, recoveryDiagnostics, removeDirectoryRule, removeIdentity, removePool, removeProfile, removeProvider, requirePool, resolveAgentShimHome, resolveClaudeHome, resolveDecisions, resolveLayoutPaths, resolveSupervisorConfig, resyncFarm, runCheck, runDoctor, runFrontDoorSupervisor, runLauncher, runSupervisor, sendRcKeepAlive, servedByPipeline, setAllowAmbientCredential, setDefaultConfigProfile, setGlobalDefaultProfile, setIdentityCredential, setPool, setProfileCategories, setProfileEntries, setProfileLaunchFlags, setProfileMetadata, setRcSessionModel, setRcSessionPermissionMode, snapshotPath, spawnClaude, startConnectServer, submitRcSessionMcpOAuthCallbackUrl, suggestRcSessionFiles, teleportRcSession, topLevelNames, updateDirectoryRule, updateProvider, useIdentity, writeDirectoryRules };
6601
- export type { AddDirectoryRuleOptions, AddProviderInput, AmbientCredentialDetection, AmbientCredentialGuardResult, AmbientCredentialVar, BuildEntryFactsParams, CaMaterial, Candidate, CarryOverParams, CarryOverResult, CategoryMap, CheckReport, CheckReportJson, CollectCheckReportParams, CollectDoctorReportParams, CompiledRule, ConditionContext, ConfigProfile, ConnectCertStore, ConnectEffects, ConnectLimits, ConnectLocalSurface, ConnectServerConfig, ConnectServerHandle, ConnectTarget, ControlApiClient, ControlApiDeps, ControlApiRouter, Credential, CredentialSource, Decision, Diagnostic, DirectoryRule, DirectoryRules, DoctorReport, DoorApiClient, DoorApiContext, DoorApiDeps, DoorApiRouter, DoorEvent, DoorEventHub, DoorEventPublisher, DoorEventStream, DoorEventsApiDeps, EffectiveWindow, EliminatedRule, EnsureFrontDoorPorts, EnsureHeadroomPorts, EntryFact, EntryFacts, EntryValue, EvaluateAmbientCredentialGuardParams, FlattenedCascade, FrontDoorRcControl, FrontDoorSessionStatus, FrontDoorStatus, FrontDoorSupervisorPorts, GlobalConfig, HeadroomSupervisorConfig, Identity, IdentityCredentialChange, IdentityListEntry, IdentityListing, InjectedCredential, LaunchEventPublisher, LaunchLifecycleEvent, LaunchPlan, Layer, LayerId, LayoutPaths, LeafCert, NestedContribution, PlanClass, Pool, PoolMember, PoolPickReport, PoolRanking, PortableConfig, PrepareClaudeLaunchOptions, PrepareLaunchParams, ProfileListEntry, Provider, ProviderListEntry, RankPoolInput, RcAnswerDecision, RcAnswerDeps, RcApiClient, RcApiDeps, RcApiRouter, RcContextUsageDetail, RcControlAnswer, RcControlHandlerDeps, RcControlRequestDeps, RcControlTransport, RcCredentialStore, RcDialAnswer, RcDialTarget, RcEventDial, RcEventFanout, RcEventWriteResult, RcExchangeObserver, RcInjectDeps, RcLiveRateLimit, RcLiveUsage, RcLiveUsageDeps, RcObservedCredential, RcObservedRequest, RcPendingRequestSummary, RcPermissionMode, RcPresenceAnswer, RcRateLimitInfo, RcRateLimitWindow, RcReadFileEncoding, RcReadFileOptions, RcSelfHostCredentialRecord, RcSelfHostDeps, RcSelfHostMintResult, RcSelfHostSurface, RcSessionStatus, RcSessionSummary, RcSessionTracker, RcSessionTrackerDeps, RcStreamAnswer, RcStreamDial, RcStreamEnvelope, RcStreamEvent, RcStreamHub, RcStreamHubDeps, RcWebFetchDeps, RcWebFetchHop, RcWebFetchOutcome, RcWebFetcher, RcWorkerFact, RcWriteHeaders, RecoverFarmParams, RecoveryResult, ResolveDecisionsInput, ResolvedState, ResyncFarmParams, ResyncFarmResult, RunCheckParams, RunDoctorParams, RunFrontDoorSupervisorOptions, RunLauncherParams, RunSupervisorOptions, SpawnClaudeParams, SseParsedEvent, StickyPick, SupervisorPorts, UnreadableIdentityListEntry, UpdateDirectoryRuleOptions, UpdateProviderInput, UsageReadFs, UsageSnapshot, WhenCondition, WhenEvaluation };
6692
+ export { AMBIENT_CREDENTIAL_VARS, CHECK_CREDENTIAL_APPLIES, CONNECT_INTERCEPT_HOST, CONNECT_INTERCEPT_HOSTS, CONNECT_LIMITS, CONTROL_PATH_PREFIX, CategoryClassificationOverlaySchema, CategoryClassificationSchema, CategoryMapSchema, CheckReportJsonSchema, CheckRunInputSchema, CliError, ConfigProfileSchema, CredentialCacheSchema, CredentialSchema, CredentialSourceSchema, DOOR_EVENT_BUFFER_EVENTS, DOOR_EVENT_SOURCE_RC, DOOR_HEALTH_EVENT_SOURCE, DirectoryRuleAlreadyExistsError, DirectoryRuleMissingTargetError, DirectoryRuleNotFoundError, DirectoryRuleSchema, DirectoryRulesSchema, DoctorFindingSchema, DoctorRunOutputSchema, DoorEventSchema, DoorEventSourceQuerySchema, DoorHealthEventSchema, EXIT_FAILURE, EXIT_USAGE, EffectiveWindowSchema, EntryValueSchema, FARM_MANIFEST_FILENAME, FrontDoorSessionStatusSchema, FrontDoorSessionsOutputSchema, FrontDoorStartError, FrontDoorStateSchema, FrontDoorStatusOutputSchema, GlobalConfigSchema, HeadroomSocketTargetSchema, HeadroomStartError, IdentityAlreadyExistsError, IdentityNotFoundError, IdentitySchema, InvalidCategoryNameError, InvalidIdentityNameError, InvalidProviderNameError, LAUNCH_EVENT_SOURCE, LaunchLifecycleEventSchema, LaunchRefusedError, LegacyProviderFileError, PROMPT_CACHE_TTL_MS, PlanClassSchema, PoolNameSchema, PoolNotFoundError, PoolPickReportSchema, PoolSchema, PortableConfigSchema, ProfileAlreadyExistsError, ProfileNotFoundError, ProviderAlreadyExistsError, ProviderKindMismatchError, ProviderNotFoundError, ProviderSchema, QUOTA_EXPIRING_EVENT_SOURCE, QuotaExpiringEventSchema, RC_CONTEXT_USAGE_DETAILS, RC_IDLE_EXPIRY_MS, RC_ORPC_PATH_PREFIX, RC_PENDING_DEADLINE_MS, RC_PERMISSION_MODES, RC_READ_FILE_ENCODINGS, RC_REQUEST_PARSE_CAP_BYTES, RC_SELF_HOST_ENV, RC_SELF_HOST_KEEPALIVE_MS, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE, RC_SELF_HOST_RETENTION_MS, RC_SELF_HOST_SCOPE_LIST, RC_SELF_HOST_WORKER_JWT_TTL_SECONDS, RC_SESSIONS_PATH_PREFIX, RC_STREAM_BACKOFF_MS, RC_WEB_FETCH_ALLOW_PRIVATE_ENV, RC_WEB_FETCH_DEADLINE_MS, RC_WEB_FETCH_MAX_BYTES, RC_WEB_FETCH_MAX_REDIRECTS, ROUTED_PATH_PREFIX, RcLiveRateLimitSchema, RcPermissionModeSchema, RcRateLimitInfoSchema, RcRateLimitWindowSchema, RcStreamEnvelopeSchema, RcStreamEventSchema, USAGE_EVENT_SOURCE, UsageError, UsageListOutputSchema, UsageLiveOutputSchema, UsageSnapshotError, UsageSnapshotSchema, UsageWindowsInputSchema, UsageWindowsOutputSchema, WhenSchema, addDirectoryRule, addIdentity, addPool, addProvider, answerRcControlRequest, authenticateRcSessionMcpServer, buildEntryFacts, buildLayoutPaths, buildRcControlRequestPayload, buildRcControlResponsePayload, buildRcEndSessionPayload, buildRcEventWriteBody, buildRcFileSuggestionsPayload, buildRcGetContextUsagePayload, buildRcGetUsagePayload, buildRcInterruptPayload, buildRcKeepAlivePayload, buildRcMarkReadBody, buildRcMcpAuthenticatePayload, buildRcMcpOAuthCallbackUrlPayload, buildRcMcpReconnectPayload, buildRcMcpStatusPayload, buildRcReadFilePayload, buildRcSetModelPayload, buildRcSetPermissionModePayload, buildRcUserMessagePayload, carryOver, checkReportHasWarnings, checkReportToJson, collectCheckReport, collectDoctorReport, collectFrontDoorStatus, collectPoolPick, createControlApiRouter, createDoorApiNodeHandler, createDoorApiRouter, createDoorEventHub, createDoorHealthPublisher, createEventsApiRouter, createLaunchEventPublisher, createLeafCache, createProfile, createQuotaExpiringPublisher, createRcApiNodeHandler, createRcApiRouter, createRcControlHandler, createRcCredentialStore, createRcEventFanout, createRcLiveUsage, createRcSelfHostSurface, createRcSessionTracker, createRcStreamHub, createSseParser, describeProviderEndpoint, detectAmbientCredential, doorApiAuth, doorApiNodeHandlerOf, effectiveWindow, endRcSession, ensureCa, ensureFrontDoor, ensureHeadroom, evaluateAmbientCredentialGuard, evaluateWhen, fetchThroughWebProxy, formatAmbientCredentialGuardMessage, formatCheckReport, formatDoctorReport, formatFrontDoorStatus, forwardableHeaders, frontDoorApiClient, frontDoorApiLink, frontDoorRcApiClient, frontDoorRcControl, generateCa, getRcSessionContextUsage, getRcSessionMcpStatus, getRcSessionUsage, headroomSocketTarget, identityExists, injectRcUserMessage, interruptRcSession, isIdentityDirectoryName, isInterceptedHost, isPrivateAddress, isRcContextUsageDetail, isRcPermissionMode, isRcReadFileEncoding, lateRcEventDial, lateRcStreamDial, listDirectoryRules, listIdentities, listProfiles, listProviders, listUsageSnapshots, matchBranch, mintLeaf, mintRcSelfHostCredential, observingRoutedRoute, parseConnectTarget, parseRcStreamEnvelope, planOf, prepareClaudeLaunch, prepareLaunch, profileExists, providerExists, rankPool, rcEventWriteResultFromAnswer, rcFanoutOnDoorHub, rcObserverAsPassthrough, rcRateLimitInfoOf, rcSelfHostFromEnv, rcWebFetchAllowsPrivateFromEnv, readActiveIdentity, readDirectoryRules, readFarmManifest, readGlobalConfig, readIdentity, readPools, readProfile, readProvider, readRcSelfHostRecord, readRcSessionFile, readUsageSnapshot, realConnectCertStore, realConnectEffects, realRcControlTransport, realRcEventDial, realRcStreamDial, realRcWebFetch, reconnectRcSessionMcpServer, recoverFarm, recoveryDiagnostics, removeDirectoryRule, removeIdentity, removePool, removeProfile, removeProvider, requirePool, resolveAgentShimHome, resolveClaudeHome, resolveDecisions, resolveLayoutPaths, resolveSupervisorConfig, resyncFarm, runCheck, runDoctor, runFrontDoorSupervisor, runLauncher, runSupervisor, sendRcKeepAlive, servedByPipeline, setAllowAmbientCredential, setDefaultConfigProfile, setGlobalDefaultProfile, setIdentityCredential, setPool, setProfileCategories, setProfileEntries, setProfileLaunchFlags, setProfileMetadata, setRcSessionModel, setRcSessionPermissionMode, snapshotPath, spawnClaude, startConnectServer, submitRcSessionMcpOAuthCallbackUrl, suggestRcSessionFiles, teleportRcSession, topLevelNames, updateDirectoryRule, updateProvider, useIdentity, writeDirectoryRules };
6693
+ export type { AddDirectoryRuleOptions, AddProviderInput, AmbientCredentialDetection, AmbientCredentialGuardResult, AmbientCredentialVar, BuildEntryFactsParams, CaMaterial, Candidate, CarryOverParams, CarryOverResult, CategoryMap, CheckReport, CheckReportJson, CollectCheckReportParams, CollectDoctorReportParams, CompiledRule, ConditionContext, ConfigProfile, ConnectCertStore, ConnectEffects, ConnectLimits, ConnectLocalSurface, ConnectServerConfig, ConnectServerHandle, ConnectTarget, ControlApiClient, ControlApiDeps, ControlApiRouter, Credential, CredentialSource, Decision, Diagnostic, DirectoryRule, DirectoryRules, DoctorReport, DoorApiClient, DoorApiContext, DoorApiDeps, DoorApiRouter, DoorEvent, DoorEventHub, DoorEventPublisher, DoorEventStream, DoorEventsApiDeps, DoorHealthEvent, DoorHealthPublisher, EffectiveWindow, EliminatedRule, EnsureFrontDoorPorts, EnsureHeadroomPorts, EntryFact, EntryFacts, EntryValue, EvaluateAmbientCredentialGuardParams, FlattenedCascade, FrontDoorRcControl, FrontDoorSessionStatus, FrontDoorStatus, FrontDoorSupervisorPorts, GlobalConfig, HeadroomSupervisorConfig, Identity, IdentityCredentialChange, IdentityListEntry, IdentityListing, InjectedCredential, LaunchEventPublisher, LaunchLifecycleEvent, LaunchPlan, Layer, LayerId, LayoutPaths, LeafCert, NestedContribution, PlanClass, Pool, PoolMember, PoolPickReport, PoolRanking, PortableConfig, PrepareClaudeLaunchOptions, PrepareLaunchParams, ProfileListEntry, Provider, ProviderListEntry, QuotaExpiringEvent, QuotaExpiringPublisher, RankPoolInput, RcAnswerDecision, RcAnswerDeps, RcApiClient, RcApiDeps, RcApiRouter, RcContextUsageDetail, RcControlAnswer, RcControlHandlerDeps, RcControlRequestDeps, RcControlTransport, RcCredentialStore, RcDialAnswer, RcDialTarget, RcEventDial, RcEventFanout, RcEventWriteResult, RcExchangeObserver, RcInjectDeps, RcLiveRateLimit, RcLiveUsage, RcLiveUsageDeps, RcObservedCredential, RcObservedRequest, RcPendingRequestSummary, RcPermissionMode, RcPresenceAnswer, RcRateLimitInfo, RcRateLimitWindow, RcReadFileEncoding, RcReadFileOptions, RcSelfHostCredentialRecord, RcSelfHostDeps, RcSelfHostMintResult, RcSelfHostSurface, RcSessionStatus, RcSessionSummary, RcSessionTracker, RcSessionTrackerDeps, RcStreamAnswer, RcStreamDial, RcStreamEnvelope, RcStreamEvent, RcStreamHub, RcStreamHubDeps, RcWebFetchDeps, RcWebFetchHop, RcWebFetchOutcome, RcWebFetcher, RcWorkerFact, RcWriteHeaders, RecoverFarmParams, RecoveryResult, ResolveDecisionsInput, ResolvedState, ResyncFarmParams, ResyncFarmResult, RunCheckParams, RunDoctorParams, RunFrontDoorSupervisorOptions, RunLauncherParams, RunSupervisorOptions, SpawnClaudeParams, SseParsedEvent, StickyPick, SupervisorPorts, UnreadableIdentityListEntry, UpdateDirectoryRuleOptions, UpdateProviderInput, UsageChangeEvent, UsageReadFs, UsageSnapshot, WhenCondition, WhenEvaluation };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-shim",
3
- "version": "8.30.0",
3
+ "version": "8.31.0",
4
4
  "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.",
5
5
  "license": "MIT",
6
6
  "author": "Joseph Mearman <joseph@mearman.co.uk>",