agent-shim 8.10.0 → 8.11.1
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 +340 -238
- package/dist/index.cjs +252 -148
- package/dist/index.mjs +251 -148
- package/dist/types/index.d.ts +46 -3
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2815,8 +2815,8 @@ function parseConnectTarget(authority) {
|
|
|
2815
2815
|
function isInterceptedHost(host, interceptHosts) {
|
|
2816
2816
|
return interceptHosts.includes(host);
|
|
2817
2817
|
}
|
|
2818
|
-
function servedByPipeline(
|
|
2819
|
-
return
|
|
2818
|
+
function servedByPipeline(path30) {
|
|
2819
|
+
return path30?.startsWith(ROUTED_PATH_PREFIX) === true;
|
|
2820
2820
|
}
|
|
2821
2821
|
var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
2822
2822
|
"connection",
|
|
@@ -3340,13 +3340,18 @@ function createRcSessionTracker(deps) {
|
|
|
3340
3340
|
entries.set(id, record);
|
|
3341
3341
|
return record;
|
|
3342
3342
|
};
|
|
3343
|
+
const persistCredential = (entry) => {
|
|
3344
|
+
if (entry.oauthAuthorization !== void 0) {
|
|
3345
|
+
deps.credentialStore?.write(entry.id, { authorization: entry.oauthAuthorization, anthropicVersion: entry.anthropicVersion, anthropicClientPlatform: entry.anthropicClientPlatform });
|
|
3346
|
+
}
|
|
3347
|
+
};
|
|
3343
3348
|
const observeExchange = (request4) => {
|
|
3344
3349
|
const method = (request4.method ?? "").toUpperCase();
|
|
3345
|
-
const
|
|
3346
|
-
if (!
|
|
3350
|
+
const path30 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
|
|
3351
|
+
if (!path30.startsWith(RC_SESSIONS_PATH_PREFIX)) {
|
|
3347
3352
|
return void 0;
|
|
3348
3353
|
}
|
|
3349
|
-
const tail =
|
|
3354
|
+
const tail = path30.slice(RC_SESSIONS_PATH_PREFIX.length);
|
|
3350
3355
|
const facts = {
|
|
3351
3356
|
oauthAuthorization: oauthAuthorizationOf(request4.headers),
|
|
3352
3357
|
anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
|
|
@@ -3379,7 +3384,7 @@ function createRcSessionTracker(deps) {
|
|
|
3379
3384
|
if (id2 === void 0) {
|
|
3380
3385
|
return;
|
|
3381
3386
|
}
|
|
3382
|
-
birth(id2, facts);
|
|
3387
|
+
persistCredential(birth(id2, facts));
|
|
3383
3388
|
}
|
|
3384
3389
|
};
|
|
3385
3390
|
}
|
|
@@ -3393,6 +3398,7 @@ function createRcSessionTracker(deps) {
|
|
|
3393
3398
|
entry.oauthAuthorization = facts.oauthAuthorization ?? entry.oauthAuthorization;
|
|
3394
3399
|
entry.anthropicVersion = facts.anthropicVersion ?? entry.anthropicVersion;
|
|
3395
3400
|
entry.anthropicClientPlatform = facts.anthropicClientPlatform ?? entry.anthropicClientPlatform;
|
|
3401
|
+
persistCredential(entry);
|
|
3396
3402
|
const bodyKind = method === "POST" && rest === `${id}/worker/events` ? "worker-events" : method === "POST" && rest === `${id}/events` ? "client-events" : method === "POST" && rest === `${id}/worker/heartbeat` ? "heartbeat" : method === "PUT" && rest === `${id}/worker` ? "worker-registration" : void 0;
|
|
3397
3403
|
let chunks = [];
|
|
3398
3404
|
let buffered = 0;
|
|
@@ -3446,6 +3452,7 @@ function createRcSessionTracker(deps) {
|
|
|
3446
3452
|
},
|
|
3447
3453
|
onResponse: (status, headers) => {
|
|
3448
3454
|
if (singleHeader(headers, CONFLICT_REASON_HEADER) !== void 0 || archiving && isSuccessful(status)) {
|
|
3455
|
+
deps.credentialStore?.remove(id);
|
|
3449
3456
|
expire(id);
|
|
3450
3457
|
return;
|
|
3451
3458
|
}
|
|
@@ -3478,7 +3485,18 @@ function createRcSessionTracker(deps) {
|
|
|
3478
3485
|
},
|
|
3479
3486
|
credentialOf: (sessionId) => {
|
|
3480
3487
|
const entry = entries.get(sessionId);
|
|
3481
|
-
|
|
3488
|
+
if (entry === void 0) {
|
|
3489
|
+
return void 0;
|
|
3490
|
+
}
|
|
3491
|
+
if (entry.oauthAuthorization === void 0 && deps.credentialStore !== void 0) {
|
|
3492
|
+
const persisted = deps.credentialStore.read(sessionId);
|
|
3493
|
+
if (persisted?.authorization !== void 0) {
|
|
3494
|
+
entry.oauthAuthorization = persisted.authorization;
|
|
3495
|
+
entry.anthropicVersion = entry.anthropicVersion ?? persisted.anthropicVersion;
|
|
3496
|
+
entry.anthropicClientPlatform = entry.anthropicClientPlatform ?? persisted.anthropicClientPlatform;
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
return { authorization: entry.oauthAuthorization, anthropicVersion: entry.anthropicVersion, anthropicClientPlatform: entry.anthropicClientPlatform };
|
|
3482
3500
|
},
|
|
3483
3501
|
noteSequenceNums: (sessionId, sequenceNums) => {
|
|
3484
3502
|
const entry = entries.get(sessionId);
|
|
@@ -4094,9 +4112,9 @@ function sequenceNumsOfBody(body) {
|
|
|
4094
4112
|
}
|
|
4095
4113
|
function frontDoorRcControl(transport, token) {
|
|
4096
4114
|
const headers = { authorization: `Bearer ${token}` };
|
|
4097
|
-
const listAnswerOf = async (
|
|
4115
|
+
const listAnswerOf = async (path30, what) => {
|
|
4098
4116
|
try {
|
|
4099
|
-
return await transport.request({ method: "GET", path:
|
|
4117
|
+
return await transport.request({ method: "GET", path: path30, headers });
|
|
4100
4118
|
} catch (error) {
|
|
4101
4119
|
throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
4102
4120
|
}
|
|
@@ -4168,10 +4186,10 @@ function frontDoorRcControl(transport, token) {
|
|
|
4168
4186
|
}
|
|
4169
4187
|
return pending;
|
|
4170
4188
|
};
|
|
4171
|
-
const writeOf = async (
|
|
4189
|
+
const writeOf = async (path30, body, describeFailure) => {
|
|
4172
4190
|
let answer;
|
|
4173
4191
|
try {
|
|
4174
|
-
answer = await transport.request({ method: "POST", path:
|
|
4192
|
+
answer = await transport.request({ method: "POST", path: path30, headers: { ...headers, "content-type": "application/json" }, body });
|
|
4175
4193
|
} catch (error) {
|
|
4176
4194
|
return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
|
|
4177
4195
|
}
|
|
@@ -4219,15 +4237,27 @@ var SUCCESS_STATUS_MAX_EXCLUSIVE2 = 300;
|
|
|
4219
4237
|
function isSuccessful2(status) {
|
|
4220
4238
|
return status >= HTTP_STATUS.ok && status < SUCCESS_STATUS_MAX_EXCLUSIVE2;
|
|
4221
4239
|
}
|
|
4222
|
-
var
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4240
|
+
var SourcePortRange = class {
|
|
4241
|
+
constructor(start, end) {
|
|
4242
|
+
this.start = start;
|
|
4243
|
+
this.end = end;
|
|
4244
|
+
this.count = end - start + 1;
|
|
4245
|
+
this.next = start;
|
|
4246
|
+
}
|
|
4247
|
+
start;
|
|
4248
|
+
end;
|
|
4249
|
+
count;
|
|
4250
|
+
next;
|
|
4251
|
+
/** The next port in rotation, wrapping from the end back to the start. */
|
|
4252
|
+
take() {
|
|
4253
|
+
const port = this.next;
|
|
4254
|
+
this.next = this.next === this.end ? this.start : this.next + 1;
|
|
4255
|
+
return port;
|
|
4256
|
+
}
|
|
4257
|
+
};
|
|
4258
|
+
var DOOR_SOURCE_PORT_START = 47900;
|
|
4259
|
+
var DOOR_SOURCE_PORT_END = 47919;
|
|
4260
|
+
var DOOR_SOURCE_PORTS = new SourcePortRange(DOOR_SOURCE_PORT_START, DOOR_SOURCE_PORT_END);
|
|
4231
4261
|
var realAddressLookup = (host, _options, callback) => {
|
|
4232
4262
|
if (net2.isIP(host) !== 0) {
|
|
4233
4263
|
callback(null, [{ address: host, family: net2.isIP(host) }]);
|
|
@@ -4265,14 +4295,14 @@ function dialTarget(options, defaultPort) {
|
|
|
4265
4295
|
function literalDial(target) {
|
|
4266
4296
|
return net2.connect({ host: target.host, port: target.port });
|
|
4267
4297
|
}
|
|
4268
|
-
async function reservedDial(target) {
|
|
4298
|
+
async function reservedDial(target, ports) {
|
|
4269
4299
|
for (let attempt = 0; ; attempt += 1) {
|
|
4270
|
-
const outcome = await dialOnce({ host: target.host, port: target.port, localPort:
|
|
4300
|
+
const outcome = await dialOnce({ host: target.host, port: target.port, localPort: ports.take(), lookup: realAddressLookup });
|
|
4271
4301
|
if (outcome.error === null) {
|
|
4272
4302
|
return outcome;
|
|
4273
4303
|
}
|
|
4274
4304
|
const held = outcome.error.code !== void 0 && HELD_PORT_ERRNOS.has(outcome.error.code);
|
|
4275
|
-
if (!held || attempt ===
|
|
4305
|
+
if (!held || attempt === ports.count - 1) {
|
|
4276
4306
|
return outcome;
|
|
4277
4307
|
}
|
|
4278
4308
|
}
|
|
@@ -4281,26 +4311,36 @@ function requestServername(options, fallback) {
|
|
|
4281
4311
|
return "servername" in options && typeof options.servername === "string" && options.servername !== "" ? options.servername : fallback;
|
|
4282
4312
|
}
|
|
4283
4313
|
var ExemptHttpAgent = class extends http.Agent {
|
|
4314
|
+
constructor(ports = DOOR_SOURCE_PORTS) {
|
|
4315
|
+
super();
|
|
4316
|
+
this.ports = ports;
|
|
4317
|
+
}
|
|
4318
|
+
ports;
|
|
4284
4319
|
// A reserved-port dial that has to retry cannot produce its socket synchronously, so it settles first and arrives through the callback (node's documented asynchronous createConnection form); a literal dial has nothing to retry and keeps node's own synchronous shape.
|
|
4285
4320
|
createConnection(options, oncreate) {
|
|
4286
4321
|
const target = dialTarget(options, HTTP_PORT);
|
|
4287
4322
|
if (net2.isIP(target.host) !== 0) {
|
|
4288
4323
|
return literalDial(target);
|
|
4289
4324
|
}
|
|
4290
|
-
void reservedDial(target).then((outcome) => {
|
|
4325
|
+
void reservedDial(target, this.ports).then((outcome) => {
|
|
4291
4326
|
oncreate?.(outcome.error, outcome.socket);
|
|
4292
4327
|
});
|
|
4293
4328
|
return void 0;
|
|
4294
4329
|
}
|
|
4295
4330
|
};
|
|
4296
4331
|
var ExemptTlsAgent = class extends https2.Agent {
|
|
4332
|
+
constructor(ports = DOOR_SOURCE_PORTS) {
|
|
4333
|
+
super();
|
|
4334
|
+
this.ports = ports;
|
|
4335
|
+
}
|
|
4336
|
+
ports;
|
|
4297
4337
|
// The same split as the plain sibling: a literal dial wraps TLS around the socket node's own agent would have returned, a reserved dial settles (retries included) first and arrives through the callback, which is exactly where node's own agent wraps its own dials.
|
|
4298
4338
|
createConnection(options, oncreate) {
|
|
4299
4339
|
const target = dialTarget(options, HTTPS_PORT);
|
|
4300
4340
|
if (net2.isIP(target.host) !== 0) {
|
|
4301
4341
|
return tls.connect({ socket: literalDial(target), servername: requestServername(options, target.host), ...tlsFacts(options) });
|
|
4302
4342
|
}
|
|
4303
|
-
void reservedDial(target).then((outcome) => {
|
|
4343
|
+
void reservedDial(target, this.ports).then((outcome) => {
|
|
4304
4344
|
if (outcome.error !== null) {
|
|
4305
4345
|
oncreate?.(outcome.error, outcome.socket);
|
|
4306
4346
|
return;
|
|
@@ -4361,12 +4401,12 @@ var NO_CHUNKS = {
|
|
|
4361
4401
|
};
|
|
4362
4402
|
function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
|
|
4363
4403
|
const agent = new ExemptTlsAgent();
|
|
4364
|
-
const request4 = async (method,
|
|
4404
|
+
const request4 = async (method, path30, headers, body, signal) => await new Promise((resolve, reject) => {
|
|
4365
4405
|
const options = {
|
|
4366
4406
|
host: target.host,
|
|
4367
4407
|
port: target.port,
|
|
4368
4408
|
method,
|
|
4369
|
-
path:
|
|
4409
|
+
path: path30,
|
|
4370
4410
|
// 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.
|
|
4371
4411
|
headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
|
|
4372
4412
|
agent,
|
|
@@ -4403,9 +4443,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
|
|
|
4403
4443
|
return { status, body: await readAll(response) };
|
|
4404
4444
|
},
|
|
4405
4445
|
openStream: async (sessionId, headers, resume, signal) => {
|
|
4406
|
-
const
|
|
4446
|
+
const path30 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
|
|
4407
4447
|
const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
|
|
4408
|
-
const { status, response } = await request4("GET",
|
|
4448
|
+
const { status, response } = await request4("GET", path30, streamHeaders, void 0, signal);
|
|
4409
4449
|
if (!isSuccessful2(status)) {
|
|
4410
4450
|
await readAll(response);
|
|
4411
4451
|
return { status, chunks: NO_CHUNKS };
|
|
@@ -4414,9 +4454,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
|
|
|
4414
4454
|
}
|
|
4415
4455
|
};
|
|
4416
4456
|
}
|
|
4417
|
-
function realConnectEffects() {
|
|
4418
|
-
const plainAgent = new ExemptHttpAgent();
|
|
4419
|
-
const tlsAgent = new ExemptTlsAgent();
|
|
4457
|
+
function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
|
|
4458
|
+
const plainAgent = new ExemptHttpAgent(ports);
|
|
4459
|
+
const tlsAgent = new ExemptTlsAgent(ports);
|
|
4420
4460
|
const listenOnce = async (port, onSocket) => await new Promise((resolve, reject) => {
|
|
4421
4461
|
const accepted = /* @__PURE__ */ new Set();
|
|
4422
4462
|
const server = net2.createServer((socket) => {
|
|
@@ -4534,7 +4574,7 @@ function realConnectEffects() {
|
|
|
4534
4574
|
};
|
|
4535
4575
|
},
|
|
4536
4576
|
connectTlsUpstream: async (host, port, clientAlpn) => {
|
|
4537
|
-
const dialled = await reservedDial({ host, port });
|
|
4577
|
+
const dialled = await reservedDial({ host, port }, ports);
|
|
4538
4578
|
if (dialled.error !== null) {
|
|
4539
4579
|
throw dialled.error;
|
|
4540
4580
|
}
|
|
@@ -4616,6 +4656,64 @@ function realConnectEffects() {
|
|
|
4616
4656
|
};
|
|
4617
4657
|
}
|
|
4618
4658
|
|
|
4659
|
+
// src/frontdoor/rcCredentialStore.ts
|
|
4660
|
+
import path9 from "node:path";
|
|
4661
|
+
function isSafeSessionId(sessionId) {
|
|
4662
|
+
return /^[A-Za-z0-9_-]+$/.test(sessionId);
|
|
4663
|
+
}
|
|
4664
|
+
function isRecord3(value) {
|
|
4665
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4666
|
+
}
|
|
4667
|
+
function credentialOfJson(parsed) {
|
|
4668
|
+
if (!isRecord3(parsed)) {
|
|
4669
|
+
return void 0;
|
|
4670
|
+
}
|
|
4671
|
+
const { authorization, anthropicVersion, anthropicClientPlatform } = parsed;
|
|
4672
|
+
if (typeof authorization !== "string" || authorization === "") {
|
|
4673
|
+
return void 0;
|
|
4674
|
+
}
|
|
4675
|
+
return {
|
|
4676
|
+
authorization,
|
|
4677
|
+
anthropicVersion: typeof anthropicVersion === "string" ? anthropicVersion : void 0,
|
|
4678
|
+
anthropicClientPlatform: typeof anthropicClientPlatform === "string" ? anthropicClientPlatform : void 0
|
|
4679
|
+
};
|
|
4680
|
+
}
|
|
4681
|
+
function createRcCredentialStore(fs12, dir) {
|
|
4682
|
+
fs12.mkdirPrivate(dir);
|
|
4683
|
+
const fileFor = (sessionId) => path9.join(dir, `${sessionId}.json`);
|
|
4684
|
+
return {
|
|
4685
|
+
read: (sessionId) => {
|
|
4686
|
+
if (!isSafeSessionId(sessionId)) {
|
|
4687
|
+
return void 0;
|
|
4688
|
+
}
|
|
4689
|
+
const raw = fs12.readFileUtf8(fileFor(sessionId));
|
|
4690
|
+
if (raw === void 0) {
|
|
4691
|
+
return void 0;
|
|
4692
|
+
}
|
|
4693
|
+
let parsed;
|
|
4694
|
+
try {
|
|
4695
|
+
parsed = JSON.parse(raw);
|
|
4696
|
+
} catch {
|
|
4697
|
+
return void 0;
|
|
4698
|
+
}
|
|
4699
|
+
return credentialOfJson(parsed);
|
|
4700
|
+
},
|
|
4701
|
+
write: (sessionId, credential) => {
|
|
4702
|
+
if (!isSafeSessionId(sessionId)) {
|
|
4703
|
+
return;
|
|
4704
|
+
}
|
|
4705
|
+
fs12.writeFilePrivate(fileFor(sessionId), `${JSON.stringify(credential, null, 2)}
|
|
4706
|
+
`);
|
|
4707
|
+
},
|
|
4708
|
+
remove: (sessionId) => {
|
|
4709
|
+
if (!isSafeSessionId(sessionId)) {
|
|
4710
|
+
return;
|
|
4711
|
+
}
|
|
4712
|
+
fs12.removeRecursive(fileFor(sessionId));
|
|
4713
|
+
}
|
|
4714
|
+
};
|
|
4715
|
+
}
|
|
4716
|
+
|
|
4619
4717
|
// src/frontdoor/rcApi.ts
|
|
4620
4718
|
import { createORPCClient, ORPCError } from "@orpc/client";
|
|
4621
4719
|
import { RPCLink } from "@orpc/client/fetch";
|
|
@@ -4873,7 +4971,7 @@ function createSseParser() {
|
|
|
4873
4971
|
}
|
|
4874
4972
|
};
|
|
4875
4973
|
}
|
|
4876
|
-
function
|
|
4974
|
+
function isRecord4(value) {
|
|
4877
4975
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4878
4976
|
}
|
|
4879
4977
|
function sequenceNumOf(value) {
|
|
@@ -4895,7 +4993,7 @@ function parseRcStreamEnvelope(parsed) {
|
|
|
4895
4993
|
} catch {
|
|
4896
4994
|
return void 0;
|
|
4897
4995
|
}
|
|
4898
|
-
if (!
|
|
4996
|
+
if (!isRecord4(data)) {
|
|
4899
4997
|
return void 0;
|
|
4900
4998
|
}
|
|
4901
4999
|
const eventType = data.event_type;
|
|
@@ -4984,6 +5082,7 @@ function createRcStreamHub(deps) {
|
|
|
4984
5082
|
if (!isSuccessful3(answer.status)) {
|
|
4985
5083
|
throw new Error(`the client read stream answered HTTP ${String(answer.status)}`);
|
|
4986
5084
|
}
|
|
5085
|
+
deps.log?.(`rc stream ${attachment.sessionId}: attached as client ${attachment.clientId}${resume === void 0 ? ", reading from the stream's own head" : `, resuming after sequence number ${String(resume.fromSequenceNum)}`}`);
|
|
4987
5086
|
const parser = createSseParser();
|
|
4988
5087
|
for await (const chunk of answer.chunks) {
|
|
4989
5088
|
attachment.controller.signal.throwIfAborted();
|
|
@@ -5007,6 +5106,7 @@ function createRcStreamHub(deps) {
|
|
|
5007
5106
|
const live = deps.trackedSessions().includes(attachment.sessionId);
|
|
5008
5107
|
const credential = deps.credentialOf(attachment.sessionId);
|
|
5009
5108
|
if (!live || credential?.authorization === void 0) {
|
|
5109
|
+
deps.log?.(`rc stream ${attachment.sessionId}: the attachment ended (${live ? "the session's client credential is no longer known" : "the tracker gave up on the session"})`);
|
|
5010
5110
|
if (attachments.get(attachment.sessionId) === attachment) {
|
|
5011
5111
|
attachments.delete(attachment.sessionId);
|
|
5012
5112
|
}
|
|
@@ -5028,6 +5128,7 @@ function createRcStreamHub(deps) {
|
|
|
5028
5128
|
return;
|
|
5029
5129
|
}
|
|
5030
5130
|
if (outcome === "dropped") {
|
|
5131
|
+
deps.log?.(`rc stream ${attachment.sessionId}: the stream ended of its own accord, reconnecting`);
|
|
5031
5132
|
retriedUnauthorized = false;
|
|
5032
5133
|
continue;
|
|
5033
5134
|
}
|
|
@@ -5077,7 +5178,7 @@ import { randomUUID as randomUUID3 } from "node:crypto";
|
|
|
5077
5178
|
|
|
5078
5179
|
// src/headroom/state.ts
|
|
5079
5180
|
import { createHash as createHash3 } from "node:crypto";
|
|
5080
|
-
import
|
|
5181
|
+
import path10 from "node:path";
|
|
5081
5182
|
import { z as z5 } from "zod";
|
|
5082
5183
|
var HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
|
|
5083
5184
|
var HEADROOM_STATE_SCHEMA_VERSION = 2;
|
|
@@ -5118,7 +5219,7 @@ function readHeadroomState(fs12, stateFile) {
|
|
|
5118
5219
|
}
|
|
5119
5220
|
}
|
|
5120
5221
|
function writeHeadroomState(fs12, stateFile, state) {
|
|
5121
|
-
fs12.mkdirp(
|
|
5222
|
+
fs12.mkdirp(path10.dirname(stateFile));
|
|
5122
5223
|
fs12.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
|
|
5123
5224
|
`);
|
|
5124
5225
|
}
|
|
@@ -5146,7 +5247,7 @@ function readAllProviders(fs12, providersDir) {
|
|
|
5146
5247
|
continue;
|
|
5147
5248
|
}
|
|
5148
5249
|
try {
|
|
5149
|
-
const parsed = parseJson(fs12.readFileUtf8(
|
|
5250
|
+
const parsed = parseJson(fs12.readFileUtf8(path10.join(providersDir, name)), ProviderSchema);
|
|
5150
5251
|
if (parsed !== void 0) {
|
|
5151
5252
|
result.push({ name: name.slice(0, -".json".length), provider: parsed });
|
|
5152
5253
|
}
|
|
@@ -5158,11 +5259,11 @@ function readAllProviders(fs12, providersDir) {
|
|
|
5158
5259
|
}
|
|
5159
5260
|
function writeSession(fs12, sessionsDir, session) {
|
|
5160
5261
|
fs12.mkdirp(sessionsDir);
|
|
5161
|
-
fs12.writeFileUtf8(
|
|
5262
|
+
fs12.writeFileUtf8(path10.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
|
|
5162
5263
|
`);
|
|
5163
5264
|
}
|
|
5164
5265
|
function removeSession(fs12, sessionsDir, pid) {
|
|
5165
|
-
fs12.removeRecursive(
|
|
5266
|
+
fs12.removeRecursive(path10.join(sessionsDir, `${String(pid)}.json`));
|
|
5166
5267
|
}
|
|
5167
5268
|
function listSessions(fs12, sessionsDir) {
|
|
5168
5269
|
const sessions = [];
|
|
@@ -5171,7 +5272,7 @@ function listSessions(fs12, sessionsDir) {
|
|
|
5171
5272
|
continue;
|
|
5172
5273
|
}
|
|
5173
5274
|
try {
|
|
5174
|
-
const parsed = parseJson(fs12.readFileUtf8(
|
|
5275
|
+
const parsed = parseJson(fs12.readFileUtf8(path10.join(sessionsDir, name)), HeadroomSessionSchema);
|
|
5175
5276
|
if (parsed !== void 0) {
|
|
5176
5277
|
sessions.push(parsed);
|
|
5177
5278
|
}
|
|
@@ -5276,10 +5377,10 @@ function ensureFrontDoor(params) {
|
|
|
5276
5377
|
}
|
|
5277
5378
|
|
|
5278
5379
|
// src/usage/read.ts
|
|
5279
|
-
import
|
|
5380
|
+
import path12 from "node:path";
|
|
5280
5381
|
|
|
5281
5382
|
// src/usage/account.ts
|
|
5282
|
-
import
|
|
5383
|
+
import path11 from "node:path";
|
|
5283
5384
|
|
|
5284
5385
|
// src/usage/schema.ts
|
|
5285
5386
|
import { z as z6 } from "zod";
|
|
@@ -5445,7 +5546,7 @@ function isIdentityName(name) {
|
|
|
5445
5546
|
return IdentitySchema.shape.name.safeParse(name).success;
|
|
5446
5547
|
}
|
|
5447
5548
|
function claudeJsonPath(identitiesDir, identity) {
|
|
5448
|
-
return
|
|
5549
|
+
return path11.join(identitiesDir, identity, CLAUDE_JSON);
|
|
5449
5550
|
}
|
|
5450
5551
|
function readAccountMetadata(fs12, identitiesDir, identity) {
|
|
5451
5552
|
if (!isIdentityName(identity)) {
|
|
@@ -5504,7 +5605,7 @@ function readUsageLog(fs12, logDir, options = {}) {
|
|
|
5504
5605
|
if (sinceMs !== void 0 && segment.endsAt <= sinceMs) {
|
|
5505
5606
|
continue;
|
|
5506
5607
|
}
|
|
5507
|
-
const contents = fs12.readFileUtf8(
|
|
5608
|
+
const contents = fs12.readFileUtf8(path12.join(logDir, segment.name));
|
|
5508
5609
|
if (contents === void 0) {
|
|
5509
5610
|
continue;
|
|
5510
5611
|
}
|
|
@@ -5546,7 +5647,7 @@ function snapshotPath(snapshotsDir, identity) {
|
|
|
5546
5647
|
if (!isIdentityName(identity)) {
|
|
5547
5648
|
throw new Error(`"${identity}" is not a valid identity name.`);
|
|
5548
5649
|
}
|
|
5549
|
-
return
|
|
5650
|
+
return path12.join(snapshotsDir, `${identity}.json`);
|
|
5550
5651
|
}
|
|
5551
5652
|
function readUsageSnapshot(fs12, snapshotsDir, identity) {
|
|
5552
5653
|
const file = snapshotPath(snapshotsDir, identity);
|
|
@@ -5880,7 +5981,7 @@ function rankPool(input) {
|
|
|
5880
5981
|
}
|
|
5881
5982
|
|
|
5882
5983
|
// src/usage/poolPick.ts
|
|
5883
|
-
import
|
|
5984
|
+
import path13 from "node:path";
|
|
5884
5985
|
import { z as z9 } from "zod";
|
|
5885
5986
|
|
|
5886
5987
|
// src/usage/store.ts
|
|
@@ -5947,13 +6048,13 @@ function recordStickyPick(fs12, picksFile, directory, identity, nowMs) {
|
|
|
5947
6048
|
const current = readPicksFile(fs12, picksFile).file.picks;
|
|
5948
6049
|
const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
|
|
5949
6050
|
const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
|
|
5950
|
-
fs12.mkdirPrivate(
|
|
6051
|
+
fs12.mkdirPrivate(path13.dirname(picksFile));
|
|
5951
6052
|
fs12.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
|
|
5952
6053
|
`);
|
|
5953
6054
|
}
|
|
5954
6055
|
|
|
5955
6056
|
// src/launcher/identity.ts
|
|
5956
|
-
import
|
|
6057
|
+
import path14 from "node:path";
|
|
5957
6058
|
function poolNameOf(selector) {
|
|
5958
6059
|
return selector.startsWith(POOL_SELECTOR_PREFIX) ? selector.slice(POOL_SELECTOR_PREFIX.length) : void 0;
|
|
5959
6060
|
}
|
|
@@ -6002,7 +6103,7 @@ function decideConfigProfile(params) {
|
|
|
6002
6103
|
return { source: "none" };
|
|
6003
6104
|
}
|
|
6004
6105
|
function loadIdentity(identitiesDir, name, fs12) {
|
|
6005
|
-
return loadConfigFile(
|
|
6106
|
+
return loadConfigFile(path14.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
|
|
6006
6107
|
}
|
|
6007
6108
|
|
|
6008
6109
|
// src/launcher/pool.ts
|
|
@@ -6217,7 +6318,7 @@ function hashSettings(settings) {
|
|
|
6217
6318
|
}
|
|
6218
6319
|
|
|
6219
6320
|
// src/headroom/socket.ts
|
|
6220
|
-
import
|
|
6321
|
+
import path15 from "node:path";
|
|
6221
6322
|
var GROUP_OR_OTHER_BITS = 63;
|
|
6222
6323
|
var OCTAL_RADIX = 8;
|
|
6223
6324
|
var MODE_DIGITS = 4;
|
|
@@ -6226,7 +6327,7 @@ var HEADROOM_SOCKET_NAME = /^(\d+)\.sock$/;
|
|
|
6226
6327
|
var UNIX_SOCKET_PATH_MAX_BYTES = 103;
|
|
6227
6328
|
var PLATFORMS_WITHOUT_UNIX_SOCKETS = ["win32"];
|
|
6228
6329
|
function headroomSocketPath(paths, supervisorPid) {
|
|
6229
|
-
return
|
|
6330
|
+
return path15.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
|
|
6230
6331
|
}
|
|
6231
6332
|
function platformRefusal(platform) {
|
|
6232
6333
|
return PLATFORMS_WITHOUT_UNIX_SOCKETS.includes(platform) ? `headroom routing needs a unix domain socket, which headroom cannot serve on ${platform}; agent-shim never falls back to a TCP port for this hop` : void 0;
|
|
@@ -6275,7 +6376,7 @@ function pruneStaleHeadroomSockets(fs12, paths, isRunning) {
|
|
|
6275
6376
|
if (pid === void 0 || isRunning(Number.parseInt(pid, 10))) {
|
|
6276
6377
|
continue;
|
|
6277
6378
|
}
|
|
6278
|
-
fs12.removeRecursive(
|
|
6379
|
+
fs12.removeRecursive(path15.join(paths.headroomSocketDir, name));
|
|
6279
6380
|
removed.push(name);
|
|
6280
6381
|
}
|
|
6281
6382
|
return removed;
|
|
@@ -6599,14 +6700,14 @@ function evaluateAmbientCredentialGuard(params) {
|
|
|
6599
6700
|
// src/paths.ts
|
|
6600
6701
|
import fs3 from "node:fs";
|
|
6601
6702
|
import os3 from "node:os";
|
|
6602
|
-
import
|
|
6703
|
+
import path16 from "node:path";
|
|
6603
6704
|
function resolveAgentShimHome(env = process.env, home = os3.homedir(), isDirectory = isExistingDirectory) {
|
|
6604
6705
|
const fromEnv = env.AGENT_SHIM_HOME;
|
|
6605
6706
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
6606
6707
|
return fromEnv;
|
|
6607
6708
|
}
|
|
6608
|
-
const current =
|
|
6609
|
-
const legacy =
|
|
6709
|
+
const current = path16.join(home, HOME_DIRNAME);
|
|
6710
|
+
const legacy = path16.join(home, LEGACY_HOME_DIRNAME);
|
|
6610
6711
|
return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
|
|
6611
6712
|
}
|
|
6612
6713
|
function isExistingDirectory(candidate) {
|
|
@@ -6617,40 +6718,41 @@ function resolveClaudeHome() {
|
|
|
6617
6718
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
6618
6719
|
return fromEnv;
|
|
6619
6720
|
}
|
|
6620
|
-
return
|
|
6721
|
+
return path16.join(os3.homedir(), ".claude");
|
|
6621
6722
|
}
|
|
6622
6723
|
function buildLayoutPaths(root) {
|
|
6623
6724
|
return {
|
|
6624
6725
|
root,
|
|
6625
|
-
identitiesDir:
|
|
6626
|
-
configProfilesDir:
|
|
6627
|
-
providersDir:
|
|
6628
|
-
directoryRulesFile:
|
|
6629
|
-
activeIdentityFile:
|
|
6630
|
-
globalConfigFile:
|
|
6631
|
-
categoriesLocalFile:
|
|
6632
|
-
claudeShimFile:
|
|
6633
|
-
headroomDir:
|
|
6634
|
-
headroomStateFile:
|
|
6635
|
-
headroomSocketDir:
|
|
6636
|
-
headroomLockFile:
|
|
6637
|
-
headroomSessionsDir:
|
|
6638
|
-
logsDir:
|
|
6639
|
-
headroomLogPath:
|
|
6640
|
-
frontdoorDir:
|
|
6641
|
-
frontdoorCaDir:
|
|
6642
|
-
frontdoorCaCertFile:
|
|
6643
|
-
frontdoorCaKeyFile:
|
|
6644
|
-
frontdoorCaBundlesDir:
|
|
6645
|
-
frontdoorStateFile:
|
|
6646
|
-
frontdoorLockFile:
|
|
6647
|
-
frontdoorControlTokenFile:
|
|
6648
|
-
frontdoorSessionsDir:
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6726
|
+
identitiesDir: path16.join(root, "identities"),
|
|
6727
|
+
configProfilesDir: path16.join(root, "config-profiles"),
|
|
6728
|
+
providersDir: path16.join(root, "providers"),
|
|
6729
|
+
directoryRulesFile: path16.join(root, "directory-rules.json"),
|
|
6730
|
+
activeIdentityFile: path16.join(root, "active-identity"),
|
|
6731
|
+
globalConfigFile: path16.join(root, "config.json"),
|
|
6732
|
+
categoriesLocalFile: path16.join(root, "categories.local.json"),
|
|
6733
|
+
claudeShimFile: path16.join(root, "claude-shim.json"),
|
|
6734
|
+
headroomDir: path16.join(root, "headroom"),
|
|
6735
|
+
headroomStateFile: path16.join(root, "headroom", `state.v${String(HEADROOM_STATE_SCHEMA_VERSION)}.json`),
|
|
6736
|
+
headroomSocketDir: path16.join(root, "headroom", "run"),
|
|
6737
|
+
headroomLockFile: path16.join(root, "headroom", "start.lock"),
|
|
6738
|
+
headroomSessionsDir: path16.join(root, "headroom", "sessions"),
|
|
6739
|
+
logsDir: path16.join(root, "logs"),
|
|
6740
|
+
headroomLogPath: path16.join(root, "logs", "headroom.log"),
|
|
6741
|
+
frontdoorDir: path16.join(root, "frontdoor"),
|
|
6742
|
+
frontdoorCaDir: path16.join(root, "frontdoor", "ca"),
|
|
6743
|
+
frontdoorCaCertFile: path16.join(root, "frontdoor", "ca", "ca.pem"),
|
|
6744
|
+
frontdoorCaKeyFile: path16.join(root, "frontdoor", "ca", "ca.key"),
|
|
6745
|
+
frontdoorCaBundlesDir: path16.join(root, "frontdoor", "ca", "bundles"),
|
|
6746
|
+
frontdoorStateFile: path16.join(root, "frontdoor", "state.json"),
|
|
6747
|
+
frontdoorLockFile: path16.join(root, "frontdoor", "start.lock"),
|
|
6748
|
+
frontdoorControlTokenFile: path16.join(root, "frontdoor", "control-token"),
|
|
6749
|
+
frontdoorSessionsDir: path16.join(root, "frontdoor", "sessions"),
|
|
6750
|
+
frontdoorRcCredentialsDir: path16.join(root, "frontdoor", "rc-credentials"),
|
|
6751
|
+
frontdoorLogPath: path16.join(root, "logs", "frontdoor.log"),
|
|
6752
|
+
usageDir: path16.join(root, "usage"),
|
|
6753
|
+
usageLogDir: path16.join(root, "usage", "log"),
|
|
6754
|
+
usageSnapshotsDir: path16.join(root, "usage", "snapshots"),
|
|
6755
|
+
usagePicksFile: path16.join(root, "usage", "picks.json")
|
|
6654
6756
|
};
|
|
6655
6757
|
}
|
|
6656
6758
|
function resolveLayoutPaths() {
|
|
@@ -6659,11 +6761,11 @@ function resolveLayoutPaths() {
|
|
|
6659
6761
|
|
|
6660
6762
|
// src/identityStore.ts
|
|
6661
6763
|
import fs5 from "node:fs";
|
|
6662
|
-
import
|
|
6764
|
+
import path18 from "node:path";
|
|
6663
6765
|
|
|
6664
6766
|
// src/configProfilesStore.ts
|
|
6665
6767
|
import fs4 from "node:fs";
|
|
6666
|
-
import
|
|
6768
|
+
import path17 from "node:path";
|
|
6667
6769
|
var ProfileNotFoundError = class extends CliError {
|
|
6668
6770
|
constructor(profileName) {
|
|
6669
6771
|
super(`No configuration profile named "${profileName}". Run \`agent-shim profile add ${profileName}\` first.`);
|
|
@@ -6689,7 +6791,7 @@ var InvalidCategoryNameError = class extends CliError {
|
|
|
6689
6791
|
categoryName;
|
|
6690
6792
|
};
|
|
6691
6793
|
function profileJsonPath(paths, name) {
|
|
6692
|
-
return
|
|
6794
|
+
return path17.join(paths.configProfilesDir, `${name}.json`);
|
|
6693
6795
|
}
|
|
6694
6796
|
function profileExists(paths, name) {
|
|
6695
6797
|
return fs4.existsSync(profileJsonPath(paths, name));
|
|
@@ -6877,7 +6979,7 @@ var InvalidIdentityNameError = class extends CliError {
|
|
|
6877
6979
|
attemptedName;
|
|
6878
6980
|
};
|
|
6879
6981
|
function identityJsonPath(paths, name) {
|
|
6880
|
-
return
|
|
6982
|
+
return path18.join(paths.identitiesDir, name, "identity.json");
|
|
6881
6983
|
}
|
|
6882
6984
|
function identityExists(paths, name) {
|
|
6883
6985
|
return fs5.existsSync(identityJsonPath(paths, name));
|
|
@@ -6978,7 +7080,7 @@ function setIdentityCredential(paths, identityName, change) {
|
|
|
6978
7080
|
});
|
|
6979
7081
|
}
|
|
6980
7082
|
function belongsToIdentity(entry, name) {
|
|
6981
|
-
return entry === name || entry ===
|
|
7083
|
+
return entry === name || entry === path18.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
|
|
6982
7084
|
}
|
|
6983
7085
|
function removeIdentity(paths, name) {
|
|
6984
7086
|
if (!identityExists(paths, name)) {
|
|
@@ -6986,7 +7088,7 @@ function removeIdentity(paths, name) {
|
|
|
6986
7088
|
}
|
|
6987
7089
|
for (const entry of fs5.readdirSync(paths.identitiesDir)) {
|
|
6988
7090
|
if (belongsToIdentity(entry, name)) {
|
|
6989
|
-
fs5.rmSync(
|
|
7091
|
+
fs5.rmSync(path18.join(paths.identitiesDir, entry), { recursive: true, force: true });
|
|
6990
7092
|
}
|
|
6991
7093
|
}
|
|
6992
7094
|
if (readActiveIdentity(paths) === name) {
|
|
@@ -6996,7 +7098,7 @@ function removeIdentity(paths, name) {
|
|
|
6996
7098
|
|
|
6997
7099
|
// src/providersStore.ts
|
|
6998
7100
|
import fs6 from "node:fs";
|
|
6999
|
-
import
|
|
7101
|
+
import path19 from "node:path";
|
|
7000
7102
|
|
|
7001
7103
|
// src/credentialCache.ts
|
|
7002
7104
|
import { z as z12 } from "zod";
|
|
@@ -7261,7 +7363,7 @@ var InvalidProviderNameError = class extends CliError {
|
|
|
7261
7363
|
};
|
|
7262
7364
|
var PROVIDER_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._@-]*$/;
|
|
7263
7365
|
function providerJsonPath(paths, name) {
|
|
7264
|
-
return
|
|
7366
|
+
return path19.join(paths.providersDir, `${name}.json`);
|
|
7265
7367
|
}
|
|
7266
7368
|
function providerExists(paths, name) {
|
|
7267
7369
|
return fs6.existsSync(providerJsonPath(paths, name));
|
|
@@ -7269,14 +7371,14 @@ function providerExists(paths, name) {
|
|
|
7269
7371
|
var LEGACY_PROVIDER_FIELDS = ["tokenEnv", "tokenCommand", "authScheme"];
|
|
7270
7372
|
var LEGACY_ENV_CREDENTIAL_KEYS = Object.values(CREDENTIAL_TARGET_VARS);
|
|
7271
7373
|
var LEGACY_LITERAL_PLACEHOLDER = "<the value of env.ANTHROPIC_AUTH_TOKEN>";
|
|
7272
|
-
function
|
|
7374
|
+
function isRecord5(value) {
|
|
7273
7375
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7274
7376
|
}
|
|
7275
7377
|
function legacyProviderConversion(raw) {
|
|
7276
|
-
if (!
|
|
7378
|
+
if (!isRecord5(raw) || "credential" in raw) {
|
|
7277
7379
|
return void 0;
|
|
7278
7380
|
}
|
|
7279
|
-
const env =
|
|
7381
|
+
const env = isRecord5(raw.env) ? raw.env : void 0;
|
|
7280
7382
|
const legacyEnvKeys = env === void 0 ? [] : Object.keys(env).filter((key) => LEGACY_ENV_CREDENTIAL_KEYS.includes(key));
|
|
7281
7383
|
const fields = [...LEGACY_PROVIDER_FIELDS.filter((field) => field in raw), ...legacyEnvKeys.map((key) => `env.${key}`)];
|
|
7282
7384
|
if (fields.length === 0) {
|
|
@@ -7337,7 +7439,7 @@ function readProvider(paths, name) {
|
|
|
7337
7439
|
return parseProviderFile(filePath, raw);
|
|
7338
7440
|
}
|
|
7339
7441
|
function loadProvider(providersDir, name, port) {
|
|
7340
|
-
const filePath =
|
|
7442
|
+
const filePath = path19.join(providersDir, `${name}.json`);
|
|
7341
7443
|
const raw = port.readConfigFile(filePath);
|
|
7342
7444
|
return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
|
|
7343
7445
|
}
|
|
@@ -7592,21 +7694,21 @@ function removeDirectoryRule(paths, rulePath) {
|
|
|
7592
7694
|
import os5 from "node:os";
|
|
7593
7695
|
|
|
7594
7696
|
// src/launcher/cascade.ts
|
|
7595
|
-
import
|
|
7697
|
+
import path21 from "node:path";
|
|
7596
7698
|
|
|
7597
7699
|
// src/pathNorm.ts
|
|
7598
|
-
import
|
|
7700
|
+
import path20 from "node:path";
|
|
7599
7701
|
function expandTilde(value, home) {
|
|
7600
7702
|
if (value === "~") {
|
|
7601
7703
|
return home;
|
|
7602
7704
|
}
|
|
7603
7705
|
if (value.startsWith("~/")) {
|
|
7604
|
-
return
|
|
7706
|
+
return path20.join(home, value.slice(2));
|
|
7605
7707
|
}
|
|
7606
7708
|
return value;
|
|
7607
7709
|
}
|
|
7608
7710
|
function normaliseRulePath(rulePath, home) {
|
|
7609
|
-
return
|
|
7711
|
+
return path20.resolve(expandTilde(rulePath, home));
|
|
7610
7712
|
}
|
|
7611
7713
|
|
|
7612
7714
|
// src/launcher/cascade.ts
|
|
@@ -7616,7 +7718,7 @@ function loadCascadeInput(params) {
|
|
|
7616
7718
|
const globalConfig = loadConfigFile(params.paths.globalConfigFile, GlobalConfigSchema, params.read);
|
|
7617
7719
|
const directoryRules = loadConfigFile(params.paths.directoryRulesFile, DirectoryRulesSchema, params.read);
|
|
7618
7720
|
const loadProfile = (name) => {
|
|
7619
|
-
const filepath =
|
|
7721
|
+
const filepath = path21.join(params.paths.configProfilesDir, `${name}.json`);
|
|
7620
7722
|
const loaded = loadConfigFile(filepath, ConfigProfileSchema, params.read);
|
|
7621
7723
|
if (loaded === void 0) {
|
|
7622
7724
|
return void 0;
|
|
@@ -7631,8 +7733,8 @@ function loadCascadeInput(params) {
|
|
|
7631
7733
|
});
|
|
7632
7734
|
const levels = [];
|
|
7633
7735
|
for (const dir of dirs) {
|
|
7634
|
-
const portable = loadConfigFile(
|
|
7635
|
-
const portableLocal = loadConfigFile(
|
|
7736
|
+
const portable = loadConfigFile(path21.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path21.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
7737
|
+
const portableLocal = loadConfigFile(path21.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path21.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
7636
7738
|
const rules = (directoryRules?.config.rules ?? []).map((rule, index) => ({ rule, index })).filter(({ rule }) => normaliseRulePath(rule.path, params.home) === dir).map(({ rule, index }) => {
|
|
7637
7739
|
const entryOrder = directoryRules?.ruleEntryOrders[index];
|
|
7638
7740
|
return {
|
|
@@ -7683,7 +7785,7 @@ function readDirectorySelections(loaded) {
|
|
|
7683
7785
|
// src/realCredentialCache.ts
|
|
7684
7786
|
import { spawnSync } from "node:child_process";
|
|
7685
7787
|
import fs7 from "node:fs";
|
|
7686
|
-
import
|
|
7788
|
+
import path22 from "node:path";
|
|
7687
7789
|
var KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
|
|
7688
7790
|
var CACHE_DIR_MODE = 448;
|
|
7689
7791
|
var CACHE_FILE_MODE = 384;
|
|
@@ -7710,8 +7812,8 @@ function security(args, stdin) {
|
|
|
7710
7812
|
return { status: result.status, stdout: result.stdout };
|
|
7711
7813
|
}
|
|
7712
7814
|
function createRealCredentialCache(root) {
|
|
7713
|
-
const dir =
|
|
7714
|
-
const filePath = (owner) =>
|
|
7815
|
+
const dir = path22.join(root, "credential-cache");
|
|
7816
|
+
const filePath = (owner) => path22.join(dir, cacheFileNameFor(owner));
|
|
7715
7817
|
return {
|
|
7716
7818
|
read(store, owner) {
|
|
7717
7819
|
if (store === "file") {
|
|
@@ -7763,7 +7865,7 @@ import { spawn, spawnSync as spawnSync2 } from "node:child_process";
|
|
|
7763
7865
|
import { createHash as createHash5 } from "node:crypto";
|
|
7764
7866
|
import fs8 from "node:fs";
|
|
7765
7867
|
import os4 from "node:os";
|
|
7766
|
-
import
|
|
7868
|
+
import path23 from "node:path";
|
|
7767
7869
|
import { isSea } from "node:sea";
|
|
7768
7870
|
function isEnoent3(error) {
|
|
7769
7871
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
@@ -7922,7 +8024,7 @@ var realRunPort = {
|
|
|
7922
8024
|
}
|
|
7923
8025
|
};
|
|
7924
8026
|
function expandHome2(filePath) {
|
|
7925
|
-
return filePath.startsWith("~/") ?
|
|
8027
|
+
return filePath.startsWith("~/") ? path23.join(os4.homedir(), filePath.slice(1)) : filePath;
|
|
7926
8028
|
}
|
|
7927
8029
|
var MACOS_GUI_SESSION_MANAGER = "Aqua";
|
|
7928
8030
|
function hasDesktopSession() {
|
|
@@ -7995,7 +8097,7 @@ function spawnDaemonThrough(executable) {
|
|
|
7995
8097
|
return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: executable, args: [subcommand] }, paths, subcommand, logPath);
|
|
7996
8098
|
}
|
|
7997
8099
|
function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
|
|
7998
|
-
fs8.mkdirSync(
|
|
8100
|
+
fs8.mkdirSync(path23.dirname(logPath), { recursive: true });
|
|
7999
8101
|
const logFd = fs8.openSync(logPath, "a");
|
|
8000
8102
|
try {
|
|
8001
8103
|
const child = spawn(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
|
|
@@ -8077,7 +8179,7 @@ function listVersionsDir(dir) {
|
|
|
8077
8179
|
throw error;
|
|
8078
8180
|
}
|
|
8079
8181
|
return entries.filter((entry) => entry.isFile()).map((entry) => {
|
|
8080
|
-
const fullPath =
|
|
8182
|
+
const fullPath = path23.join(dir, entry.name);
|
|
8081
8183
|
const stat = fs8.statSync(fullPath);
|
|
8082
8184
|
return {
|
|
8083
8185
|
name: entry.name,
|
|
@@ -8092,7 +8194,7 @@ function windowsPathExtensions(pathext) {
|
|
|
8092
8194
|
return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
|
|
8093
8195
|
}
|
|
8094
8196
|
function resolveExecutableCandidate(dir, name, env) {
|
|
8095
|
-
const candidate =
|
|
8197
|
+
const candidate = path23.join(dir, name);
|
|
8096
8198
|
if (env.platform === "win32") {
|
|
8097
8199
|
const extensions = windowsPathExtensions(env.pathext);
|
|
8098
8200
|
const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
|
|
@@ -8141,13 +8243,13 @@ function resolveOwnExecutablePath(env) {
|
|
|
8141
8243
|
if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
|
|
8142
8244
|
return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
|
|
8143
8245
|
}
|
|
8144
|
-
const candidate = env.argv1 === void 0 ? env.execPath :
|
|
8145
|
-
const candidateDir =
|
|
8146
|
-
const candidateDirOnPath = env.pathDirs.some((dir) =>
|
|
8246
|
+
const candidate = env.argv1 === void 0 ? env.execPath : path23.resolve(env.cwd, env.argv1);
|
|
8247
|
+
const candidateDir = path23.dirname(candidate);
|
|
8248
|
+
const candidateDirOnPath = env.pathDirs.some((dir) => path23.resolve(dir) === candidateDir);
|
|
8147
8249
|
if (candidateDirOnPath) {
|
|
8148
8250
|
return candidate;
|
|
8149
8251
|
}
|
|
8150
|
-
const viaPath = searchPathForExecutable(env.pathDirs,
|
|
8252
|
+
const viaPath = searchPathForExecutable(env.pathDirs, path23.basename(candidate), env.findExecutableInDir);
|
|
8151
8253
|
return viaPath ?? candidate;
|
|
8152
8254
|
}
|
|
8153
8255
|
function realOwnExecutablePath() {
|
|
@@ -8155,7 +8257,7 @@ function realOwnExecutablePath() {
|
|
|
8155
8257
|
argv1: process.argv[1],
|
|
8156
8258
|
execPath: process.execPath,
|
|
8157
8259
|
cwd: process.cwd(),
|
|
8158
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
8260
|
+
pathDirs: (process.env.PATH ?? "").split(path23.delimiter).filter((dir) => dir !== ""),
|
|
8159
8261
|
findExecutableInDir
|
|
8160
8262
|
});
|
|
8161
8263
|
}
|
|
@@ -8168,7 +8270,7 @@ function realContentSourcePath() {
|
|
|
8168
8270
|
function realResolveClaudeBinary(isOwnBinary) {
|
|
8169
8271
|
return (request4) => discoverClaudeBinary({
|
|
8170
8272
|
listVersionsDir,
|
|
8171
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
8273
|
+
pathDirs: (process.env.PATH ?? "").split(path23.delimiter).filter((dir) => dir !== ""),
|
|
8172
8274
|
findExecutableInDir,
|
|
8173
8275
|
isOwnBinary,
|
|
8174
8276
|
...request4?.version === void 0 ? {} : { version: request4.version }
|
|
@@ -8179,7 +8281,7 @@ function realInstalledClaudeVersions() {
|
|
|
8179
8281
|
}
|
|
8180
8282
|
|
|
8181
8283
|
// src/checkReport.ts
|
|
8182
|
-
import
|
|
8284
|
+
import path24 from "node:path";
|
|
8183
8285
|
import { z as z13 } from "zod";
|
|
8184
8286
|
|
|
8185
8287
|
// src/cli/bool.ts
|
|
@@ -8611,10 +8713,10 @@ function collectCheckReport(params) {
|
|
|
8611
8713
|
}).input;
|
|
8612
8714
|
const providerName = cascadeProviderName(cascade);
|
|
8613
8715
|
const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
|
|
8614
|
-
const farmRoot = identityDecision.name === void 0 ? void 0 :
|
|
8716
|
+
const farmRoot = identityDecision.name === void 0 ? void 0 : path24.join(paths.identitiesDir, identityDecision.name);
|
|
8615
8717
|
const settingsFiles = {
|
|
8616
|
-
"settings.json": realFsPort.readFileUtf8(
|
|
8617
|
-
"settings.local.json": realFsPort.readFileUtf8(
|
|
8718
|
+
"settings.json": realFsPort.readFileUtf8(path24.join(claudeHome, "settings.json")),
|
|
8719
|
+
"settings.local.json": realFsPort.readFileUtf8(path24.join(claudeHome, "settings.local.json"))
|
|
8618
8720
|
};
|
|
8619
8721
|
const report = runCheck({
|
|
8620
8722
|
cwd,
|
|
@@ -8646,7 +8748,7 @@ function collectCheckReport(params) {
|
|
|
8646
8748
|
|
|
8647
8749
|
// src/claudeShim.ts
|
|
8648
8750
|
import fs9 from "node:fs";
|
|
8649
|
-
import
|
|
8751
|
+
import path25 from "node:path";
|
|
8650
8752
|
import { z as z14 } from "zod";
|
|
8651
8753
|
var ClaudeShimStateSchema = z14.strictObject({
|
|
8652
8754
|
targetPath: z14.string().min(1),
|
|
@@ -8658,10 +8760,10 @@ function commandFilename(ownExecutablePath, commandName) {
|
|
|
8658
8760
|
}
|
|
8659
8761
|
function resolveOwnBinaryCheck(paths, contentSourcePath) {
|
|
8660
8762
|
const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
8661
|
-
const recordedTarget = state === void 0 ? void 0 :
|
|
8763
|
+
const recordedTarget = state === void 0 ? void 0 : path25.resolve(state.targetPath);
|
|
8662
8764
|
let ownStat;
|
|
8663
8765
|
return (candidate) => {
|
|
8664
|
-
if (recordedTarget !== void 0 &&
|
|
8766
|
+
if (recordedTarget !== void 0 && path25.resolve(candidate) === recordedTarget) {
|
|
8665
8767
|
return true;
|
|
8666
8768
|
}
|
|
8667
8769
|
ownStat ??= statOrUndefined(contentSourcePath);
|
|
@@ -8685,20 +8787,20 @@ function statOrUndefined(target) {
|
|
|
8685
8787
|
}
|
|
8686
8788
|
var nodeLinkFs = { link: fs9.linkSync, copyFile: fs9.copyFileSync, chmod: fs9.chmodSync };
|
|
8687
8789
|
function findPathShadow(params) {
|
|
8688
|
-
const resolvedTargetDir =
|
|
8790
|
+
const resolvedTargetDir = path25.resolve(params.targetDir);
|
|
8689
8791
|
for (const dir of params.pathDirs) {
|
|
8690
8792
|
const found = params.findExecutableInDir(dir, params.targetFilename);
|
|
8691
8793
|
if (found === void 0) {
|
|
8692
8794
|
continue;
|
|
8693
8795
|
}
|
|
8694
|
-
return
|
|
8796
|
+
return path25.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
|
|
8695
8797
|
}
|
|
8696
|
-
return params.pathDirs.some((dir) =>
|
|
8798
|
+
return params.pathDirs.some((dir) => path25.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
|
|
8697
8799
|
}
|
|
8698
8800
|
|
|
8699
8801
|
// src/doctorReport.ts
|
|
8700
8802
|
import fs10 from "node:fs";
|
|
8701
|
-
import
|
|
8803
|
+
import path26 from "node:path";
|
|
8702
8804
|
function refinePathShadow(status, ownExecutablePath, realpath) {
|
|
8703
8805
|
if (status.status !== "shadowed") {
|
|
8704
8806
|
return status;
|
|
@@ -8722,7 +8824,7 @@ function validateJson(schema, input) {
|
|
|
8722
8824
|
return { ok: true, data: result.data };
|
|
8723
8825
|
}
|
|
8724
8826
|
function pushPathResolution(push, resolution) {
|
|
8725
|
-
const ownDir =
|
|
8827
|
+
const ownDir = path26.dirname(resolution.ownExecutablePath);
|
|
8726
8828
|
switch (resolution.agentShim.status) {
|
|
8727
8829
|
case "ok":
|
|
8728
8830
|
push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
|
|
@@ -8798,14 +8900,14 @@ function pushProvider(push, entry, cacheEnv) {
|
|
|
8798
8900
|
}
|
|
8799
8901
|
function pushLegacyName(push, params) {
|
|
8800
8902
|
const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
|
|
8801
|
-
if (legacyVariables.length === 0 &&
|
|
8903
|
+
if (legacyVariables.length === 0 && path26.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
|
|
8802
8904
|
push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
|
|
8803
8905
|
return;
|
|
8804
8906
|
}
|
|
8805
8907
|
for (const name of legacyVariables) {
|
|
8806
8908
|
push("legacy-name", "warn", `${name} is the former name of ${name.replace(LEGACY_ENV_PREFIX, ENV_PREFIX)}. Rename it; the old name still works but is only a fallback.`, name);
|
|
8807
8909
|
}
|
|
8808
|
-
if (
|
|
8910
|
+
if (path26.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
|
|
8809
8911
|
push(
|
|
8810
8912
|
"legacy-name",
|
|
8811
8913
|
"warn",
|
|
@@ -9124,18 +9226,18 @@ function collectDoctorReport(params) {
|
|
|
9124
9226
|
const { paths } = params;
|
|
9125
9227
|
const identityNames = fs10.existsSync(paths.identitiesDir) ? fs10.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
|
|
9126
9228
|
const identities = identityNames.map((name) => {
|
|
9127
|
-
const farmRoot =
|
|
9128
|
-
const identityPath =
|
|
9229
|
+
const farmRoot = path26.join(paths.identitiesDir, name);
|
|
9230
|
+
const identityPath = path26.join(farmRoot, "identity.json");
|
|
9129
9231
|
return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
|
|
9130
9232
|
});
|
|
9131
9233
|
const profileNames = fs10.existsSync(paths.configProfilesDir) ? fs10.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
9132
9234
|
const configProfiles = profileNames.map((name) => {
|
|
9133
|
-
const profilePath =
|
|
9235
|
+
const profilePath = path26.join(paths.configProfilesDir, `${name}.json`);
|
|
9134
9236
|
return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
|
|
9135
9237
|
});
|
|
9136
9238
|
const providerNames = fs10.existsSync(paths.providersDir) ? fs10.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
9137
9239
|
const providers = providerNames.map((name) => {
|
|
9138
|
-
const providerPath =
|
|
9240
|
+
const providerPath = path26.join(paths.providersDir, `${name}.json`);
|
|
9139
9241
|
return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
|
|
9140
9242
|
});
|
|
9141
9243
|
const ownExecutablePath = realOwnExecutablePath();
|
|
@@ -9147,12 +9249,12 @@ function collectDoctorReport(params) {
|
|
|
9147
9249
|
binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
|
|
9148
9250
|
}
|
|
9149
9251
|
const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
9150
|
-
const pathDirs = (params.env.PATH ?? "").split(
|
|
9252
|
+
const pathDirs = (params.env.PATH ?? "").split(path26.delimiter).filter((dir) => dir !== "");
|
|
9151
9253
|
const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
|
|
9152
9254
|
findPathShadow({
|
|
9153
9255
|
pathDirs,
|
|
9154
|
-
targetDir:
|
|
9155
|
-
targetFilename:
|
|
9256
|
+
targetDir: path26.dirname(shimState.targetPath),
|
|
9257
|
+
targetFilename: path26.basename(shimState.targetPath),
|
|
9156
9258
|
findExecutableInDir
|
|
9157
9259
|
}),
|
|
9158
9260
|
shimState.targetPath,
|
|
@@ -9177,7 +9279,7 @@ function collectDoctorReport(params) {
|
|
|
9177
9279
|
agentShim: refinePathShadow(
|
|
9178
9280
|
findPathShadow({
|
|
9179
9281
|
pathDirs,
|
|
9180
|
-
targetDir:
|
|
9282
|
+
targetDir: path26.dirname(ownExecutablePath),
|
|
9181
9283
|
targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
|
|
9182
9284
|
findExecutableInDir
|
|
9183
9285
|
}),
|
|
@@ -9198,7 +9300,7 @@ function collectDoctorReport(params) {
|
|
|
9198
9300
|
|
|
9199
9301
|
// src/launcher.ts
|
|
9200
9302
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
9201
|
-
import
|
|
9303
|
+
import path28 from "node:path";
|
|
9202
9304
|
|
|
9203
9305
|
// src/launcher/argv.ts
|
|
9204
9306
|
var ConflictingIdentityError = class extends UsageError {
|
|
@@ -9463,7 +9565,7 @@ function buildCliOverride(params) {
|
|
|
9463
9565
|
}
|
|
9464
9566
|
|
|
9465
9567
|
// src/launcher/flags.ts
|
|
9466
|
-
import
|
|
9568
|
+
import path27 from "node:path";
|
|
9467
9569
|
|
|
9468
9570
|
// src/headroom/headers.ts
|
|
9469
9571
|
function mergeAnthropicCustomHeaders(existing, additions) {
|
|
@@ -9533,7 +9635,7 @@ function buildEnv(params) {
|
|
|
9533
9635
|
const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
9534
9636
|
let providerCustomHeaders;
|
|
9535
9637
|
if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
|
|
9536
|
-
env.CLAUDE_CONFIG_DIR =
|
|
9638
|
+
env.CLAUDE_CONFIG_DIR = path27.join(params.identitiesDir, params.resolvedIdentityName);
|
|
9537
9639
|
}
|
|
9538
9640
|
if (params.provider !== void 0) {
|
|
9539
9641
|
const providerEnv = params.provider.definition.env ?? {};
|
|
@@ -9694,7 +9796,7 @@ function prepareLaunch(params) {
|
|
|
9694
9796
|
identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
|
|
9695
9797
|
globalDefaultConfigProfile: params.globalDefaultConfigProfile
|
|
9696
9798
|
});
|
|
9697
|
-
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(
|
|
9799
|
+
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path28.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
|
|
9698
9800
|
log.error(
|
|
9699
9801
|
`agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
|
|
9700
9802
|
);
|
|
@@ -9940,11 +10042,11 @@ function probeFrontDoorSync(port, caPem) {
|
|
|
9940
10042
|
|
|
9941
10043
|
// src/frontdoor/trust.ts
|
|
9942
10044
|
import { createHash as createHash6 } from "node:crypto";
|
|
9943
|
-
import
|
|
10045
|
+
import path29 from "node:path";
|
|
9944
10046
|
var BUNDLE_NAME_HEX_DIGITS = 16;
|
|
9945
10047
|
function resolveTrustBundle(params) {
|
|
9946
10048
|
const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
|
|
9947
|
-
if (inherited === void 0 || inherited === "" ||
|
|
10049
|
+
if (inherited === void 0 || inherited === "" || path29.resolve(inherited) === path29.resolve(caCertFile)) {
|
|
9948
10050
|
return { path: caCertFile };
|
|
9949
10051
|
}
|
|
9950
10052
|
const caPem = fs12.readFileUtf8(caCertFile);
|
|
@@ -9962,7 +10064,7 @@ function resolveTrustBundle(params) {
|
|
|
9962
10064
|
}
|
|
9963
10065
|
const combined = `${inheritedPem.trimEnd()}
|
|
9964
10066
|
${caPem}`;
|
|
9965
|
-
const bundle =
|
|
10067
|
+
const bundle = path29.join(bundlesDir, `${createHash6("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
|
|
9966
10068
|
if (!fs12.exists(bundle)) {
|
|
9967
10069
|
fs12.mkdirp(bundlesDir);
|
|
9968
10070
|
fs12.writeFileAtomic(bundle, combined);
|
|
@@ -10189,6 +10291,7 @@ export {
|
|
|
10189
10291
|
createRcApiNodeHandler,
|
|
10190
10292
|
createRcApiRouter,
|
|
10191
10293
|
createRcControlHandler,
|
|
10294
|
+
createRcCredentialStore,
|
|
10192
10295
|
createRcEventFanout,
|
|
10193
10296
|
createRcSessionTracker,
|
|
10194
10297
|
createRcStreamHub,
|