agent-shim 8.38.1 → 8.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -63708,7 +63708,7 @@ function registerIdentityCommand(program2, deps) {
63708
63708
  // package.json
63709
63709
  var package_default = {
63710
63710
  name: "agent-shim",
63711
- version: "8.38.1",
63711
+ version: "8.40.0",
63712
63712
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
63713
63713
  license: "MIT",
63714
63714
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -65215,12 +65215,7 @@ function rankNamedPool(input2, poolName, stack, sticky) {
65215
65215
  }
65216
65216
  continue;
65217
65217
  }
65218
- if (input2.pools[nestedName] === void 0) {
65219
- throw new PoolGraphError(`Pool "${poolName}" member "${poolMemberIdentity(entry)}" names a pool that is not defined.`);
65220
- }
65221
- if (childStack.includes(nestedName)) {
65222
- throw new PoolGraphError(`Pool "${poolName}" member "${poolMemberIdentity(entry)}" closes a cycle: ${[...childStack.slice(childStack.indexOf(nestedName)), nestedName].join(" -> ")}. A pool cannot nest itself, directly or through another pool.`);
65223
- }
65218
+ assertNestable(input2.pools, poolName, poolMemberIdentity(entry), nestedName, childStack);
65224
65219
  const nested = nestedMember(input2, nestedName, childStack, sticky);
65225
65220
  members2.push(typeof entry === "string" ? nested.member : { ...nested.member, policy: entry.when });
65226
65221
  missing.push(...nested.missing);
@@ -65234,6 +65229,14 @@ function rankNamedPool(input2, poolName, stack, sticky) {
65234
65229
  });
65235
65230
  return { ranking, missing };
65236
65231
  }
65232
+ function assertNestable(pools, poolName, member, nestedName, childStack) {
65233
+ if (pools[nestedName] === void 0) {
65234
+ throw new PoolGraphError(`Pool "${poolName}" member "${member}" names a pool that is not defined.`);
65235
+ }
65236
+ if (childStack.includes(nestedName)) {
65237
+ throw new PoolGraphError(`Pool "${poolName}" member "${member}" closes a cycle: ${[...childStack.slice(childStack.indexOf(nestedName)), nestedName].join(" -> ")}. A pool cannot nest itself, directly or through another pool.`);
65238
+ }
65239
+ }
65237
65240
  function nestedMember(input2, nestedName, childStack, sticky) {
65238
65241
  const nested = rankNamedPool(input2, nestedName, childStack, sticky);
65239
65242
  const pick2 = nested.ranking.pick;
@@ -93736,7 +93739,13 @@ function resolvePoolLaunch(params) {
93736
93739
  if (pick2 !== void 0) {
93737
93740
  recordStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd, pick2.identity, nowMs);
93738
93741
  const move = movedOff === void 0 ? "" : `moved off ${movedOff.identity} (${movedOff.reason}); `;
93739
- return { ok: true, identity: pick2.identity, explanation: `pool ${poolName}: ${move}${pick2.reasons.slice(0, REASONS_LOGGED).join("; ")}` };
93742
+ return {
93743
+ ok: true,
93744
+ identity: pick2.identity,
93745
+ explanation: `pool ${poolName}: ${move}${pick2.reasons.slice(0, REASONS_LOGGED).join("; ")}`,
93746
+ reasons: pick2.reasons,
93747
+ ...movedOff === void 0 ? {} : { movedOff }
93748
+ };
93740
93749
  }
93741
93750
  if (earliestReturn === void 0) {
93742
93751
  return { ok: false, message: `agent-shim: no member of pool "${poolName}" can be picked.` };
@@ -94082,7 +94091,11 @@ function pickFromPool(decided, params, parsedArgv) {
94082
94091
  log.error(resolution.message);
94083
94092
  return proc.exit(1);
94084
94093
  }
94085
- return { identityDecision: { ...decided, name: resolution.identity }, poolExplanation: resolution.explanation };
94094
+ return {
94095
+ identityDecision: { ...decided, name: resolution.identity },
94096
+ poolExplanation: resolution.explanation,
94097
+ poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } }
94098
+ };
94086
94099
  }
94087
94100
  function prepareLaunch(params) {
94088
94101
  const { paths, fs: fs20, proc, log } = params;
@@ -94108,7 +94121,7 @@ function prepareLaunch(params) {
94108
94121
  return trimmed === "" ? void 0 : trimmed;
94109
94122
  }
94110
94123
  });
94111
- const { identityDecision, poolExplanation } = pickFromPool(decidedIdentity, params, parsedArgv);
94124
+ const { identityDecision, poolExplanation, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv);
94112
94125
  const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
94113
94126
  const farm = farmIdentity === void 0 ? void 0 : params.farm;
94114
94127
  if (farm !== void 0 && farmIdentity !== void 0) {
@@ -94322,7 +94335,18 @@ function prepareLaunch(params) {
94322
94335
  registered();
94323
94336
  }
94324
94337
  };
94325
- return { bin: discovered.path, args: finalArgv, env: finalEnv, release, markChildStarted: updateCheck.markChildStarted };
94338
+ const configDir = finalEnv.CLAUDE_CONFIG_DIR;
94339
+ const decision = {
94340
+ identitySource: identityDecision.source,
94341
+ configDirEscapeHatch: identityDecision.configDirEscapeHatch,
94342
+ configProfileSource: configProfileDecision.source,
94343
+ ...identityDecision.name === void 0 ? {} : { identity: identityDecision.name },
94344
+ ...poolPick === void 0 ? {} : { pool: poolPick },
94345
+ ...configDir === void 0 || configDir === "" ? {} : { configDir },
94346
+ ...configProfileDecision.name === void 0 ? {} : { configProfile: configProfileDecision.name },
94347
+ ...resolvedProvider === void 0 ? {} : { provider: resolvedProvider.name }
94348
+ };
94349
+ return { bin: discovered.path, args: finalArgv, env: finalEnv, release, markChildStarted: updateCheck.markChildStarted, decision };
94326
94350
  }
