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 +35 -11
- package/dist/index.cjs +116 -47
- package/dist/index.mjs +114 -47
- package/dist/types/index.d.ts +54 -3
- package/package.json +1 -1
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.
|
|
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
|
-
|
|
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 {
|
|
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 {
|
|
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
|
-
|
|
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(
|
|
3227
|
-
return
|
|
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
|
|
3762
|
-
if (!
|
|
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 =
|
|
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,
|
|
4148
|
-
return buildRcControlRequestPayload(requestId, { subtype: "read_file", path:
|
|
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,
|
|
4251
|
-
if (
|
|
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,
|
|
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
|
|
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 ||
|
|
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,
|
|
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 (
|
|
4741
|
+
const listAnswerOf = async (path33, what) => {
|
|
4738
4742
|
try {
|
|
4739
|
-
return await transport.request({ method: "GET", path:
|
|
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 (
|
|
4815
|
+
const writeOf = async (path33, body, describeFailure) => {
|
|
4812
4816
|
let answer;
|
|
4813
4817
|
try {
|
|
4814
|
-
answer = await transport.request({ method: "POST", path:
|
|
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,
|
|
4849
|
+
readFile: async (sessionId, path33, options) => await writeOf(
|
|
4846
4850
|
`${CONTROL_PATH_PREFIX}/read-file`,
|
|
4847
|
-
JSON.stringify({ session: sessionId, path:
|
|
4848
|
-
(status, message) => `reading ${
|
|
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 (
|
|
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:
|
|
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,
|
|
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:
|
|
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
|
|
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",
|
|
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.
|
|
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
|
-
|
|
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,
|
|
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 [...
|
|
7272
|
+
return [...path33, nested];
|
|
7245
7273
|
}
|
|
7246
|
-
if (
|
|
7274
|
+
if (path33.includes(nested)) {
|
|
7247
7275
|
continue;
|
|
7248
7276
|
}
|
|
7249
|
-
const found = walk(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 {
|
|
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 {
|
|
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
|
-
|
|
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
|
|
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 === "" ||
|
|
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 =
|
|
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(
|
|
2915
|
-
return
|
|
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
|
|
3450
|
-
if (!
|
|
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 =
|
|
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,
|
|
3836
|
-
return buildRcControlRequestPayload(requestId, { subtype: "read_file", path:
|
|
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,
|
|
3939
|
-
if (
|
|
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,
|
|
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
|
|
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 ||
|
|
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,
|
|
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 (
|
|
4427
|
+
const listAnswerOf = async (path33, what) => {
|
|
4426
4428
|
try {
|
|
4427
|
-
return await transport.request({ method: "GET", path:
|
|
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 (
|
|
4501
|
+
const writeOf = async (path33, body, describeFailure) => {
|
|
4500
4502
|
let answer;
|
|
4501
4503
|
try {
|
|
4502
|
-
answer = await transport.request({ method: "POST", path:
|
|
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,
|
|
4535
|
+
readFile: async (sessionId, path33, options) => await writeOf(
|
|
4534
4536
|
`${CONTROL_PATH_PREFIX}/read-file`,
|
|
4535
|
-
JSON.stringify({ session: sessionId, path:
|
|
4536
|
-
(status, message) => `reading ${
|
|
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 (
|
|
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:
|
|
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,
|
|
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:
|
|
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
|
|
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",
|
|
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.
|
|
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
|
-
|
|
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,
|
|
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 [...
|
|
6958
|
+
return [...path33, nested];
|
|
6933
6959
|
}
|
|
6934
|
-
if (
|
|
6960
|
+
if (path33.includes(nested)) {
|
|
6935
6961
|
continue;
|
|
6936
6962
|
}
|
|
6937
|
-
const found = walk(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 {
|
|
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 {
|
|
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
|
-
|
|
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
|
|
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 === "" ||
|
|
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 =
|
|
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,
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
7712
|
-
|
|
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.
|
|
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>",
|