agent-shim 8.25.0 → 8.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -114,11 +114,15 @@ __export(index_exports, {
114
114
  RC_WEB_FETCH_MAX_BYTES: () => RC_WEB_FETCH_MAX_BYTES,
115
115
  RC_WEB_FETCH_MAX_REDIRECTS: () => RC_WEB_FETCH_MAX_REDIRECTS,
116
116
  ROUTED_PATH_PREFIX: () => ROUTED_PATH_PREFIX,
117
+ RcLiveRateLimitSchema: () => RcLiveRateLimitSchema,
117
118
  RcPermissionModeSchema: () => RcPermissionModeSchema,
119
+ RcRateLimitInfoSchema: () => RcRateLimitInfoSchema,
120
+ RcRateLimitWindowSchema: () => RcRateLimitWindowSchema,
118
121
  RcStreamEnvelopeSchema: () => RcStreamEnvelopeSchema,
119
122
  RcStreamEventSchema: () => RcStreamEventSchema,
120
123
  UsageError: () => UsageError,
121
124
  UsageListOutputSchema: () => UsageListOutputSchema,
125
+ UsageLiveOutputSchema: () => UsageLiveOutputSchema,
122
126
  UsageSnapshotError: () => UsageSnapshotError,
123
127
  UsageSnapshotSchema: () => UsageSnapshotSchema,
124
128
  UsageWindowsInputSchema: () => UsageWindowsInputSchema,
@@ -170,6 +174,7 @@ __export(index_exports, {
170
174
  createRcControlHandler: () => createRcControlHandler,
171
175
  createRcCredentialStore: () => createRcCredentialStore,
172
176
  createRcEventFanout: () => createRcEventFanout,
177
+ createRcLiveUsage: () => createRcLiveUsage,
173
178
  createRcSelfHostSurface: () => createRcSelfHostSurface,
174
179
  createRcSessionTracker: () => createRcSessionTracker,
175
180
  createRcStreamHub: () => createRcStreamHub,
@@ -231,6 +236,7 @@ __export(index_exports, {
231
236
  rcEventWriteResultFromAnswer: () => rcEventWriteResultFromAnswer,
232
237
  rcFanoutOnDoorHub: () => rcFanoutOnDoorHub,
233
238
  rcObserverAsPassthrough: () => rcObserverAsPassthrough,
239
+ rcRateLimitInfoOf: () => rcRateLimitInfoOf,
234
240
  rcSelfHostFromEnv: () => rcSelfHostFromEnv,
235
241
  rcWebFetchAllowsPrivateFromEnv: () => rcWebFetchAllowsPrivateFromEnv,
236
242
  readActiveIdentity: () => readActiveIdentity,
@@ -5373,6 +5379,35 @@ var RcStreamEventSchema = import_zod4.z.strictObject({
5373
5379
  session: import_zod4.z.string(),
5374
5380
  envelope: RcStreamEnvelopeSchema
5375
5381
  });
5382
+ var RcRateLimitWindowSchema = import_zod4.z.looseObject({
5383
+ /** The fraction of the window used, usually between 0 and 1, above 1 when usage legitimately runs past the window's cap (the CLI's own field description states both). */
5384
+ utilization: import_zod4.z.number().optional(),
5385
+ /** When the window resets, in unix epoch seconds: the unit is the CLI's own field description, stated in the 2.1.289 bundle's schema. */
5386
+ resetsAt: import_zod4.z.number().optional()
5387
+ });
5388
+ var RcRateLimitInfoSchema = import_zod4.z.looseObject({
5389
+ /** The limiting window's own status (`allowed`, `allowed_warning`, `rejected`), asserted only as a string because the vocabulary grows with the CLI. */
5390
+ status: import_zod4.z.string(),
5391
+ /** When the limiting window resets, in unix epoch seconds. */
5392
+ resetsAt: import_zod4.z.number().optional(),
5393
+ /** Which window the top-level fields describe (`five_hour`, `seven_day`, and kin), the payload's own name for it. */
5394
+ rateLimitType: import_zod4.z.string().optional(),
5395
+ /** The fraction of the limiting window used, on the same scale the per-window utilizations carry. */
5396
+ utilization: import_zod4.z.number().optional(),
5397
+ /** Whether usage beyond the plan (extra usage) is currently covering the overflow, the payload's own flag for it. */
5398
+ isUsingOverage: import_zod4.z.boolean().optional(),
5399
+ /** The overage's own status, the same vocabulary the limiting window's `status` carries. */
5400
+ overageStatus: import_zod4.z.string().optional(),
5401
+ /** When the overage window resets, in unix epoch seconds. */
5402
+ overageResetsAt: import_zod4.z.number().optional(),
5403
+ /** Each subscription window the account's response headers carried: the session (five-hour), weekly (seven-day), and overage-included weekly windows, each present only when the account's responses carry it. */
5404
+ unifiedWindows: import_zod4.z.looseObject({ five_hour: RcRateLimitWindowSchema.optional(), seven_day: RcRateLimitWindowSchema.optional(), seven_day_overage_included: RcRateLimitWindowSchema.optional() }).optional()
5405
+ });
5406
+ var RcLiveRateLimitSchema = import_zod4.z.strictObject({
5407
+ session: import_zod4.z.string(),
5408
+ observedAt: import_zod4.z.number(),
5409
+ rateLimit: RcRateLimitInfoSchema
5410
+ });
5376
5411
  var RcSessionQuerySchema = import_zod4.z.strictObject({
5377
5412
  session: import_zod4.z.string().min(1).optional()
5378
5413
  });
@@ -9983,6 +10018,12 @@ var UsageWindowsOutputSchema = import_zod19.z.strictObject({
9983
10018
  fiveHour: EffectiveWindowSchema.optional(),
9984
10019
  sevenDay: EffectiveWindowSchema.optional()
9985
10020
  });
10021
+ var UsageLiveOutputSchema = import_zod19.z.strictObject({
10022
+ /** The freshest observation the door holds, never narrowed by the read's session filter because it is the door's single latest statement of the account's quota; absent while no rate_limit_event has been filed at all. */
10023
+ latest: RcLiveRateLimitSchema.optional(),
10024
+ /** One observation per session whose stream has filed a rate_limit_event this door generation. */
10025
+ sessions: import_zod19.z.readonly(import_zod19.z.array(RcLiveRateLimitSchema))
10026
+ });
9986
10027
  var FrontDoorSessionStatusSchema = import_zod19.z.strictObject({
9987
10028
  pid: import_zod19.z.int().positive(),
9988
10029
  startedAt: import_zod19.z.number(),
@@ -10097,6 +10138,16 @@ function createControlApiRouter(deps) {
10097
10138
  ...unified?.fiveHour === void 0 ? {} : { fiveHour: effectiveWindow(unified.fiveHour, now) },
10098
10139
  ...unified?.sevenDay === void 0 ? {} : { sevenDay: effectiveWindow(unified.sevenDay, now) }
10099
10140
  };
10141
+ }),
10142
+ live: authed.input(RcSessionQuerySchema).output(UsageLiveOutputSchema).handler(({ input }) => {
10143
+ const sessions = deps.liveRateLimits(input.session);
10144
+ if (input.session !== void 0 && sessions.length === 0) {
10145
+ if (deps.list().some((session) => session.id === input.session)) {
10146
+ throw new import_client3.ORPCError("NOT_FOUND", { message: `session ${input.session} has filed no rate_limit_event on its stream yet: the worker emits one only once a turn has completed, so retry after this session's next turn` });
10147
+ }
10148
+ throw new import_client3.ORPCError("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
10149
+ }
10150
+ return { latest: deps.latestRateLimit(), sessions };
10100
10151
  })
10101
10152
  },
10102
10153
  frontdoor: {
@@ -10317,6 +10368,42 @@ function createLaunchEventPublisher(hub, now) {
10317
10368
  };
10318
10369
  }
10319
10370
 
10371
+ // src/frontdoor/rcLiveUsage.ts
10372
+ var RC_RATE_LIMIT_EVENT_TYPE = "rate_limit_event";
10373
+ function isRecord5(value) {
10374
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10375
+ }
10376
+ function rcRateLimitInfoOf(event) {
10377
+ const payload = event.envelope.payload;
10378
+ if (!isRecord5(payload) || payload.type !== RC_RATE_LIMIT_EVENT_TYPE) {
10379
+ return void 0;
10380
+ }
10381
+ if (!isRecord5(payload.rate_limit_info)) {
10382
+ return void 0;
10383
+ }
10384
+ const parsed = RcRateLimitInfoSchema.safeParse(payload.rate_limit_info);
10385
+ return parsed.success ? parsed.data : void 0;
10386
+ }
10387
+ function createRcLiveUsage(deps) {
10388
+ const observed = /* @__PURE__ */ new Map();
10389
+ deps.hub.subscribe([DOOR_EVENT_SOURCE_RC], (event) => {
10390
+ const stream = RcStreamEventSchema.safeParse(event.payload);
10391
+ if (!stream.success) {
10392
+ return;
10393
+ }
10394
+ const rateLimit = rcRateLimitInfoOf(stream.data);
10395
+ if (rateLimit === void 0) {
10396
+ return;
10397
+ }
10398
+ observed.set(stream.data.session, { session: stream.data.session, observedAt: deps.now(), rateLimit });
10399
+ });
10400
+ const sorted = () => [...observed.values()].sort((left, right) => left.observedAt - right.observedAt || (left.session < right.session ? -1 : 1));
10401
+ return {
10402
+ liveOf: (sessionId) => sorted().filter((entry) => sessionId === void 0 || entry.session === sessionId),
10403
+ latestOf: () => sorted().at(-1)
10404
+ };
10405
+ }
10406
+
10320
10407
  // src/frontdoor/rcStream.ts
10321
10408
  var RC_STREAM_EVENT_NAME = "client_event";
10322
10409
  var SSE_BYTE_ORDER_MARK = 65279;
@@ -10379,7 +10466,7 @@ function createSseParser() {
10379
10466
  }
10380
10467
  };
10381
10468
  }
10382
- function isRecord5(value) {
10469
+ function isRecord6(value) {
10383
10470
  return typeof value === "object" && value !== null && !Array.isArray(value);
10384
10471
  }
10385
10472
  function sequenceNumOf(value) {
@@ -10401,7 +10488,7 @@ function parseRcStreamEnvelope(parsed) {
10401
10488
  } catch {
10402
10489
  return void 0;
10403
10490
  }
10404
- if (!isRecord5(data)) {
10491
+ if (!isRecord6(data)) {
10405
10492
  return void 0;
10406
10493
  }
10407
10494
  const eventType = data.event_type;
@@ -10632,7 +10719,7 @@ function createRcStreamHub(deps) {
10632
10719
  // src/frontdoor/rcSelfHostEndpoints.ts
10633
10720
  var RC_SOURCE_WORKER = "worker";
10634
10721
  var RC_SOURCE_CLIENT = "client";
10635
- function isRecord6(value) {
10722
+ function isRecord7(value) {
10636
10723
  return typeof value === "object" && value !== null && !Array.isArray(value);
10637
10724
  }
10638
10725
  function parseJsonObject2(body) {
@@ -10642,7 +10729,7 @@ function parseJsonObject2(body) {
10642
10729
  } catch {
10643
10730
  return void 0;
10644
10731
  }
10645
- return isRecord6(parsed) ? parsed : void 0;
10732
+ return isRecord7(parsed) ? parsed : void 0;
10646
10733
  }
10647
10734
  function nonEmptyString2(record, field) {
10648
10735
  const value = record === void 0 ? void 0 : record[field];
@@ -10716,7 +10803,7 @@ async function serveRcClientChannels(ctx, tail, method, maxBatchEvents) {
10716
10803
  }
10717
10804
  const results = [];
10718
10805
  for (const event of events) {
10719
- if (!isRecord6(event) || !isRecord6(event.payload)) {
10806
+ if (!isRecord7(event) || !isRecord7(event.payload)) {
10720
10807
  await ctx.answerJson(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a teleport write is an object carrying one payload object" } });
10721
10808
  return true;
10722
10809
  }
@@ -11086,7 +11173,7 @@ var RC_SELF_HOST_WORKER_EPOCH = 1;
11086
11173
  var RC_STREAM_EVENT_NAME2 = "client_event";
11087
11174
  var CONFLICT_REASON_HEADER2 = "x-ccr-conflict-reason";
11088
11175
  var CONFLICT_REASON_EPOCH_STALE = "epoch_stale";
11089
- function isRecord7(value) {
11176
+ function isRecord8(value) {
11090
11177
  return typeof value === "object" && value !== null && !Array.isArray(value);
11091
11178
  }
11092
11179
  function isWebSearchRefusal(value) {
@@ -11170,7 +11257,7 @@ function parseJsonObject3(body) {
11170
11257
  } catch {
11171
11258
  return void 0;
11172
11259
  }
11173
- return isRecord7(parsed) ? parsed : void 0;
11260
+ return isRecord8(parsed) ? parsed : void 0;
11174
11261
  }
11175
11262
  function mintWorkerJwt(randomToken, issuedAt) {
11176
11263
  const encode = (value) => Buffer.from(JSON.stringify(value), "utf8").toString("base64url");
@@ -11417,7 +11504,7 @@ data: ${JSON.stringify(envelope)}
11417
11504
  if (status !== void 0) {
11418
11505
  session.workerStatus = status;
11419
11506
  }
11420
- if (isRecord7(body?.external_metadata)) {
11507
+ if (isRecord8(body?.external_metadata)) {
11421
11508
  session.externalMetadata = body.external_metadata;
11422
11509
  }
11423
11510
  await answerJson2(response, HTTP_STATUS.ok, {});
@@ -11447,7 +11534,7 @@ data: ${JSON.stringify(envelope)}
11447
11534
  }
11448
11535
  const results = [];
11449
11536
  for (const event of events) {
11450
- if (!isRecord7(event) || !isRecord7(event.payload)) {
11537
+ if (!isRecord8(event) || !isRecord8(event.payload)) {
11451
11538
  await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a batch is an object carrying one payload object" } });
11452
11539
  return;
11453
11540
  }
@@ -11480,7 +11567,7 @@ data: ${JSON.stringify(envelope)}
11480
11567
  return;
11481
11568
  }
11482
11569
  for (const event of events) {
11483
- if (isRecord7(event)) {
11570
+ if (isRecord8(event)) {
11484
11571
  session.internalEvents.push({ eventId: deps.newUuid(), body: event });
11485
11572
  }
11486
11573
  }
@@ -11576,7 +11663,7 @@ data: ${JSON.stringify(envelope)}
11576
11663
  }
11577
11664
  const results = [];
11578
11665
  for (const event of events) {
11579
- if (!isRecord7(event) || !isRecord7(event.payload)) {
11666
+ if (!isRecord8(event) || !isRecord8(event.payload)) {
11580
11667
  await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a write is an object carrying one payload object" } });
11581
11668
  return;
11582
11669
  }
@@ -11770,7 +11857,7 @@ var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
11770
11857
  var RC_SELF_HOST_RECORD_FILE = "credential.json";
11771
11858
  var SELF_HOST_EMAIL = "selfhost@agent-shim.invalid";
11772
11859
  var SELF_HOST_SUBSCRIPTION_TYPE = "max";
11773
- function isRecord8(value) {
11860
+ function isRecord9(value) {
11774
11861
  return typeof value === "object" && value !== null && !Array.isArray(value);
11775
11862
  }
11776
11863
  function readJsonObject(fs12, file) {
@@ -11784,7 +11871,7 @@ function readJsonObject(fs12, file) {
11784
11871
  } catch {
11785
11872
  return void 0;
11786
11873
  }
11787
- return isRecord8(parsed) ? parsed : void 0;
11874
+ return isRecord9(parsed) ? parsed : void 0;
11788
11875
  }
11789
11876
  function readRcSelfHostRecord(fs12, frontdoorDir) {
11790
11877
  const parsed = readJsonObject(fs12, import_node_path28.default.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
@@ -11808,7 +11895,7 @@ function mintRcSelfHostCredential(deps) {
11808
11895
  const recordFile = import_node_path28.default.join(recordDir, RC_SELF_HOST_RECORD_FILE);
11809
11896
  const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
11810
11897
  const existingCredentials = readJsonObject(deps.fs, credentialsFile);
11811
- const existingOauth = isRecord8(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
11898
+ const existingOauth = isRecord9(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
11812
11899
  const existingToken = typeof existingOauth?.accessToken === "string" && existingOauth.accessToken !== "" ? existingOauth.accessToken : void 0;
11813
11900
  const existingIsOwn = existingToken !== void 0 && previousRecord?.accessToken === existingToken;
11814
11901
  if (existingToken !== void 0 && !existingIsOwn && !deps.force) {
@@ -11825,7 +11912,7 @@ function mintRcSelfHostCredential(deps) {
11825
11912
  deps.fs.writeFilePrivate(credentialsFile, `${JSON.stringify({ ...existingCredentials, claudeAiOauth: { accessToken, refreshToken, expiresAt: null, scopes: [...RC_SELF_HOST_SCOPE_LIST], subscriptionType: SELF_HOST_SUBSCRIPTION_TYPE, rateLimitTier: null } }, null, 2)}
11826
11913
  `);
11827
11914
  const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
11828
- const existingBlock = (value) => isRecord8(value) ? value : {};
11915
+ const existingBlock = (value) => isRecord9(value) ? value : {};
11829
11916
  deps.fs.writeFilePrivate(claudeJsonFile, `${JSON.stringify({
11830
11917
  ...claudeJson,
11831
11918
  oauthAccount: {
@@ -12024,7 +12111,7 @@ var import_node_path30 = __toESM(require("node:path"), 1);
12024
12111
  // package.json
12025
12112
  var package_default = {
12026
12113
  name: "agent-shim",
12027
- version: "8.25.0",
12114
+ version: "8.26.0",
12028
12115
  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.",
12029
12116
  license: "MIT",
12030
12117
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -13288,11 +13375,15 @@ function prepareClaudeLaunch(options) {
13288
13375
  RC_WEB_FETCH_MAX_BYTES,
13289
13376
  RC_WEB_FETCH_MAX_REDIRECTS,
13290
13377
  ROUTED_PATH_PREFIX,
13378
+ RcLiveRateLimitSchema,
13291
13379
  RcPermissionModeSchema,
13380
+ RcRateLimitInfoSchema,
13381
+ RcRateLimitWindowSchema,
13292
13382
  RcStreamEnvelopeSchema,
13293
13383
  RcStreamEventSchema,
13294
13384
  UsageError,
13295
13385
  UsageListOutputSchema,
13386
+ UsageLiveOutputSchema,
13296
13387
  UsageSnapshotError,
13297
13388
  UsageSnapshotSchema,
13298
13389
  UsageWindowsInputSchema,
@@ -13344,6 +13435,7 @@ function prepareClaudeLaunch(options) {
13344
13435
  createRcControlHandler,
13345
13436
  createRcCredentialStore,
13346
13437
  createRcEventFanout,
13438
+ createRcLiveUsage,
13347
13439
  createRcSelfHostSurface,
13348
13440
  createRcSessionTracker,
13349
13441
  createRcStreamHub,
@@ -13405,6 +13497,7 @@ function prepareClaudeLaunch(options) {
13405
13497
  rcEventWriteResultFromAnswer,
13406
13498
  rcFanoutOnDoorHub,
13407
13499
  rcObserverAsPassthrough,
13500
+ rcRateLimitInfoOf,
13408
13501
  rcSelfHostFromEnv,
13409
13502
  rcWebFetchAllowsPrivateFromEnv,
13410
13503
  readActiveIdentity,
package/dist/index.mjs CHANGED
@@ -5074,6 +5074,35 @@ var RcStreamEventSchema = z4.strictObject({
5074
5074
  session: z4.string(),
5075
5075
  envelope: RcStreamEnvelopeSchema
5076
5076
  });
5077
+ var RcRateLimitWindowSchema = z4.looseObject({
5078
+ /** The fraction of the window used, usually between 0 and 1, above 1 when usage legitimately runs past the window's cap (the CLI's own field description states both). */
5079
+ utilization: z4.number().optional(),
5080
+ /** When the window resets, in unix epoch seconds: the unit is the CLI's own field description, stated in the 2.1.289 bundle's schema. */
5081
+ resetsAt: z4.number().optional()
5082
+ });
5083
+ var RcRateLimitInfoSchema = z4.looseObject({
5084
+ /** The limiting window's own status (`allowed`, `allowed_warning`, `rejected`), asserted only as a string because the vocabulary grows with the CLI. */
5085
+ status: z4.string(),
5086
+ /** When the limiting window resets, in unix epoch seconds. */
5087
+ resetsAt: z4.number().optional(),
5088
+ /** Which window the top-level fields describe (`five_hour`, `seven_day`, and kin), the payload's own name for it. */
5089
+ rateLimitType: z4.string().optional(),
5090
+ /** The fraction of the limiting window used, on the same scale the per-window utilizations carry. */
5091
+ utilization: z4.number().optional(),
5092
+ /** Whether usage beyond the plan (extra usage) is currently covering the overflow, the payload's own flag for it. */
5093
+ isUsingOverage: z4.boolean().optional(),
5094
+ /** The overage's own status, the same vocabulary the limiting window's `status` carries. */
5095
+ overageStatus: z4.string().optional(),
5096
+ /** When the overage window resets, in unix epoch seconds. */
5097
+ overageResetsAt: z4.number().optional(),
5098
+ /** Each subscription window the account's response headers carried: the session (five-hour), weekly (seven-day), and overage-included weekly windows, each present only when the account's responses carry it. */
5099
+ unifiedWindows: z4.looseObject({ five_hour: RcRateLimitWindowSchema.optional(), seven_day: RcRateLimitWindowSchema.optional(), seven_day_overage_included: RcRateLimitWindowSchema.optional() }).optional()
5100
+ });
5101
+ var RcLiveRateLimitSchema = z4.strictObject({
5102
+ session: z4.string(),
5103
+ observedAt: z4.number(),
5104
+ rateLimit: RcRateLimitInfoSchema
5105
+ });
5077
5106
  var RcSessionQuerySchema = z4.strictObject({
5078
5107
  session: z4.string().min(1).optional()
5079
5108
  });
@@ -9684,6 +9713,12 @@ var UsageWindowsOutputSchema = z19.strictObject({
9684
9713
  fiveHour: EffectiveWindowSchema.optional(),
9685
9714
  sevenDay: EffectiveWindowSchema.optional()
9686
9715
  });
9716
+ var UsageLiveOutputSchema = z19.strictObject({
9717
+ /** The freshest observation the door holds, never narrowed by the read's session filter because it is the door's single latest statement of the account's quota; absent while no rate_limit_event has been filed at all. */
9718
+ latest: RcLiveRateLimitSchema.optional(),
9719
+ /** One observation per session whose stream has filed a rate_limit_event this door generation. */
9720
+ sessions: z19.readonly(z19.array(RcLiveRateLimitSchema))
9721
+ });
9687
9722
  var FrontDoorSessionStatusSchema = z19.strictObject({
9688
9723
  pid: z19.int().positive(),
9689
9724
  startedAt: z19.number(),
@@ -9798,6 +9833,16 @@ function createControlApiRouter(deps) {
9798
9833
  ...unified?.fiveHour === void 0 ? {} : { fiveHour: effectiveWindow(unified.fiveHour, now) },
9799
9834
  ...unified?.sevenDay === void 0 ? {} : { sevenDay: effectiveWindow(unified.sevenDay, now) }
9800
9835
  };
9836
+ }),
9837
+ live: authed.input(RcSessionQuerySchema).output(UsageLiveOutputSchema).handler(({ input }) => {
9838
+ const sessions = deps.liveRateLimits(input.session);
9839
+ if (input.session !== void 0 && sessions.length === 0) {
9840
+ if (deps.list().some((session) => session.id === input.session)) {
9841
+ throw new ORPCError3("NOT_FOUND", { message: `session ${input.session} has filed no rate_limit_event on its stream yet: the worker emits one only once a turn has completed, so retry after this session's next turn` });
9842
+ }
9843
+ throw new ORPCError3("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
9844
+ }
9845
+ return { latest: deps.latestRateLimit(), sessions };
9801
9846
  })
9802
9847
  },
9803
9848
  frontdoor: {
@@ -10018,6 +10063,42 @@ function createLaunchEventPublisher(hub, now) {
10018
10063
  };
10019
10064
  }
10020
10065
 
10066
+ // src/frontdoor/rcLiveUsage.ts
10067
+ var RC_RATE_LIMIT_EVENT_TYPE = "rate_limit_event";
10068
+ function isRecord5(value) {
10069
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10070
+ }
10071
+ function rcRateLimitInfoOf(event) {
10072
+ const payload = event.envelope.payload;
10073
+ if (!isRecord5(payload) || payload.type !== RC_RATE_LIMIT_EVENT_TYPE) {
10074
+ return void 0;
10075
+ }
10076
+ if (!isRecord5(payload.rate_limit_info)) {
10077
+ return void 0;
10078
+ }
10079
+ const parsed = RcRateLimitInfoSchema.safeParse(payload.rate_limit_info);
10080
+ return parsed.success ? parsed.data : void 0;
10081
+ }
10082
+ function createRcLiveUsage(deps) {
10083
+ const observed = /* @__PURE__ */ new Map();
10084
+ deps.hub.subscribe([DOOR_EVENT_SOURCE_RC], (event) => {
10085
+ const stream = RcStreamEventSchema.safeParse(event.payload);
10086
+ if (!stream.success) {
10087
+ return;
10088
+ }
10089
+ const rateLimit = rcRateLimitInfoOf(stream.data);
10090
+ if (rateLimit === void 0) {
10091
+ return;
10092
+ }
10093
+ observed.set(stream.data.session, { session: stream.data.session, observedAt: deps.now(), rateLimit });
10094
+ });
10095
+ const sorted = () => [...observed.values()].sort((left, right) => left.observedAt - right.observedAt || (left.session < right.session ? -1 : 1));
10096
+ return {
10097
+ liveOf: (sessionId) => sorted().filter((entry) => sessionId === void 0 || entry.session === sessionId),
10098
+ latestOf: () => sorted().at(-1)
10099
+ };
10100
+ }
10101
+
10021
10102
  // src/frontdoor/rcStream.ts
10022
10103
  var RC_STREAM_EVENT_NAME = "client_event";
10023
10104
  var SSE_BYTE_ORDER_MARK = 65279;
@@ -10080,7 +10161,7 @@ function createSseParser() {
10080
10161
  }
10081
10162
  };
10082
10163
  }
10083
- function isRecord5(value) {
10164
+ function isRecord6(value) {
10084
10165
  return typeof value === "object" && value !== null && !Array.isArray(value);
10085
10166
  }
10086
10167
  function sequenceNumOf(value) {
@@ -10102,7 +10183,7 @@ function parseRcStreamEnvelope(parsed) {
10102
10183
  } catch {
10103
10184
  return void 0;
10104
10185
  }
10105
- if (!isRecord5(data)) {
10186
+ if (!isRecord6(data)) {
10106
10187
  return void 0;
10107
10188
  }
10108
10189
  const eventType = data.event_type;
@@ -10333,7 +10414,7 @@ function createRcStreamHub(deps) {
10333
10414
  // src/frontdoor/rcSelfHostEndpoints.ts
10334
10415
  var RC_SOURCE_WORKER = "worker";
10335
10416
  var RC_SOURCE_CLIENT = "client";
10336
- function isRecord6(value) {
10417
+ function isRecord7(value) {
10337
10418
  return typeof value === "object" && value !== null && !Array.isArray(value);
10338
10419
  }
10339
10420
  function parseJsonObject2(body) {
@@ -10343,7 +10424,7 @@ function parseJsonObject2(body) {
10343
10424
  } catch {
10344
10425
  return void 0;
10345
10426
  }
10346
- return isRecord6(parsed) ? parsed : void 0;
10427
+ return isRecord7(parsed) ? parsed : void 0;
10347
10428
  }
10348
10429
  function nonEmptyString2(record, field) {
10349
10430
  const value = record === void 0 ? void 0 : record[field];
@@ -10417,7 +10498,7 @@ async function serveRcClientChannels(ctx, tail, method, maxBatchEvents) {
10417
10498
  }
10418
10499
  const results = [];
10419
10500
  for (const event of events) {
10420
- if (!isRecord6(event) || !isRecord6(event.payload)) {
10501
+ if (!isRecord7(event) || !isRecord7(event.payload)) {
10421
10502
  await ctx.answerJson(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a teleport write is an object carrying one payload object" } });
10422
10503
  return true;
10423
10504
  }
@@ -10787,7 +10868,7 @@ var RC_SELF_HOST_WORKER_EPOCH = 1;
10787
10868
  var RC_STREAM_EVENT_NAME2 = "client_event";
10788
10869
  var CONFLICT_REASON_HEADER2 = "x-ccr-conflict-reason";
10789
10870
  var CONFLICT_REASON_EPOCH_STALE = "epoch_stale";
10790
- function isRecord7(value) {
10871
+ function isRecord8(value) {
10791
10872
  return typeof value === "object" && value !== null && !Array.isArray(value);
10792
10873
  }
10793
10874
  function isWebSearchRefusal(value) {
@@ -10871,7 +10952,7 @@ function parseJsonObject3(body) {
10871
10952
  } catch {
10872
10953
  return void 0;
10873
10954
  }
10874
- return isRecord7(parsed) ? parsed : void 0;
10955
+ return isRecord8(parsed) ? parsed : void 0;
10875
10956
  }
10876
10957
  function mintWorkerJwt(randomToken, issuedAt) {
10877
10958
  const encode = (value) => Buffer.from(JSON.stringify(value), "utf8").toString("base64url");
@@ -11118,7 +11199,7 @@ data: ${JSON.stringify(envelope)}
11118
11199
  if (status !== void 0) {
11119
11200
  session.workerStatus = status;
11120
11201
  }
11121
- if (isRecord7(body?.external_metadata)) {
11202
+ if (isRecord8(body?.external_metadata)) {
11122
11203
  session.externalMetadata = body.external_metadata;
11123
11204
  }
11124
11205
  await answerJson2(response, HTTP_STATUS.ok, {});
@@ -11148,7 +11229,7 @@ data: ${JSON.stringify(envelope)}
11148
11229
  }
11149
11230
  const results = [];
11150
11231
  for (const event of events) {
11151
- if (!isRecord7(event) || !isRecord7(event.payload)) {
11232
+ if (!isRecord8(event) || !isRecord8(event.payload)) {
11152
11233
  await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a batch is an object carrying one payload object" } });
11153
11234
  return;
11154
11235
  }
@@ -11181,7 +11262,7 @@ data: ${JSON.stringify(envelope)}
11181
11262
  return;
11182
11263
  }
11183
11264
  for (const event of events) {
11184
- if (isRecord7(event)) {
11265
+ if (isRecord8(event)) {
11185
11266
  session.internalEvents.push({ eventId: deps.newUuid(), body: event });
11186
11267
  }
11187
11268
  }
@@ -11277,7 +11358,7 @@ data: ${JSON.stringify(envelope)}
11277
11358
  }
11278
11359
  const results = [];
11279
11360
  for (const event of events) {
11280
- if (!isRecord7(event) || !isRecord7(event.payload)) {
11361
+ if (!isRecord8(event) || !isRecord8(event.payload)) {
11281
11362
  await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a write is an object carrying one payload object" } });
11282
11363
  return;
11283
11364
  }
@@ -11471,7 +11552,7 @@ var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
11471
11552
  var RC_SELF_HOST_RECORD_FILE = "credential.json";
11472
11553
  var SELF_HOST_EMAIL = "selfhost@agent-shim.invalid";
11473
11554
  var SELF_HOST_SUBSCRIPTION_TYPE = "max";
11474
- function isRecord8(value) {
11555
+ function isRecord9(value) {
11475
11556
  return typeof value === "object" && value !== null && !Array.isArray(value);
11476
11557
  }
11477
11558
  function readJsonObject(fs12, file) {
@@ -11485,7 +11566,7 @@ function readJsonObject(fs12, file) {
11485
11566
  } catch {
11486
11567
  return void 0;
11487
11568
  }
11488
- return isRecord8(parsed) ? parsed : void 0;
11569
+ return isRecord9(parsed) ? parsed : void 0;
11489
11570
  }
11490
11571
  function readRcSelfHostRecord(fs12, frontdoorDir) {
11491
11572
  const parsed = readJsonObject(fs12, path28.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
@@ -11509,7 +11590,7 @@ function mintRcSelfHostCredential(deps) {
11509
11590
  const recordFile = path28.join(recordDir, RC_SELF_HOST_RECORD_FILE);
11510
11591
  const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
11511
11592
  const existingCredentials = readJsonObject(deps.fs, credentialsFile);
11512
- const existingOauth = isRecord8(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
11593
+ const existingOauth = isRecord9(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
11513
11594
  const existingToken = typeof existingOauth?.accessToken === "string" && existingOauth.accessToken !== "" ? existingOauth.accessToken : void 0;
11514
11595
  const existingIsOwn = existingToken !== void 0 && previousRecord?.accessToken === existingToken;
11515
11596
  if (existingToken !== void 0 && !existingIsOwn && !deps.force) {
@@ -11526,7 +11607,7 @@ function mintRcSelfHostCredential(deps) {
11526
11607
  deps.fs.writeFilePrivate(credentialsFile, `${JSON.stringify({ ...existingCredentials, claudeAiOauth: { accessToken, refreshToken, expiresAt: null, scopes: [...RC_SELF_HOST_SCOPE_LIST], subscriptionType: SELF_HOST_SUBSCRIPTION_TYPE, rateLimitTier: null } }, null, 2)}
11527
11608
  `);
11528
11609
  const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
11529
- const existingBlock = (value) => isRecord8(value) ? value : {};
11610
+ const existingBlock = (value) => isRecord9(value) ? value : {};
11530
11611
  deps.fs.writeFilePrivate(claudeJsonFile, `${JSON.stringify({
11531
11612
  ...claudeJson,
11532
11613
  oauthAccount: {
@@ -11725,7 +11806,7 @@ import path30 from "node:path";
11725
11806
  // package.json
11726
11807
  var package_default = {
11727
11808
  name: "agent-shim",
11728
- version: "8.25.0",
11809
+ version: "8.26.0",
11729
11810
  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.",
11730
11811
  license: "MIT",
11731
11812
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -12988,11 +13069,15 @@ export {
12988
13069
  RC_WEB_FETCH_MAX_BYTES,
12989
13070
  RC_WEB_FETCH_MAX_REDIRECTS,
12990
13071
  ROUTED_PATH_PREFIX,
13072
+ RcLiveRateLimitSchema,
12991
13073
  RcPermissionModeSchema,
13074
+ RcRateLimitInfoSchema,
13075
+ RcRateLimitWindowSchema,
12992
13076
  RcStreamEnvelopeSchema,
12993
13077
  RcStreamEventSchema,
12994
13078
  UsageError,
12995
13079
  UsageListOutputSchema,
13080
+ UsageLiveOutputSchema,
12996
13081
  UsageSnapshotError,
12997
13082
  UsageSnapshotSchema,
12998
13083
  UsageWindowsInputSchema,
@@ -13044,6 +13129,7 @@ export {
13044
13129
  createRcControlHandler,
13045
13130
  createRcCredentialStore,
13046
13131
  createRcEventFanout,
13132
+ createRcLiveUsage,
13047
13133
  createRcSelfHostSurface,
13048
13134
  createRcSessionTracker,
13049
13135
  createRcStreamHub,
@@ -13105,6 +13191,7 @@ export {
13105
13191
  rcEventWriteResultFromAnswer,
13106
13192
  rcFanoutOnDoorHub,
13107
13193
  rcObserverAsPassthrough,
13194
+ rcRateLimitInfoOf,
13108
13195
  rcSelfHostFromEnv,
13109
13196
  rcWebFetchAllowsPrivateFromEnv,
13110
13197
  readActiveIdentity,