94327
94351
  function runLauncher(params) {
94328
94352
  const plan = prepareLaunch(params);
package/dist/index.cjs CHANGED
@@ -1,3 +1,4 @@
1
+ const __AGENT_SHIM_DIST_DIR__ = __dirname;
1
2
  "use strict";
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
@@ -82,6 +83,7 @@ __export(index_exports, {
82
83
  LaunchLifecycleEventSchema: () => LaunchLifecycleEventSchema,
83
84
  LaunchRefusedError: () => LaunchRefusedError,
84
85
  LegacyProviderFileError: () => LegacyProviderFileError,
86
+ OWN_CLI_FILE_NAME: () => OWN_CLI_FILE_NAME,
85
87
  PROMPT_CACHE_TTL_MS: () => PROMPT_CACHE_TTL_MS,
86
88
  PlanClassSchema: () => PlanClassSchema,
87
89
  PoolNameSchema: () => PoolNameSchema,
@@ -137,6 +139,7 @@ __export(index_exports, {
137
139
  addIdentity: () => addIdentity,
138
140
  addPool: () => addPool,
139
141
  addProvider: () => addProvider,
142
+ agentShimCliPath: () => agentShimCliPath,
140
143
  answerRcControlRequest: () => answerRcControlRequest,
141
144
  authenticateRcSessionMcpServer: () => authenticateRcSessionMcpServer,
142
145
  buildEntryFacts: () => buildEntryFacts,
@@ -235,6 +238,7 @@ __export(index_exports, {
235
238
  parseConnectTarget: () => parseConnectTarget,
236
239
  parseRcStreamEnvelope: () => parseRcStreamEnvelope,
237
240
  planOf: () => planOf,
241
+ poolIdentities: () => poolIdentities,
238
242
  prepareClaudeLaunch: () => prepareClaudeLaunch,
239
243
  prepareLaunch: () => prepareLaunch,
240
244
  profileExists: () => profileExists,
@@ -3223,8 +3227,8 @@ function parseConnectTarget(authority) {
3223
3227
  function isInterceptedHost(host, interceptHosts) {
3224
3228
  return interceptHosts.includes(host);
3225
3229
  }
3226
- function servedByPipeline(path32) {
3227
- return path32?.startsWith(ROUTED_PATH_PREFIX) === true;
3230
+ function servedByPipeline(path33) {
3231
+ return path33?.startsWith(ROUTED_PATH_PREFIX) === true;
3228
3232
  }
3229
3233
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
3230
3234
  "connection",
@@ -3758,11 +3762,11 @@ function createRcSessionTracker(deps) {
3758
3762
  };
3759
3763
  const observeExchange = (request4) => {
3760
3764
  const method = (request4.method ?? "").toUpperCase();
3761
- const path32 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
3762
- if (!path32.startsWith(RC_SESSIONS_PATH_PREFIX)) {
3765
+ const path33 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
3766
+ if (!path33.startsWith(RC_SESSIONS_PATH_PREFIX)) {
3763
3767
  return void 0;
3764
3768
  }
3765
- const tail = path32.slice(RC_SESSIONS_PATH_PREFIX.length);
3769
+ const tail = path33.slice(RC_SESSIONS_PATH_PREFIX.length);
3766
3770
  const facts = {
3767
3771
  oauthAuthorization: oauthAuthorizationOf(request4.headers),
3768
3772
  anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
@@ -4144,8 +4148,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
4144
4148
  function isRcReadFileEncoding(value) {
4145
4149
  return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
4146
4150
  }
4147
- function buildRcReadFilePayload(requestId, path32, options) {
4148
- return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path32, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
4151
+ function buildRcReadFilePayload(requestId, path33, options) {
4152
+ return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path33, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
4149
4153
  }
4150
4154
  function buildRcFileSuggestionsPayload(requestId, query) {
4151
4155
  return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
@@ -4247,15 +4251,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
4247
4251
  const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
4248
4252
  return result.ok ? { ...result, requestId } : result;
4249
4253
  }
4250
- async function readRcSessionFile(deps, sessionId, path32, options) {
4251
- if (path32 === "") {
4254
+ async function readRcSessionFile(deps, sessionId, path33, options) {
4255
+ if (path33 === "") {
4252
4256
  return { ok: false, message: "a read-file write needs a non-empty path: the SDK's own field names the file the worker resolves against the session's cwd, and an empty string names none" };
4253
4257
  }
4254
4258
  if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
4255
4259
  return { ok: false, message: "a read-file write's max-bytes is a positive whole number of bytes: the SDK's own field caps the read, and a zero or negative cap reads nothing" };
4256
4260
  }
4257
4261
  const requestId = deps.newUuid();
4258
- const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path32, options), `read ${path32} from session ${sessionId}`);
4262
+ const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path33, options), `read ${path33} from session ${sessionId}`);
4259
4263
  return result.ok ? { ...result, requestId } : result;
4260
4264
  }
4261
4265
  async function suggestRcSessionFiles(deps, sessionId, query) {
@@ -4420,11 +4424,11 @@ function createRcControlHandler(deps) {
4420
4424
  path: "read-file",
4421
4425
  read: (body) => {
4422
4426
  const session = bodyString(body, "session");
4423
- const path32 = bodyString(body, "path");
4427
+ const path33 = bodyString(body, "path");
4424
4428
  const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
4425
4429
  const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
4426
- const refused2 = session === void 0 || path32 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
4427
- return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path32, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
4430
+ const refused2 = session === void 0 || path33 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
4431
+ return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path33, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
4428
4432
  }
4429
4433
  },
4430
4434
  {
@@ -4734,9 +4738,9 @@ function requestIdOfBody(body) {
4734
4738
  }
4735
4739
  function frontDoorRcControl(transport, token) {
4736
4740
  const headers = { authorization: `Bearer ${token}` };
4737
- const listAnswerOf = async (path32, what) => {
4741
+ const listAnswerOf = async (path33, what) => {
4738
4742
  try {
4739
- return await transport.request({ method: "GET", path: path32, headers });
4743
+ return await transport.request({ method: "GET", path: path33, headers });
4740
4744
  } catch (error) {
4741
4745
  throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
4742
4746
  }
@@ -4808,10 +4812,10 @@ function frontDoorRcControl(transport, token) {
4808
4812
  }
4809
4813
  return pending;
4810
4814
  };
4811
- const writeOf = async (path32, body, describeFailure) => {
4815
+ const writeOf = async (path33, body, describeFailure) => {
4812
4816
  let answer;
4813
4817
  try {
4814
- answer = await transport.request({ method: "POST", path: path32, headers: { ...headers, "content-type": "application/json" }, body });
4818
+ answer = await transport.request({ method: "POST", path: path33, headers: { ...headers, "content-type": "application/json" }, body });
4815
4819
  } catch (error) {
4816
4820
  return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
4817
4821
  }
@@ -4842,10 +4846,10 @@ function frontDoorRcControl(transport, token) {
4842
4846
  endSession: async (sessionId, reason) => await writeOf(`${CONTROL_PATH_PREFIX}/end-session`, JSON.stringify({ session: sessionId, ...reason === void 0 ? {} : { reason } }), (status, message) => `ending ${sessionId} failed (HTTP ${String(status)}): ${message}`),
4843
4847
  getUsage: async (sessionId, skipBehaviors) => await writeOf(`${CONTROL_PATH_PREFIX}/get-usage`, JSON.stringify({ session: sessionId, ...skipBehaviors === void 0 ? {} : { skipBehaviors } }), (status, message) => `requesting the usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
4844
4848
  getContextUsage: async (sessionId, detail) => await writeOf(`${CONTROL_PATH_PREFIX}/get-context-usage`, JSON.stringify({ session: sessionId, ...detail === void 0 ? {} : { detail } }), (status, message) => `requesting the context usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
4845
- readFile: async (sessionId, path32, options) => await writeOf(
4849
+ readFile: async (sessionId, path33, options) => await writeOf(
4846
4850
  `${CONTROL_PATH_PREFIX}/read-file`,
4847
- JSON.stringify({ session: sessionId, path: path32, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
4848
- (status, message) => `reading ${path32} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
4851
+ JSON.stringify({ session: sessionId, path: path33, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
4852
+ (status, message) => `reading ${path33} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
4849
4853
  ),
4850
4854
  fileSuggestions: async (sessionId, query) => await writeOf(`${CONTROL_PATH_PREFIX}/file-suggestions`, JSON.stringify({ session: sessionId, query }), (status, message) => `requesting file suggestions from ${sessionId} failed (HTTP ${String(status)}): ${message}`),
4851
4855
  keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
@@ -5000,12 +5004,12 @@ function tlsFacts(options) {
5000
5004
  }
5001
5005
  function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
5002
5006
  const agent = new ExemptTlsAgent();
5003
- const post = async (path32, headers, body) => await new Promise((resolve, reject) => {
5007
+ const post = async (path33, headers, body) => await new Promise((resolve, reject) => {
5004
5008
  const options = {
5005
5009
  host: target.host,
5006
5010
  port: target.port,
5007
5011
  method: "POST",
5008
- path: path32,
5012
+ path: path33,
5009
5013
  // 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.
5010
5014
  headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
5011
5015
  agent
@@ -5070,12 +5074,12 @@ function lateRcStreamDial(resolve) {
5070
5074
  }
5071
5075
  function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
5072
5076
  const agent = new ExemptTlsAgent();
5073
- const request4 = async (method, path32, headers, body, signal) => await new Promise((resolve, reject) => {
5077
+ const request4 = async (method, path33, headers, body, signal) => await new Promise((resolve, reject) => {
5074
5078
  const options = {
5075
5079
  host: target.host,
5076
5080
  port: target.port,
5077
5081
  method,
5078
- path: path32,
5082
+ path: path33,
5079
5083
  // 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.
5080
5084
  headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
5081
5085
  agent,
@@ -5117,9 +5121,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
5117
5121
  return { status, body: await readAll(response) };
5118
5122
  },
5119
5123
  openStream: async (sessionId, headers, resume, signal) => {
5120
- const path32 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
5124
+ const path33 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
5121
5125
  const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
5122
- const { status, response } = await request4("GET", path32, streamHeaders, void 0, signal);
5126
+ const { status, response } = await request4("GET", path33, streamHeaders, void 0, signal);
5123
5127
  if (!isSuccessful2(status)) {
5124
5128
  await readAll(response);
5125
5129
  return { status, chunks: NO_CHUNKS };
@@ -5423,7 +5427,7 @@ var import_undici = require("undici");
5423
5427
  // package.json
5424
5428
  var package_default = {
5425
5429
  name: "agent-shim",
5426
- version: "8.38.1",
5430
+ version: "8.40.0",
5427
5431
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
5428
5432
  license: "MIT",
5429
5433
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -6968,12 +6972,7 @@ function rankNamedPool(input, poolName, stack, sticky) {
6968
6972
  }
6969
6973
  continue;
6970
6974
  }
6971
- if (input.pools[nestedName] === void 0) {
6972
- throw new PoolGraphError(`Pool "${poolName}" member "${poolMemberIdentity(entry)}" names a pool that is not defined.`);
6973
- }
6974
- if (childStack.includes(nestedName)) {
6975
- throw new PoolGraphError(`Pool "${poolName}" member "${poolMemberIdentity(entry)}" closes a cycle: ${[...childStack.slice(childStack.indexOf(nestedName)), nestedName].join(" -> ")}. A pool cannot nest itself, directly or through another pool.`);
6976
- }
6975
+ assertNestable(input.pools, poolName, poolMemberIdentity(entry), nestedName, childStack);
6977
6976
  const nested = nestedMember(input, nestedName, childStack, sticky);
6978
6977
  members.push(typeof entry === "string" ? nested.member : { ...nested.member, policy: entry.when });
6979
6978
  missing.push(...nested.missing);
@@ -6987,6 +6986,14 @@ function rankNamedPool(input, poolName, stack, sticky) {
6987
6986
  });
6988
6987
  return { ranking, missing };
6989
6988
  }
6989
+ function assertNestable(pools, poolName, member, nestedName, childStack) {
6990
+ if (pools[nestedName] === void 0) {
6991
+ throw new PoolGraphError(`Pool "${poolName}" member "${member}" names a pool that is not defined.`);
6992
+ }
6993
+ if (childStack.includes(nestedName)) {
6994
+ throw new PoolGraphError(`Pool "${poolName}" member "${member}" closes a cycle: ${[...childStack.slice(childStack.indexOf(nestedName)), nestedName].join(" -> ")}. A pool cannot nest itself, directly or through another pool.`);
6995
+ }
6996
+ }
6990
6997
  function nestedMember(input, nestedName, childStack, sticky) {
6991
6998
  const nested = rankNamedPool(input, nestedName, childStack, sticky);
6992
6999
  const pick = nested.ranking.pick;
@@ -7004,6 +7011,27 @@ function nestedMember(input, nestedName, childStack, sticky) {
7004
7011
  missing: nested.missing
7005
7012
  };
7006
7013
  }
7014
+ function poolIdentities(pools, poolName) {
7015
+ const found = /* @__PURE__ */ new Set();
7016
+ collectPoolIdentities(pools, poolName, [], found);
7017
+ return [...found];
7018
+ }
7019
+ function collectPoolIdentities(pools, poolName, stack, found) {
7020
+ const pool = pools[poolName];
7021
+ if (pool === void 0) {
7022
+ throw new PoolGraphError(`No pool named "${poolName}". Run \`agent-shim pool add ${poolName} --identity <name>...\` first.`);
7023
+ }
7024
+ const childStack = [...stack, poolName];
7025
+ for (const entry of pool.identities) {
7026
+ const nestedName = poolNameOf(poolMemberIdentity(entry));
7027
+ if (nestedName === void 0) {
7028
+ found.add(poolMemberIdentity(entry));
7029
+ continue;
7030
+ }
7031
+ assertNestable(pools, poolName, poolMemberIdentity(entry), nestedName, childStack);
7032
+ collectPoolIdentities(pools, nestedName, childStack, found);
7033
+ }
7034
+ }
7007
7035
  function readPicksFile(fs12, file) {
7008
7036
  const empty = { schemaVersion: SCHEMA_VERSION, picks: {} };
7009
7037
  const raw = fs12.readFileUtf8(file);
@@ -7234,19 +7262,19 @@ function writePools(paths, pools) {
7234
7262
  applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
7235
7263
  }
7236
7264
  function poolCycleOf(pools, name) {
7237
- const walk = (current, path32) => {
7265
+ const walk = (current, path33) => {
7238
7266
  for (const entry of pools[current]?.identities ?? []) {
7239
7267
  const nested = poolNameOf(poolMemberIdentity(entry));
7240
7268
  if (nested === void 0) {
7241
7269
  continue;
7242
7270
  }
7243
7271
  if (nested === name) {
7244
- return [...path32, nested];
7272
+ return [...path33, nested];
7245
7273
  }
7246
- if (path32.includes(nested)) {
7274
+ if (path33.includes(nested)) {
7247
7275
  continue;
7248
7276
  }
7249
- const found = walk(nested, [...path32, nested]);
7277
+ const found = walk(nested, [...path33, nested]);
7250
7278
  if (found !== void 0) {
7251
7279
  return found;
7252
7280
  }
@@ -8553,6 +8581,9 @@ function detachedDaemonSpawnOptions(logFd, env) {
8553
8581
  function spawnDaemonThrough(executable) {
8554
8582
  return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: executable, args: [subcommand] }, paths, subcommand, logPath);
8555
8583
  }
8584
+ function spawnDaemonThroughScript(script) {
8585
+ return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: process.execPath, args: [script, subcommand] }, paths, subcommand, logPath);
8586
+ }
8556
8587
  function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
8557
8588
  import_node_fs6.default.mkdirSync(import_node_path22.default.dirname(logPath), { recursive: true });
8558
8589
  const logFd = import_node_fs6.default.openSync(logPath, "a");
@@ -13089,7 +13120,13 @@ function resolvePoolLaunch(params) {
13089
13120
  if (pick !== void 0) {
13090
13121
  recordStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd, pick.identity, nowMs);
13091
13122
  const move = movedOff === void 0 ? "" : `moved off ${movedOff.identity} (${movedOff.reason}); `;
13092
- return { ok: true, identity: pick.identity, explanation: `pool ${poolName}: ${move}${pick.reasons.slice(0, REASONS_LOGGED).join("; ")}` };
13123
+ return {
13124
+ ok: true,
13125
+ identity: pick.identity,
13126
+ explanation: `pool ${poolName}: ${move}${pick.reasons.slice(0, REASONS_LOGGED).join("; ")}`,
13127
+ reasons: pick.reasons,
13128
+ ...movedOff === void 0 ? {} : { movedOff }
13129
+ };
13093
13130
  }
13094
13131
  if (earliestReturn === void 0) {
13095
13132
  return { ok: false, message: `agent-shim: no member of pool "${poolName}" can be picked.` };
@@ -13247,7 +13284,11 @@ function pickFromPool(decided, params, parsedArgv) {
13247
13284
  log.error(resolution.message);
13248
13285
  return proc.exit(1);
13249
13286
  }
13250
- return { identityDecision: { ...decided, name: resolution.identity }, poolExplanation: resolution.explanation };
13287
+ return {
13288
+ identityDecision: { ...decided, name: resolution.identity },
13289
+ poolExplanation: resolution.explanation,
13290
+ poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } }
13291
+ };
13251
13292
  }
13252
13293
  function prepareLaunch(params) {
13253
13294
  const { paths, fs: fs12, proc, log } = params;
@@ -13273,7 +13314,7 @@ function prepareLaunch(params) {
13273
13314
  return trimmed === "" ? void 0 : trimmed;
13274
13315
  }
13275
13316
  });
13276
- const { identityDecision, poolExplanation } = pickFromPool(decidedIdentity, params, parsedArgv);
13317
+ const { identityDecision, poolExplanation, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv);
13277
13318
  const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
13278
13319
  const farm = farmIdentity === void 0 ? void 0 : params.farm;
13279
13320
  if (farm !== void 0 && farmIdentity !== void 0) {
@@ -13487,7 +13528,18 @@ function prepareLaunch(params) {
13487
13528
  registered();
13488
13529
  }
13489
13530
  };
13490
- return { bin: discovered.path, args: finalArgv, env: finalEnv, release, markChildStarted: updateCheck.markChildStarted };
13531
+ const configDir = finalEnv.CLAUDE_CONFIG_DIR;
13532
+ const decision = {
13533
+ identitySource: identityDecision.source,
13534
+ configDirEscapeHatch: identityDecision.configDirEscapeHatch,
13535
+ configProfileSource: configProfileDecision.source,
13536
+ ...identityDecision.name === void 0 ? {} : { identity: identityDecision.name },
13537
+ ...poolPick === void 0 ? {} : { pool: poolPick },
13538
+ ...configDir === void 0 || configDir === "" ? {} : { configDir },
13539
+ ...configProfileDecision.name === void 0 ? {} : { configProfile: configProfileDecision.name },
13540
+ ...resolvedProvider === void 0 ? {} : { provider: resolvedProvider.name }
13541
+ };
13542
+ return { bin: discovered.path, args: finalArgv, env: finalEnv, release, markChildStarted: updateCheck.markChildStarted, decision };
13491
13543
  }
13492
13544
  function runLauncher(params) {
13493
13545
  const plan = prepareLaunch(params);
@@ -13503,6 +13555,22 @@ function runLauncher(params) {
13503
13555
  var import_node_os6 = __toESM(require("node:os"), 1);
13504
13556
  var import_node_crypto12 = require("node:crypto");
13505
13557
 
13558
+ // src/ownCli.ts
13559
+ var import_node_path31 = __toESM(require("node:path"), 1);
13560
+ var OWN_CLI_FILE_NAME = "cli.cjs";
13561
+ var OwnCliPathUnknownError = class extends CliError {
13562
+ constructor() {
13563
+ super("this agent-shim build does not record where it was loaded from, so the path of its command line bundle is unknown: pass the path of the agent-shim executable explicitly");
13564
+ this.name = "OwnCliPathUnknownError";
13565
+ }
13566
+ };
13567
+ function agentShimCliPath(distDir = typeof __AGENT_SHIM_DIST_DIR__ === "string" ? __AGENT_SHIM_DIST_DIR__ : void 0) {
13568
+ if (distDir === void 0) {
13569
+ throw new OwnCliPathUnknownError();
13570
+ }
13571
+ return import_node_path31.default.join(distDir, OWN_CLI_FILE_NAME);
13572
+ }
13573
+
13506
13574
  // src/frontdoor/realFrontDoorPort.ts
13507
13575
  var import_node_fs10 = __toESM(require("node:fs"), 1);
13508
13576
 
@@ -13572,11 +13640,11 @@ function probeFrontDoorSync(port, caPem) {
13572
13640
 
13573
13641
  // src/frontdoor/trust.ts
13574
13642
  var import_node_crypto11 = require("node:crypto");
13575
- var import_node_path31 = __toESM(require("node:path"), 1);
13643
+ var import_node_path32 = __toESM(require("node:path"), 1);
13576
13644
  var BUNDLE_NAME_HEX_DIGITS = 16;
13577
13645
  function resolveTrustBundle(params) {
13578
13646
  const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
13579
- if (inherited === void 0 || inherited === "" || import_node_path31.default.resolve(inherited) === import_node_path31.default.resolve(caCertFile)) {
13647
+ if (inherited === void 0 || inherited === "" || import_node_path32.default.resolve(inherited) === import_node_path32.default.resolve(caCertFile)) {
13580
13648
  return { path: caCertFile };
13581
13649
  }
13582
13650
  const caPem = fs12.readFileUtf8(caCertFile);
@@ -13594,7 +13662,7 @@ function resolveTrustBundle(params) {
13594
13662
  }
13595
13663
  const combined = `${inheritedPem.trimEnd()}
13596
13664
  ${caPem}`;
13597
- const bundle = import_node_path31.default.join(bundlesDir, `${(0, import_node_crypto11.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
13665
+ const bundle = import_node_path32.default.join(bundlesDir, `${(0, import_node_crypto11.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
13598
13666
  if (!fs12.exists(bundle)) {
13599
13667
  fs12.mkdirp(bundlesDir);
13600
13668
  fs12.writeFileAtomic(bundle, combined);
@@ -13733,9 +13801,7 @@ function prepareClaudeLaunch(options) {
13733
13801
  throw new LaunchRefusedError(refusals.join("\n") || `the launch was refused (exit ${String(code)})`, code);
13734
13802
  }
13735
13803
  };
13736
- const spawnDaemon = options.agentShim === void 0 ? () => {
13737
- throw new LaunchRefusedError("this launch routes through the front door or headroom, which need `agentShim`, the path of the agent-shim executable, to start their daemons", 1);
13738
- } : spawnDaemonThrough(options.agentShim);
13804
+ const spawnDaemon = options.agentShim === void 0 ? (spawnPaths, subcommand, logPath) => spawnDaemonThroughScript(agentShimCliPath())(spawnPaths, subcommand, logPath) : spawnDaemonThrough(options.agentShim);
13739
13805
  return prepareLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) }));
13740
13806
  }
13741
13807
  // Annotate the CommonJS export names for ESM import in node:
@@ -13792,6 +13858,7 @@ function prepareClaudeLaunch(options) {
13792
13858
  LaunchLifecycleEventSchema,
13793
13859
  LaunchRefusedError,
13794
13860
  LegacyProviderFileError,
13861
+ OWN_CLI_FILE_NAME,
13795
13862
  PROMPT_CACHE_TTL_MS,
13796
13863
  PlanClassSchema,
13797
13864
  PoolNameSchema,
@@ -13847,6 +13914,7 @@ function prepareClaudeLaunch(options) {
13847
13914
  addIdentity,
13848
13915
  addPool,
13849
13916
  addProvider,
13917
+ agentShimCliPath,
13850
13918
  answerRcControlRequest,
13851
13919
  authenticateRcSessionMcpServer,
13852
13920
  buildEntryFacts,
@@ -13945,6 +14013,7 @@ function prepareClaudeLaunch(options) {
13945
14013
  parseConnectTarget,
13946
14014
  parseRcStreamEnvelope,
13947
14015
  planOf,
14016
+ poolIdentities,
13948
14017
  prepareClaudeLaunch,
13949
14018
  prepareLaunch,
13950
14019
  profileExists,
package/dist/index.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ const __AGENT_SHIM_DIST_DIR__ = import.meta.dirname;
2
+
1
3
  // src/config/classify.ts
2
4
  import picomatch from "picomatch";
3
5
 
@@ -2911,8 +2913,8 @@ function parseConnectTarget(authority) {
2911
2913
  function isInterceptedHost(host, interceptHosts) {
2912
2914
  return interceptHosts.includes(host);
2913
2915
  }
2914
- function servedByPipeline(path32) {
2915
- return path32?.startsWith(ROUTED_PATH_PREFIX) === true;
2916
+ function servedByPipeline(path33) {
2917
+ return path33?.startsWith(ROUTED_PATH_PREFIX) === true;
2916
2918
  }
2917
2919
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
2918
2920
  "connection",
@@ -3446,11 +3448,11 @@ function createRcSessionTracker(deps) {
3446
3448
  };
3447
3449
  const observeExchange = (request4) => {
3448
3450
  const method = (request4.method ?? "").toUpperCase();
3449
- const path32 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
3450
- if (!path32.startsWith(RC_SESSIONS_PATH_PREFIX)) {
3451
+ const path33 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
3452
+ if (!path33.startsWith(RC_SESSIONS_PATH_PREFIX)) {
3451
3453
  return void 0;
3452
3454
  }
3453
- const tail = path32.slice(RC_SESSIONS_PATH_PREFIX.length);
3455
+ const tail = path33.slice(RC_SESSIONS_PATH_PREFIX.length);
3454
3456
  const facts = {
3455
3457
  oauthAuthorization: oauthAuthorizationOf(request4.headers),
3456
3458
  anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
@@ -3832,8 +3834,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
3832
3834
  function isRcReadFileEncoding(value) {
3833
3835
  return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
3834
3836
  }
3835
- function buildRcReadFilePayload(requestId, path32, options) {
3836
- return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path32, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
3837
+ function buildRcReadFilePayload(requestId, path33, options) {
3838
+ return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path33, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
3837
3839
  }
3838
3840
  function buildRcFileSuggestionsPayload(requestId, query) {
3839
3841
  return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
@@ -3935,15 +3937,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
3935
3937
  const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
3936
3938
  return result.ok ? { ...result, requestId } : result;
3937
3939
  }
3938
- async function readRcSessionFile(deps, sessionId, path32, options) {
3939
- if (path32 === "") {
3940
+ async function readRcSessionFile(deps, sessionId, path33, options) {
3941
+ if (path33 === "") {
3940
3942
  return { ok: false, message: "a read-file write needs a non-empty path: the SDK's own field names the file the worker resolves against the session's cwd, and an empty string names none" };
3941
3943
  }
3942
3944
  if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
3943
3945
  return { ok: false, message: "a read-file write's max-bytes is a positive whole number of bytes: the SDK's own field caps the read, and a zero or negative cap reads nothing" };
3944
3946
  }
3945
3947
  const requestId = deps.newUuid();
3946
- const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path32, options), `read ${path32} from session ${sessionId}`);
3948
+ const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path33, options), `read ${path33} from session ${sessionId}`);
3947
3949
  return result.ok ? { ...result, requestId } : result;
3948
3950
  }
3949
3951
  async function suggestRcSessionFiles(deps, sessionId, query) {
@@ -4108,11 +4110,11 @@ function createRcControlHandler(deps) {
4108
4110
  path: "read-file",
4109
4111
  read: (body) => {
4110
4112
  const session = bodyString(body, "session");
4111
- const path32 = bodyString(body, "path");
4113
+ const path33 = bodyString(body, "path");
4112
4114
  const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
4113
4115
  const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
4114
- const refused2 = session === void 0 || path32 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
4115
- return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path32, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
4116
+ const refused2 = session === void 0 || path33 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
4117
+ return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path33, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
4116
4118
  }
4117
4119
  },
4118
4120
  {
@@ -4422,9 +4424,9 @@ function requestIdOfBody(body) {
4422
4424
  }
4423
4425
  function frontDoorRcControl(transport, token) {
4424
4426
  const headers = { authorization: `Bearer ${token}` };
4425
- const listAnswerOf = async (path32, what) => {
4427
+ const listAnswerOf = async (path33, what) => {
4426
4428
  try {
4427
- return await transport.request({ method: "GET", path: path32, headers });
4429
+ return await transport.request({ method: "GET", path: path33, headers });
4428
4430
  } catch (error) {
4429
4431
  throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
4430
4432
  }
@@ -4496,10 +4498,10 @@ function frontDoorRcControl(transport, token) {
4496
4498
  }
4497
4499
  return pending;
4498
4500
  };
4499
- const writeOf = async (path32, body, describeFailure) => {
4501
+ const writeOf = async (path33, body, describeFailure) => {
4500
4502
  let answer;
4501
4503
  try {
4502
- answer = await transport.request({ method: "POST", path: path32, headers: { ...headers, "content-type": "application/json" }, body });
4504
+ answer = await transport.request({ method: "POST", path: path33, headers: { ...headers, "content-type": "application/json" }, body });
4503
4505
  } catch (error) {
4504
4506
  return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
4505
4507
  }
@@ -4530,10 +4532,10 @@ function frontDoorRcControl(transport, token) {
4530
4532
  endSession: async (sessionId, reason) => await writeOf(`${CONTROL_PATH_PREFIX}/end-session`, JSON.stringify({ session: sessionId, ...reason === void 0 ? {} : { reason } }), (status, message) => `ending ${sessionId} failed (HTTP ${String(status)}): ${message}`),
4531
4533
  getUsage: async (sessionId, skipBehaviors) => await writeOf(`${CONTROL_PATH_PREFIX}/get-usage`, JSON.stringify({ session: sessionId, ...skipBehaviors === void 0 ? {} : { skipBehaviors } }), (status, message) => `requesting the usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
4532
4534
  getContextUsage: async (sessionId, detail) => await writeOf(`${CONTROL_PATH_PREFIX}/get-context-usage`, JSON.stringify({ session: sessionId, ...detail === void 0 ? {} : { detail } }), (status, message) => `requesting the context usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
4533
- readFile: async (sessionId, path32, options) => await writeOf(
4535
+ readFile: async (sessionId, path33, options) => await writeOf(
4534
4536
  `${CONTROL_PATH_PREFIX}/read-file`,
4535
- JSON.stringify({ session: sessionId, path: path32, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
4536
- (status, message) => `reading ${path32} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
4537
+ JSON.stringify({ session: sessionId, path: path33, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
4538
+ (status, message) => `reading ${path33} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
4537
4539
  ),
4538
4540
  fileSuggestions: async (sessionId, query) => await writeOf(`${CONTROL_PATH_PREFIX}/file-suggestions`, JSON.stringify({ session: sessionId, query }), (status, message) => `requesting file suggestions from ${sessionId} failed (HTTP ${String(status)}): ${message}`),
4539
4541
  keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
@@ -4688,12 +4690,12 @@ function tlsFacts(options) {
4688
4690
  }
4689
4691
  function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
4690
4692
  const agent = new ExemptTlsAgent();
4691
- const post = async (path32, headers, body) => await new Promise((resolve, reject) => {
4693
+ const post = async (path33, headers, body) => await new Promise((resolve, reject) => {
4692
4694
  const options = {
4693
4695
  host: target.host,
4694
4696
  port: target.port,
4695
4697
  method: "POST",
4696
- path: path32,
4698
+ path: path33,
4697
4699
  // 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.
4698
4700
  headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
4699
4701
  agent
@@ -4758,12 +4760,12 @@ function lateRcStreamDial(resolve) {
4758
4760
  }
4759
4761
  function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
4760
4762
  const agent = new ExemptTlsAgent();
4761
- const request4 = async (method, path32, headers, body, signal) => await new Promise((resolve, reject) => {
4763
+ const request4 = async (method, path33, headers, body, signal) => await new Promise((resolve, reject) => {
4762
4764
  const options = {
4763
4765
  host: target.host,
4764
4766
  port: target.port,
4765
4767
  method,
4766
- path: path32,
4768
+ path: path33,
4767
4769
  // 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.
4768
4770
  headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
4769
4771
  agent,
@@ -4805,9 +4807,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
4805
4807
  return { status, body: await readAll(response) };
4806
4808
  },
4807
4809
  openStream: async (sessionId, headers, resume, signal) => {
4808
- const path32 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
4810
+ const path33 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
4809
4811
  const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
4810
- const { status, response } = await request4("GET", path32, streamHeaders, void 0, signal);
4812
+ const { status, response } = await request4("GET", path33, streamHeaders, void 0, signal);
4811
4813
  if (!isSuccessful2(status)) {
4812
4814
  await readAll(response);
4813
4815
  return { status, chunks: NO_CHUNKS };
@@ -5111,7 +5113,7 @@ import { Agent as Agent3, fetch as undiciFetch } from "undici";
5111
5113
  // package.json
5112
5114
  var package_default = {
5113
5115
  name: "agent-shim",
5114
- version: "8.38.1",
5116
+ version: "8.40.0",
5115
5117
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
5116
5118
  license: "MIT",
5117
5119
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -6656,12 +6658,7 @@ function rankNamedPool(input, poolName, stack, sticky) {
6656
6658
  }
6657
6659
  continue;
6658
6660
  }
6659
- if (input.pools[nestedName] === void 0) {
6660
- throw new PoolGraphError(`Pool "${poolName}" member "${poolMemberIdentity(entry)}" names a pool that is not defined.`);
6661
- }
6662
- if (childStack.includes(nestedName)) {
6663
- throw new PoolGraphError(`Pool "${poolName}" member "${poolMemberIdentity(entry)}" closes a cycle: ${[...childStack.slice(childStack.indexOf(nestedName)), nestedName].join(" -> ")}. A pool cannot nest itself, directly or through another pool.`);
6664
- }
6661
+ assertNestable(input.pools, poolName, poolMemberIdentity(entry), nestedName, childStack);
6665
6662
  const nested = nestedMember(input, nestedName, childStack, sticky);
6666
6663
  members.push(typeof entry === "string" ? nested.member : { ...nested.member, policy: entry.when });
6667
6664
  missing.push(...nested.missing);
@@ -6675,6 +6672,14 @@ function rankNamedPool(input, poolName, stack, sticky) {
6675
6672
  });
6676
6673
  return { ranking, missing };
6677
6674
  }
6675
+ function assertNestable(pools, poolName, member, nestedName, childStack) {
6676
+ if (pools[nestedName] === void 0) {
6677
+ throw new PoolGraphError(`Pool "${poolName}" member "${member}" names a pool that is not defined.`);
6678
+ }
6679
+ if (childStack.includes(nestedName)) {
6680
+ throw new PoolGraphError(`Pool "${poolName}" member "${member}" closes a cycle: ${[...childStack.slice(childStack.indexOf(nestedName)), nestedName].join(" -> ")}. A pool cannot nest itself, directly or through another pool.`);
6681
+ }
6682
+ }
6678
6683
  function nestedMember(input, nestedName, childStack, sticky) {
6679
6684
  const nested = rankNamedPool(input, nestedName, childStack, sticky);
6680
6685
  const pick = nested.ranking.pick;
@@ -6692,6 +6697,27 @@ function nestedMember(input, nestedName, childStack, sticky) {
6692
6697
  missing: nested.missing
6693
6698
  };
6694
6699
  }
6700
+ function poolIdentities(pools, poolName) {
6701
+ const found = /* @__PURE__ */ new Set();
6702
+ collectPoolIdentities(pools, poolName, [], found);
6703
+ return [...found];
6704
+ }
6705
+ function collectPoolIdentities(pools, poolName, stack, found) {
6706
+ const pool = pools[poolName];
6707
+ if (pool === void 0) {
6708
+ throw new PoolGraphError(`No pool named "${poolName}". Run \`agent-shim pool add ${poolName} --identity <name>...\` first.`);
6709
+ }
6710
+ const childStack = [...stack, poolName];
6711
+ for (const entry of pool.identities) {
6712
+ const nestedName = poolNameOf(poolMemberIdentity(entry));
6713
+ if (nestedName === void 0) {
6714
+ found.add(poolMemberIdentity(entry));
6715
+ continue;
6716
+ }
6717
+ assertNestable(pools, poolName, poolMemberIdentity(entry), nestedName, childStack);
6718
+ collectPoolIdentities(pools, nestedName, childStack, found);
6719
+ }
6720
+ }
6695
6721
  function readPicksFile(fs12, file) {
6696
6722
  const empty = { schemaVersion: SCHEMA_VERSION, picks: {} };
6697
6723
  const raw = fs12.readFileUtf8(file);
@@ -6922,19 +6948,19 @@ function writePools(paths, pools) {
6922
6948
  applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
6923
6949
  }
6924
6950
  function poolCycleOf(pools, name) {
6925
- const walk = (current, path32) => {
6951
+ const walk = (current, path33) => {
6926
6952
  for (const entry of pools[current]?.identities ?? []) {
6927
6953
  const nested = poolNameOf(poolMemberIdentity(entry));
6928
6954
  if (nested === void 0) {
6929
6955
  continue;
6930
6956
  }
6931
6957
  if (nested === name) {
6932
- return [...path32, nested];
6958
+ return [...path33, nested];
6933
6959
  }
6934
- if (path32.includes(nested)) {
6960
+ if (path33.includes(nested)) {
6935
6961
  continue;
6936
6962
  }
6937
- const found = walk(nested, [...path32, nested]);
6963
+ const found = walk(nested, [...path33, nested]);
6938
6964
  if (found !== void 0) {
6939
6965
  return found;
6940
6966
  }
@@ -8241,6 +8267,9 @@ function detachedDaemonSpawnOptions(logFd, env) {
8241
8267
  function spawnDaemonThrough(executable) {
8242
8268
  return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: executable, args: [subcommand] }, paths, subcommand, logPath);
8243
8269
  }
8270
+ function spawnDaemonThroughScript(script) {
8271
+ return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: process.execPath, args: [script, subcommand] }, paths, subcommand, logPath);
8272
+ }
8244
8273
  function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
8245
8274
  fs7.mkdirSync(path22.dirname(logPath), { recursive: true });
8246
8275
  const logFd = fs7.openSync(logPath, "a");
@@ -12777,7 +12806,13 @@ function resolvePoolLaunch(params) {
12777
12806
  if (pick !== void 0) {
12778
12807
  recordStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd, pick.identity, nowMs);
12779
12808
  const move = movedOff === void 0 ? "" : `moved off ${movedOff.identity} (${movedOff.reason}); `;
12780
- return { ok: true, identity: pick.identity, explanation: `pool ${poolName}: ${move}${pick.reasons.slice(0, REASONS_LOGGED).join("; ")}` };
12809
+ return {
12810
+ ok: true,
12811
+ identity: pick.identity,
12812
+ explanation: `pool ${poolName}: ${move}${pick.reasons.slice(0, REASONS_LOGGED).join("; ")}`,
12813
+ reasons: pick.reasons,
12814
+ ...movedOff === void 0 ? {} : { movedOff }
12815
+ };
12781
12816
  }
12782
12817
  if (earliestReturn === void 0) {
12783
12818
  return { ok: false, message: `agent-shim: no member of pool "${poolName}" can be picked.` };
@@ -12935,7 +12970,11 @@ function pickFromPool(decided, params, parsedArgv) {
12935
12970
  log.error(resolution.message);
12936
12971
  return proc.exit(1);
12937
12972
  }
12938
- return { identityDecision: { ...decided, name: resolution.identity }, poolExplanation: resolution.explanation };
12973
+ return {
12974
+ identityDecision: { ...decided, name: resolution.identity },
12975
+ poolExplanation: resolution.explanation,
12976
+ poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } }
12977
+ };
12939
12978
  }
12940
12979
  function prepareLaunch(params) {
12941
12980
  const { paths, fs: fs12, proc, log } = params;
@@ -12961,7 +13000,7 @@ function prepareLaunch(params) {
12961
13000
  return trimmed === "" ? void 0 : trimmed;
12962
13001
  }
12963
13002
  });
12964
- const { identityDecision, poolExplanation } = pickFromPool(decidedIdentity, params, parsedArgv);
13003
+ const { identityDecision, poolExplanation, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv);
12965
13004
  const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
12966
13005
  const farm = farmIdentity === void 0 ? void 0 : params.farm;
12967
13006
  if (farm !== void 0 && farmIdentity !== void 0) {
@@ -13175,7 +13214,18 @@ function prepareLaunch(params) {
13175
13214
  registered();
13176
13215
  }
13177
13216
  };
13178
- return { bin: discovered.path, args: finalArgv, env: finalEnv, release, markChildStarted: updateCheck.markChildStarted };
13217
+ const configDir = finalEnv.CLAUDE_CONFIG_DIR;
13218
+ const decision = {
13219
+ identitySource: identityDecision.source,
13220
+ configDirEscapeHatch: identityDecision.configDirEscapeHatch,
13221
+ configProfileSource: configProfileDecision.source,
13222
+ ...identityDecision.name === void 0 ? {} : { identity: identityDecision.name },
13223
+ ...poolPick === void 0 ? {} : { pool: poolPick },
13224
+ ...configDir === void 0 || configDir === "" ? {} : { configDir },
13225
+ ...configProfileDecision.name === void 0 ? {} : { configProfile: configProfileDecision.name },
13226
+ ...resolvedProvider === void 0 ? {} : { provider: resolvedProvider.name }
13227
+ };
13228
+ return { bin: discovered.path, args: finalArgv, env: finalEnv, release, markChildStarted: updateCheck.markChildStarted, decision };
13179
13229
  }
13180
13230
  function runLauncher(params) {
13181
13231
  const plan = prepareLaunch(params);
@@ -13191,6 +13241,22 @@ function runLauncher(params) {
13191
13241
  import os7 from "node:os";
13192
13242
  import { randomUUID as randomUUID5 } from "node:crypto";
13193
13243
 
13244
+ // src/ownCli.ts
13245
+ import path31 from "node:path";
13246
+ var OWN_CLI_FILE_NAME = "cli.cjs";
13247
+ var OwnCliPathUnknownError = class extends CliError {
13248
+ constructor() {
13249
+ super("this agent-shim build does not record where it was loaded from, so the path of its command line bundle is unknown: pass the path of the agent-shim executable explicitly");
13250
+ this.name = "OwnCliPathUnknownError";
13251
+ }
13252
+ };
13253
+ function agentShimCliPath(distDir = typeof __AGENT_SHIM_DIST_DIR__ === "string" ? __AGENT_SHIM_DIST_DIR__ : void 0) {
13254
+ if (distDir === void 0) {
13255
+ throw new OwnCliPathUnknownError();
13256
+ }
13257
+ return path31.join(distDir, OWN_CLI_FILE_NAME);
13258
+ }
13259
+
13194
13260
  // src/frontdoor/realFrontDoorPort.ts
13195
13261
  import fs11 from "node:fs";
13196
13262
 
@@ -13260,11 +13326,11 @@ function probeFrontDoorSync(port, caPem) {
13260
13326
 
13261
13327
  // src/frontdoor/trust.ts
13262
13328
  import { createHash as createHash6 } from "node:crypto";
13263
- import path31 from "node:path";
13329
+ import path32 from "node:path";
13264
13330
  var BUNDLE_NAME_HEX_DIGITS = 16;
13265
13331
  function resolveTrustBundle(params) {
13266
13332
  const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
13267
- if (inherited === void 0 || inherited === "" || path31.resolve(inherited) === path31.resolve(caCertFile)) {
13333
+ if (inherited === void 0 || inherited === "" || path32.resolve(inherited) === path32.resolve(caCertFile)) {
13268
13334
  return { path: caCertFile };
13269
13335
  }
13270
13336
  const caPem = fs12.readFileUtf8(caCertFile);
@@ -13282,7 +13348,7 @@ function resolveTrustBundle(params) {
13282
13348
  }
13283
13349
  const combined = `${inheritedPem.trimEnd()}
13284
13350
  ${caPem}`;
13285
- const bundle = path31.join(bundlesDir, `${createHash6("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
13351
+ const bundle = path32.join(bundlesDir, `${createHash6("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
13286
13352
  if (!fs12.exists(bundle)) {
13287
13353
  fs12.mkdirp(bundlesDir);
13288
13354
  fs12.writeFileAtomic(bundle, combined);
@@ -13421,9 +13487,7 @@ function prepareClaudeLaunch(options) {
13421
13487
  throw new LaunchRefusedError(refusals.join("\n") || `the launch was refused (exit ${String(code)})`, code);
13422
13488
  }
13423
13489
  };
13424
- const spawnDaemon = options.agentShim === void 0 ? () => {
13425
- throw new LaunchRefusedError("this launch routes through the front door or headroom, which need `agentShim`, the path of the agent-shim executable, to start their daemons", 1);
13426
- } : spawnDaemonThrough(options.agentShim);
13490
+ const spawnDaemon = options.agentShim === void 0 ? (spawnPaths, subcommand, logPath) => spawnDaemonThroughScript(agentShimCliPath())(spawnPaths, subcommand, logPath) : spawnDaemonThrough(options.agentShim);
13427
13491
  return prepareLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) }));
13428
13492
  }
13429
13493
  export {
@@ -13479,6 +13543,7 @@ export {
13479
13543
  LaunchLifecycleEventSchema,
13480
13544
  LaunchRefusedError,
13481
13545
  LegacyProviderFileError,
13546
+ OWN_CLI_FILE_NAME,
13482
13547
  PROMPT_CACHE_TTL_MS,
13483
13548
  PlanClassSchema,
13484
13549
  PoolNameSchema,
@@ -13534,6 +13599,7 @@ export {
13534
13599
  addIdentity,
13535
13600
  addPool,
13536
13601
  addProvider,
13602
+ agentShimCliPath,
13537
13603
  answerRcControlRequest,
13538
13604
  authenticateRcSessionMcpServer,
13539
13605
  buildEntryFacts,
@@ -13632,6 +13698,7 @@ export {
13632
13698
  parseConnectTarget,
13633
13699
  parseRcStreamEnvelope,
13634
13700
  planOf,
13701
+ poolIdentities,
13635
13702
  prepareClaudeLaunch,
13636
13703
  prepareLaunch,
13637
13704
  profileExists,
@@ -7067,6 +7067,13 @@ interface PoolRanking {
7067
7067
  */
7068
7068
  declare function rankPool(input: RankPoolInput): PoolRanking;
7069
7069
 
7070
+ /**
7071
+ * The concrete identities the pool named `poolName` can launch as, in member order with a nested `pool:<name>` entry replaced by the identities of that pool at the entry's position, each identity once. It reads no usage and no identity file, so it lists every identity the pool graph names, whether or not it exists or is eligible: ranking is `rankPoolGraph`'s job.
7072
+ *
7073
+ * Throws `PoolGraphError` when the pool, or a pool it nests, is not defined, or when the graph reaches a pool it is already inside.
7074
+ */
7075
+ declare function poolIdentities(pools: Readonly<Record<string, Pool>>, poolName: string): readonly string[];
7076
+
7070
7077
  /**
7071
7078
  * Ranks a pool exactly as a launch from `directory` would right now, without recording a pick. Shares `rankPoolGraph` with the launcher, so what this prints is what a launch does.
7072
7079
  */
@@ -7634,6 +7641,39 @@ interface PrepareLaunchParams {
7634
7641
  interface RunLauncherParams extends PrepareLaunchParams {
7635
7642
  readonly spawn: SpawnPort;
7636
7643
  }
7644
+ /** The pick a pool made for a launch: the pool, why the ranking chose the member it did, and, for a resumed conversation, the member it left. */
7645
+ interface LaunchPoolDecision {
7646
+ /** The pool the launch selected with `pool:<name>`. */
7647
+ readonly name: string;
7648
+ /** Every reason the ranking gave for the chosen member, in the ranking's order. */
7649
+ readonly reasons: readonly string[];
7650
+ /** The member a resumed conversation left, and why the ranking could not keep it. */
7651
+ readonly movedOff?: {
7652
+ readonly identity: string;
7653
+ readonly reason: string;
7654
+ };
7655
+ }
7656
+ /**
7657
+ * What a launch resolved to, and where each decision came from. Everything here is a name or a path, never a credential.
7658
+ */
7659
+ interface LaunchDecision {
7660
+ /** The identity the launch runs as. Absent when the escape hatch applied or nothing resolved one. */
7661
+ readonly identity?: string;
7662
+ /** Which precedence rule selected the identity (or the pool the identity was picked from). */
7663
+ readonly identitySource: IdentityDecisionSource;
7664
+ /** The pool pick behind `identity`, when the launch selected a pool. */
7665
+ readonly pool?: LaunchPoolDecision;
7666
+ /** True when `CLAUDE_CONFIG_DIR` was already set, so no identity was resolved and no farm was managed. */
7667
+ readonly configDirEscapeHatch: boolean;
7668
+ /** The configuration directory the child runs with: the identity's own, or the one the caller named. Absent when none is set. */
7669
+ readonly configDir?: string;
7670
+ /** The configuration profile that applied, when one did. */
7671
+ readonly configProfile?: string;
7672
+ /** Which precedence rule selected the configuration profile. */
7673
+ readonly configProfileSource: ConfigProfileDecisionSource;
7674
+ /** The provider the launch routes through, when it selected one. */
7675
+ readonly provider?: string;
7676
+ }
7637
7677
  /**
7638
7678
  * What one launch resolved to, once every effect its child depends on is in place (the identity's farm resynced, the front door and headroom up and this launch registered with them): the real binary, its arguments and its environment.
7639
7679
  */
@@ -7643,6 +7683,8 @@ interface LaunchPlan {
7643
7683
  readonly env: Readonly<Record<string, string | undefined>>;
7644
7684
  /** Releases the daemon session registrations this launch holds. Call it when the child has exited; it is safe to call more than once. */
7645
7685
  readonly release: () => void;
7686
+ /** What the launch resolved to, as data: the facts the launcher's decision line reports. */
7687
+ readonly decision: LaunchDecision;
7646
7688
  /** Marks the moment this plan's child is spawned: the launch-time update check suppresses its notify line from then on, since a line printed after the child took over the terminal would land mid-session. Call it immediately before spawning; it is safe to call more than once. */
7647
7689
  readonly markChildStarted: () => void;
7648
7690
  }
@@ -7698,7 +7740,7 @@ interface PrepareClaudeLaunchOptions {
7698
7740
  readonly env: Readonly<Record<string, string | undefined>>;
7699
7741
  /** The state root; defaults to the one the command line resolves. */
7700
7742
  readonly paths?: LayoutPaths;
7701
- /** The path of the agent-shim executable, used to start the front door and headroom daemons when the launch routes through them. Without it such a launch is refused: this process is not agent-shim, and re-running it would run the host program again. */
7743
+ /** The path of the agent-shim executable, used to start the front door and headroom daemons when the launch routes through them. Without it the daemons start through the command line bundle of this same package (`agentShimCliPath`), run with the Node running this process; pass it to use another build or a compiled binary. */
7702
7744
  readonly agentShim?: string;
7703
7745
  }
7704
7746
  /**
@@ -7708,5 +7750,14 @@ interface PrepareClaudeLaunchOptions {
7708
7750
  */
7709
7751
  declare function prepareClaudeLaunch(options: PrepareClaudeLaunchOptions): LaunchPlan;
7710
7752
 
7711
- export { AMBIENT_CREDENTIAL_VARS, CHECK_CREDENTIAL_APPLIES, CONNECT_INTERCEPT_HOST, CONNECT_INTERCEPT_HOSTS, CONNECT_LIMITS, CONTROL_PATH_PREFIX, CategoryClassificationOverlaySchema, CategoryClassificationSchema, CategoryMapSchema, CheckReportJsonSchema, CheckRunInputSchema, CliError, ConfigProfileSchema, CredentialCacheSchema, CredentialSchema, CredentialSourceSchema, DOOR_EVENT_BUFFER_EVENTS, DOOR_EVENT_SOURCE_RC, DOOR_HEALTH_EVENT_SOURCE, DirectoryRuleAlreadyExistsError, DirectoryRuleMissingTargetError, DirectoryRuleNotFoundError, DirectoryRuleSchema, DirectoryRulesSchema, DoctorFindingSchema, DoctorRunOutputSchema, DoorEventSchema, DoorEventSourceQuerySchema, DoorHealthEventSchema, EXIT_FAILURE, EXIT_USAGE, EffectiveWindowSchema, EntryValueSchema, FARM_MANIFEST_FILENAME, FrontDoorSessionStatusSchema, FrontDoorSessionsOutputSchema, FrontDoorStartError, FrontDoorStateSchema, FrontDoorStatusOutputSchema, GlobalConfigSchema, HeadroomSocketTargetSchema, HeadroomStartError, IdentityAlreadyExistsError, IdentityNotFoundError, IdentitySchema, InvalidCategoryNameError, InvalidIdentityNameError, InvalidProviderNameError, LAUNCH_EVENT_SOURCE, LaunchLifecycleEventSchema, LaunchRefusedError, LegacyProviderFileError, PROMPT_CACHE_TTL_MS, PlanClassSchema, PoolNameSchema, PoolNotFoundError, PoolPickReportSchema, PoolSchema, PortableConfigSchema, ProfileAlreadyExistsError, ProfileNotFoundError, ProviderAlreadyExistsError, ProviderKindMismatchError, ProviderNotFoundError, ProviderSchema, QUOTA_EXPIRING_EVENT_SOURCE, QuotaExpiringEventSchema, RC_CONTEXT_USAGE_DETAILS, RC_IDLE_EXPIRY_MS, RC_ORPC_PATH_PREFIX, RC_PENDING_DEADLINE_MS, RC_PERMISSION_MODES, RC_READ_FILE_ENCODINGS, RC_REQUEST_PARSE_CAP_BYTES, RC_SELF_HOST_ENV, RC_SELF_HOST_KEEPALIVE_MS, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE, RC_SELF_HOST_RETENTION_MS, RC_SELF_HOST_SCOPE_LIST, RC_SELF_HOST_WORKER_JWT_TTL_SECONDS, RC_SESSIONS_PATH_PREFIX, RC_STREAM_BACKOFF_MS, RC_WEB_FETCH_ALLOW_PRIVATE_ENV, RC_WEB_FETCH_DEADLINE_MS, RC_WEB_FETCH_MAX_BYTES, RC_WEB_FETCH_MAX_REDIRECTS, ROUTED_PATH_PREFIX, RcLiveRateLimitSchema, RcPermissionModeSchema, RcRateLimitInfoSchema, RcRateLimitWindowSchema, RcStreamEnvelopeSchema, RcStreamEventSchema, USAGE_EVENT_SOURCE, UsageError, UsageListOutputSchema, UsageLiveOutputSchema, UsageSnapshotError, UsageSnapshotSchema, UsageWindowsInputSchema, UsageWindowsOutputSchema, WhenSchema, addDirectoryRule, addIdentity, addPool, addProvider, answerRcControlRequest, authenticateRcSessionMcpServer, buildEntryFacts, buildLayoutPaths, buildRcControlRequestPayload, buildRcControlResponsePayload, buildRcEndSessionPayload, buildRcEventWriteBody, buildRcFileSuggestionsPayload, buildRcGetContextUsagePayload, buildRcGetUsagePayload, buildRcInterruptPayload, buildRcKeepAlivePayload, buildRcMarkReadBody, buildRcMcpAuthenticatePayload, buildRcMcpOAuthCallbackUrlPayload, buildRcMcpReconnectPayload, buildRcMcpStatusPayload, buildRcReadFilePayload, buildRcSetModelPayload, buildRcSetPermissionModePayload, buildRcUserMessagePayload, carryOver, checkReportHasWarnings, checkReportToJson, collectCheckReport, collectDoctorReport, collectFrontDoorStatus, collectPoolPick, createControlApiRouter, createDoorApiNodeHandler, createDoorApiRouter, createDoorEventHub, createDoorHealthPublisher, createEventsApiRouter, createLaunchEventPublisher, createLeafCache, createProfile, createQuotaExpiringPublisher, createRcApiNodeHandler, createRcApiRouter, createRcControlHandler, createRcCredentialStore, createRcEventFanout, createRcLiveUsage, createRcSelfHostSurface, createRcSessionTracker, createRcStreamHub, createSseParser, describeProviderEndpoint, detectAmbientCredential, doorApiAuth, doorApiNodeHandlerOf, effectiveWindow, endRcSession, ensureCa, ensureFrontDoor, ensureHeadroom, evaluateAmbientCredentialGuard, evaluateWhen, fetchThroughWebProxy, formatAmbientCredentialGuardMessage, formatCheckReport, formatDoctorReport, formatFrontDoorStatus, forwardableHeaders, frontDoorApiClient, frontDoorApiLink, frontDoorRcApiClient, frontDoorRcControl, generateCa, getRcSessionContextUsage, getRcSessionMcpStatus, getRcSessionUsage, headroomSocketTarget, identityExists, injectRcUserMessage, interruptRcSession, isIdentityDirectoryName, isInterceptedHost, isPrivateAddress, isRcContextUsageDetail, isRcPermissionMode, isRcReadFileEncoding, lateRcEventDial, lateRcStreamDial, listDirectoryRules, listIdentities, listProfiles, listProviders, listUsageSnapshots, matchBranch, mintLeaf, mintRcSelfHostCredential, observingRoutedRoute, parseConnectTarget, parseRcStreamEnvelope, planOf, prepareClaudeLaunch, prepareLaunch, profileExists, providerExists, rankPool, rcEventWriteResultFromAnswer, rcFanoutOnDoorHub, rcObserverAsPassthrough, rcRateLimitInfoOf, rcSelfHostFromEnv, rcWebFetchAllowsPrivateFromEnv, readActiveIdentity, readDirectoryRules, readFarmManifest, readGlobalConfig, readIdentity, readPools, readProfile, readProvider, readRcSelfHostRecord, readRcSessionFile, readUsageSnapshot, realConnectCertStore, realConnectEffects, realRcControlTransport, realRcEventDial, realRcStreamDial, realRcWebFetch, reconnectRcSessionMcpServer, recoverFarm, recoveryDiagnostics, removeDirectoryRule, removeIdentity, removePool, removeProfile, removeProvider, requirePool, resolveAgentShimHome, resolveClaudeHome, resolveDecisions, resolveLayoutPaths, resolveSupervisorConfig, resyncFarm, runCheck, runDoctor, runFrontDoorSupervisor, runLauncher, runSupervisor, sendRcKeepAlive, servedByPipeline, setAllowAmbientCredential, setDefaultConfigProfile, setGlobalDefaultProfile, setIdentityCredential, setPool, setProfileCategories, setProfileEntries, setProfileLaunchFlags, setProfileMetadata, setRcSessionModel, setRcSessionPermissionMode, snapshotPath, spawnClaude, startConnectServer, submitRcSessionMcpOAuthCallbackUrl, suggestRcSessionFiles, teleportRcSession, topLevelNames, updateDirectoryRule, updateProvider, useIdentity, writeDirectoryRules };
7712
- export type { AddDirectoryRuleOptions, AddProviderInput, AmbientCredentialDetection, AmbientCredentialGuardResult, AmbientCredentialVar, BuildEntryFactsParams, CaMaterial, Candidate, CarryOverParams, CarryOverResult, CategoryMap, CheckReport, CheckReportJson, CollectCheckReportParams, CollectDoctorReportParams, CompiledRule, ConditionContext, ConfigProfile, ConnectCertStore, ConnectEffects, ConnectLimits, ConnectLocalSurface, ConnectServerConfig, ConnectServerHandle, ConnectTarget, ControlApiClient, ControlApiDeps, ControlApiRouter, Credential, CredentialSource, Decision, Diagnostic, DirectoryRule, DirectoryRules, DoctorReport, DoorApiClient, DoorApiContext, DoorApiDeps, DoorApiRouter, DoorEvent, DoorEventHub, DoorEventPublisher, DoorEventStream, DoorEventsApiDeps, DoorHealthEvent, DoorHealthPublisher, EffectiveWindow, EliminatedRule, EnsureFrontDoorPorts, EnsureHeadroomPorts, EntryFact, EntryFacts, EntryValue, EvaluateAmbientCredentialGuardParams, FlattenedCascade, FrontDoorRcControl, FrontDoorSessionStatus, FrontDoorStatus, FrontDoorSupervisorPorts, GlobalConfig, HeadroomSupervisorConfig, Identity, IdentityCredentialChange, IdentityListEntry, IdentityListing, InjectedCredential, LaunchEventPublisher, LaunchLifecycleEvent, LaunchPlan, Layer, LayerId, LayoutPaths, LeafCert, NestedContribution, PlanClass, Pool, PoolMember, PoolPickReport, PoolRanking, PortableConfig, PrepareClaudeLaunchOptions, PrepareLaunchParams, ProfileListEntry, Provider, ProviderListEntry, QuotaExpiringEvent, QuotaExpiringPublisher, RankPoolInput, RcAnswerDecision, RcAnswerDeps, RcApiClient, RcApiDeps, RcApiRouter, RcContextUsageDetail, RcControlAnswer, RcControlHandlerDeps, RcControlRequestDeps, RcControlTransport, RcCredentialStore, RcDialAnswer, RcDialTarget, RcEventDial, RcEventFanout, RcEventWriteResult, RcExchangeObserver, RcInjectDeps, RcLiveRateLimit, RcLiveUsage, RcLiveUsageDeps, RcObservedCredential, RcObservedRequest, RcPendingRequestSummary, RcPermissionMode, RcPresenceAnswer, RcRateLimitInfo, RcRateLimitWindow, RcReadFileEncoding, RcReadFileOptions, RcSelfHostCredentialRecord, RcSelfHostDeps, RcSelfHostMintResult, RcSelfHostSurface, RcSessionStatus, RcSessionSummary, RcSessionTracker, RcSessionTrackerDeps, RcStreamAnswer, RcStreamDial, RcStreamEnvelope, RcStreamEvent, RcStreamHub, RcStreamHubDeps, RcWebFetchDeps, RcWebFetchHop, RcWebFetchOutcome, RcWebFetcher, RcWorkerFact, RcWriteHeaders, RecoverFarmParams, RecoveryResult, ResolveDecisionsInput, ResolvedState, ResyncFarmParams, ResyncFarmResult, RunCheckParams, RunDoctorParams, RunFrontDoorSupervisorOptions, RunLauncherParams, RunSupervisorOptions, SpawnClaudeParams, SseParsedEvent, StickyPick, SupervisorPorts, UnreadableIdentityListEntry, UpdateDirectoryRuleOptions, UpdateProviderInput, UsageChangeEvent, UsageReadFs, UsageSnapshot, WhenCondition, WhenEvaluation };
7753
+ /** The file name of the command line bundle that ships beside the library files in `dist/`. */
7754
+ declare const OWN_CLI_FILE_NAME = "cli.cjs";
7755
+ /**
7756
+ * The path of the command line bundle (`dist/cli.cjs`) of the installed agent-shim package, found from where the library file itself was loaded, so a host that embeds the library can start the front door and headroom daemons through the same release without resolving the package manifest itself. Run it with Node: `spawn(process.execPath, [agentShimCliPath(), ...])`.
7757
+ *
7758
+ * `distDir` is the directory of the library file and exists for a caller or test that knows better; it defaults to the one the build recorded. Throws an `OwnCliPathUnknownError` when there is none, which is the case only when the sources run unbuilt.
7759
+ */
7760
+ declare function agentShimCliPath(distDir?: string | undefined): string;
7761
+
7762
+ export { AMBIENT_CREDENTIAL_VARS, CHECK_CREDENTIAL_APPLIES, CONNECT_INTERCEPT_HOST, CONNECT_INTERCEPT_HOSTS, CONNECT_LIMITS, CONTROL_PATH_PREFIX, CategoryClassificationOverlaySchema, CategoryClassificationSchema, CategoryMapSchema, CheckReportJsonSchema, CheckRunInputSchema, CliError, ConfigProfileSchema, CredentialCacheSchema, CredentialSchema, CredentialSourceSchema, DOOR_EVENT_BUFFER_EVENTS, DOOR_EVENT_SOURCE_RC, DOOR_HEALTH_EVENT_SOURCE, DirectoryRuleAlreadyExistsError, DirectoryRuleMissingTargetError, DirectoryRuleNotFoundError, DirectoryRuleSchema, DirectoryRulesSchema, DoctorFindingSchema, DoctorRunOutputSchema, DoorEventSchema, DoorEventSourceQuerySchema, DoorHealthEventSchema, EXIT_FAILURE, EXIT_USAGE, EffectiveWindowSchema, EntryValueSchema, FARM_MANIFEST_FILENAME, FrontDoorSessionStatusSchema, FrontDoorSessionsOutputSchema, FrontDoorStartError, FrontDoorStateSchema, FrontDoorStatusOutputSchema, GlobalConfigSchema, HeadroomSocketTargetSchema, HeadroomStartError, IdentityAlreadyExistsError, IdentityNotFoundError, IdentitySchema, InvalidCategoryNameError, InvalidIdentityNameError, InvalidProviderNameError, LAUNCH_EVENT_SOURCE, LaunchLifecycleEventSchema, LaunchRefusedError, LegacyProviderFileError, OWN_CLI_FILE_NAME, PROMPT_CACHE_TTL_MS, PlanClassSchema, PoolNameSchema, PoolNotFoundError, PoolPickReportSchema, PoolSchema, PortableConfigSchema, ProfileAlreadyExistsError, ProfileNotFoundError, ProviderAlreadyExistsError, ProviderKindMismatchError, ProviderNotFoundError, ProviderSchema, QUOTA_EXPIRING_EVENT_SOURCE, QuotaExpiringEventSchema, RC_CONTEXT_USAGE_DETAILS, RC_IDLE_EXPIRY_MS, RC_ORPC_PATH_PREFIX, RC_PENDING_DEADLINE_MS, RC_PERMISSION_MODES, RC_READ_FILE_ENCODINGS, RC_REQUEST_PARSE_CAP_BYTES, RC_SELF_HOST_ENV, RC_SELF_HOST_KEEPALIVE_MS, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE, RC_SELF_HOST_RETENTION_MS, RC_SELF_HOST_SCOPE_LIST, RC_SELF_HOST_WORKER_JWT_TTL_SECONDS, RC_SESSIONS_PATH_PREFIX, RC_STREAM_BACKOFF_MS, RC_WEB_FETCH_ALLOW_PRIVATE_ENV, RC_WEB_FETCH_DEADLINE_MS, RC_WEB_FETCH_MAX_BYTES, RC_WEB_FETCH_MAX_REDIRECTS, ROUTED_PATH_PREFIX, RcLiveRateLimitSchema, RcPermissionModeSchema, RcRateLimitInfoSchema, RcRateLimitWindowSchema, RcStreamEnvelopeSchema, RcStreamEventSchema, USAGE_EVENT_SOURCE, UsageError, UsageListOutputSchema, UsageLiveOutputSchema, UsageSnapshotError, UsageSnapshotSchema, UsageWindowsInputSchema, UsageWindowsOutputSchema, WhenSchema, addDirectoryRule, addIdentity, addPool, addProvider, agentShimCliPath, answerRcControlRequest, authenticateRcSessionMcpServer, buildEntryFacts, buildLayoutPaths, buildRcControlRequestPayload, buildRcControlResponsePayload, buildRcEndSessionPayload, buildRcEventWriteBody, buildRcFileSuggestionsPayload, buildRcGetContextUsagePayload, buildRcGetUsagePayload, buildRcInterruptPayload, buildRcKeepAlivePayload, buildRcMarkReadBody, buildRcMcpAuthenticatePayload, buildRcMcpOAuthCallbackUrlPayload, buildRcMcpReconnectPayload, buildRcMcpStatusPayload, buildRcReadFilePayload, buildRcSetModelPayload, buildRcSetPermissionModePayload, buildRcUserMessagePayload, carryOver, checkReportHasWarnings, checkReportToJson, collectCheckReport, collectDoctorReport, collectFrontDoorStatus, collectPoolPick, createControlApiRouter, createDoorApiNodeHandler, createDoorApiRouter, createDoorEventHub, createDoorHealthPublisher, createEventsApiRouter, createLaunchEventPublisher, createLeafCache, createProfile, createQuotaExpiringPublisher, createRcApiNodeHandler, createRcApiRouter, createRcControlHandler, createRcCredentialStore, createRcEventFanout, createRcLiveUsage, createRcSelfHostSurface, createRcSessionTracker, createRcStreamHub, createSseParser, describeProviderEndpoint, detectAmbientCredential, doorApiAuth, doorApiNodeHandlerOf, effectiveWindow, endRcSession, ensureCa, ensureFrontDoor, ensureHeadroom, evaluateAmbientCredentialGuard, evaluateWhen, fetchThroughWebProxy, formatAmbientCredentialGuardMessage, formatCheckReport, formatDoctorReport, formatFrontDoorStatus, forwardableHeaders, frontDoorApiClient, frontDoorApiLink, frontDoorRcApiClient, frontDoorRcControl, generateCa, getRcSessionContextUsage, getRcSessionMcpStatus, getRcSessionUsage, headroomSocketTarget, identityExists, injectRcUserMessage, interruptRcSession, isIdentityDirectoryName, isInterceptedHost, isPrivateAddress, isRcContextUsageDetail, isRcPermissionMode, isRcReadFileEncoding, lateRcEventDial, lateRcStreamDial, listDirectoryRules, listIdentities, listProfiles, listProviders, listUsageSnapshots, matchBranch, mintLeaf, mintRcSelfHostCredential, observingRoutedRoute, parseConnectTarget, parseRcStreamEnvelope, planOf, poolIdentities, prepareClaudeLaunch, prepareLaunch, profileExists, providerExists, rankPool, rcEventWriteResultFromAnswer, rcFanoutOnDoorHub, rcObserverAsPassthrough, rcRateLimitInfoOf, rcSelfHostFromEnv, rcWebFetchAllowsPrivateFromEnv, readActiveIdentity, readDirectoryRules, readFarmManifest, readGlobalConfig, readIdentity, readPools, readProfile, readProvider, readRcSelfHostRecord, readRcSessionFile, readUsageSnapshot, realConnectCertStore, realConnectEffects, realRcControlTransport, realRcEventDial, realRcStreamDial, realRcWebFetch, reconnectRcSessionMcpServer, recoverFarm, recoveryDiagnostics, removeDirectoryRule, removeIdentity, removePool, removeProfile, removeProvider, requirePool, resolveAgentShimHome, resolveClaudeHome, resolveDecisions, resolveLayoutPaths, resolveSupervisorConfig, resyncFarm, runCheck, runDoctor, runFrontDoorSupervisor, runLauncher, runSupervisor, sendRcKeepAlive, servedByPipeline, setAllowAmbientCredential, setDefaultConfigProfile, setGlobalDefaultProfile, setIdentityCredential, setPool, setProfileCategories, setProfileEntries, setProfileLaunchFlags, setProfileMetadata, setRcSessionModel, setRcSessionPermissionMode, snapshotPath, spawnClaude, startConnectServer, submitRcSessionMcpOAuthCallbackUrl, suggestRcSessionFiles, teleportRcSession, topLevelNames, updateDirectoryRule, updateProvider, useIdentity, writeDirectoryRules };
7763
+ export type { AddDirectoryRuleOptions, AddProviderInput, AmbientCredentialDetection, AmbientCredentialGuardResult, AmbientCredentialVar, BuildEntryFactsParams, CaMaterial, Candidate, CarryOverParams, CarryOverResult, CategoryMap, CheckReport, CheckReportJson, CollectCheckReportParams, CollectDoctorReportParams, CompiledRule, ConditionContext, ConfigProfile, ConnectCertStore, ConnectEffects, ConnectLimits, ConnectLocalSurface, ConnectServerConfig, ConnectServerHandle, ConnectTarget, ControlApiClient, ControlApiDeps, ControlApiRouter, Credential, CredentialSource, Decision, Diagnostic, DirectoryRule, DirectoryRules, DoctorReport, DoorApiClient, DoorApiContext, DoorApiDeps, DoorApiRouter, DoorEvent, DoorEventHub, DoorEventPublisher, DoorEventStream, DoorEventsApiDeps, DoorHealthEvent, DoorHealthPublisher, EffectiveWindow, EliminatedRule, EnsureFrontDoorPorts, EnsureHeadroomPorts, EntryFact, EntryFacts, EntryValue, EvaluateAmbientCredentialGuardParams, FlattenedCascade, FrontDoorRcControl, FrontDoorSessionStatus, FrontDoorStatus, FrontDoorSupervisorPorts, GlobalConfig, HeadroomSupervisorConfig, Identity, IdentityCredentialChange, IdentityListEntry, IdentityListing, InjectedCredential, LaunchDecision, LaunchEventPublisher, LaunchLifecycleEvent, LaunchPlan, LaunchPoolDecision, Layer, LayerId, LayoutPaths, LeafCert, NestedContribution, PlanClass, Pool, PoolMember, PoolPickReport, PoolRanking, PortableConfig, PrepareClaudeLaunchOptions, PrepareLaunchParams, ProfileListEntry, Provider, ProviderListEntry, QuotaExpiringEvent, QuotaExpiringPublisher, RankPoolInput, RcAnswerDecision, RcAnswerDeps, RcApiClient, RcApiDeps, RcApiRouter, RcContextUsageDetail, RcControlAnswer, RcControlHandlerDeps, RcControlRequestDeps, RcControlTransport, RcCredentialStore, RcDialAnswer, RcDialTarget, RcEventDial, RcEventFanout, RcEventWriteResult, RcExchangeObserver, RcInjectDeps, RcLiveRateLimit, RcLiveUsage, RcLiveUsageDeps, RcObservedCredential, RcObservedRequest, RcPendingRequestSummary, RcPermissionMode, RcPresenceAnswer, RcRateLimitInfo, RcRateLimitWindow, RcReadFileEncoding, RcReadFileOptions, RcSelfHostCredentialRecord, RcSelfHostDeps, RcSelfHostMintResult, RcSelfHostSurface, RcSessionStatus, RcSessionSummary, RcSessionTracker, RcSessionTrackerDeps, RcStreamAnswer, RcStreamDial, RcStreamEnvelope, RcStreamEvent, RcStreamHub, RcStreamHubDeps, RcWebFetchDeps, RcWebFetchHop, RcWebFetchOutcome, RcWebFetcher, RcWorkerFact, RcWriteHeaders, RecoverFarmParams, RecoveryResult, ResolveDecisionsInput, ResolvedState, ResyncFarmParams, ResyncFarmResult, RunCheckParams, RunDoctorParams, RunFrontDoorSupervisorOptions, RunLauncherParams, RunSupervisorOptions, SpawnClaudeParams, SseParsedEvent, StickyPick, SupervisorPorts, UnreadableIdentityListEntry, UpdateDirectoryRuleOptions, UpdateProviderInput, UsageChangeEvent, UsageReadFs, UsageSnapshot, WhenCondition, WhenEvaluation };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-shim",
3
- "version": "8.38.1",
3
+ "version": "8.40.0",
4
4
  "description": "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
5
5
  "license": "MIT",
6
6
  "author": "Joseph Mearman <joseph@mearman.co.uk>",