agent-shim 8.11.3 → 8.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2815,8 +2815,8 @@ function parseConnectTarget(authority) {
2815
2815
  function isInterceptedHost(host, interceptHosts) {
2816
2816
  return interceptHosts.includes(host);
2817
2817
  }
2818
- function servedByPipeline(path30) {
2819
- return path30?.startsWith(ROUTED_PATH_PREFIX) === true;
2818
+ function servedByPipeline(path31) {
2819
+ return path31?.startsWith(ROUTED_PATH_PREFIX) === true;
2820
2820
  }
2821
2821
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
2822
2822
  "connection",
@@ -2898,14 +2898,17 @@ ${request4.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
2898
2898
  pumpTapSession(socket, async (clientAlpn) => await effects.connectTlsUpstream(host, HTTPS_PORT, clientAlpn), config.capture?.tapStream?.(host), Buffer.from(headText, "utf8"));
2899
2899
  };
2900
2900
  const sessions = config.interceptHosts.map((host) => {
2901
- if (config.tapHosts.includes(host)) {
2901
+ if (config.tapHosts.includes(host) && !(config.localSurface?.parsesHost(host) ?? false)) {
2902
2902
  const serveSecure2 = (secure) => {
2903
2903
  pumpTapSession(secure, async (clientAlpn) => await effects.connectTlsUpstream(host, HTTPS_PORT, clientAlpn), config.capture?.tapStream?.(host));
2904
2904
  };
2905
2905
  const tlsAcceptor2 = effects.createTlsAcceptor(config.leafFor(host), serveSecure2, TAP_ALPN_PROTOCOLS);
2906
2906
  return { host, serveSecure: serveSecure2, tlsAcceptor: tlsAcceptor2 };
2907
2907
  }
2908
- const handler = (request4, response) => {
2908
+ const handleHostRequest = async (request4, response) => {
2909
+ if (config.localSurface !== void 0 && await config.localSurface.serve(host, request4, response)) {
2910
+ return;
2911
+ }
2909
2912
  if (host === config.routedHost && servedByPipeline(request4.url)) {
2910
2913
  const tunnelToken = tunnelTokens.get(request4.socket);
2911
2914
  if (tunnelToken !== void 0 && request4.headers[AUTH_HEADER] === void 0) {
@@ -2916,6 +2919,9 @@ ${request4.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
2916
2919
  }
2917
2920
  effects.forwardHttp(config.upstreamFor(host), request4, response, config.capture?.observePassthrough(request4));
2918
2921
  };
2922
+ const handler = (request4, response) => {
2923
+ void handleHostRequest(request4, response);
2924
+ };
2919
2925
  const httpSession = effects.createHttpSession(handler, onUpgrade(host));
2920
2926
  const serveSecure = (secure, capability) => {
2921
2927
  tunnelTokens.set(secure, capability);
@@ -3298,7 +3304,7 @@ function parseRcRequestBody(kind, body) {
3298
3304
  return { controlRequests: [], answeredRequestIds: [], idleSeconds: finiteNumber(parseJsonObject(body), "idle_seconds"), workerStatus: void 0 };
3299
3305
  }
3300
3306
  if (kind === "worker-registration") {
3301
- return { controlRequests: [], answeredRequestIds: [], idleSeconds: void 0, workerStatus: nonEmptyString(parseJsonObject(body), "status") };
3307
+ return { controlRequests: [], answeredRequestIds: [], idleSeconds: void 0, workerStatus: nonEmptyString(parseJsonObject(body), "worker_status") };
3302
3308
  }
3303
3309
  const controlRequests = [];
3304
3310
  const answeredRequestIds = [];
@@ -3347,11 +3353,11 @@ function createRcSessionTracker(deps) {
3347
3353
  };
3348
3354
  const observeExchange = (request4) => {
3349
3355
  const method = (request4.method ?? "").toUpperCase();
3350
- const path30 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
3351
- if (!path30.startsWith(RC_SESSIONS_PATH_PREFIX)) {
3356
+ const path31 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
3357
+ if (!path31.startsWith(RC_SESSIONS_PATH_PREFIX)) {
3352
3358
  return void 0;
3353
3359
  }
3354
- const tail = path30.slice(RC_SESSIONS_PATH_PREFIX.length);
3360
+ const tail = path31.slice(RC_SESSIONS_PATH_PREFIX.length);
3355
3361
  const facts = {
3356
3362
  oauthAuthorization: oauthAuthorizationOf(request4.headers),
3357
3363
  anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
@@ -4112,9 +4118,9 @@ function sequenceNumsOfBody(body) {
4112
4118
  }
4113
4119
  function frontDoorRcControl(transport, token) {
4114
4120
  const headers = { authorization: `Bearer ${token}` };
4115
- const listAnswerOf = async (path30, what) => {
4121
+ const listAnswerOf = async (path31, what) => {
4116
4122
  try {
4117
- return await transport.request({ method: "GET", path: path30, headers });
4123
+ return await transport.request({ method: "GET", path: path31, headers });
4118
4124
  } catch (error) {
4119
4125
  throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
4120
4126
  }
@@ -4186,10 +4192,10 @@ function frontDoorRcControl(transport, token) {
4186
4192
  }
4187
4193
  return pending;
4188
4194
  };
4189
- const writeOf = async (path30, body, describeFailure) => {
4195
+ const writeOf = async (path31, body, describeFailure) => {
4190
4196
  let answer;
4191
4197
  try {
4192
- answer = await transport.request({ method: "POST", path: path30, headers: { ...headers, "content-type": "application/json" }, body });
4198
+ answer = await transport.request({ method: "POST", path: path31, headers: { ...headers, "content-type": "application/json" }, body });
4193
4199
  } catch (error) {
4194
4200
  return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
4195
4201
  }
@@ -4399,14 +4405,41 @@ var NO_CHUNKS = {
4399
4405
  next: async () => await Promise.resolve({ done: true, value: void 0 })
4400
4406
  })
4401
4407
  };
4408
+ function lateRcEventDial(resolve) {
4409
+ let built;
4410
+ const dialFor = () => {
4411
+ const target = resolve();
4412
+ if (built === void 0 || built.for !== target) {
4413
+ built = { for: target, dial: realRcEventDial(target) };
4414
+ }
4415
+ return built.dial;
4416
+ };
4417
+ return {
4418
+ writeEvents: async (sessionId, headers, body) => await dialFor().writeEvents(sessionId, headers, body)
4419
+ };
4420
+ }
4421
+ function lateRcStreamDial(resolve) {
4422
+ let built;
4423
+ const dialFor = () => {
4424
+ const target = resolve();
4425
+ if (built === void 0 || built.for !== target) {
4426
+ built = { for: target, dial: realRcStreamDial(target) };
4427
+ }
4428
+ return built.dial;
4429
+ };
4430
+ return {
4431
+ announcePresence: async (sessionId, headers, clientId) => await dialFor().announcePresence(sessionId, headers, clientId),
4432
+ openStream: async (sessionId, headers, resume, signal) => await dialFor().openStream(sessionId, headers, resume, signal)
4433
+ };
4434
+ }
4402
4435
  function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
4403
4436
  const agent = new ExemptTlsAgent();
4404
- const request4 = async (method, path30, headers, body, signal) => await new Promise((resolve, reject) => {
4437
+ const request4 = async (method, path31, headers, body, signal) => await new Promise((resolve, reject) => {
4405
4438
  const options = {
4406
4439
  host: target.host,
4407
4440
  port: target.port,
4408
4441
  method,
4409
- path: path30,
4442
+ path: path31,
4410
4443
  // The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
4411
4444
  headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
4412
4445
  agent,
@@ -4443,9 +4476,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
4443
4476
  return { status, body: await readAll(response) };
4444
4477
  },
4445
4478
  openStream: async (sessionId, headers, resume, signal) => {
4446
- const path30 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
4479
+ const path31 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
4447
4480
  const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
4448
- const { status, response } = await request4("GET", path30, streamHeaders, void 0, signal);
4481
+ const { status, response } = await request4("GET", path31, streamHeaders, void 0, signal);
4449
4482
  if (!isSuccessful2(status)) {
4450
4483
  await readAll(response);
4451
4484
  return { status, chunks: NO_CHUNKS };
@@ -5140,37 +5173,930 @@ function createRcStreamHub(deps) {
5140
5173
  await deps.sleep(deps.backoffMs);
5141
5174
  retriedUnauthorized = false;
5142
5175
  }
5143
- };
5144
- return {
5145
- reconcile: () => {
5146
- const live = new Set(deps.trackedSessions());
5147
- for (const [sessionId, attachment] of attachments) {
5148
- if (!live.has(sessionId)) {
5149
- attachment.stop();
5150
- attachments.delete(sessionId);
5151
- }
5152
- }
5153
- for (const sessionId of live) {
5154
- if (attachments.has(sessionId)) {
5155
- continue;
5156
- }
5157
- if (deps.credentialOf(sessionId)?.authorization === void 0) {
5158
- continue;
5159
- }
5160
- const attachment = birth(sessionId);
5161
- attachments.set(sessionId, attachment);
5162
- void runLoop(attachment).catch((error) => {
5163
- deps.log?.(`rc stream ${sessionId}: the attachment loop ended unexpectedly (${error instanceof Error ? error.message : String(error)})`);
5164
- });
5165
- }
5176
+ };
5177
+ return {
5178
+ reconcile: () => {
5179
+ const live = new Set(deps.trackedSessions());
5180
+ for (const [sessionId, attachment] of attachments) {
5181
+ if (!live.has(sessionId)) {
5182
+ attachment.stop();
5183
+ attachments.delete(sessionId);
5184
+ }
5185
+ }
5186
+ for (const sessionId of live) {
5187
+ if (attachments.has(sessionId)) {
5188
+ continue;
5189
+ }
5190
+ if (deps.credentialOf(sessionId)?.authorization === void 0) {
5191
+ continue;
5192
+ }
5193
+ const attachment = birth(sessionId);
5194
+ attachments.set(sessionId, attachment);
5195
+ void runLoop(attachment).catch((error) => {
5196
+ deps.log?.(`rc stream ${sessionId}: the attachment loop ended unexpectedly (${error instanceof Error ? error.message : String(error)})`);
5197
+ });
5198
+ }
5199
+ },
5200
+ close: () => {
5201
+ for (const attachment of attachments.values()) {
5202
+ attachment.stop();
5203
+ }
5204
+ attachments.clear();
5205
+ }
5206
+ };
5207
+ }
5208
+
5209
+ // src/frontdoor/rcSelfHost.ts
5210
+ var RC_SELF_HOST_ENV = "AGENT_SHIM_FRONTDOOR_RC_SELF_HOST";
5211
+ function rcSelfHostFromEnv(env) {
5212
+ return env[RC_SELF_HOST_ENV] === "1";
5213
+ }
5214
+ var RC_SELF_HOST_SCOPE_LIST = ["user:profile", "user:inference", "user:sessions:claude_code", "user:mcp_servers", "user:file_upload"];
5215
+ var RC_SESSIONS_PATH_PREFIX2 = "/v1/code/sessions";
5216
+ var RC_COMPAT_SESSIONS_PATH = "/v1/sessions";
5217
+ var RC_SESSION_ID_PREFIX2 = "cse_";
5218
+ var RC_SELF_HOST_API_BASE_URL = "https://api.anthropic.com";
5219
+ var RC_SELF_HOST_OAUTH_HOST = "platform.claude.com";
5220
+ var HTTP_CONFLICT = 409;
5221
+ var MS_PER_SECOND2 = 1e3;
5222
+ var HTTP_SERVICE_UNAVAILABLE = 503;
5223
+ var RC_SELF_HOST_WORKER_JWT_TTL_SECONDS = 46800;
5224
+ var RC_SELF_HOST_OAUTH_TOKEN_TTL_SECONDS = 3600;
5225
+ var RC_SELF_HOST_KEEPALIVE_MS = 15e3;
5226
+ var RC_SELF_HOST_RETENTION_MS = 6e5;
5227
+ var RC_PRESENCE_REFRESH_SECONDS = 60;
5228
+ var RC_SELF_HOST_MAX_BATCH_EVENTS = 100;
5229
+ var RC_SELF_HOST_WORKER_EPOCH = 1;
5230
+ var RC_STREAM_EVENT_NAME2 = "client_event";
5231
+ var RC_SOURCE_WORKER = "worker";
5232
+ var RC_SOURCE_CLIENT = "client";
5233
+ var CONFLICT_REASON_HEADER2 = "x-ccr-conflict-reason";
5234
+ var CONFLICT_REASON_EPOCH_STALE = "epoch_stale";
5235
+ function isRecord5(value) {
5236
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5237
+ }
5238
+ function nonEmptyString2(record, field) {
5239
+ const value = record === void 0 ? void 0 : record[field];
5240
+ return typeof value === "string" && value !== "" ? value : void 0;
5241
+ }
5242
+ function numberOf(record, field) {
5243
+ const value = record === void 0 ? void 0 : record[field];
5244
+ if (typeof value === "number" && Number.isFinite(value)) {
5245
+ return value;
5246
+ }
5247
+ if (typeof value === "string" && /^[0-9]+$/.test(value)) {
5248
+ return Number(value);
5249
+ }
5250
+ return void 0;
5251
+ }
5252
+ function singleHeader2(headers, name) {
5253
+ const value = headers[name];
5254
+ return typeof value === "string" ? value : void 0;
5255
+ }
5256
+ function bearerOf(headers) {
5257
+ const presented = singleHeader2(headers, "authorization");
5258
+ if (presented === void 0) {
5259
+ return void 0;
5260
+ }
5261
+ return presented.slice(0, "bearer ".length).toLowerCase() === "bearer " ? presented.slice("bearer ".length) : void 0;
5262
+ }
5263
+ async function readBody2(request4, capBytes) {
5264
+ return await new Promise((resolve, reject) => {
5265
+ const chunks = [];
5266
+ let total = 0;
5267
+ request4.on("data", (chunk) => {
5268
+ total += chunk.length;
5269
+ if (total > capBytes) {
5270
+ request4.destroy();
5271
+ reject(new Error("body too large"));
5272
+ return;
5273
+ }
5274
+ chunks.push(chunk);
5275
+ });
5276
+ request4.on("end", () => {
5277
+ resolve(Buffer.concat(chunks).toString("utf8"));
5278
+ });
5279
+ request4.on("error", () => {
5280
+ reject(new Error("the request body ended early"));
5281
+ });
5282
+ });
5283
+ }
5284
+ function parseJsonObject2(body) {
5285
+ let parsed;
5286
+ try {
5287
+ parsed = JSON.parse(body);
5288
+ } catch {
5289
+ return void 0;
5290
+ }
5291
+ return isRecord5(parsed) ? parsed : void 0;
5292
+ }
5293
+ function mintWorkerJwt(randomToken, issuedAt) {
5294
+ const encode = (value) => Buffer.from(JSON.stringify(value), "utf8").toString("base64url");
5295
+ const header = encode({ alg: "HS256", typ: "JWT" });
5296
+ const payload = encode({ exp: Math.floor((issuedAt + RC_SELF_HOST_WORKER_JWT_TTL_SECONDS * MS_PER_SECOND2) / MS_PER_SECOND2), iat: Math.floor(issuedAt / MS_PER_SECOND2) });
5297
+ return `${header}.${payload}.${Buffer.from(randomToken(), "utf8").toString("base64url")}`;
5298
+ }
5299
+ function growthBookFeatures() {
5300
+ return {
5301
+ tengu_ccr_bridge: { defaultValue: true },
5302
+ tengu_bridge_repl_v2: { defaultValue: true },
5303
+ tengu_bridge_repl_v2_cse_shim_enabled: { defaultValue: true },
5304
+ tengu_bridge_min_version: { defaultValue: { minVersion: "0.0.0" } }
5305
+ };
5306
+ }
5307
+ function createRcSelfHostSurface(deps) {
5308
+ const sessions = /* @__PURE__ */ new Map();
5309
+ const sweep = () => {
5310
+ const now = deps.now();
5311
+ for (const session of sessions.values()) {
5312
+ while (session.events[0] !== void 0 && now - session.events[0].storedAt > RC_SELF_HOST_RETENTION_MS) {
5313
+ const dropped = session.events.shift();
5314
+ const uuid = dropped === void 0 ? void 0 : nonEmptyString2(dropped.payload, "uuid");
5315
+ if (uuid !== void 0) {
5316
+ session.seenPayloadUuids.delete(uuid);
5317
+ }
5318
+ }
5319
+ if (session.workerStreams.size === 0 && session.clientStreams.size === 0 && now - session.lastTrafficAt > RC_SELF_HOST_RETENTION_MS) {
5320
+ sessions.delete(session.id);
5321
+ }
5322
+ }
5323
+ };
5324
+ const timer = setInterval(sweep, RC_SELF_HOST_RETENTION_MS);
5325
+ timer.unref();
5326
+ const keepalive = setInterval(() => {
5327
+ for (const session of sessions.values()) {
5328
+ for (const sink of [...session.workerStreams, ...session.clientStreams]) {
5329
+ sink.write(": keep-alive\n\n");
5330
+ }
5331
+ }
5332
+ }, RC_SELF_HOST_KEEPALIVE_MS);
5333
+ keepalive.unref();
5334
+ const presentsCredential = (headers) => {
5335
+ const expected = deps.credentialRecord()?.accessToken;
5336
+ const presented = bearerOf(headers);
5337
+ return expected !== void 0 && presented !== void 0 && isLiveCapability(presented, [expected]);
5338
+ };
5339
+ const presentsWorkerJwt = (headers, session) => {
5340
+ const presented = bearerOf(headers);
5341
+ if (presented === void 0) {
5342
+ return false;
5343
+ }
5344
+ for (const minted of session.workerJwts) {
5345
+ if (isLiveCapability(presented, [minted])) {
5346
+ return true;
5347
+ }
5348
+ }
5349
+ return false;
5350
+ };
5351
+ const frameOf = (event) => {
5352
+ const envelope = {
5353
+ event_id: event.eventId,
5354
+ event_type: nonEmptyString2(event.payload, "type") ?? "event",
5355
+ sequence_num: event.sequenceNum,
5356
+ source: event.source,
5357
+ payload: event.payload,
5358
+ created_at: event.createdAt
5359
+ };
5360
+ return `event: ${RC_STREAM_EVENT_NAME2}
5361
+ id: ${String(event.sequenceNum)}
5362
+ data: ${JSON.stringify(envelope)}
5363
+
5364
+ `;
5365
+ };
5366
+ const holdStream = async (session, which, wantsReplay, request4, response) => {
5367
+ const url = new URL(request4.url, "http://127.0.0.1");
5368
+ const cursor = numberOf({ value: url.searchParams.get("from_sequence_num") }, "value") ?? numberOf({ value: singleHeader2(request4.headers, "last-event-id") }, "value");
5369
+ const replay = cursor === void 0 ? [] : session.events.filter((event) => wantsReplay(event) && event.sequenceNum > cursor);
5370
+ response.start(HTTP_STATUS.ok, { "content-type": "text/event-stream", "cache-control": "no-cache" });
5371
+ response.flush();
5372
+ let pending = Promise.resolve();
5373
+ const sink = {
5374
+ write: (frame) => {
5375
+ pending = pending.then(async () => {
5376
+ await response.write(frame);
5377
+ }).catch(() => {
5378
+ });
5379
+ },
5380
+ retire: () => {
5381
+ session[which].delete(sink);
5382
+ }
5383
+ };
5384
+ session[which].add(sink);
5385
+ session.lastTrafficAt = deps.now();
5386
+ for (const event of replay) {
5387
+ sink.write(frameOf(event));
5388
+ }
5389
+ await new Promise((resolve) => {
5390
+ request4.signal.addEventListener("abort", () => {
5391
+ resolve(void 0);
5392
+ }, { once: true });
5393
+ });
5394
+ sink.retire();
5395
+ response.end();
5396
+ };
5397
+ const publish = (session, source, payload) => {
5398
+ const uuid = nonEmptyString2(payload, "uuid");
5399
+ const duplicate = uuid !== void 0 && session.seenPayloadUuids.has(uuid);
5400
+ session.sequenceNum += 1;
5401
+ const event = {
5402
+ sequenceNum: session.sequenceNum,
5403
+ eventId: uuid ?? deps.newUuid(),
5404
+ source,
5405
+ // The one enrichment the real service was observed making on the live rig's stream: the wall-clock instant it took the write. The worker's handler ignores it; the door's own parser forwards it verbatim.
5406
+ payload: source === RC_SOURCE_CLIENT ? { ...payload, server_received_wall_ms: deps.now() } : payload,
5407
+ createdAt: new Date(deps.now()).toISOString(),
5408
+ toWorker: source === RC_SOURCE_CLIENT,
5409
+ storedAt: deps.now()
5410
+ };
5411
+ session.events.push(event);
5412
+ if (uuid !== void 0) {
5413
+ session.seenPayloadUuids.add(uuid);
5414
+ }
5415
+ session.lastTrafficAt = event.storedAt;
5416
+ const frame = frameOf(event);
5417
+ if (event.toWorker) {
5418
+ for (const sink of [...session.workerStreams]) {
5419
+ sink.write(frame);
5420
+ }
5421
+ }
5422
+ for (const sink of [...session.clientStreams]) {
5423
+ sink.write(frame);
5424
+ }
5425
+ return { sequenceNum: event.sequenceNum, eventId: event.eventId, duplicate };
5426
+ };
5427
+ const answerJson2 = async (response, status, body, extraHeaders = {}) => {
5428
+ const text = JSON.stringify(body);
5429
+ response.start(status, { "content-type": "application/json", "content-length": String(Buffer.byteLength(text, "utf8")), ...extraHeaders });
5430
+ await response.write(text);
5431
+ response.end();
5432
+ };
5433
+ const noCredential = async (response) => {
5434
+ await answerJson2(response, HTTP_SERVICE_UNAVAILABLE, { type: "error", error: { type: "api_error", message: "the front door's self-hosted Remote Control surface is on but no credential has been minted for it; run agent-shim frontdoor rc selfhost mint first" } });
5435
+ };
5436
+ const epochStale = async (response) => {
5437
+ await answerJson2(response, HTTP_CONFLICT, { type: "error", error: { type: "api_error", message: "worker_epoch does not match the session's live epoch" } }, { [CONFLICT_REASON_HEADER2]: CONFLICT_REASON_EPOCH_STALE });
5438
+ };
5439
+ const unauthorized = async (response) => {
5440
+ await answerJson2(response, HTTP_STATUS.unauthorized, { type: "error", error: { type: "authentication_error", message: "the self-hosted Remote Control surface did not recognise the presented credential" } });
5441
+ };
5442
+ const serveSessionPath = async (session, tail, request4, response) => {
5443
+ const method = request4.method.toUpperCase();
5444
+ if (session === void 0) {
5445
+ await answerJson2(response, HTTP_STATUS.notFound, { type: "error", error: { type: "api_error", message: "no such Remote Control session on this door" } });
5446
+ return;
5447
+ }
5448
+ session.lastTrafficAt = deps.now();
5449
+ if (tail === "") {
5450
+ if (method !== "GET") {
5451
+ await answerJson2(response, HTTP_STATUS.methodNotAllowed, { type: "error", error: { type: "api_error", message: "the session read is a GET" } });
5452
+ return;
5453
+ }
5454
+ await answerJson2(response, HTTP_STATUS.ok, { session: { id: session.id, title: session.title, created_at: new Date(session.createdAt).toISOString(), status: "active" } });
5455
+ return;
5456
+ }
5457
+ if (tail === "bridge" && method === "POST") {
5458
+ if (!presentsCredential(request4.headers)) {
5459
+ await unauthorized(response);
5460
+ return;
5461
+ }
5462
+ const workerJwt = mintWorkerJwt(deps.randomToken, deps.now());
5463
+ session.workerJwts.add(workerJwt);
5464
+ deps.log?.(`rc selfhost ${session.id}: bridge registration minted a worker credential`);
5465
+ await answerJson2(response, HTTP_STATUS.ok, { worker_jwt: workerJwt, expires_in: RC_SELF_HOST_WORKER_JWT_TTL_SECONDS, api_base_url: RC_SELF_HOST_API_BASE_URL, worker_epoch: RC_SELF_HOST_WORKER_EPOCH });
5466
+ return;
5467
+ }
5468
+ if (tail === "archive" && method === "POST") {
5469
+ if (!presentsCredential(request4.headers)) {
5470
+ await unauthorized(response);
5471
+ return;
5472
+ }
5473
+ for (const sink of [...session.workerStreams, ...session.clientStreams]) {
5474
+ sink.retire();
5475
+ }
5476
+ sessions.delete(session.id);
5477
+ deps.log?.(`rc selfhost ${session.id}: archived at its client's request`);
5478
+ await answerJson2(response, HTTP_STATUS.ok, {});
5479
+ return;
5480
+ }
5481
+ if (tail === "worker" || tail.startsWith("worker/")) {
5482
+ if (!presentsWorkerJwt(request4.headers, session)) {
5483
+ await unauthorized(response);
5484
+ return;
5485
+ }
5486
+ const workerTail = tail === "worker" ? "" : tail.slice("worker/".length);
5487
+ if (workerTail === "" && method === "GET") {
5488
+ await answerJson2(response, HTTP_STATUS.ok, { worker: { external_metadata: session.externalMetadata ?? null } });
5489
+ return;
5490
+ }
5491
+ if (workerTail === "" && method === "PUT") {
5492
+ const body = parseJsonObject2(await readBody2(request4.body, CONTROL_BODY_CAP_BYTES));
5493
+ const claimedEpoch = numberOf(body, "worker_epoch");
5494
+ if (claimedEpoch !== void 0 && claimedEpoch !== RC_SELF_HOST_WORKER_EPOCH) {
5495
+ await epochStale(response);
5496
+ return;
5497
+ }
5498
+ const status = nonEmptyString2(body, "worker_status");
5499
+ if (status !== void 0) {
5500
+ session.workerStatus = status;
5501
+ }
5502
+ if (isRecord5(body?.external_metadata)) {
5503
+ session.externalMetadata = body.external_metadata;
5504
+ }
5505
+ await answerJson2(response, HTTP_STATUS.ok, {});
5506
+ return;
5507
+ }
5508
+ if (workerTail === "register" && method === "POST") {
5509
+ await readBody2(request4.body, CONTROL_BODY_CAP_BYTES);
5510
+ await answerJson2(response, HTTP_STATUS.ok, { worker_epoch: RC_SELF_HOST_WORKER_EPOCH });
5511
+ return;
5512
+ }
5513
+ if (workerTail === "heartbeat" && method === "POST") {
5514
+ await readBody2(request4.body, CONTROL_BODY_CAP_BYTES);
5515
+ await answerJson2(response, HTTP_STATUS.ok, {});
5516
+ return;
5517
+ }
5518
+ if (workerTail === "events" && method === "POST") {
5519
+ const body = parseJsonObject2(await readBody2(request4.body, CONTROL_BODY_CAP_BYTES));
5520
+ const claimedEpoch = numberOf(body, "worker_epoch");
5521
+ if (claimedEpoch !== void 0 && claimedEpoch !== RC_SELF_HOST_WORKER_EPOCH) {
5522
+ await epochStale(response);
5523
+ return;
5524
+ }
5525
+ const events = body?.events;
5526
+ if (!Array.isArray(events) || events.length === 0 || events.length > RC_SELF_HOST_MAX_BATCH_EVENTS) {
5527
+ await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: `a worker event batch is a non-empty array of at most ${String(RC_SELF_HOST_MAX_BATCH_EVENTS)} events` } });
5528
+ return;
5529
+ }
5530
+ const results = [];
5531
+ for (const event of events) {
5532
+ if (!isRecord5(event) || !isRecord5(event.payload)) {
5533
+ 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" } });
5534
+ return;
5535
+ }
5536
+ const published = publish(session, RC_SOURCE_WORKER, event.payload);
5537
+ results.push({ event_id: published.eventId, sequence_num: String(published.sequenceNum) });
5538
+ }
5539
+ sweep();
5540
+ await answerJson2(response, HTTP_STATUS.ok, { results });
5541
+ return;
5542
+ }
5543
+ if (workerTail === "events/stream" && method === "GET") {
5544
+ await holdStream(session, "workerStreams", (event) => event.toWorker, request4, response);
5545
+ return;
5546
+ }
5547
+ if (workerTail === "events/delivery" && method === "POST") {
5548
+ await readBody2(request4.body, CONTROL_BODY_CAP_BYTES);
5549
+ await answerJson2(response, HTTP_STATUS.ok, {});
5550
+ return;
5551
+ }
5552
+ if (workerTail === "internal-events" && method === "POST") {
5553
+ const body = parseJsonObject2(await readBody2(request4.body, CONTROL_BODY_CAP_BYTES));
5554
+ const claimedEpoch = numberOf(body, "worker_epoch");
5555
+ if (claimedEpoch !== void 0 && claimedEpoch !== RC_SELF_HOST_WORKER_EPOCH) {
5556
+ await epochStale(response);
5557
+ return;
5558
+ }
5559
+ const events = body?.events;
5560
+ if (!Array.isArray(events)) {
5561
+ await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "an internal event batch is an array" } });
5562
+ return;
5563
+ }
5564
+ for (const event of events) {
5565
+ if (isRecord5(event)) {
5566
+ session.internalEvents.push({ cursor: deps.newUuid(), body: event });
5567
+ }
5568
+ }
5569
+ await answerJson2(response, HTTP_STATUS.ok, {});
5570
+ return;
5571
+ }
5572
+ if (workerTail === "internal-events" && method === "GET") {
5573
+ const url = new URL(request4.url, "http://127.0.0.1");
5574
+ const cursor = url.searchParams.get("cursor");
5575
+ const from = cursor === null ? 0 : session.internalEvents.findIndex((event) => event.cursor === cursor) + 1;
5576
+ const page = session.internalEvents.slice(from);
5577
+ await answerJson2(response, HTTP_STATUS.ok, { data: page.map((event) => event.body), next_cursor: page.length === 0 ? void 0 : page[page.length - 1]?.cursor });
5578
+ return;
5579
+ }
5580
+ if (workerTail === "diagnostics" && method === "POST") {
5581
+ await readBody2(request4.body, CONTROL_BODY_CAP_BYTES);
5582
+ await answerJson2(response, HTTP_STATUS.ok, {});
5583
+ return;
5584
+ }
5585
+ await answerJson2(response, HTTP_STATUS.notFound, { type: "error", error: { type: "api_error", message: `the self-hosted Remote Control surface serves no worker path "${workerTail}"` } });
5586
+ return;
5587
+ }
5588
+ if (!presentsCredential(request4.headers)) {
5589
+ await unauthorized(response);
5590
+ return;
5591
+ }
5592
+ if (tail === "events" && method === "POST") {
5593
+ const body = parseJsonObject2(await readBody2(request4.body, CONTROL_BODY_CAP_BYTES));
5594
+ const events = body?.events;
5595
+ if (!Array.isArray(events) || events.length === 0 || events.length > RC_SELF_HOST_MAX_BATCH_EVENTS) {
5596
+ await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: `a client event write is a non-empty array of at most ${String(RC_SELF_HOST_MAX_BATCH_EVENTS)} events` } });
5597
+ return;
5598
+ }
5599
+ const results = [];
5600
+ for (const event of events) {
5601
+ if (!isRecord5(event) || !isRecord5(event.payload)) {
5602
+ 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" } });
5603
+ return;
5604
+ }
5605
+ const published = publish(session, RC_SOURCE_CLIENT, event.payload);
5606
+ results.push({ sequence_num: String(published.sequenceNum), duplicate: published.duplicate });
5607
+ }
5608
+ sweep();
5609
+ await answerJson2(response, HTTP_STATUS.ok, { results });
5610
+ return;
5611
+ }
5612
+ if (tail === "events" && method === "GET") {
5613
+ await answerJson2(response, HTTP_STATUS.ok, { data: session.events.map((event) => ({ event_id: event.eventId, event_type: nonEmptyString2(event.payload, "type") ?? "event", sequence_num: event.sequenceNum, source: event.source, payload: event.payload, created_at: event.createdAt })) });
5614
+ return;
5615
+ }
5616
+ if (tail === "events/stream" && method === "GET") {
5617
+ await holdStream(session, "clientStreams", () => true, request4, response);
5618
+ return;
5619
+ }
5620
+ if (tail === "client/presence" && method === "POST") {
5621
+ await readBody2(request4.body, CONTROL_BODY_CAP_BYTES);
5622
+ await answerJson2(response, HTTP_STATUS.ok, { refresh_after_seconds: RC_PRESENCE_REFRESH_SECONDS });
5623
+ return;
5624
+ }
5625
+ if (tail === "mark_read" && method === "POST") {
5626
+ await readBody2(request4.body, CONTROL_BODY_CAP_BYTES);
5627
+ await answerJson2(response, HTTP_STATUS.ok, {});
5628
+ return;
5629
+ }
5630
+ if (tail === "teleport-events" && method === "POST") {
5631
+ await readBody2(request4.body, CONTROL_BODY_CAP_BYTES);
5632
+ await answerJson2(response, HTTP_STATUS.ok, {});
5633
+ return;
5634
+ }
5635
+ await answerJson2(response, HTTP_STATUS.notFound, { type: "error", error: { type: "api_error", message: `the self-hosted Remote Control surface serves no path "${tail}"` } });
5636
+ };
5637
+ const recordMissing = () => deps.credentialRecord() === void 0;
5638
+ const route = {
5639
+ name: "rc-selfhost",
5640
+ headroomEligible: false,
5641
+ headroomUpstream: void 0,
5642
+ serve: async (request4, response) => {
5643
+ const method = request4.method.toUpperCase();
5644
+ const pathname = new URL(request4.url, "http://127.0.0.1").pathname;
5645
+ if (recordMissing()) {
5646
+ await noCredential(response);
5647
+ return;
5648
+ }
5649
+ if (pathname === RC_COMPAT_SESSIONS_PATH) {
5650
+ if (method !== "GET") {
5651
+ await answerJson2(response, HTTP_STATUS.methodNotAllowed, { type: "error", error: { type: "api_error", message: "the compatibility session list is a GET" } });
5652
+ return;
5653
+ }
5654
+ if (!presentsCredential(request4.headers)) {
5655
+ await unauthorized(response);
5656
+ return;
5657
+ }
5658
+ await answerJson2(response, HTTP_STATUS.ok, { data: [] });
5659
+ return;
5660
+ }
5661
+ if (pathname !== RC_SESSIONS_PATH_PREFIX2 && !pathname.startsWith(`${RC_SESSIONS_PATH_PREFIX2}/`)) {
5662
+ await answerJson2(response, HTTP_STATUS.notFound, { type: "error", error: { type: "api_error", message: `the self-hosted Remote Control surface serves no path "${pathname}"` } });
5663
+ return;
5664
+ }
5665
+ if (pathname === RC_SESSIONS_PATH_PREFIX2) {
5666
+ if (method === "POST") {
5667
+ if (!presentsCredential(request4.headers)) {
5668
+ await unauthorized(response);
5669
+ return;
5670
+ }
5671
+ const body = parseJsonObject2(await readBody2(request4.body, CONTROL_BODY_CAP_BYTES));
5672
+ const session = {
5673
+ id: `${RC_SESSION_ID_PREFIX2}${deps.newUuid()}`,
5674
+ createdAt: deps.now(),
5675
+ title: nonEmptyString2(body, "title"),
5676
+ workerJwts: /* @__PURE__ */ new Set(),
5677
+ sequenceNum: 0,
5678
+ events: [],
5679
+ seenPayloadUuids: /* @__PURE__ */ new Set(),
5680
+ workerStreams: /* @__PURE__ */ new Set(),
5681
+ clientStreams: /* @__PURE__ */ new Set(),
5682
+ internalEvents: [],
5683
+ workerStatus: void 0,
5684
+ externalMetadata: void 0,
5685
+ lastTrafficAt: deps.now()
5686
+ };
5687
+ sessions.set(session.id, session);
5688
+ deps.log?.(`rc selfhost ${session.id}: session created on the door's own surface`);
5689
+ await answerJson2(response, HTTP_STATUS.ok, { session: { id: session.id, title: session.title, created_at: new Date(session.createdAt).toISOString(), status: "active" } });
5690
+ return;
5691
+ }
5692
+ if (method === "GET") {
5693
+ if (!presentsCredential(request4.headers)) {
5694
+ await unauthorized(response);
5695
+ return;
5696
+ }
5697
+ await answerJson2(response, HTTP_STATUS.ok, { data: [...sessions.values()].map((session) => ({ id: session.id, title: session.title, created_at: new Date(session.createdAt).toISOString(), updated_at: new Date(session.lastTrafficAt).toISOString(), session_status: "active" })) });
5698
+ return;
5699
+ }
5700
+ await answerJson2(response, HTTP_STATUS.methodNotAllowed, { type: "error", error: { type: "api_error", message: "the session collection is a POST (create) and a GET (list)" } });
5701
+ return;
5702
+ }
5703
+ const rest = pathname.slice(`${RC_SESSIONS_PATH_PREFIX2}/`.length);
5704
+ const slash = rest.indexOf("/");
5705
+ const id = slash === -1 ? rest : rest.slice(0, slash);
5706
+ const tail = slash === -1 ? "" : rest.slice(slash + 1);
5707
+ if (!id.startsWith(RC_SESSION_ID_PREFIX2)) {
5708
+ await answerJson2(response, HTTP_STATUS.notFound, { type: "error", error: { type: "api_error", message: "the session family names one cse_-prefixed session id" } });
5709
+ return;
5710
+ }
5711
+ await serveSessionPath(sessions.get(id), tail, request4, response);
5712
+ }
5713
+ };
5714
+ const answerServerJson = (response, status, body) => {
5715
+ const text = JSON.stringify(body);
5716
+ response.writeHead(status, { "content-type": "application/json", "content-length": String(Buffer.byteLength(text, "utf8")) });
5717
+ response.end(text);
5718
+ };
5719
+ const local = {
5720
+ parsesHost: (host) => host === RC_SELF_HOST_OAUTH_HOST,
5721
+ serve: async (host, request4, response) => {
5722
+ const method = (request4.method ?? "").toUpperCase();
5723
+ const pathname = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
5724
+ if (host === RC_SELF_HOST_OAUTH_HOST) {
5725
+ if (method === "POST" && pathname === "/v1/oauth/token") {
5726
+ const body = parseJsonObject2(await readBody2(request4, CONTROL_BODY_CAP_BYTES));
5727
+ const record = deps.credentialRecord();
5728
+ if (record === void 0) {
5729
+ answerServerJson(response, HTTP_SERVICE_UNAVAILABLE, { error: "the front door's self-hosted Remote Control surface is on but no credential has been minted for it" });
5730
+ return true;
5731
+ }
5732
+ if (body?.grant_type !== void 0 && body.grant_type !== "refresh_token") {
5733
+ answerServerJson(response, HTTP_STATUS.badRequest, { error: "unsupported_grant_type" });
5734
+ return true;
5735
+ }
5736
+ answerServerJson(response, HTTP_STATUS.ok, { access_token: record.accessToken, refresh_token: record.refreshToken, expires_in: RC_SELF_HOST_OAUTH_TOKEN_TTL_SECONDS, scope: RC_SELF_HOST_SCOPE_LIST.join(" ") });
5737
+ return true;
5738
+ }
5739
+ if (method === "GET" && pathname === "/v1/oauth/hello") {
5740
+ answerServerJson(response, HTTP_STATUS.ok, {});
5741
+ return true;
5742
+ }
5743
+ return false;
5744
+ }
5745
+ if (method === "POST" && pathname.startsWith("/api/eval/")) {
5746
+ await readBody2(request4, CONTROL_BODY_CAP_BYTES);
5747
+ answerServerJson(response, HTTP_STATUS.ok, { features: growthBookFeatures(), dateUpdated: Math.floor(deps.now() / MS_PER_SECOND2) });
5748
+ return true;
5749
+ }
5750
+ if (method === "GET" && pathname === "/api/oauth/profile") {
5751
+ const record = deps.credentialRecord();
5752
+ if (record === void 0) {
5753
+ answerServerJson(response, HTTP_SERVICE_UNAVAILABLE, { error: "the front door's self-hosted Remote Control surface is on but no credential has been minted for it" });
5754
+ return true;
5755
+ }
5756
+ answerServerJson(response, HTTP_STATUS.ok, {
5757
+ account: { uuid: record.accountUuid, display_name: "agent-shim self-hosted", created_at: (/* @__PURE__ */ new Date(0)).toISOString() },
5758
+ organization: { uuid: record.organizationUuid, organization_type: "claude_max" }
5759
+ });
5760
+ return true;
5761
+ }
5762
+ if (method === "GET" && pathname === "/api/claude_code/policy_limits") {
5763
+ answerServerJson(response, HTTP_STATUS.ok, {});
5764
+ return true;
5765
+ }
5766
+ if (method === "POST" && pathname === "/api/oauth/validate") {
5767
+ await readBody2(request4, CONTROL_BODY_CAP_BYTES);
5768
+ const record = deps.credentialRecord();
5769
+ if (record === void 0) {
5770
+ answerServerJson(response, HTTP_SERVICE_UNAVAILABLE, { error: "the front door's self-hosted Remote Control surface is on but no credential has been minted for it" });
5771
+ return true;
5772
+ }
5773
+ answerServerJson(response, HTTP_STATUS.ok, { scopes: [...RC_SELF_HOST_SCOPE_LIST], expiresAt: null, subscriptionType: "max", account_uuid: record.accountUuid, organization_uuid: record.organizationUuid });
5774
+ return true;
5775
+ }
5776
+ if (method === "POST" && (pathname === "/api/event_logging/v2/batch" || pathname === "/api/claude_code/metrics" || pathname === "/api/claude_cli_feedback")) {
5777
+ await readBody2(request4, CONTROL_BODY_CAP_BYTES);
5778
+ answerServerJson(response, HTTP_STATUS.ok, {});
5779
+ return true;
5780
+ }
5781
+ if (method === "GET" && pathname === "/api/hello") {
5782
+ answerServerJson(response, HTTP_STATUS.ok, {});
5783
+ return true;
5784
+ }
5785
+ return false;
5786
+ }
5787
+ };
5788
+ return {
5789
+ route,
5790
+ local,
5791
+ close: () => {
5792
+ clearInterval(timer);
5793
+ clearInterval(keepalive);
5794
+ for (const session of sessions.values()) {
5795
+ for (const sink of [...session.workerStreams, ...session.clientStreams]) {
5796
+ sink.retire();
5797
+ }
5798
+ }
5799
+ sessions.clear();
5800
+ }
5801
+ };
5802
+ }
5803
+
5804
+ // src/frontdoor/rcSelfHostMint.ts
5805
+ import path11 from "node:path";
5806
+
5807
+ // src/usage/account.ts
5808
+ import path10 from "node:path";
5809
+
5810
+ // src/usage/schema.ts
5811
+ import { z as z5 } from "zod";
5812
+ var USAGE_SCHEMA_VERSION = 1;
5813
+ var VersionSchema = z5.literal(USAGE_SCHEMA_VERSION);
5814
+ var InstantSchema = z5.iso.datetime();
5815
+ var TokenCountSchema = z5.number().int().nonnegative();
5816
+ var TokenUsageSchema = z5.strictObject({
5817
+ inputTokens: TokenCountSchema.optional(),
5818
+ outputTokens: TokenCountSchema.optional(),
5819
+ cacheCreationInputTokens: TokenCountSchema.optional(),
5820
+ cacheReadInputTokens: TokenCountSchema.optional()
5821
+ });
5822
+ var LIMIT_KINDS = ["rate-limited", "quota-exhausted"];
5823
+ var LimitClassificationSchema = z5.strictObject({
5824
+ kind: z5.enum(LIMIT_KINDS),
5825
+ /** Seconds to wait before retrying, from the response's `retry-after`. */
5826
+ retryAfterSeconds: z5.number().nonnegative().optional(),
5827
+ /** When the limiting window resets, from the upstream's own reset header. */
5828
+ resetAt: InstantSchema.optional(),
5829
+ /** The window the upstream named as the binding one (`anthropic-ratelimit-unified-representative-claim`), such as `five_hour` or `seven_day`. */
5830
+ window: z5.string().optional(),
5831
+ /** The signals the classification rests on, each `<name>=<value>` from a response header or the error body's `type` or `code`. Never the error message. */
5832
+ evidence: z5.array(z5.string())
5833
+ });
5834
+ var UsageRecordSchema = z5.strictObject({
5835
+ schemaVersion: VersionSchema,
5836
+ /** When the front door received the request. */
5837
+ at: InstantSchema,
5838
+ /** The launching identity, when the launch resolved one. */
5839
+ identity: z5.string().optional(),
5840
+ /** `anthropic` for an OAuth session's request to Claude Code's own API, otherwise the provider's name. */
5841
+ provider: z5.string(),
5842
+ /** The launch's session id, generated per launch. */
5843
+ sessionId: z5.string().optional(),
5844
+ /** The project the launch ran in (its git repository root), when the launch sent one: headroom launches do. */
5845
+ project: z5.string().optional(),
5846
+ /** The front-door route that served the request. */
5847
+ route: z5.string(),
5848
+ method: z5.string(),
5849
+ /** The API path as the upstream sees it (`/v1/messages`), without the provider prefix or a query string. */
5850
+ endpoint: z5.string(),
5851
+ /** The model the response named. */
5852
+ model: z5.string().optional(),
5853
+ status: z5.number().int(),
5854
+ /** Milliseconds from the request's arrival to its response head. */
5855
+ latencyMs: z5.number().int().nonnegative(),
5856
+ /** Milliseconds from the request's arrival to the end of its response body. */
5857
+ durationMs: z5.number().int().nonnegative(),
5858
+ /** Whether the client received the whole body. */
5859
+ outcome: z5.enum(["completed", "aborted"]),
5860
+ usage: TokenUsageSchema.optional(),
5861
+ /** The response's quota and rate-limit headers, by name (see `isRateLimitHeader`). */
5862
+ rateLimitHeaders: z5.record(z5.string(), z5.string()).optional(),
5863
+ limit: LimitClassificationSchema.optional(),
5864
+ /** The upstream's request id (`request-id`), for matching a record to the provider's own logs. */
5865
+ requestId: z5.string().optional()
5866
+ });
5867
+ var QuotaWindowSchema = z5.strictObject({
5868
+ /** The fraction of the window used, as the upstream reports it (0 to 1). */
5869
+ utilization: z5.number().nonnegative().optional(),
5870
+ resetsAt: InstantSchema.optional(),
5871
+ /** The window's own status (`allowed`, `allowed_warning`, `rejected`). */
5872
+ status: z5.string().optional()
5873
+ });
5874
+ var UnifiedRateLimitSchema = z5.strictObject({
5875
+ /** The overall status: `allowed`, `allowed_warning` or `rejected`. */
5876
+ status: z5.string().optional(),
5877
+ fiveHour: QuotaWindowSchema.optional(),
5878
+ sevenDay: QuotaWindowSchema.optional(),
5879
+ /** The window that currently binds. */
5880
+ representativeClaim: z5.string().optional(),
5881
+ /** When the binding window resets. */
5882
+ resetAt: InstantSchema.optional(),
5883
+ /** Whether usage beyond the plan (extra usage) is available: `allowed` or `rejected`. */
5884
+ overageStatus: z5.string().optional()
5885
+ });
5886
+ var RateLimitStateSchema = z5.strictObject({
5887
+ observedAt: InstantSchema,
5888
+ /** Every quota and rate-limit header on that response, by name. */
5889
+ headers: z5.record(z5.string(), z5.string()),
5890
+ unified: UnifiedRateLimitSchema.optional()
5891
+ });
5892
+ var LimitEventSchema = LimitClassificationSchema.extend({
5893
+ observedAt: InstantSchema,
5894
+ status: z5.number().int()
5895
+ });
5896
+ var ProviderQuotaWindowSchema = z5.strictObject({
5897
+ /** What the window measures, in the provider's terms (`tokens`, `tool-calls`). */
5898
+ measures: z5.string(),
5899
+ /** The window's length in milliseconds, when the provider's unit is one this project knows; absent for an unrecognised unit, with `period` carrying the raw code. */
5900
+ periodMs: z5.number().int().positive().optional(),
5901
+ /** The provider's own description of the period when `periodMs` could not be derived, such as `unit 4 x 1`. */
5902
+ period: z5.string().optional(),
5903
+ /** The fraction of the window used (0 to 1). */
5904
+ utilization: z5.number().nonnegative(),
5905
+ resetsAt: InstantSchema.optional(),
5906
+ /** Absolute counts, when the provider reports them for this window. */
5907
+ limit: z5.number().nonnegative().optional(),
5908
+ used: z5.number().nonnegative().optional(),
5909
+ remaining: z5.number().nonnegative().optional()
5910
+ });
5911
+ var ProviderQuotaSchema = z5.strictObject({
5912
+ observedAt: InstantSchema,
5913
+ /** Which usage endpoint produced it (`z.ai`). */
5914
+ source: z5.string(),
5915
+ /** The subscription level the endpoint reports, when it does. */
5916
+ level: z5.string().optional(),
5917
+ windows: z5.array(ProviderQuotaWindowSchema)
5918
+ });
5919
+ var ProviderUsageStateSchema = z5.strictObject({
5920
+ lastRequestAt: InstantSchema,
5921
+ lastStatus: z5.number().int(),
5922
+ lastModel: z5.string().optional(),
5923
+ /** The latest rate-limit state, from the last response that carried any rate-limit header. */
5924
+ rateLimit: RateLimitStateSchema.optional(),
5925
+ /** The latest classified refusal. It stays after later successes, so a reader compares its `resetAt` (or `observedAt` plus `retryAfterSeconds`) with the current time. */
5926
+ lastLimit: LimitEventSchema.optional(),
5927
+ /** The latest quota the provider's usage endpoint reported, for providers whose quota is not visible in response headers. */
5928
+ quota: ProviderQuotaSchema.optional()
5929
+ });
5930
+ var AccountMetadataSchema = z5.strictObject({
5931
+ accountUuid: z5.string().optional(),
5932
+ emailAddress: z5.string().optional(),
5933
+ displayName: z5.string().optional(),
5934
+ organizationUuid: z5.string().optional(),
5935
+ organizationName: z5.string().optional(),
5936
+ organizationType: z5.string().optional(),
5937
+ organizationRole: z5.string().optional(),
5938
+ workspaceRole: z5.string().optional(),
5939
+ billingType: z5.string().optional(),
5940
+ seatTier: z5.string().optional(),
5941
+ organizationRateLimitTier: z5.string().optional(),
5942
+ userRateLimitTier: z5.string().optional(),
5943
+ hasExtraUsageEnabled: z5.boolean().optional(),
5944
+ subscriptionCreatedAt: z5.string().optional(),
5945
+ accountCreatedAt: z5.string().optional()
5946
+ });
5947
+ var UsageSnapshotSchema = z5.strictObject({
5948
+ schemaVersion: VersionSchema,
5949
+ identity: z5.string(),
5950
+ updatedAt: InstantSchema,
5951
+ /** The identity's account metadata as of `updatedAt`. */
5952
+ account: AccountMetadataSchema.optional(),
5953
+ /** Latest state per provider, keyed by provider name (`anthropic` for OAuth sessions). */
5954
+ providers: z5.record(z5.string(), ProviderUsageStateSchema)
5955
+ });
5956
+
5957
+ // src/usage/account.ts
5958
+ var CLAUDE_JSON = ".claude.json";
5959
+ var AccountMetadataError = class extends CliError {
5960
+ constructor(file, detail) {
5961
+ super(`${file}: ${detail}, so its account metadata cannot be read.`);
5962
+ this.file = file;
5963
+ this.name = "AccountMetadataError";
5964
+ }
5965
+ file;
5966
+ };
5967
+ function isObject(value) {
5968
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5969
+ }
5970
+ function isIdentityName(name) {
5971
+ return IdentitySchema.shape.name.safeParse(name).success;
5972
+ }
5973
+ function claudeJsonPath(identitiesDir, identity) {
5974
+ return path10.join(identitiesDir, identity, CLAUDE_JSON);
5975
+ }
5976
+ function readAccountMetadata(fs12, identitiesDir, identity) {
5977
+ if (!isIdentityName(identity)) {
5978
+ throw new Error(`"${identity}" is not a valid identity name.`);
5979
+ }
5980
+ const file = claudeJsonPath(identitiesDir, identity);
5981
+ const raw = fs12.readFileUtf8(file);
5982
+ if (raw === void 0) {
5983
+ return void 0;
5984
+ }
5985
+ let parsed;
5986
+ try {
5987
+ parsed = JSON.parse(raw);
5988
+ } catch {
5989
+ throw new AccountMetadataError(file, "not valid JSON");
5990
+ }
5991
+ if (!isObject(parsed)) {
5992
+ throw new AccountMetadataError(file, "not a JSON object");
5993
+ }
5994
+ const oauthAccount = parsed.oauthAccount;
5995
+ if (!isObject(oauthAccount)) {
5996
+ return void 0;
5997
+ }
5998
+ const picked = {};
5999
+ for (const key of Object.keys(AccountMetadataSchema.shape)) {
6000
+ const value = oauthAccount[key];
6001
+ if (value !== null && value !== void 0) {
6002
+ picked[key] = value;
6003
+ }
6004
+ }
6005
+ const account = AccountMetadataSchema.safeParse(picked);
6006
+ if (!account.success) {
6007
+ throw new AccountMetadataError(file, account.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; "));
6008
+ }
6009
+ return account.data;
6010
+ }
6011
+
6012
+ // src/frontdoor/rcSelfHostMint.ts
6013
+ var CREDENTIALS_FILE = ".credentials.json";
6014
+ var CLAUDE_JSON2 = ".claude.json";
6015
+ var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
6016
+ var RC_SELF_HOST_RECORD_FILE = "credential.json";
6017
+ var SELF_HOST_EMAIL = "selfhost@agent-shim.invalid";
6018
+ var SELF_HOST_SUBSCRIPTION_TYPE = "max";
6019
+ function isRecord6(value) {
6020
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6021
+ }
6022
+ function readJsonObject(fs12, file) {
6023
+ const raw = fs12.readFileUtf8(file);
6024
+ if (raw === void 0) {
6025
+ return void 0;
6026
+ }
6027
+ let parsed;
6028
+ try {
6029
+ parsed = JSON.parse(raw);
6030
+ } catch {
6031
+ return void 0;
6032
+ }
6033
+ return isRecord6(parsed) ? parsed : void 0;
6034
+ }
6035
+ function readRcSelfHostRecord(fs12, frontdoorDir) {
6036
+ const parsed = readJsonObject(fs12, path11.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
6037
+ if (parsed === void 0) {
6038
+ return void 0;
6039
+ }
6040
+ const { accessToken, refreshToken, organizationUuid, accountUuid } = parsed;
6041
+ if (typeof accessToken !== "string" || accessToken === "" || typeof refreshToken !== "string" || refreshToken === "" || typeof organizationUuid !== "string" || organizationUuid === "" || typeof accountUuid !== "string" || accountUuid === "") {
6042
+ return void 0;
6043
+ }
6044
+ return { accessToken, refreshToken, organizationUuid, accountUuid };
6045
+ }
6046
+ function mintRcSelfHostCredential(deps) {
6047
+ if (!isIdentityName(deps.identity)) {
6048
+ throw new Error(`"${deps.identity}" is not a valid identity name.`);
6049
+ }
6050
+ const identityDir = path11.join(deps.identitiesDir, deps.identity);
6051
+ const credentialsFile = path11.join(identityDir, CREDENTIALS_FILE);
6052
+ const claudeJsonFile = path11.join(identityDir, CLAUDE_JSON2);
6053
+ const recordDir = path11.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
6054
+ const recordFile = path11.join(recordDir, RC_SELF_HOST_RECORD_FILE);
6055
+ const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
6056
+ const existingCredentials = readJsonObject(deps.fs, credentialsFile);
6057
+ const existingOauth = isRecord6(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
6058
+ const existingToken = typeof existingOauth?.accessToken === "string" && existingOauth.accessToken !== "" ? existingOauth.accessToken : void 0;
6059
+ const existingIsOwn = existingToken !== void 0 && previousRecord?.accessToken === existingToken;
6060
+ if (existingToken !== void 0 && !existingIsOwn && !deps.force) {
6061
+ throw new Error(
6062
+ `identity ${deps.identity} already holds an OAuth credential this door did not mint (a real claude.ai login): pass --force to replace it, or mint into an identity with no login. The self-hosted mode expects no Anthropic credential to be in play.`
6063
+ );
6064
+ }
6065
+ const accessToken = `sk-ant-oat${deps.randomToken()}`;
6066
+ const refreshToken = deps.randomToken();
6067
+ const organizationUuid = deps.newUuid();
6068
+ const accountUuid = deps.newUuid();
6069
+ const mintedAt = new Date(deps.now()).toISOString();
6070
+ deps.fs.mkdirPrivate(path11.dirname(credentialsFile));
6071
+ 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)}
6072
+ `);
6073
+ const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
6074
+ const existingBlock = (value) => isRecord6(value) ? value : {};
6075
+ deps.fs.writeFilePrivate(claudeJsonFile, `${JSON.stringify({
6076
+ ...claudeJson,
6077
+ oauthAccount: {
6078
+ ...existingBlock(claudeJson.oauthAccount),
6079
+ accountUuid,
6080
+ emailAddress: SELF_HOST_EMAIL,
6081
+ organizationUuid,
6082
+ organizationName: "agent-shim self-hosted",
6083
+ // The billing and creation fields exist so the CLI's "populate the account block if it is missing" step finds a complete block and skips its profile fetch; the door answers that fetch locally anyway, so these are the quiet path, not a load-bearing claim.
6084
+ billingType: "stripe_subscription",
6085
+ accountCreatedAt: mintedAt,
6086
+ subscriptionCreatedAt: mintedAt
5166
6087
  },
5167
- close: () => {
5168
- for (const attachment of attachments.values()) {
5169
- attachment.stop();
5170
- }
5171
- attachments.clear();
6088
+ cachedGrowthBookFeatures: {
6089
+ ...existingBlock(claudeJson.cachedGrowthBookFeatures),
6090
+ tengu_ccr_bridge: true,
6091
+ tengu_bridge_repl_v2: true,
6092
+ tengu_bridge_repl_v2_cse_shim_enabled: true
5172
6093
  }
5173
- };
6094
+ }, null, 2)}
6095
+ `);
6096
+ deps.fs.mkdirPrivate(recordDir);
6097
+ deps.fs.writeFilePrivate(recordFile, `${JSON.stringify({ accessToken, refreshToken, organizationUuid, accountUuid }, null, 2)}
6098
+ `);
6099
+ return { identity: deps.identity, organizationUuid, credentialsFile, claudeJsonFile, recordFile, replaced: existingIsOwn };
5174
6100
  }
5175
6101
 
5176
6102
  // src/frontdoor/ensure.ts
@@ -5178,32 +6104,32 @@ import { randomUUID as randomUUID3 } from "node:crypto";
5178
6104
 
5179
6105
  // src/headroom/state.ts
5180
6106
  import { createHash as createHash3 } from "node:crypto";
5181
- import path10 from "node:path";
5182
- import { z as z5 } from "zod";
6107
+ import path12 from "node:path";
6108
+ import { z as z6 } from "zod";
5183
6109
  var HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
5184
6110
  var HEADROOM_STATE_SCHEMA_VERSION = 2;
5185
- var HeadroomStateSchema = z5.strictObject({
6111
+ var HeadroomStateSchema = z6.strictObject({
5186
6112
  /** The supervisor process owning the daemon. Alive means someone is keeping headroom running. */
5187
- supervisorPid: z5.number().int().positive().optional(),
6113
+ supervisorPid: z6.number().int().positive().optional(),
5188
6114
  /** The headroom proxy process itself. Absent while the supervisor is between restarts. */
5189
- headroomPid: z5.number().int().positive().optional(),
6115
+ headroomPid: z6.number().int().positive().optional(),
5190
6116
  /**
5191
6117
  * The unix socket the proxy serves on, inside the owner-only socket directory. Absent until the proxy has passed its readiness check, so "socketPath is set" is itself the ready signal a launcher polls for. The front door reads it on every hop, so a restart (which keeps the generation's path) is followed without anything being relaunched.
5192
6118
  */
5193
- socketPath: z5.string().min(1).optional(),
6119
+ socketPath: z6.string().min(1).optional(),
5194
6120
  /** The `headroom --version` output of the running install. */
5195
- version: z5.string().optional(),
6121
+ version: z6.string().optional(),
5196
6122
  /** Hash of the allowlist the running proxy was started with, so a provider-file change is detected as drift. */
5197
- allowlistHash: z5.string().optional(),
6123
+ allowlistHash: z6.string().optional(),
5198
6124
  /** Hash of the token-saving settings the running proxy was started with, so a settings change is detected as drift. */
5199
- settingsHash: z5.string().optional(),
6125
+ settingsHash: z6.string().optional(),
5200
6126
  /** The install spec the running install was last installed from, so a `source` config change is detected as drift. */
5201
- installedSource: z5.string().optional(),
6127
+ installedSource: z6.string().optional(),
5202
6128
  /** The last fatal error, kept across shutdowns so `headroom status` can explain a daemon that is not running. */
5203
- lastError: z5.string().optional()
6129
+ lastError: z6.string().optional()
5204
6130
  });
5205
- var HeadroomSessionSchema = z5.strictObject({ pid: z5.number().int().positive(), startedAt: z5.number(), supervisorPid: z5.number().int().positive() });
5206
- var HeadroomLockSchema = z5.strictObject({ pid: z5.number().int().positive(), at: z5.number() });
6131
+ var HeadroomSessionSchema = z6.strictObject({ pid: z6.number().int().positive(), startedAt: z6.number(), supervisorPid: z6.number().int().positive() });
6132
+ var HeadroomLockSchema = z6.strictObject({ pid: z6.number().int().positive(), at: z6.number() });
5207
6133
  function parseJson(raw, schema) {
5208
6134
  if (raw === void 0 || raw.trim() === "") {
5209
6135
  return void 0;
@@ -5219,7 +6145,7 @@ function readHeadroomState(fs12, stateFile) {
5219
6145
  }
5220
6146
  }
5221
6147
  function writeHeadroomState(fs12, stateFile, state) {
5222
- fs12.mkdirp(path10.dirname(stateFile));
6148
+ fs12.mkdirp(path12.dirname(stateFile));
5223
6149
  fs12.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
5224
6150
  `);
5225
6151
  }
@@ -5247,7 +6173,7 @@ function readAllProviders(fs12, providersDir) {
5247
6173
  continue;
5248
6174
  }
5249
6175
  try {
5250
- const parsed = parseJson(fs12.readFileUtf8(path10.join(providersDir, name)), ProviderSchema);
6176
+ const parsed = parseJson(fs12.readFileUtf8(path12.join(providersDir, name)), ProviderSchema);
5251
6177
  if (parsed !== void 0) {
5252
6178
  result.push({ name: name.slice(0, -".json".length), provider: parsed });
5253
6179
  }
@@ -5259,11 +6185,11 @@ function readAllProviders(fs12, providersDir) {
5259
6185
  }
5260
6186
  function writeSession(fs12, sessionsDir, session) {
5261
6187
  fs12.mkdirp(sessionsDir);
5262
- fs12.writeFileUtf8(path10.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
6188
+ fs12.writeFileUtf8(path12.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
5263
6189
  `);
5264
6190
  }
5265
6191
  function removeSession(fs12, sessionsDir, pid) {
5266
- fs12.removeRecursive(path10.join(sessionsDir, `${String(pid)}.json`));
6192
+ fs12.removeRecursive(path12.join(sessionsDir, `${String(pid)}.json`));
5267
6193
  }
5268
6194
  function listSessions(fs12, sessionsDir) {
5269
6195
  const sessions = [];
@@ -5272,7 +6198,7 @@ function listSessions(fs12, sessionsDir) {
5272
6198
  continue;
5273
6199
  }
5274
6200
  try {
5275
- const parsed = parseJson(fs12.readFileUtf8(path10.join(sessionsDir, name)), HeadroomSessionSchema);
6201
+ const parsed = parseJson(fs12.readFileUtf8(path12.join(sessionsDir, name)), HeadroomSessionSchema);
5276
6202
  if (parsed !== void 0) {
5277
6203
  sessions.push(parsed);
5278
6204
  }
@@ -5377,214 +6303,7 @@ function ensureFrontDoor(params) {
5377
6303
  }
5378
6304
 
5379
6305
  // src/usage/read.ts
5380
- import path12 from "node:path";
5381
-
5382
- // src/usage/account.ts
5383
- import path11 from "node:path";
5384
-
5385
- // src/usage/schema.ts
5386
- import { z as z6 } from "zod";
5387
- var USAGE_SCHEMA_VERSION = 1;
5388
- var VersionSchema = z6.literal(USAGE_SCHEMA_VERSION);
5389
- var InstantSchema = z6.iso.datetime();
5390
- var TokenCountSchema = z6.number().int().nonnegative();
5391
- var TokenUsageSchema = z6.strictObject({
5392
- inputTokens: TokenCountSchema.optional(),
5393
- outputTokens: TokenCountSchema.optional(),
5394
- cacheCreationInputTokens: TokenCountSchema.optional(),
5395
- cacheReadInputTokens: TokenCountSchema.optional()
5396
- });
5397
- var LIMIT_KINDS = ["rate-limited", "quota-exhausted"];
5398
- var LimitClassificationSchema = z6.strictObject({
5399
- kind: z6.enum(LIMIT_KINDS),
5400
- /** Seconds to wait before retrying, from the response's `retry-after`. */
5401
- retryAfterSeconds: z6.number().nonnegative().optional(),
5402
- /** When the limiting window resets, from the upstream's own reset header. */
5403
- resetAt: InstantSchema.optional(),
5404
- /** The window the upstream named as the binding one (`anthropic-ratelimit-unified-representative-claim`), such as `five_hour` or `seven_day`. */
5405
- window: z6.string().optional(),
5406
- /** The signals the classification rests on, each `<name>=<value>` from a response header or the error body's `type` or `code`. Never the error message. */
5407
- evidence: z6.array(z6.string())
5408
- });
5409
- var UsageRecordSchema = z6.strictObject({
5410
- schemaVersion: VersionSchema,
5411
- /** When the front door received the request. */
5412
- at: InstantSchema,
5413
- /** The launching identity, when the launch resolved one. */
5414
- identity: z6.string().optional(),
5415
- /** `anthropic` for an OAuth session's request to Claude Code's own API, otherwise the provider's name. */
5416
- provider: z6.string(),
5417
- /** The launch's session id, generated per launch. */
5418
- sessionId: z6.string().optional(),
5419
- /** The project the launch ran in (its git repository root), when the launch sent one: headroom launches do. */
5420
- project: z6.string().optional(),
5421
- /** The front-door route that served the request. */
5422
- route: z6.string(),
5423
- method: z6.string(),
5424
- /** The API path as the upstream sees it (`/v1/messages`), without the provider prefix or a query string. */
5425
- endpoint: z6.string(),
5426
- /** The model the response named. */
5427
- model: z6.string().optional(),
5428
- status: z6.number().int(),
5429
- /** Milliseconds from the request's arrival to its response head. */
5430
- latencyMs: z6.number().int().nonnegative(),
5431
- /** Milliseconds from the request's arrival to the end of its response body. */
5432
- durationMs: z6.number().int().nonnegative(),
5433
- /** Whether the client received the whole body. */
5434
- outcome: z6.enum(["completed", "aborted"]),
5435
- usage: TokenUsageSchema.optional(),
5436
- /** The response's quota and rate-limit headers, by name (see `isRateLimitHeader`). */
5437
- rateLimitHeaders: z6.record(z6.string(), z6.string()).optional(),
5438
- limit: LimitClassificationSchema.optional(),
5439
- /** The upstream's request id (`request-id`), for matching a record to the provider's own logs. */
5440
- requestId: z6.string().optional()
5441
- });
5442
- var QuotaWindowSchema = z6.strictObject({
5443
- /** The fraction of the window used, as the upstream reports it (0 to 1). */
5444
- utilization: z6.number().nonnegative().optional(),
5445
- resetsAt: InstantSchema.optional(),
5446
- /** The window's own status (`allowed`, `allowed_warning`, `rejected`). */
5447
- status: z6.string().optional()
5448
- });
5449
- var UnifiedRateLimitSchema = z6.strictObject({
5450
- /** The overall status: `allowed`, `allowed_warning` or `rejected`. */
5451
- status: z6.string().optional(),
5452
- fiveHour: QuotaWindowSchema.optional(),
5453
- sevenDay: QuotaWindowSchema.optional(),
5454
- /** The window that currently binds. */
5455
- representativeClaim: z6.string().optional(),
5456
- /** When the binding window resets. */
5457
- resetAt: InstantSchema.optional(),
5458
- /** Whether usage beyond the plan (extra usage) is available: `allowed` or `rejected`. */
5459
- overageStatus: z6.string().optional()
5460
- });
5461
- var RateLimitStateSchema = z6.strictObject({
5462
- observedAt: InstantSchema,
5463
- /** Every quota and rate-limit header on that response, by name. */
5464
- headers: z6.record(z6.string(), z6.string()),
5465
- unified: UnifiedRateLimitSchema.optional()
5466
- });
5467
- var LimitEventSchema = LimitClassificationSchema.extend({
5468
- observedAt: InstantSchema,
5469
- status: z6.number().int()
5470
- });
5471
- var ProviderQuotaWindowSchema = z6.strictObject({
5472
- /** What the window measures, in the provider's terms (`tokens`, `tool-calls`). */
5473
- measures: z6.string(),
5474
- /** The window's length in milliseconds, when the provider's unit is one this project knows; absent for an unrecognised unit, with `period` carrying the raw code. */
5475
- periodMs: z6.number().int().positive().optional(),
5476
- /** The provider's own description of the period when `periodMs` could not be derived, such as `unit 4 x 1`. */
5477
- period: z6.string().optional(),
5478
- /** The fraction of the window used (0 to 1). */
5479
- utilization: z6.number().nonnegative(),
5480
- resetsAt: InstantSchema.optional(),
5481
- /** Absolute counts, when the provider reports them for this window. */
5482
- limit: z6.number().nonnegative().optional(),
5483
- used: z6.number().nonnegative().optional(),
5484
- remaining: z6.number().nonnegative().optional()
5485
- });
5486
- var ProviderQuotaSchema = z6.strictObject({
5487
- observedAt: InstantSchema,
5488
- /** Which usage endpoint produced it (`z.ai`). */
5489
- source: z6.string(),
5490
- /** The subscription level the endpoint reports, when it does. */
5491
- level: z6.string().optional(),
5492
- windows: z6.array(ProviderQuotaWindowSchema)
5493
- });
5494
- var ProviderUsageStateSchema = z6.strictObject({
5495
- lastRequestAt: InstantSchema,
5496
- lastStatus: z6.number().int(),
5497
- lastModel: z6.string().optional(),
5498
- /** The latest rate-limit state, from the last response that carried any rate-limit header. */
5499
- rateLimit: RateLimitStateSchema.optional(),
5500
- /** The latest classified refusal. It stays after later successes, so a reader compares its `resetAt` (or `observedAt` plus `retryAfterSeconds`) with the current time. */
5501
- lastLimit: LimitEventSchema.optional(),
5502
- /** The latest quota the provider's usage endpoint reported, for providers whose quota is not visible in response headers. */
5503
- quota: ProviderQuotaSchema.optional()
5504
- });
5505
- var AccountMetadataSchema = z6.strictObject({
5506
- accountUuid: z6.string().optional(),
5507
- emailAddress: z6.string().optional(),
5508
- displayName: z6.string().optional(),
5509
- organizationUuid: z6.string().optional(),
5510
- organizationName: z6.string().optional(),
5511
- organizationType: z6.string().optional(),
5512
- organizationRole: z6.string().optional(),
5513
- workspaceRole: z6.string().optional(),
5514
- billingType: z6.string().optional(),
5515
- seatTier: z6.string().optional(),
5516
- organizationRateLimitTier: z6.string().optional(),
5517
- userRateLimitTier: z6.string().optional(),
5518
- hasExtraUsageEnabled: z6.boolean().optional(),
5519
- subscriptionCreatedAt: z6.string().optional(),
5520
- accountCreatedAt: z6.string().optional()
5521
- });
5522
- var UsageSnapshotSchema = z6.strictObject({
5523
- schemaVersion: VersionSchema,
5524
- identity: z6.string(),
5525
- updatedAt: InstantSchema,
5526
- /** The identity's account metadata as of `updatedAt`. */
5527
- account: AccountMetadataSchema.optional(),
5528
- /** Latest state per provider, keyed by provider name (`anthropic` for OAuth sessions). */
5529
- providers: z6.record(z6.string(), ProviderUsageStateSchema)
5530
- });
5531
-
5532
- // src/usage/account.ts
5533
- var CLAUDE_JSON = ".claude.json";
5534
- var AccountMetadataError = class extends CliError {
5535
- constructor(file, detail) {
5536
- super(`${file}: ${detail}, so its account metadata cannot be read.`);
5537
- this.file = file;
5538
- this.name = "AccountMetadataError";
5539
- }
5540
- file;
5541
- };
5542
- function isObject(value) {
5543
- return typeof value === "object" && value !== null && !Array.isArray(value);
5544
- }
5545
- function isIdentityName(name) {
5546
- return IdentitySchema.shape.name.safeParse(name).success;
5547
- }
5548
- function claudeJsonPath(identitiesDir, identity) {
5549
- return path11.join(identitiesDir, identity, CLAUDE_JSON);
5550
- }
5551
- function readAccountMetadata(fs12, identitiesDir, identity) {
5552
- if (!isIdentityName(identity)) {
5553
- throw new Error(`"${identity}" is not a valid identity name.`);
5554
- }
5555
- const file = claudeJsonPath(identitiesDir, identity);
5556
- const raw = fs12.readFileUtf8(file);
5557
- if (raw === void 0) {
5558
- return void 0;
5559
- }
5560
- let parsed;
5561
- try {
5562
- parsed = JSON.parse(raw);
5563
- } catch {
5564
- throw new AccountMetadataError(file, "not valid JSON");
5565
- }
5566
- if (!isObject(parsed)) {
5567
- throw new AccountMetadataError(file, "not a JSON object");
5568
- }
5569
- const oauthAccount = parsed.oauthAccount;
5570
- if (!isObject(oauthAccount)) {
5571
- return void 0;
5572
- }
5573
- const picked = {};
5574
- for (const key of Object.keys(AccountMetadataSchema.shape)) {
5575
- const value = oauthAccount[key];
5576
- if (value !== null && value !== void 0) {
5577
- picked[key] = value;
5578
- }
5579
- }
5580
- const account = AccountMetadataSchema.safeParse(picked);
5581
- if (!account.success) {
5582
- throw new AccountMetadataError(file, account.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; "));
5583
- }
5584
- return account.data;
5585
- }
5586
-
5587
- // src/usage/read.ts
6306
+ import path13 from "node:path";
5588
6307
  var SEGMENT_RE = /^(\d{4}-\d{2}-\d{2})\.(\d+)\.jsonl$/;
5589
6308
  var DAY_MS = 864e5;
5590
6309
  function listLogSegments(fs12, logDir) {
@@ -5605,7 +6324,7 @@ function readUsageLog(fs12, logDir, options = {}) {
5605
6324
  if (sinceMs !== void 0 && segment.endsAt <= sinceMs) {
5606
6325
  continue;
5607
6326
  }
5608
- const contents = fs12.readFileUtf8(path12.join(logDir, segment.name));
6327
+ const contents = fs12.readFileUtf8(path13.join(logDir, segment.name));
5609
6328
  if (contents === void 0) {
5610
6329
  continue;
5611
6330
  }
@@ -5647,7 +6366,7 @@ function snapshotPath(snapshotsDir, identity) {
5647
6366
  if (!isIdentityName(identity)) {
5648
6367
  throw new Error(`"${identity}" is not a valid identity name.`);
5649
6368
  }
5650
- return path12.join(snapshotsDir, `${identity}.json`);
6369
+ return path13.join(snapshotsDir, `${identity}.json`);
5651
6370
  }
5652
6371
  function readUsageSnapshot(fs12, snapshotsDir, identity) {
5653
6372
  const file = snapshotPath(snapshotsDir, identity);
@@ -5682,13 +6401,13 @@ function listUsageSnapshots(fs12, snapshotsDir) {
5682
6401
  }
5683
6402
 
5684
6403
  // src/usage/preflight.ts
5685
- var MS_PER_SECOND2 = 1e3;
6404
+ var MS_PER_SECOND3 = 1e3;
5686
6405
  var SECONDS_PER_MINUTE = 60;
5687
6406
  var MINUTES_PER_HOUR = 60;
5688
6407
  var HOURS_PER_DAY = 24;
5689
6408
  var WARNING_STATUSES = /* @__PURE__ */ new Set(["allowed_warning", "rejected"]);
5690
6409
  function formatAge(ms) {
5691
- const minutes = Math.floor(ms / (MS_PER_SECOND2 * SECONDS_PER_MINUTE));
6410
+ const minutes = Math.floor(ms / (MS_PER_SECOND3 * SECONDS_PER_MINUTE));
5692
6411
  if (minutes < MINUTES_PER_HOUR) {
5693
6412
  return `${String(Math.max(minutes, 0))}m`;
5694
6413
  }
@@ -5766,13 +6485,13 @@ function planOf(account) {
5766
6485
  }
5767
6486
 
5768
6487
  // src/usage/rateLimit.ts
5769
- var MS_PER_SECOND3 = 1e3;
6488
+ var MS_PER_SECOND4 = 1e3;
5770
6489
  function epochSecondsToIso(value) {
5771
6490
  if (value === void 0) {
5772
6491
  return void 0;
5773
6492
  }
5774
6493
  const seconds = Number(value);
5775
- return Number.isFinite(seconds) && seconds > 0 ? new Date(seconds * MS_PER_SECOND3).toISOString() : void 0;
6494
+ return Number.isFinite(seconds) && seconds > 0 ? new Date(seconds * MS_PER_SECOND4).toISOString() : void 0;
5776
6495
  }
5777
6496
  function nonNegativeNumber(value) {
5778
6497
  if (value === void 0 || value.trim() === "") {
@@ -5829,7 +6548,7 @@ var ErrorObjectSchema = z8.looseObject({
5829
6548
  var ANTHROPIC_PROVIDER = "anthropic";
5830
6549
 
5831
6550
  // src/usage/pick.ts
5832
- var MS_PER_SECOND4 = 1e3;
6551
+ var MS_PER_SECOND5 = 1e3;
5833
6552
  var MS_PER_HOUR = 36e5;
5834
6553
  var HOURS_PER_DAY2 = 24;
5835
6554
  var FIVE_HOURS = 5;
@@ -5851,7 +6570,7 @@ function limitBlockedUntil(state, nowMs) {
5851
6570
  if (Date.parse(state.lastRequestAt) > Date.parse(limit.observedAt)) {
5852
6571
  return void 0;
5853
6572
  }
5854
- const until = limit.resetAt === void 0 ? limit.retryAfterSeconds === void 0 ? void 0 : Date.parse(limit.observedAt) + limit.retryAfterSeconds * MS_PER_SECOND4 : Date.parse(limit.resetAt);
6573
+ const until = limit.resetAt === void 0 ? limit.retryAfterSeconds === void 0 ? void 0 : Date.parse(limit.observedAt) + limit.retryAfterSeconds * MS_PER_SECOND5 : Date.parse(limit.resetAt);
5855
6574
  return until !== void 0 && until > nowMs ? until : void 0;
5856
6575
  }
5857
6576
  function windowBlockedUntil(windows) {
@@ -5928,10 +6647,10 @@ function assess(member, nowMs) {
5928
6647
  return { candidate: { ...base, class: "unknown", reasons: ["quota windows reported no utilisation", ...windowReasons, ...planReasons] } };
5929
6648
  }
5930
6649
  const remaining = Math.max(0, 1 - basis.window.utilization);
5931
- const untilResetMs = basis.window.resetsAtMs === void 0 ? basis.windowMs : Math.max(basis.window.resetsAtMs - nowMs, MS_PER_SECOND4);
6650
+ const untilResetMs = basis.window.resetsAtMs === void 0 ? basis.windowMs : Math.max(basis.window.resetsAtMs - nowMs, MS_PER_SECOND5);
5932
6651
  const score = remaining * plan.capacity / (untilResetMs / MS_PER_HOUR);
5933
6652
  const fiveRemaining = five?.utilization === void 0 ? void 0 : Math.max(0, 1 - five.utilization);
5934
- const fiveUntil = five?.resetsAtMs === void 0 ? FIVE_HOUR_WINDOW_MS : Math.max(five.resetsAtMs - nowMs, MS_PER_SECOND4);
6653
+ const fiveUntil = five?.resetsAtMs === void 0 ? FIVE_HOUR_WINDOW_MS : Math.max(five.resetsAtMs - nowMs, MS_PER_SECOND5);
5935
6654
  const burn = fiveHourBurn(member.records);
5936
6655
  return {
5937
6656
  candidate: { ...base, class: "scored", score, reasons: [...windowReasons.map((reason, index) => index === windowReasons.length - 1 ? `${reason}${observedAgo}` : reason), ...planReasons] },
@@ -5981,7 +6700,7 @@ function rankPool(input) {
5981
6700
  }
5982
6701
 
5983
6702
  // src/usage/poolPick.ts
5984
- import path13 from "node:path";
6703
+ import path14 from "node:path";
5985
6704
  import { z as z9 } from "zod";
5986
6705
 
5987
6706
  // src/usage/store.ts
@@ -6048,13 +6767,13 @@ function recordStickyPick(fs12, picksFile, directory, identity, nowMs) {
6048
6767
  const current = readPicksFile(fs12, picksFile).file.picks;
6049
6768
  const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
6050
6769
  const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
6051
- fs12.mkdirPrivate(path13.dirname(picksFile));
6770
+ fs12.mkdirPrivate(path14.dirname(picksFile));
6052
6771
  fs12.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
6053
6772
  `);
6054
6773
  }
6055
6774
 
6056
6775
  // src/launcher/identity.ts
6057
- import path14 from "node:path";
6776
+ import path15 from "node:path";
6058
6777
  function poolNameOf(selector) {
6059
6778
  return selector.startsWith(POOL_SELECTOR_PREFIX) ? selector.slice(POOL_SELECTOR_PREFIX.length) : void 0;
6060
6779
  }
@@ -6103,7 +6822,7 @@ function decideConfigProfile(params) {
6103
6822
  return { source: "none" };
6104
6823
  }
6105
6824
  function loadIdentity(identitiesDir, name, fs12) {
6106
- return loadConfigFile(path14.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
6825
+ return loadConfigFile(path15.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
6107
6826
  }
6108
6827
 
6109
6828
  // src/launcher/pool.ts
@@ -6318,7 +7037,7 @@ function hashSettings(settings) {
6318
7037
  }
6319
7038
 
6320
7039
  // src/headroom/socket.ts
6321
- import path15 from "node:path";
7040
+ import path16 from "node:path";
6322
7041
  var GROUP_OR_OTHER_BITS = 63;
6323
7042
  var OCTAL_RADIX = 8;
6324
7043
  var MODE_DIGITS = 4;
@@ -6327,7 +7046,7 @@ var HEADROOM_SOCKET_NAME = /^(\d+)\.sock$/;
6327
7046
  var UNIX_SOCKET_PATH_MAX_BYTES = 103;
6328
7047
  var PLATFORMS_WITHOUT_UNIX_SOCKETS = ["win32"];
6329
7048
  function headroomSocketPath(paths, supervisorPid) {
6330
- return path15.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
7049
+ return path16.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
6331
7050
  }
6332
7051
  function platformRefusal(platform) {
6333
7052
  return PLATFORMS_WITHOUT_UNIX_SOCKETS.includes(platform) ? `headroom routing needs a unix domain socket, which headroom cannot serve on ${platform}; agent-shim never falls back to a TCP port for this hop` : void 0;
@@ -6376,7 +7095,7 @@ function pruneStaleHeadroomSockets(fs12, paths, isRunning) {
6376
7095
  if (pid === void 0 || isRunning(Number.parseInt(pid, 10))) {
6377
7096
  continue;
6378
7097
  }
6379
- fs12.removeRecursive(path15.join(paths.headroomSocketDir, name));
7098
+ fs12.removeRecursive(path16.join(paths.headroomSocketDir, name));
6380
7099
  removed.push(name);
6381
7100
  }
6382
7101
  return removed;
@@ -6700,14 +7419,14 @@ function evaluateAmbientCredentialGuard(params) {
6700
7419
  // src/paths.ts
6701
7420
  import fs3 from "node:fs";
6702
7421
  import os3 from "node:os";
6703
- import path16 from "node:path";
7422
+ import path17 from "node:path";
6704
7423
  function resolveAgentShimHome(env = process.env, home = os3.homedir(), isDirectory = isExistingDirectory) {
6705
7424
  const fromEnv = env.AGENT_SHIM_HOME;
6706
7425
  if (fromEnv !== void 0 && fromEnv !== "") {
6707
7426
  return fromEnv;
6708
7427
  }
6709
- const current = path16.join(home, HOME_DIRNAME);
6710
- const legacy = path16.join(home, LEGACY_HOME_DIRNAME);
7428
+ const current = path17.join(home, HOME_DIRNAME);
7429
+ const legacy = path17.join(home, LEGACY_HOME_DIRNAME);
6711
7430
  return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
6712
7431
  }
6713
7432
  function isExistingDirectory(candidate) {
@@ -6718,41 +7437,41 @@ function resolveClaudeHome() {
6718
7437
  if (fromEnv !== void 0 && fromEnv !== "") {
6719
7438
  return fromEnv;
6720
7439
  }
6721
- return path16.join(os3.homedir(), ".claude");
7440
+ return path17.join(os3.homedir(), ".claude");
6722
7441
  }
6723
7442
  function buildLayoutPaths(root) {
6724
7443
  return {
6725
7444
  root,
6726
- identitiesDir: path16.join(root, "identities"),
6727
- configProfilesDir: path16.join(root, "config-profiles"),
6728
- providersDir: path16.join(root, "providers"),
6729
- directoryRulesFile: path16.join(root, "directory-rules.json"),
6730
- activeIdentityFile: path16.join(root, "active-identity"),
6731
- globalConfigFile: path16.join(root, "config.json"),
6732
- categoriesLocalFile: path16.join(root, "categories.local.json"),
6733
- claudeShimFile: path16.join(root, "claude-shim.json"),
6734
- headroomDir: path16.join(root, "headroom"),
6735
- headroomStateFile: path16.join(root, "headroom", `state.v${String(HEADROOM_STATE_SCHEMA_VERSION)}.json`),
6736
- headroomSocketDir: path16.join(root, "headroom", "run"),
6737
- headroomLockFile: path16.join(root, "headroom", "start.lock"),
6738
- headroomSessionsDir: path16.join(root, "headroom", "sessions"),
6739
- logsDir: path16.join(root, "logs"),
6740
- headroomLogPath: path16.join(root, "logs", "headroom.log"),
6741
- frontdoorDir: path16.join(root, "frontdoor"),
6742
- frontdoorCaDir: path16.join(root, "frontdoor", "ca"),
6743
- frontdoorCaCertFile: path16.join(root, "frontdoor", "ca", "ca.pem"),
6744
- frontdoorCaKeyFile: path16.join(root, "frontdoor", "ca", "ca.key"),
6745
- frontdoorCaBundlesDir: path16.join(root, "frontdoor", "ca", "bundles"),
6746
- frontdoorStateFile: path16.join(root, "frontdoor", "state.json"),
6747
- frontdoorLockFile: path16.join(root, "frontdoor", "start.lock"),
6748
- frontdoorControlTokenFile: path16.join(root, "frontdoor", "control-token"),
6749
- frontdoorSessionsDir: path16.join(root, "frontdoor", "sessions"),
6750
- frontdoorRcCredentialsDir: path16.join(root, "frontdoor", "rc-credentials"),
6751
- frontdoorLogPath: path16.join(root, "logs", "frontdoor.log"),
6752
- usageDir: path16.join(root, "usage"),
6753
- usageLogDir: path16.join(root, "usage", "log"),
6754
- usageSnapshotsDir: path16.join(root, "usage", "snapshots"),
6755
- usagePicksFile: path16.join(root, "usage", "picks.json")
7445
+ identitiesDir: path17.join(root, "identities"),
7446
+ configProfilesDir: path17.join(root, "config-profiles"),
7447
+ providersDir: path17.join(root, "providers"),
7448
+ directoryRulesFile: path17.join(root, "directory-rules.json"),
7449
+ activeIdentityFile: path17.join(root, "active-identity"),
7450
+ globalConfigFile: path17.join(root, "config.json"),
7451
+ categoriesLocalFile: path17.join(root, "categories.local.json"),
7452
+ claudeShimFile: path17.join(root, "claude-shim.json"),
7453
+ headroomDir: path17.join(root, "headroom"),
7454
+ headroomStateFile: path17.join(root, "headroom", `state.v${String(HEADROOM_STATE_SCHEMA_VERSION)}.json`),
7455
+ headroomSocketDir: path17.join(root, "headroom", "run"),
7456
+ headroomLockFile: path17.join(root, "headroom", "start.lock"),
7457
+ headroomSessionsDir: path17.join(root, "headroom", "sessions"),
7458
+ logsDir: path17.join(root, "logs"),
7459
+ headroomLogPath: path17.join(root, "logs", "headroom.log"),
7460
+ frontdoorDir: path17.join(root, "frontdoor"),
7461
+ frontdoorCaDir: path17.join(root, "frontdoor", "ca"),
7462
+ frontdoorCaCertFile: path17.join(root, "frontdoor", "ca", "ca.pem"),
7463
+ frontdoorCaKeyFile: path17.join(root, "frontdoor", "ca", "ca.key"),
7464
+ frontdoorCaBundlesDir: path17.join(root, "frontdoor", "ca", "bundles"),
7465
+ frontdoorStateFile: path17.join(root, "frontdoor", "state.json"),
7466
+ frontdoorLockFile: path17.join(root, "frontdoor", "start.lock"),
7467
+ frontdoorControlTokenFile: path17.join(root, "frontdoor", "control-token"),
7468
+ frontdoorSessionsDir: path17.join(root, "frontdoor", "sessions"),
7469
+ frontdoorRcCredentialsDir: path17.join(root, "frontdoor", "rc-credentials"),
7470
+ frontdoorLogPath: path17.join(root, "logs", "frontdoor.log"),
7471
+ usageDir: path17.join(root, "usage"),
7472
+ usageLogDir: path17.join(root, "usage", "log"),
7473
+ usageSnapshotsDir: path17.join(root, "usage", "snapshots"),
7474
+ usagePicksFile: path17.join(root, "usage", "picks.json")
6756
7475
  };
6757
7476
  }
6758
7477
  function resolveLayoutPaths() {
@@ -6761,11 +7480,11 @@ function resolveLayoutPaths() {
6761
7480
 
6762
7481
  // src/identityStore.ts
6763
7482
  import fs5 from "node:fs";
6764
- import path18 from "node:path";
7483
+ import path19 from "node:path";
6765
7484
 
6766
7485
  // src/configProfilesStore.ts
6767
7486
  import fs4 from "node:fs";
6768
- import path17 from "node:path";
7487
+ import path18 from "node:path";
6769
7488
  var ProfileNotFoundError = class extends CliError {
6770
7489
  constructor(profileName) {
6771
7490
  super(`No configuration profile named "${profileName}". Run \`agent-shim profile add ${profileName}\` first.`);
@@ -6791,7 +7510,7 @@ var InvalidCategoryNameError = class extends CliError {
6791
7510
  categoryName;
6792
7511
  };
6793
7512
  function profileJsonPath(paths, name) {
6794
- return path17.join(paths.configProfilesDir, `${name}.json`);
7513
+ return path18.join(paths.configProfilesDir, `${name}.json`);
6795
7514
  }
6796
7515
  function profileExists(paths, name) {
6797
7516
  return fs4.existsSync(profileJsonPath(paths, name));
@@ -6979,7 +7698,7 @@ var InvalidIdentityNameError = class extends CliError {
6979
7698
  attemptedName;
6980
7699
  };
6981
7700
  function identityJsonPath(paths, name) {
6982
- return path18.join(paths.identitiesDir, name, "identity.json");
7701
+ return path19.join(paths.identitiesDir, name, "identity.json");
6983
7702
  }
6984
7703
  function identityExists(paths, name) {
6985
7704
  return fs5.existsSync(identityJsonPath(paths, name));
@@ -7080,7 +7799,7 @@ function setIdentityCredential(paths, identityName, change) {
7080
7799
  });
7081
7800
  }
7082
7801
  function belongsToIdentity(entry, name) {
7083
- return entry === name || entry === path18.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
7802
+ return entry === name || entry === path19.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
7084
7803
  }
7085
7804
  function removeIdentity(paths, name) {
7086
7805
  if (!identityExists(paths, name)) {
@@ -7088,7 +7807,7 @@ function removeIdentity(paths, name) {
7088
7807
  }
7089
7808
  for (const entry of fs5.readdirSync(paths.identitiesDir)) {
7090
7809
  if (belongsToIdentity(entry, name)) {
7091
- fs5.rmSync(path18.join(paths.identitiesDir, entry), { recursive: true, force: true });
7810
+ fs5.rmSync(path19.join(paths.identitiesDir, entry), { recursive: true, force: true });
7092
7811
  }
7093
7812
  }
7094
7813
  if (readActiveIdentity(paths) === name) {
@@ -7098,7 +7817,7 @@ function removeIdentity(paths, name) {
7098
7817
 
7099
7818
  // src/providersStore.ts
7100
7819
  import fs6 from "node:fs";
7101
- import path19 from "node:path";
7820
+ import path20 from "node:path";
7102
7821
 
7103
7822
  // src/credentialCache.ts
7104
7823
  import { z as z12 } from "zod";
@@ -7363,7 +8082,7 @@ var InvalidProviderNameError = class extends CliError {
7363
8082
  };
7364
8083
  var PROVIDER_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._@-]*$/;
7365
8084
  function providerJsonPath(paths, name) {
7366
- return path19.join(paths.providersDir, `${name}.json`);
8085
+ return path20.join(paths.providersDir, `${name}.json`);
7367
8086
  }
7368
8087
  function providerExists(paths, name) {
7369
8088
  return fs6.existsSync(providerJsonPath(paths, name));
@@ -7371,14 +8090,14 @@ function providerExists(paths, name) {
7371
8090
  var LEGACY_PROVIDER_FIELDS = ["tokenEnv", "tokenCommand", "authScheme"];
7372
8091
  var LEGACY_ENV_CREDENTIAL_KEYS = Object.values(CREDENTIAL_TARGET_VARS);
7373
8092
  var LEGACY_LITERAL_PLACEHOLDER = "<the value of env.ANTHROPIC_AUTH_TOKEN>";
7374
- function isRecord5(value) {
8093
+ function isRecord7(value) {
7375
8094
  return typeof value === "object" && value !== null && !Array.isArray(value);
7376
8095
  }
7377
8096
  function legacyProviderConversion(raw) {
7378
- if (!isRecord5(raw) || "credential" in raw) {
8097
+ if (!isRecord7(raw) || "credential" in raw) {
7379
8098
  return void 0;
7380
8099
  }
7381
- const env = isRecord5(raw.env) ? raw.env : void 0;
8100
+ const env = isRecord7(raw.env) ? raw.env : void 0;
7382
8101
  const legacyEnvKeys = env === void 0 ? [] : Object.keys(env).filter((key) => LEGACY_ENV_CREDENTIAL_KEYS.includes(key));
7383
8102
  const fields = [...LEGACY_PROVIDER_FIELDS.filter((field) => field in raw), ...legacyEnvKeys.map((key) => `env.${key}`)];
7384
8103
  if (fields.length === 0) {
@@ -7439,7 +8158,7 @@ function readProvider(paths, name) {
7439
8158
  return parseProviderFile(filePath, raw);
7440
8159
  }
7441
8160
  function loadProvider(providersDir, name, port) {
7442
- const filePath = path19.join(providersDir, `${name}.json`);
8161
+ const filePath = path20.join(providersDir, `${name}.json`);
7443
8162
  const raw = port.readConfigFile(filePath);
7444
8163
  return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
7445
8164
  }
@@ -7694,21 +8413,21 @@ function removeDirectoryRule(paths, rulePath) {
7694
8413
  import os5 from "node:os";
7695
8414
 
7696
8415
  // src/launcher/cascade.ts
7697
- import path21 from "node:path";
8416
+ import path22 from "node:path";
7698
8417
 
7699
8418
  // src/pathNorm.ts
7700
- import path20 from "node:path";
8419
+ import path21 from "node:path";
7701
8420
  function expandTilde(value, home) {
7702
8421
  if (value === "~") {
7703
8422
  return home;
7704
8423
  }
7705
8424
  if (value.startsWith("~/")) {
7706
- return path20.join(home, value.slice(2));
8425
+ return path21.join(home, value.slice(2));
7707
8426
  }
7708
8427
  return value;
7709
8428
  }
7710
8429
  function normaliseRulePath(rulePath, home) {
7711
- return path20.resolve(expandTilde(rulePath, home));
8430
+ return path21.resolve(expandTilde(rulePath, home));
7712
8431
  }
7713
8432
 
7714
8433
  // src/launcher/cascade.ts
@@ -7718,7 +8437,7 @@ function loadCascadeInput(params) {
7718
8437
  const globalConfig = loadConfigFile(params.paths.globalConfigFile, GlobalConfigSchema, params.read);
7719
8438
  const directoryRules = loadConfigFile(params.paths.directoryRulesFile, DirectoryRulesSchema, params.read);
7720
8439
  const loadProfile = (name) => {
7721
- const filepath = path21.join(params.paths.configProfilesDir, `${name}.json`);
8440
+ const filepath = path22.join(params.paths.configProfilesDir, `${name}.json`);
7722
8441
  const loaded = loadConfigFile(filepath, ConfigProfileSchema, params.read);
7723
8442
  if (loaded === void 0) {
7724
8443
  return void 0;
@@ -7733,8 +8452,8 @@ function loadCascadeInput(params) {
7733
8452
  });
7734
8453
  const levels = [];
7735
8454
  for (const dir of dirs) {
7736
- const portable = loadConfigFile(path21.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path21.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
7737
- const portableLocal = loadConfigFile(path21.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path21.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
8455
+ const portable = loadConfigFile(path22.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path22.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
8456
+ const portableLocal = loadConfigFile(path22.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path22.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
7738
8457
  const rules = (directoryRules?.config.rules ?? []).map((rule, index) => ({ rule, index })).filter(({ rule }) => normaliseRulePath(rule.path, params.home) === dir).map(({ rule, index }) => {
7739
8458
  const entryOrder = directoryRules?.ruleEntryOrders[index];
7740
8459
  return {
@@ -7785,7 +8504,7 @@ function readDirectorySelections(loaded) {
7785
8504
  // src/realCredentialCache.ts
7786
8505
  import { spawnSync } from "node:child_process";
7787
8506
  import fs7 from "node:fs";
7788
- import path22 from "node:path";
8507
+ import path23 from "node:path";
7789
8508
  var KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
7790
8509
  var CACHE_DIR_MODE = 448;
7791
8510
  var CACHE_FILE_MODE = 384;
@@ -7812,8 +8531,8 @@ function security(args, stdin) {
7812
8531
  return { status: result.status, stdout: result.stdout };
7813
8532
  }
7814
8533
  function createRealCredentialCache(root) {
7815
- const dir = path22.join(root, "credential-cache");
7816
- const filePath = (owner) => path22.join(dir, cacheFileNameFor(owner));
8534
+ const dir = path23.join(root, "credential-cache");
8535
+ const filePath = (owner) => path23.join(dir, cacheFileNameFor(owner));
7817
8536
  return {
7818
8537
  read(store, owner) {
7819
8538
  if (store === "file") {
@@ -7865,7 +8584,7 @@ import { spawn, spawnSync as spawnSync2 } from "node:child_process";
7865
8584
  import { createHash as createHash5 } from "node:crypto";
7866
8585
  import fs8 from "node:fs";
7867
8586
  import os4 from "node:os";
7868
- import path23 from "node:path";
8587
+ import path24 from "node:path";
7869
8588
  import { isSea } from "node:sea";
7870
8589
  function isEnoent3(error) {
7871
8590
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
@@ -8024,7 +8743,7 @@ var realRunPort = {
8024
8743
  }
8025
8744
  };
8026
8745
  function expandHome2(filePath) {
8027
- return filePath.startsWith("~/") ? path23.join(os4.homedir(), filePath.slice(1)) : filePath;
8746
+ return filePath.startsWith("~/") ? path24.join(os4.homedir(), filePath.slice(1)) : filePath;
8028
8747
  }
8029
8748
  var MACOS_GUI_SESSION_MANAGER = "Aqua";
8030
8749
  function hasDesktopSession() {
@@ -8097,7 +8816,7 @@ function spawnDaemonThrough(executable) {
8097
8816
  return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: executable, args: [subcommand] }, paths, subcommand, logPath);
8098
8817
  }
8099
8818
  function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
8100
- fs8.mkdirSync(path23.dirname(logPath), { recursive: true });
8819
+ fs8.mkdirSync(path24.dirname(logPath), { recursive: true });
8101
8820
  const logFd = fs8.openSync(logPath, "a");
8102
8821
  try {
8103
8822
  const child = spawn(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
@@ -8179,7 +8898,7 @@ function listVersionsDir(dir) {
8179
8898
  throw error;
8180
8899
  }
8181
8900
  return entries.filter((entry) => entry.isFile()).map((entry) => {
8182
- const fullPath = path23.join(dir, entry.name);
8901
+ const fullPath = path24.join(dir, entry.name);
8183
8902
  const stat = fs8.statSync(fullPath);
8184
8903
  return {
8185
8904
  name: entry.name,
@@ -8194,7 +8913,7 @@ function windowsPathExtensions(pathext) {
8194
8913
  return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
8195
8914
  }
8196
8915
  function resolveExecutableCandidate(dir, name, env) {
8197
- const candidate = path23.join(dir, name);
8916
+ const candidate = path24.join(dir, name);
8198
8917
  if (env.platform === "win32") {
8199
8918
  const extensions = windowsPathExtensions(env.pathext);
8200
8919
  const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
@@ -8243,13 +8962,13 @@ function resolveOwnExecutablePath(env) {
8243
8962
  if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
8244
8963
  return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
8245
8964
  }
8246
- const candidate = env.argv1 === void 0 ? env.execPath : path23.resolve(env.cwd, env.argv1);
8247
- const candidateDir = path23.dirname(candidate);
8248
- const candidateDirOnPath = env.pathDirs.some((dir) => path23.resolve(dir) === candidateDir);
8965
+ const candidate = env.argv1 === void 0 ? env.execPath : path24.resolve(env.cwd, env.argv1);
8966
+ const candidateDir = path24.dirname(candidate);
8967
+ const candidateDirOnPath = env.pathDirs.some((dir) => path24.resolve(dir) === candidateDir);
8249
8968
  if (candidateDirOnPath) {
8250
8969
  return candidate;
8251
8970
  }
8252
- const viaPath = searchPathForExecutable(env.pathDirs, path23.basename(candidate), env.findExecutableInDir);
8971
+ const viaPath = searchPathForExecutable(env.pathDirs, path24.basename(candidate), env.findExecutableInDir);
8253
8972
  return viaPath ?? candidate;
8254
8973
  }
8255
8974
  function realOwnExecutablePath() {
@@ -8257,7 +8976,7 @@ function realOwnExecutablePath() {
8257
8976
  argv1: process.argv[1],
8258
8977
  execPath: process.execPath,
8259
8978
  cwd: process.cwd(),
8260
- pathDirs: (process.env.PATH ?? "").split(path23.delimiter).filter((dir) => dir !== ""),
8979
+ pathDirs: (process.env.PATH ?? "").split(path24.delimiter).filter((dir) => dir !== ""),
8261
8980
  findExecutableInDir
8262
8981
  });
8263
8982
  }
@@ -8270,7 +8989,7 @@ function realContentSourcePath() {
8270
8989
  function realResolveClaudeBinary(isOwnBinary) {
8271
8990
  return (request4) => discoverClaudeBinary({
8272
8991
  listVersionsDir,
8273
- pathDirs: (process.env.PATH ?? "").split(path23.delimiter).filter((dir) => dir !== ""),
8992
+ pathDirs: (process.env.PATH ?? "").split(path24.delimiter).filter((dir) => dir !== ""),
8274
8993
  findExecutableInDir,
8275
8994
  isOwnBinary,
8276
8995
  ...request4?.version === void 0 ? {} : { version: request4.version }
@@ -8281,7 +9000,7 @@ function realInstalledClaudeVersions() {
8281
9000
  }
8282
9001
 
8283
9002
  // src/checkReport.ts
8284
- import path24 from "node:path";
9003
+ import path25 from "node:path";
8285
9004
  import { z as z13 } from "zod";
8286
9005
 
8287
9006
  // src/cli/bool.ts
@@ -8713,10 +9432,10 @@ function collectCheckReport(params) {
8713
9432
  }).input;
8714
9433
  const providerName = cascadeProviderName(cascade);
8715
9434
  const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
8716
- const farmRoot = identityDecision.name === void 0 ? void 0 : path24.join(paths.identitiesDir, identityDecision.name);
9435
+ const farmRoot = identityDecision.name === void 0 ? void 0 : path25.join(paths.identitiesDir, identityDecision.name);
8717
9436
  const settingsFiles = {
8718
- "settings.json": realFsPort.readFileUtf8(path24.join(claudeHome, "settings.json")),
8719
- "settings.local.json": realFsPort.readFileUtf8(path24.join(claudeHome, "settings.local.json"))
9437
+ "settings.json": realFsPort.readFileUtf8(path25.join(claudeHome, "settings.json")),
9438
+ "settings.local.json": realFsPort.readFileUtf8(path25.join(claudeHome, "settings.local.json"))
8720
9439
  };
8721
9440
  const report = runCheck({
8722
9441
  cwd,
@@ -8748,7 +9467,7 @@ function collectCheckReport(params) {
8748
9467
 
8749
9468
  // src/claudeShim.ts
8750
9469
  import fs9 from "node:fs";
8751
- import path25 from "node:path";
9470
+ import path26 from "node:path";
8752
9471
  import { z as z14 } from "zod";
8753
9472
  var ClaudeShimStateSchema = z14.strictObject({
8754
9473
  targetPath: z14.string().min(1),
@@ -8760,10 +9479,10 @@ function commandFilename(ownExecutablePath, commandName) {
8760
9479
  }
8761
9480
  function resolveOwnBinaryCheck(paths, contentSourcePath) {
8762
9481
  const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
8763
- const recordedTarget = state === void 0 ? void 0 : path25.resolve(state.targetPath);
9482
+ const recordedTarget = state === void 0 ? void 0 : path26.resolve(state.targetPath);
8764
9483
  let ownStat;
8765
9484
  return (candidate) => {
8766
- if (recordedTarget !== void 0 && path25.resolve(candidate) === recordedTarget) {
9485
+ if (recordedTarget !== void 0 && path26.resolve(candidate) === recordedTarget) {
8767
9486
  return true;
8768
9487
  }
8769
9488
  ownStat ??= statOrUndefined(contentSourcePath);
@@ -8787,20 +9506,20 @@ function statOrUndefined(target) {
8787
9506
  }
8788
9507
  var nodeLinkFs = { link: fs9.linkSync, copyFile: fs9.copyFileSync, chmod: fs9.chmodSync };
8789
9508
  function findPathShadow(params) {
8790
- const resolvedTargetDir = path25.resolve(params.targetDir);
9509
+ const resolvedTargetDir = path26.resolve(params.targetDir);
8791
9510
  for (const dir of params.pathDirs) {
8792
9511
  const found = params.findExecutableInDir(dir, params.targetFilename);
8793
9512
  if (found === void 0) {
8794
9513
  continue;
8795
9514
  }
8796
- return path25.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
9515
+ return path26.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
8797
9516
  }
8798
- return params.pathDirs.some((dir) => path25.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
9517
+ return params.pathDirs.some((dir) => path26.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
8799
9518
  }
8800
9519
 
8801
9520
  // src/doctorReport.ts
8802
9521
  import fs10 from "node:fs";
8803
- import path26 from "node:path";
9522
+ import path27 from "node:path";
8804
9523
  function refinePathShadow(status, ownExecutablePath, realpath) {
8805
9524
  if (status.status !== "shadowed") {
8806
9525
  return status;
@@ -8824,7 +9543,7 @@ function validateJson(schema, input) {
8824
9543
  return { ok: true, data: result.data };
8825
9544
  }
8826
9545
  function pushPathResolution(push, resolution) {
8827
- const ownDir = path26.dirname(resolution.ownExecutablePath);
9546
+ const ownDir = path27.dirname(resolution.ownExecutablePath);
8828
9547
  switch (resolution.agentShim.status) {
8829
9548
  case "ok":
8830
9549
  push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
@@ -8903,14 +9622,14 @@ function pushProvider(push, entry, cacheEnv) {
8903
9622
  }
8904
9623
  function pushLegacyName(push, params) {
8905
9624
  const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
8906
- if (legacyVariables.length === 0 && path26.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
9625
+ if (legacyVariables.length === 0 && path27.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
8907
9626
  push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
8908
9627
  return;
8909
9628
  }
8910
9629
  for (const name of legacyVariables) {
8911
9630
  push("legacy-name", "warn", `${name} is the former name of ${name.replace(LEGACY_ENV_PREFIX, ENV_PREFIX)}. Rename it; the old name still works but is only a fallback.`, name);
8912
9631
  }
8913
- if (path26.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
9632
+ if (path27.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
8914
9633
  push(
8915
9634
  "legacy-name",
8916
9635
  "warn",
@@ -9229,18 +9948,18 @@ function collectDoctorReport(params) {
9229
9948
  const { paths } = params;
9230
9949
  const identityNames = fs10.existsSync(paths.identitiesDir) ? fs10.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
9231
9950
  const identities = identityNames.map((name) => {
9232
- const farmRoot = path26.join(paths.identitiesDir, name);
9233
- const identityPath = path26.join(farmRoot, "identity.json");
9951
+ const farmRoot = path27.join(paths.identitiesDir, name);
9952
+ const identityPath = path27.join(farmRoot, "identity.json");
9234
9953
  return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
9235
9954
  });
9236
9955
  const profileNames = fs10.existsSync(paths.configProfilesDir) ? fs10.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
9237
9956
  const configProfiles = profileNames.map((name) => {
9238
- const profilePath = path26.join(paths.configProfilesDir, `${name}.json`);
9957
+ const profilePath = path27.join(paths.configProfilesDir, `${name}.json`);
9239
9958
  return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
9240
9959
  });
9241
9960
  const providerNames = fs10.existsSync(paths.providersDir) ? fs10.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
9242
9961
  const providers = providerNames.map((name) => {
9243
- const providerPath = path26.join(paths.providersDir, `${name}.json`);
9962
+ const providerPath = path27.join(paths.providersDir, `${name}.json`);
9244
9963
  return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
9245
9964
  });
9246
9965
  const ownExecutablePath = realOwnExecutablePath();
@@ -9252,12 +9971,12 @@ function collectDoctorReport(params) {
9252
9971
  binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
9253
9972
  }
9254
9973
  const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
9255
- const pathDirs = (params.env.PATH ?? "").split(path26.delimiter).filter((dir) => dir !== "");
9974
+ const pathDirs = (params.env.PATH ?? "").split(path27.delimiter).filter((dir) => dir !== "");
9256
9975
  const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
9257
9976
  findPathShadow({
9258
9977
  pathDirs,
9259
- targetDir: path26.dirname(shimState.targetPath),
9260
- targetFilename: path26.basename(shimState.targetPath),
9978
+ targetDir: path27.dirname(shimState.targetPath),
9979
+ targetFilename: path27.basename(shimState.targetPath),
9261
9980
  findExecutableInDir
9262
9981
  }),
9263
9982
  shimState.targetPath,
@@ -9282,7 +10001,7 @@ function collectDoctorReport(params) {
9282
10001
  agentShim: refinePathShadow(
9283
10002
  findPathShadow({
9284
10003
  pathDirs,
9285
- targetDir: path26.dirname(ownExecutablePath),
10004
+ targetDir: path27.dirname(ownExecutablePath),
9286
10005
  targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
9287
10006
  findExecutableInDir
9288
10007
  }),
@@ -9303,7 +10022,7 @@ function collectDoctorReport(params) {
9303
10022
 
9304
10023
  // src/launcher.ts
9305
10024
  import { randomUUID as randomUUID4 } from "node:crypto";
9306
- import path28 from "node:path";
10025
+ import path29 from "node:path";
9307
10026
 
9308
10027
  // src/launcher/argv.ts
9309
10028
  var ConflictingIdentityError = class extends UsageError {
@@ -9568,7 +10287,7 @@ function buildCliOverride(params) {
9568
10287
  }
9569
10288
 
9570
10289
  // src/launcher/flags.ts
9571
- import path27 from "node:path";
10290
+ import path28 from "node:path";
9572
10291
 
9573
10292
  // src/headroom/headers.ts
9574
10293
  function mergeAnthropicCustomHeaders(existing, additions) {
@@ -9638,7 +10357,7 @@ function buildEnv(params) {
9638
10357
  const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
9639
10358
  let providerCustomHeaders;
9640
10359
  if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
9641
- env.CLAUDE_CONFIG_DIR = path27.join(params.identitiesDir, params.resolvedIdentityName);
10360
+ env.CLAUDE_CONFIG_DIR = path28.join(params.identitiesDir, params.resolvedIdentityName);
9642
10361
  }
9643
10362
  if (params.provider !== void 0) {
9644
10363
  const providerEnv = params.provider.definition.env ?? {};
@@ -9799,7 +10518,7 @@ function prepareLaunch(params) {
9799
10518
  identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
9800
10519
  globalDefaultConfigProfile: params.globalDefaultConfigProfile
9801
10520
  });
9802
- if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path28.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
10521
+ if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path29.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
9803
10522
  log.error(
9804
10523
  `agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
9805
10524
  );
@@ -10045,11 +10764,11 @@ function probeFrontDoorSync(port, caPem) {
10045
10764
 
10046
10765
  // src/frontdoor/trust.ts
10047
10766
  import { createHash as createHash6 } from "node:crypto";
10048
- import path29 from "node:path";
10767
+ import path30 from "node:path";
10049
10768
  var BUNDLE_NAME_HEX_DIGITS = 16;
10050
10769
  function resolveTrustBundle(params) {
10051
10770
  const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
10052
- if (inherited === void 0 || inherited === "" || path29.resolve(inherited) === path29.resolve(caCertFile)) {
10771
+ if (inherited === void 0 || inherited === "" || path30.resolve(inherited) === path30.resolve(caCertFile)) {
10053
10772
  return { path: caCertFile };
10054
10773
  }
10055
10774
  const caPem = fs12.readFileUtf8(caCertFile);
@@ -10067,7 +10786,7 @@ function resolveTrustBundle(params) {
10067
10786
  }
10068
10787
  const combined = `${inheritedPem.trimEnd()}
10069
10788
  ${caPem}`;
10070
- const bundle = path29.join(bundlesDir, `${createHash6("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
10789
+ const bundle = path30.join(bundlesDir, `${createHash6("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
10071
10790
  if (!fs12.exists(bundle)) {
10072
10791
  fs12.mkdirp(bundlesDir);
10073
10792
  fs12.writeFileAtomic(bundle, combined);
@@ -10260,6 +10979,13 @@ export {
10260
10979
  RC_PENDING_DEADLINE_MS,
10261
10980
  RC_PERMISSION_MODES,
10262
10981
  RC_REQUEST_PARSE_CAP_BYTES,
10982
+ RC_SELF_HOST_ENV,
10983
+ RC_SELF_HOST_KEEPALIVE_MS,
10984
+ RC_SELF_HOST_RECORD_DIR,
10985
+ RC_SELF_HOST_RECORD_FILE,
10986
+ RC_SELF_HOST_RETENTION_MS,
10987
+ RC_SELF_HOST_SCOPE_LIST,
10988
+ RC_SELF_HOST_WORKER_JWT_TTL_SECONDS,
10263
10989
  RC_SESSIONS_PATH_PREFIX,
10264
10990
  RC_STREAM_BACKOFF_MS,
10265
10991
  ROUTED_PATH_PREFIX,
@@ -10296,6 +11022,7 @@ export {
10296
11022
  createRcControlHandler,
10297
11023
  createRcCredentialStore,
10298
11024
  createRcEventFanout,
11025
+ createRcSelfHostSurface,
10299
11026
  createRcSessionTracker,
10300
11027
  createRcStreamHub,
10301
11028
  createSseParser,
@@ -10320,6 +11047,8 @@ export {
10320
11047
  isIdentityDirectoryName,
10321
11048
  isInterceptedHost,
10322
11049
  isRcPermissionMode,
11050
+ lateRcEventDial,
11051
+ lateRcStreamDial,
10323
11052
  listDirectoryRules,
10324
11053
  listIdentities,
10325
11054
  listProfiles,
@@ -10327,6 +11056,7 @@ export {
10327
11056
  listUsageSnapshots,
10328
11057
  matchBranch,
10329
11058
  mintLeaf,
11059
+ mintRcSelfHostCredential,
10330
11060
  observingRoutedRoute,
10331
11061
  parseConnectTarget,
10332
11062
  parseRcStreamEnvelope,
@@ -10338,6 +11068,7 @@ export {
10338
11068
  rankPool,
10339
11069
  rcEventWriteResultFromAnswer,
10340
11070
  rcObserverAsPassthrough,
11071
+ rcSelfHostFromEnv,
10341
11072
  readActiveIdentity,
10342
11073
  readDirectoryRules,
10343
11074
  readFarmManifest,
@@ -10346,6 +11077,7 @@ export {
10346
11077
  readPools,
10347
11078
  readProfile,
10348
11079
  readProvider,
11080
+ readRcSelfHostRecord,
10349
11081
  readUsageSnapshot,
10350
11082
  realConnectCertStore,
10351
11083
  realConnectEffects,