claude-use 7.13.2 → 8.0.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 +506 -362
- package/dist/index.cjs +293 -154
- package/dist/index.mjs +293 -154
- package/dist/types/index.d.ts +34 -17
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -247,7 +247,7 @@ var HeadroomGlobalConfigSchema = HeadroomGlobalConfigObjectSchema.superRefine((c
|
|
|
247
247
|
context.addIssue({ code: "custom", path: ["readMaturation"], message: "readMaturation needs rolloutChannel beta or dev" });
|
|
248
248
|
}
|
|
249
249
|
});
|
|
250
|
-
var HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@
|
|
250
|
+
var HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@53525f479f2f48e8ef6b08cf729601feab7d2382";
|
|
251
251
|
var HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES = 15;
|
|
252
252
|
var FrontDoorGlobalConfigSchema = z.strictObject({
|
|
253
253
|
/** How long the front door may sit with no registered sessions before it closes and exits. Defaults to FRONTDOOR_DEFAULT_IDLE_SHUTDOWN_MINUTES. */
|
|
@@ -2484,7 +2484,7 @@ function providerBaseUrl(port, provider) {
|
|
|
2484
2484
|
// src/frontdoor/state.ts
|
|
2485
2485
|
import path7 from "node:path";
|
|
2486
2486
|
import { z as z3 } from "zod";
|
|
2487
|
-
var FRONT_DOOR_PROTOCOL =
|
|
2487
|
+
var FRONT_DOOR_PROTOCOL = 2;
|
|
2488
2488
|
var FrontDoorSessionSchema = z3.strictObject({ pid: z3.number().int().positive(), startedAt: z3.number(), token: z3.string().min(1) });
|
|
2489
2489
|
var FrontDoorStateSchema = z3.strictObject({
|
|
2490
2490
|
/**
|
|
@@ -2709,8 +2709,8 @@ function parseConnectTarget(authority) {
|
|
|
2709
2709
|
function isInterceptedHost(host, interceptHosts) {
|
|
2710
2710
|
return interceptHosts.includes(host);
|
|
2711
2711
|
}
|
|
2712
|
-
function servedByPipeline(
|
|
2713
|
-
return
|
|
2712
|
+
function servedByPipeline(path29) {
|
|
2713
|
+
return path29?.startsWith(ROUTED_PATH_PREFIX) === true;
|
|
2714
2714
|
}
|
|
2715
2715
|
var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
2716
2716
|
"connection",
|
|
@@ -3043,13 +3043,63 @@ function realConnectCertStore(paths) {
|
|
|
3043
3043
|
}
|
|
3044
3044
|
|
|
3045
3045
|
// src/frontdoor/connectEffects.ts
|
|
3046
|
+
import * as dns from "node:dns";
|
|
3046
3047
|
import * as http from "node:http";
|
|
3047
3048
|
import * as https from "node:https";
|
|
3048
3049
|
import * as net2 from "node:net";
|
|
3049
3050
|
import * as tls from "node:tls";
|
|
3051
|
+
var UPSTREAM_LOCAL_PORT_START = 47900;
|
|
3052
|
+
var UPSTREAM_LOCAL_PORT_END = 47919;
|
|
3053
|
+
var nextUpstreamLocalPort = UPSTREAM_LOCAL_PORT_START;
|
|
3054
|
+
function upstreamLocalPort() {
|
|
3055
|
+
const port = nextUpstreamLocalPort;
|
|
3056
|
+
nextUpstreamLocalPort = nextUpstreamLocalPort === UPSTREAM_LOCAL_PORT_END ? UPSTREAM_LOCAL_PORT_START : nextUpstreamLocalPort + 1;
|
|
3057
|
+
return port;
|
|
3058
|
+
}
|
|
3059
|
+
var realAddressLookup = (host, _options, callback) => {
|
|
3060
|
+
if (net2.isIP(host) !== 0) {
|
|
3061
|
+
callback(null, [{ address: host, family: net2.isIP(host) }]);
|
|
3062
|
+
return;
|
|
3063
|
+
}
|
|
3064
|
+
dns.resolve4(host, (error, addresses) => {
|
|
3065
|
+
const first = addresses[0];
|
|
3066
|
+
if (error !== null || first === void 0) {
|
|
3067
|
+
callback(error ?? new Error(`no A record for ${host}`), [{ address: "", family: 4 }]);
|
|
3068
|
+
return;
|
|
3069
|
+
}
|
|
3070
|
+
callback(null, [{ address: first, family: 4 }]);
|
|
3071
|
+
});
|
|
3072
|
+
};
|
|
3073
|
+
var HTTP_PORT = 80;
|
|
3074
|
+
function exemptDial(options, defaultPort) {
|
|
3075
|
+
const host = typeof options.host === "string" ? options.host : "";
|
|
3076
|
+
const port = typeof options.port === "number" ? options.port : defaultPort;
|
|
3077
|
+
return net2.connect(net2.isIP(host) === 0 ? { host, port, localPort: upstreamLocalPort(), lookup: realAddressLookup } : { host, port });
|
|
3078
|
+
}
|
|
3079
|
+
function requestServername(options, fallback) {
|
|
3080
|
+
return "servername" in options && typeof options.servername === "string" && options.servername !== "" ? options.servername : fallback;
|
|
3081
|
+
}
|
|
3082
|
+
var ExemptHttpAgent = class extends http.Agent {
|
|
3083
|
+
createConnection(options) {
|
|
3084
|
+
return exemptDial(options, HTTP_PORT);
|
|
3085
|
+
}
|
|
3086
|
+
};
|
|
3087
|
+
var ExemptTlsAgent = class extends https.Agent {
|
|
3088
|
+
createConnection(options) {
|
|
3089
|
+
const host = typeof options.host === "string" ? options.host : "";
|
|
3090
|
+
const tlsOptions = { socket: exemptDial(options, HTTPS_PORT), servername: requestServername(options, host) };
|
|
3091
|
+
if ("ca" in options && Array.isArray(options.ca)) {
|
|
3092
|
+
tlsOptions.ca = options.ca;
|
|
3093
|
+
}
|
|
3094
|
+
if ("rejectUnauthorized" in options && typeof options.rejectUnauthorized === "boolean") {
|
|
3095
|
+
tlsOptions.rejectUnauthorized = options.rejectUnauthorized;
|
|
3096
|
+
}
|
|
3097
|
+
return tls.connect(tlsOptions);
|
|
3098
|
+
}
|
|
3099
|
+
};
|
|
3050
3100
|
function realConnectEffects() {
|
|
3051
|
-
const plainAgent = new
|
|
3052
|
-
const tlsAgent = new
|
|
3101
|
+
const plainAgent = new ExemptHttpAgent();
|
|
3102
|
+
const tlsAgent = new ExemptTlsAgent();
|
|
3053
3103
|
const listenOnce = async (port, onSocket) => await new Promise((resolve, reject) => {
|
|
3054
3104
|
const accepted = /* @__PURE__ */ new Set();
|
|
3055
3105
|
const server = net2.createServer((socket) => {
|
|
@@ -3135,11 +3185,23 @@ function realConnectEffects() {
|
|
|
3135
3185
|
};
|
|
3136
3186
|
},
|
|
3137
3187
|
connectTlsUpstream: async (host, port, clientAlpn) => await new Promise((resolve, reject) => {
|
|
3138
|
-
const
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
}
|
|
3142
|
-
|
|
3188
|
+
const dial = (localPort) => {
|
|
3189
|
+
const raw = net2.connect({ host, port, localPort, lookup: realAddressLookup });
|
|
3190
|
+
return tls.connect({ socket: raw, servername: host, ...clientAlpn === void 0 ? {} : { ALPNProtocols: [clientAlpn] } });
|
|
3191
|
+
};
|
|
3192
|
+
const settle = (candidate) => {
|
|
3193
|
+
candidate.once("secureConnect", () => {
|
|
3194
|
+
resolve(candidate);
|
|
3195
|
+
});
|
|
3196
|
+
candidate.once("error", (error) => {
|
|
3197
|
+
if ("code" in error && error.code === "EADDRINUSE") {
|
|
3198
|
+
settle(dial(upstreamLocalPort()));
|
|
3199
|
+
return;
|
|
3200
|
+
}
|
|
3201
|
+
reject(error);
|
|
3202
|
+
});
|
|
3203
|
+
};
|
|
3204
|
+
settle(dial(upstreamLocalPort()));
|
|
3143
3205
|
}),
|
|
3144
3206
|
connectTcp: async (host, port) => await new Promise((resolve, reject) => {
|
|
3145
3207
|
const socket = net2.connect({ host, port });
|
|
@@ -3153,6 +3215,7 @@ function realConnectEffects() {
|
|
|
3153
3215
|
const options = {
|
|
3154
3216
|
host: target.host,
|
|
3155
3217
|
port: target.port,
|
|
3218
|
+
lookup: realAddressLookup,
|
|
3156
3219
|
method: request3.method,
|
|
3157
3220
|
path: request3.url,
|
|
3158
3221
|
headers,
|
|
@@ -3213,17 +3276,16 @@ import { createHash as createHash2 } from "node:crypto";
|
|
|
3213
3276
|
import path8 from "node:path";
|
|
3214
3277
|
import { z as z4 } from "zod";
|
|
3215
3278
|
var HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
|
|
3279
|
+
var HEADROOM_STATE_SCHEMA_VERSION = 2;
|
|
3216
3280
|
var HeadroomStateSchema = z4.strictObject({
|
|
3217
3281
|
/** The supervisor process owning the daemon. Alive means someone is keeping headroom running. */
|
|
3218
3282
|
supervisorPid: z4.number().int().positive().optional(),
|
|
3219
3283
|
/** The headroom proxy process itself. Absent while the supervisor is between restarts. */
|
|
3220
3284
|
headroomPid: z4.number().int().positive().optional(),
|
|
3221
|
-
/** The loopback port the proxy listens on. Absent until the proxy has passed its readiness check, so "port is set" is itself the ready signal a launcher polls for. */
|
|
3222
|
-
port: z4.number().int().positive().optional(),
|
|
3223
3285
|
/**
|
|
3224
|
-
* The
|
|
3286
|
+
* The unix socket the proxy serves on, inside the owner-only socket directory. Absent until the proxy has passed its readiness check, so "socketPath is set" is itself the ready signal a launcher polls for. The front door reads it on every hop, so a restart (which keeps the generation's path) is followed without anything being relaunched.
|
|
3225
3287
|
*/
|
|
3226
|
-
|
|
3288
|
+
socketPath: z4.string().min(1).optional(),
|
|
3227
3289
|
/** The `headroom --version` output of the running install. */
|
|
3228
3290
|
version: z4.string().optional(),
|
|
3229
3291
|
/** Hash of the allowlist the running proxy was started with, so a provider-file change is detected as drift. */
|
|
@@ -3730,10 +3792,10 @@ function ensureHeadroom(params) {
|
|
|
3730
3792
|
for (; ; ) {
|
|
3731
3793
|
const state = readHeadroomState(ports.fs, paths.headroomStateFile);
|
|
3732
3794
|
if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
|
|
3733
|
-
const daemonUp = state.
|
|
3734
|
-
if (daemonUp && state.
|
|
3795
|
+
const daemonUp = state.socketPath !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
|
|
3796
|
+
if (daemonUp && state.socketPath !== void 0) {
|
|
3735
3797
|
writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
|
|
3736
|
-
return {
|
|
3798
|
+
return { socketPath: state.socketPath };
|
|
3737
3799
|
}
|
|
3738
3800
|
if (state.lastError !== void 0) {
|
|
3739
3801
|
throw new HeadroomStartError(
|
|
@@ -3797,6 +3859,71 @@ function hashSettings(settings) {
|
|
|
3797
3859
|
return createHash3("sha256").update(JSON.stringify([...settingsArgs(settings), JSON.stringify(settingsEnv(settings))])).digest("hex");
|
|
3798
3860
|
}
|
|
3799
3861
|
|
|
3862
|
+
// src/headroom/socket.ts
|
|
3863
|
+
import path11 from "node:path";
|
|
3864
|
+
var GROUP_OR_OTHER_BITS = 63;
|
|
3865
|
+
var OCTAL_RADIX = 8;
|
|
3866
|
+
var MODE_DIGITS = 4;
|
|
3867
|
+
var HEADROOM_SOCKET_SUFFIX = ".sock";
|
|
3868
|
+
var HEADROOM_SOCKET_NAME = /^(\d+)\.sock$/;
|
|
3869
|
+
var UNIX_SOCKET_PATH_MAX_BYTES = 103;
|
|
3870
|
+
var PLATFORMS_WITHOUT_UNIX_SOCKETS = ["win32"];
|
|
3871
|
+
function headroomSocketPath(paths, supervisorPid) {
|
|
3872
|
+
return path11.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
|
|
3873
|
+
}
|
|
3874
|
+
function platformRefusal(platform) {
|
|
3875
|
+
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;
|
|
3876
|
+
}
|
|
3877
|
+
function ownerOnlyRefusal(label, target, stat, expected, uid) {
|
|
3878
|
+
if (stat === void 0) {
|
|
3879
|
+
return `the headroom ${label} ${target} does not exist`;
|
|
3880
|
+
}
|
|
3881
|
+
if (stat.kind === "symlink") {
|
|
3882
|
+
return `the headroom ${label} ${target} is a symlink; it must be the real ${expected === "dir" ? "directory" : "socket"}`;
|
|
3883
|
+
}
|
|
3884
|
+
if (stat.kind !== expected) {
|
|
3885
|
+
return `the headroom ${label} ${target} is not a ${expected === "dir" ? "directory" : "socket"}`;
|
|
3886
|
+
}
|
|
3887
|
+
if (stat.uid !== uid) {
|
|
3888
|
+
return `the headroom ${label} ${target} is owned by uid ${String(stat.uid)}, not by this user (uid ${String(uid)})`;
|
|
3889
|
+
}
|
|
3890
|
+
if ((stat.mode & GROUP_OR_OTHER_BITS) !== 0) {
|
|
3891
|
+
return `the headroom ${label} ${target} has mode ${stat.mode.toString(OCTAL_RADIX).padStart(MODE_DIGITS, "0")}, which lets other users reach it; it must be accessible to its owner only`;
|
|
3892
|
+
}
|
|
3893
|
+
return void 0;
|
|
3894
|
+
}
|
|
3895
|
+
function prepareHeadroomSocket(fs12, ports, paths, supervisorPid) {
|
|
3896
|
+
const unsupported = platformRefusal(ports.platform);
|
|
3897
|
+
if (unsupported !== void 0) {
|
|
3898
|
+
return { refused: unsupported };
|
|
3899
|
+
}
|
|
3900
|
+
const socketPath = headroomSocketPath(paths, supervisorPid);
|
|
3901
|
+
const length = Buffer.byteLength(socketPath, "utf8");
|
|
3902
|
+
if (length > UNIX_SOCKET_PATH_MAX_BYTES) {
|
|
3903
|
+
return {
|
|
3904
|
+
refused: `the headroom socket path ${socketPath} is ${String(length)} bytes, longer than the ${String(UNIX_SOCKET_PATH_MAX_BYTES)} a unix socket path can hold; set AGENT_SHIM_HOME to a shorter directory`
|
|
3905
|
+
};
|
|
3906
|
+
}
|
|
3907
|
+
if (ports.lstat(paths.headroomSocketDir)?.kind === "symlink") {
|
|
3908
|
+
return { refused: `the headroom socket directory ${paths.headroomSocketDir} is a symlink; it must be the real directory` };
|
|
3909
|
+
}
|
|
3910
|
+
fs12.mkdirPrivate(paths.headroomSocketDir);
|
|
3911
|
+
const refusal = ownerOnlyRefusal("socket directory", paths.headroomSocketDir, ports.lstat(paths.headroomSocketDir), "dir", ports.currentUid());
|
|
3912
|
+
return refusal === void 0 ? { socketPath } : { refused: refusal };
|
|
3913
|
+
}
|
|
3914
|
+
function pruneStaleHeadroomSockets(fs12, paths, isRunning) {
|
|
3915
|
+
const removed = [];
|
|
3916
|
+
for (const name of fs12.readdir(paths.headroomSocketDir)) {
|
|
3917
|
+
const pid = HEADROOM_SOCKET_NAME.exec(name)?.[1];
|
|
3918
|
+
if (pid === void 0 || isRunning(Number.parseInt(pid, 10))) {
|
|
3919
|
+
continue;
|
|
3920
|
+
}
|
|
3921
|
+
fs12.removeRecursive(path11.join(paths.headroomSocketDir, name));
|
|
3922
|
+
removed.push(name);
|
|
3923
|
+
}
|
|
3924
|
+
return removed;
|
|
3925
|
+
}
|
|
3926
|
+
|
|
3800
3927
|
// src/headroom/source.ts
|
|
3801
3928
|
import { z as z6 } from "zod";
|
|
3802
3929
|
var GIT_SPEC_RE = /git\+[^@\s]+(?:@([^\s#]+))?/;
|
|
@@ -3892,8 +4019,6 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3892
4019
|
return 0;
|
|
3893
4020
|
}
|
|
3894
4021
|
let installedSource = previousState?.installedSource;
|
|
3895
|
-
let lastPort = previousState?.lastPort;
|
|
3896
|
-
const sticky = () => lastPort === void 0 ? {} : { lastPort };
|
|
3897
4022
|
const ownsState = () => {
|
|
3898
4023
|
const owner = readHeadroomState(fs12, paths.headroomStateFile)?.supervisorPid;
|
|
3899
4024
|
return owner === void 0 || owner === ports.ownPid || !ports.isRunning(owner);
|
|
@@ -3906,7 +4031,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3906
4031
|
return true;
|
|
3907
4032
|
};
|
|
3908
4033
|
const fail = (message) => {
|
|
3909
|
-
if (writeOwnState({ lastError: message
|
|
4034
|
+
if (writeOwnState({ lastError: message })) {
|
|
3910
4035
|
fs12.removeRecursive(paths.headroomLockFile);
|
|
3911
4036
|
}
|
|
3912
4037
|
ports.log(`agent-shim headroom supervisor: ${message}`);
|
|
@@ -3929,11 +4054,17 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3929
4054
|
installedSource = config.source;
|
|
3930
4055
|
return true;
|
|
3931
4056
|
};
|
|
4057
|
+
const socket = prepareHeadroomSocket(fs12, ports.socketTrust, paths, ports.ownPid);
|
|
4058
|
+
if (socket.refused !== void 0) {
|
|
4059
|
+
return fail(socket.refused);
|
|
4060
|
+
}
|
|
4061
|
+
const { socketPath } = socket;
|
|
4062
|
+
pruneStaleHeadroomSockets(fs12, paths, ports.isRunning);
|
|
3932
4063
|
if (!ensureInstalled()) {
|
|
3933
4064
|
return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
|
|
3934
4065
|
}
|
|
3935
4066
|
const version = ports.headroomVersion() ?? "unknown";
|
|
3936
|
-
writeOwnState({ supervisorPid: ports.ownPid, version, installedSource
|
|
4067
|
+
writeOwnState({ supervisorPid: ports.ownPid, version, installedSource });
|
|
3937
4068
|
ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${allowlistOf(ports).join(", ")}]`);
|
|
3938
4069
|
const orphanPid = previousState?.headroomPid;
|
|
3939
4070
|
if (orphanPid !== void 0 && ports.isRunning(orphanPid)) {
|
|
@@ -3959,7 +4090,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3959
4090
|
pruneDeadSessions(fs12, paths.headroomSessionsDir, ports.isRunning);
|
|
3960
4091
|
const ownsNow = ownsState();
|
|
3961
4092
|
if (!ownsNow && !superseded) {
|
|
3962
|
-
ports.log("agent-shim headroom supervisor: another supervisor now owns state
|
|
4093
|
+
ports.log("agent-shim headroom supervisor: another supervisor now owns the state file; serving this daemon's own sessions until they end");
|
|
3963
4094
|
}
|
|
3964
4095
|
superseded = !ownsNow;
|
|
3965
4096
|
const crashed = headroomPid !== void 0 && !ports.isRunning(headroomPid);
|
|
@@ -3972,8 +4103,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3972
4103
|
writeOwnState({
|
|
3973
4104
|
supervisorPid: ports.ownPid,
|
|
3974
4105
|
version,
|
|
3975
|
-
installedSource
|
|
3976
|
-
...sticky()
|
|
4106
|
+
installedSource
|
|
3977
4107
|
});
|
|
3978
4108
|
}
|
|
3979
4109
|
if (consecutiveFailures >= HEADROOM_START_RETRY_BUDGET) {
|
|
@@ -3982,41 +4112,32 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3982
4112
|
if (installedSource !== config.source && !ensureInstalled()) {
|
|
3983
4113
|
return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
|
|
3984
4114
|
}
|
|
3985
|
-
const
|
|
3986
|
-
const
|
|
3987
|
-
const pid = ports.spawnHeadroom(port, allowlist, config.settings);
|
|
3988
|
-
const ready = await waitUntilReady(ports, port);
|
|
4115
|
+
const pid = ports.spawnHeadroom(socketPath, allowlist, config.settings);
|
|
4116
|
+
const ready = await waitUntilReady(ports, socketPath);
|
|
3989
4117
|
if (ready) {
|
|
3990
4118
|
consecutiveFailures = 0;
|
|
3991
4119
|
headroomPid = pid;
|
|
3992
4120
|
runningHash = allowlistHash;
|
|
3993
4121
|
runningSettingsHash = settingsHash;
|
|
3994
|
-
lastPort = port;
|
|
3995
|
-
if (previousSticky !== void 0 && port !== previousSticky) {
|
|
3996
|
-
ports.log(
|
|
3997
|
-
`agent-shim headroom supervisor: sticky port ${String(previousSticky)} was occupied; moving to ${String(port)} (sessions launched against the old port are stale until they relaunch)`
|
|
3998
|
-
);
|
|
3999
|
-
}
|
|
4000
4122
|
const recorded = writeOwnState({
|
|
4001
4123
|
supervisorPid: ports.ownPid,
|
|
4002
4124
|
headroomPid: pid,
|
|
4003
|
-
|
|
4125
|
+
socketPath,
|
|
4004
4126
|
version,
|
|
4005
4127
|
allowlistHash,
|
|
4006
4128
|
settingsHash,
|
|
4007
|
-
installedSource: config.source
|
|
4008
|
-
...sticky()
|
|
4129
|
+
installedSource: config.source
|
|
4009
4130
|
});
|
|
4010
4131
|
if (recorded) {
|
|
4011
4132
|
fs12.removeRecursive(paths.headroomLockFile);
|
|
4012
4133
|
}
|
|
4013
4134
|
idleSince = void 0;
|
|
4014
|
-
ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on
|
|
4135
|
+
ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on unix socket ${socketPath}`);
|
|
4015
4136
|
} else {
|
|
4016
4137
|
ports.stopProcess(pid);
|
|
4017
4138
|
consecutiveFailures += 1;
|
|
4018
4139
|
ports.log(
|
|
4019
|
-
`agent-shim headroom supervisor: headroom did not become ready on
|
|
4140
|
+
`agent-shim headroom supervisor: headroom did not become ready on unix socket ${socketPath} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
|
|
4020
4141
|
);
|
|
4021
4142
|
await ports.sleep(backoffForAttempt(consecutiveFailures));
|
|
4022
4143
|
continue;
|
|
@@ -4041,10 +4162,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
4041
4162
|
`agent-shim headroom supervisor: no sessions for ${String(config.idleShutdownMinutes)} minute(s); stopping headroom and exiting`
|
|
4042
4163
|
);
|
|
4043
4164
|
ports.stopProcess(headroomPid);
|
|
4044
|
-
writeOwnState({
|
|
4045
|
-
version,
|
|
4046
|
-
...sticky()
|
|
4047
|
-
});
|
|
4165
|
+
writeOwnState({ version });
|
|
4048
4166
|
return 0;
|
|
4049
4167
|
}
|
|
4050
4168
|
} else {
|
|
@@ -4061,10 +4179,10 @@ function currentHeadroomAllowlist(fs12, paths) {
|
|
|
4061
4179
|
function allowlistOf(ports) {
|
|
4062
4180
|
return currentHeadroomAllowlist(ports.fs, ports.paths);
|
|
4063
4181
|
}
|
|
4064
|
-
async function waitUntilReady(ports,
|
|
4182
|
+
async function waitUntilReady(ports, socketPath) {
|
|
4065
4183
|
const deadline = ports.now() + HEADROOM_READY_TIMEOUT_MS;
|
|
4066
4184
|
for (; ; ) {
|
|
4067
|
-
if (await ports.ready(
|
|
4185
|
+
if (await ports.ready(socketPath)) {
|
|
4068
4186
|
return true;
|
|
4069
4187
|
}
|
|
4070
4188
|
if (ports.now() >= deadline) {
|
|
@@ -4124,14 +4242,14 @@ function evaluateAmbientCredentialGuard(params) {
|
|
|
4124
4242
|
// src/paths.ts
|
|
4125
4243
|
import fs3 from "node:fs";
|
|
4126
4244
|
import os from "node:os";
|
|
4127
|
-
import
|
|
4245
|
+
import path12 from "node:path";
|
|
4128
4246
|
function resolveAgentShimHome(env = process.env, home = os.homedir(), isDirectory = isExistingDirectory) {
|
|
4129
4247
|
const fromEnv = env.AGENT_SHIM_HOME;
|
|
4130
4248
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
4131
4249
|
return fromEnv;
|
|
4132
4250
|
}
|
|
4133
|
-
const current =
|
|
4134
|
-
const legacy =
|
|
4251
|
+
const current = path12.join(home, HOME_DIRNAME);
|
|
4252
|
+
const legacy = path12.join(home, LEGACY_HOME_DIRNAME);
|
|
4135
4253
|
return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
|
|
4136
4254
|
}
|
|
4137
4255
|
function isExistingDirectory(candidate) {
|
|
@@ -4142,38 +4260,39 @@ function resolveClaudeHome() {
|
|
|
4142
4260
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
4143
4261
|
return fromEnv;
|
|
4144
4262
|
}
|
|
4145
|
-
return
|
|
4263
|
+
return path12.join(os.homedir(), ".claude");
|
|
4146
4264
|
}
|
|
4147
4265
|
function buildLayoutPaths(root) {
|
|
4148
4266
|
return {
|
|
4149
4267
|
root,
|
|
4150
|
-
identitiesDir:
|
|
4151
|
-
configProfilesDir:
|
|
4152
|
-
providersDir:
|
|
4153
|
-
directoryRulesFile:
|
|
4154
|
-
activeIdentityFile:
|
|
4155
|
-
globalConfigFile:
|
|
4156
|
-
categoriesLocalFile:
|
|
4157
|
-
claudeShimFile:
|
|
4158
|
-
headroomDir:
|
|
4159
|
-
headroomStateFile:
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4268
|
+
identitiesDir: path12.join(root, "identities"),
|
|
4269
|
+
configProfilesDir: path12.join(root, "config-profiles"),
|
|
4270
|
+
providersDir: path12.join(root, "providers"),
|
|
4271
|
+
directoryRulesFile: path12.join(root, "directory-rules.json"),
|
|
4272
|
+
activeIdentityFile: path12.join(root, "active-identity"),
|
|
4273
|
+
globalConfigFile: path12.join(root, "config.json"),
|
|
4274
|
+
categoriesLocalFile: path12.join(root, "categories.local.json"),
|
|
4275
|
+
claudeShimFile: path12.join(root, "claude-shim.json"),
|
|
4276
|
+
headroomDir: path12.join(root, "headroom"),
|
|
4277
|
+
headroomStateFile: path12.join(root, "headroom", `state.v${String(HEADROOM_STATE_SCHEMA_VERSION)}.json`),
|
|
4278
|
+
headroomSocketDir: path12.join(root, "headroom", "run"),
|
|
4279
|
+
headroomLockFile: path12.join(root, "headroom", "start.lock"),
|
|
4280
|
+
headroomSessionsDir: path12.join(root, "headroom", "sessions"),
|
|
4281
|
+
logsDir: path12.join(root, "logs"),
|
|
4282
|
+
headroomLogPath: path12.join(root, "logs", "headroom.log"),
|
|
4283
|
+
frontdoorDir: path12.join(root, "frontdoor"),
|
|
4284
|
+
frontdoorCaDir: path12.join(root, "frontdoor", "ca"),
|
|
4285
|
+
frontdoorCaCertFile: path12.join(root, "frontdoor", "ca", "ca.pem"),
|
|
4286
|
+
frontdoorCaKeyFile: path12.join(root, "frontdoor", "ca", "ca.key"),
|
|
4287
|
+
frontdoorCaBundlesDir: path12.join(root, "frontdoor", "ca", "bundles"),
|
|
4288
|
+
frontdoorStateFile: path12.join(root, "frontdoor", "state.json"),
|
|
4289
|
+
frontdoorLockFile: path12.join(root, "frontdoor", "start.lock"),
|
|
4290
|
+
frontdoorSessionsDir: path12.join(root, "frontdoor", "sessions"),
|
|
4291
|
+
frontdoorLogPath: path12.join(root, "logs", "frontdoor.log"),
|
|
4292
|
+
usageDir: path12.join(root, "usage"),
|
|
4293
|
+
usageLogDir: path12.join(root, "usage", "log"),
|
|
4294
|
+
usageSnapshotsDir: path12.join(root, "usage", "snapshots"),
|
|
4295
|
+
usagePicksFile: path12.join(root, "usage", "picks.json")
|
|
4177
4296
|
};
|
|
4178
4297
|
}
|
|
4179
4298
|
function resolveLayoutPaths() {
|
|
@@ -4182,10 +4301,10 @@ function resolveLayoutPaths() {
|
|
|
4182
4301
|
|
|
4183
4302
|
// src/identityStore.ts
|
|
4184
4303
|
import fs5 from "node:fs";
|
|
4185
|
-
import
|
|
4304
|
+
import path15 from "node:path";
|
|
4186
4305
|
|
|
4187
4306
|
// src/launcher/identity.ts
|
|
4188
|
-
import
|
|
4307
|
+
import path13 from "node:path";
|
|
4189
4308
|
function poolNameOf(selector) {
|
|
4190
4309
|
return selector.startsWith(POOL_SELECTOR_PREFIX) ? selector.slice(POOL_SELECTOR_PREFIX.length) : void 0;
|
|
4191
4310
|
}
|
|
@@ -4234,12 +4353,12 @@ function decideConfigProfile(params) {
|
|
|
4234
4353
|
return { source: "none" };
|
|
4235
4354
|
}
|
|
4236
4355
|
function loadIdentity(identitiesDir, name, fs12) {
|
|
4237
|
-
return loadConfigFile(
|
|
4356
|
+
return loadConfigFile(path13.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
|
|
4238
4357
|
}
|
|
4239
4358
|
|
|
4240
4359
|
// src/configProfilesStore.ts
|
|
4241
4360
|
import fs4 from "node:fs";
|
|
4242
|
-
import
|
|
4361
|
+
import path14 from "node:path";
|
|
4243
4362
|
var ProfileNotFoundError = class extends CliError {
|
|
4244
4363
|
constructor(profileName) {
|
|
4245
4364
|
super(`No configuration profile named "${profileName}". Run \`agent-shim profile add ${profileName}\` first.`);
|
|
@@ -4265,7 +4384,7 @@ var InvalidCategoryNameError = class extends CliError {
|
|
|
4265
4384
|
categoryName;
|
|
4266
4385
|
};
|
|
4267
4386
|
function profileJsonPath(paths, name) {
|
|
4268
|
-
return
|
|
4387
|
+
return path14.join(paths.configProfilesDir, `${name}.json`);
|
|
4269
4388
|
}
|
|
4270
4389
|
function profileExists(paths, name) {
|
|
4271
4390
|
return fs4.existsSync(profileJsonPath(paths, name));
|
|
@@ -4453,7 +4572,7 @@ var InvalidIdentityNameError = class extends CliError {
|
|
|
4453
4572
|
attemptedName;
|
|
4454
4573
|
};
|
|
4455
4574
|
function identityJsonPath(paths, name) {
|
|
4456
|
-
return
|
|
4575
|
+
return path15.join(paths.identitiesDir, name, "identity.json");
|
|
4457
4576
|
}
|
|
4458
4577
|
function identityExists(paths, name) {
|
|
4459
4578
|
return fs5.existsSync(identityJsonPath(paths, name));
|
|
@@ -4554,7 +4673,7 @@ function setIdentityCredential(paths, identityName, change) {
|
|
|
4554
4673
|
});
|
|
4555
4674
|
}
|
|
4556
4675
|
function belongsToIdentity(entry, name) {
|
|
4557
|
-
return entry === name || entry ===
|
|
4676
|
+
return entry === name || entry === path15.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
|
|
4558
4677
|
}
|
|
4559
4678
|
function removeIdentity(paths, name) {
|
|
4560
4679
|
if (!identityExists(paths, name)) {
|
|
@@ -4562,7 +4681,7 @@ function removeIdentity(paths, name) {
|
|
|
4562
4681
|
}
|
|
4563
4682
|
for (const entry of fs5.readdirSync(paths.identitiesDir)) {
|
|
4564
4683
|
if (belongsToIdentity(entry, name)) {
|
|
4565
|
-
fs5.rmSync(
|
|
4684
|
+
fs5.rmSync(path15.join(paths.identitiesDir, entry), { recursive: true, force: true });
|
|
4566
4685
|
}
|
|
4567
4686
|
}
|
|
4568
4687
|
if (readActiveIdentity(paths) === name) {
|
|
@@ -4572,7 +4691,7 @@ function removeIdentity(paths, name) {
|
|
|
4572
4691
|
|
|
4573
4692
|
// src/providersStore.ts
|
|
4574
4693
|
import fs6 from "node:fs";
|
|
4575
|
-
import
|
|
4694
|
+
import path16 from "node:path";
|
|
4576
4695
|
|
|
4577
4696
|
// src/credentialCache.ts
|
|
4578
4697
|
import { z as z7 } from "zod";
|
|
@@ -4609,7 +4728,7 @@ var CREDENTIAL_COMMAND_TIMEOUT_MS = 1e4;
|
|
|
4609
4728
|
var CREDENTIAL_INTERACTIVE_TIMEOUT_MS = 12e4;
|
|
4610
4729
|
var GROUP_OTHER_PERMISSION_BITS = 63;
|
|
4611
4730
|
var PERMISSION_BITS = 511;
|
|
4612
|
-
var
|
|
4731
|
+
var OCTAL_RADIX2 = 8;
|
|
4613
4732
|
function commandArgv(source) {
|
|
4614
4733
|
if ("command" in source) {
|
|
4615
4734
|
return source.command;
|
|
@@ -4702,7 +4821,7 @@ function trySource(source, params) {
|
|
|
4702
4821
|
}
|
|
4703
4822
|
if (read.mode !== void 0 && (read.mode & GROUP_OTHER_PERMISSION_BITS) !== 0) {
|
|
4704
4823
|
return none(
|
|
4705
|
-
`is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS).toString(
|
|
4824
|
+
`is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS).toString(OCTAL_RADIX2)}); run \`chmod 600 ${source.file}\``,
|
|
4706
4825
|
true
|
|
4707
4826
|
);
|
|
4708
4827
|
}
|
|
@@ -4798,7 +4917,7 @@ var InvalidProviderNameError = class extends CliError {
|
|
|
4798
4917
|
};
|
|
4799
4918
|
var PROVIDER_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._@-]*$/;
|
|
4800
4919
|
function providerJsonPath(paths, name) {
|
|
4801
|
-
return
|
|
4920
|
+
return path16.join(paths.providersDir, `${name}.json`);
|
|
4802
4921
|
}
|
|
4803
4922
|
function providerExists(paths, name) {
|
|
4804
4923
|
return fs6.existsSync(providerJsonPath(paths, name));
|
|
@@ -4874,7 +4993,7 @@ function readProvider(paths, name) {
|
|
|
4874
4993
|
return parseProviderFile(filePath, raw);
|
|
4875
4994
|
}
|
|
4876
4995
|
function loadProvider(providersDir, name, port) {
|
|
4877
|
-
const filePath =
|
|
4996
|
+
const filePath = path16.join(providersDir, `${name}.json`);
|
|
4878
4997
|
const raw = port.readConfigFile(filePath);
|
|
4879
4998
|
return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
|
|
4880
4999
|
}
|
|
@@ -5129,21 +5248,21 @@ function removeDirectoryRule(paths, rulePath) {
|
|
|
5129
5248
|
import os4 from "node:os";
|
|
5130
5249
|
|
|
5131
5250
|
// src/launcher/cascade.ts
|
|
5132
|
-
import
|
|
5251
|
+
import path18 from "node:path";
|
|
5133
5252
|
|
|
5134
5253
|
// src/pathNorm.ts
|
|
5135
|
-
import
|
|
5254
|
+
import path17 from "node:path";
|
|
5136
5255
|
function expandTilde(value, home) {
|
|
5137
5256
|
if (value === "~") {
|
|
5138
5257
|
return home;
|
|
5139
5258
|
}
|
|
5140
5259
|
if (value.startsWith("~/")) {
|
|
5141
|
-
return
|
|
5260
|
+
return path17.join(home, value.slice(2));
|
|
5142
5261
|
}
|
|
5143
5262
|
return value;
|
|
5144
5263
|
}
|
|
5145
5264
|
function normaliseRulePath(rulePath, home) {
|
|
5146
|
-
return
|
|
5265
|
+
return path17.resolve(expandTilde(rulePath, home));
|
|
5147
5266
|
}
|
|
5148
5267
|
|
|
5149
5268
|
// src/launcher/cascade.ts
|
|
@@ -5153,7 +5272,7 @@ function loadCascadeInput(params) {
|
|
|
5153
5272
|
const globalConfig = loadConfigFile(params.paths.globalConfigFile, GlobalConfigSchema, params.read);
|
|
5154
5273
|
const directoryRules = loadConfigFile(params.paths.directoryRulesFile, DirectoryRulesSchema, params.read);
|
|
5155
5274
|
const loadProfile = (name) => {
|
|
5156
|
-
const filepath =
|
|
5275
|
+
const filepath = path18.join(params.paths.configProfilesDir, `${name}.json`);
|
|
5157
5276
|
const loaded = loadConfigFile(filepath, ConfigProfileSchema, params.read);
|
|
5158
5277
|
if (loaded === void 0) {
|
|
5159
5278
|
return void 0;
|
|
@@ -5168,8 +5287,8 @@ function loadCascadeInput(params) {
|
|
|
5168
5287
|
});
|
|
5169
5288
|
const levels = [];
|
|
5170
5289
|
for (const dir of dirs) {
|
|
5171
|
-
const portable = loadConfigFile(
|
|
5172
|
-
const portableLocal = loadConfigFile(
|
|
5290
|
+
const portable = loadConfigFile(path18.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path18.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
5291
|
+
const portableLocal = loadConfigFile(path18.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path18.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
5173
5292
|
const rules = (directoryRules?.config.rules ?? []).map((rule, index) => ({ rule, index })).filter(({ rule }) => normaliseRulePath(rule.path, params.home) === dir).map(({ rule, index }) => {
|
|
5174
5293
|
const entryOrder = directoryRules?.ruleEntryOrders[index];
|
|
5175
5294
|
return {
|
|
@@ -5266,7 +5385,7 @@ function quotaWarnings(snapshot, provider, nowMs) {
|
|
|
5266
5385
|
}
|
|
5267
5386
|
|
|
5268
5387
|
// src/usage/poolPick.ts
|
|
5269
|
-
import
|
|
5388
|
+
import path19 from "node:path";
|
|
5270
5389
|
import { z as z9 } from "zod";
|
|
5271
5390
|
|
|
5272
5391
|
// src/usage/plan.ts
|
|
@@ -5568,7 +5687,7 @@ function recordStickyPick(fs12, picksFile, directory, identity, nowMs) {
|
|
|
5568
5687
|
const current = readPicksFile(fs12, picksFile).file.picks;
|
|
5569
5688
|
const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
|
|
5570
5689
|
const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
|
|
5571
|
-
fs12.mkdirPrivate(
|
|
5690
|
+
fs12.mkdirPrivate(path19.dirname(picksFile));
|
|
5572
5691
|
fs12.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
|
|
5573
5692
|
`);
|
|
5574
5693
|
}
|
|
@@ -5665,14 +5784,14 @@ import { spawn, spawnSync } from "node:child_process";
|
|
|
5665
5784
|
import { createHash as createHash4 } from "node:crypto";
|
|
5666
5785
|
import fs7 from "node:fs";
|
|
5667
5786
|
import os3 from "node:os";
|
|
5668
|
-
import
|
|
5787
|
+
import path21 from "node:path";
|
|
5669
5788
|
import { isSea } from "node:sea";
|
|
5670
5789
|
|
|
5671
5790
|
// src/versionDiscovery.ts
|
|
5672
5791
|
import os2 from "node:os";
|
|
5673
|
-
import
|
|
5792
|
+
import path20 from "node:path";
|
|
5674
5793
|
function defaultVersionsDir() {
|
|
5675
|
-
return
|
|
5794
|
+
return path20.join(os2.homedir(), ".local", "share", "claude", "versions");
|
|
5676
5795
|
}
|
|
5677
5796
|
var NUMERIC_DOTTED_VERSION_RE = /^\d+(?:\.\d+)*$/;
|
|
5678
5797
|
function isNumericDottedVersion(name) {
|
|
@@ -5714,14 +5833,14 @@ function discoverClaudeBinary(options) {
|
|
|
5714
5833
|
const highestVersion = pickHighestVersion(entries);
|
|
5715
5834
|
if (highestVersion !== void 0) {
|
|
5716
5835
|
return {
|
|
5717
|
-
path:
|
|
5836
|
+
path: path20.join(versionsDir, highestVersion),
|
|
5718
5837
|
source: "versions-dir",
|
|
5719
5838
|
version: highestVersion
|
|
5720
5839
|
};
|
|
5721
5840
|
}
|
|
5722
|
-
const ownInstallDirs = new Set(options.ownInstallDirs.map((dir) =>
|
|
5841
|
+
const ownInstallDirs = new Set(options.ownInstallDirs.map((dir) => path20.resolve(dir)));
|
|
5723
5842
|
for (const dir of options.pathDirs) {
|
|
5724
|
-
if (ownInstallDirs.has(
|
|
5843
|
+
if (ownInstallDirs.has(path20.resolve(dir))) {
|
|
5725
5844
|
continue;
|
|
5726
5845
|
}
|
|
5727
5846
|
const found = options.findExecutableInDir(dir, "claude");
|
|
@@ -5892,7 +6011,7 @@ var realRunPort = {
|
|
|
5892
6011
|
}
|
|
5893
6012
|
};
|
|
5894
6013
|
function expandHome2(filePath) {
|
|
5895
|
-
return filePath.startsWith("~/") ?
|
|
6014
|
+
return filePath.startsWith("~/") ? path21.join(os3.homedir(), filePath.slice(1)) : filePath;
|
|
5896
6015
|
}
|
|
5897
6016
|
var MACOS_GUI_SESSION_MANAGER = "Aqua";
|
|
5898
6017
|
function hasDesktopSession() {
|
|
@@ -5965,7 +6084,7 @@ function spawnDaemonThrough(executable) {
|
|
|
5965
6084
|
return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: executable, args: [subcommand] }, paths, subcommand, logPath);
|
|
5966
6085
|
}
|
|
5967
6086
|
function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
|
|
5968
|
-
fs7.mkdirSync(
|
|
6087
|
+
fs7.mkdirSync(path21.dirname(logPath), { recursive: true });
|
|
5969
6088
|
const logFd = fs7.openSync(logPath, "a");
|
|
5970
6089
|
try {
|
|
5971
6090
|
const child = spawn(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
|
|
@@ -5981,6 +6100,29 @@ function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
|
|
|
5981
6100
|
function spawnHeadroomSupervisor(paths, spawnDaemon) {
|
|
5982
6101
|
return spawnDaemon(paths, "__headroom-supervisor", paths.headroomLogPath);
|
|
5983
6102
|
}
|
|
6103
|
+
var SOCKET_PERMISSION_BITS = 511;
|
|
6104
|
+
var realHeadroomSocketTrust = {
|
|
6105
|
+
platform: process.platform,
|
|
6106
|
+
currentUid: () => {
|
|
6107
|
+
if (process.getuid === void 0) {
|
|
6108
|
+
throw new Error(`no POSIX user id on ${process.platform}`);
|
|
6109
|
+
}
|
|
6110
|
+
return process.getuid();
|
|
6111
|
+
},
|
|
6112
|
+
lstat: (target) => {
|
|
6113
|
+
let stat;
|
|
6114
|
+
try {
|
|
6115
|
+
stat = fs7.lstatSync(target);
|
|
6116
|
+
} catch (error) {
|
|
6117
|
+
if (isEnoent3(error)) {
|
|
6118
|
+
return void 0;
|
|
6119
|
+
}
|
|
6120
|
+
throw error;
|
|
6121
|
+
}
|
|
6122
|
+
const kind = stat.isSymbolicLink() ? "symlink" : stat.isDirectory() ? "dir" : stat.isSocket() ? "socket" : "other";
|
|
6123
|
+
return { kind, uid: stat.uid, mode: stat.mode & SOCKET_PERMISSION_BITS };
|
|
6124
|
+
}
|
|
6125
|
+
};
|
|
5984
6126
|
function realHeadroomPort(paths, options) {
|
|
5985
6127
|
return {
|
|
5986
6128
|
ensure: () => {
|
|
@@ -5997,7 +6139,7 @@ function realHeadroomPort(paths, options) {
|
|
|
5997
6139
|
}
|
|
5998
6140
|
});
|
|
5999
6141
|
return {
|
|
6000
|
-
|
|
6142
|
+
socketPath: up.socketPath,
|
|
6001
6143
|
projectId: resolveGitRoot(realRunPort, options.cwd) ?? options.cwd
|
|
6002
6144
|
};
|
|
6003
6145
|
},
|
|
@@ -6023,7 +6165,7 @@ function listVersionsDir(dir) {
|
|
|
6023
6165
|
throw error;
|
|
6024
6166
|
}
|
|
6025
6167
|
return entries.filter((entry) => entry.isFile()).map((entry) => {
|
|
6026
|
-
const fullPath =
|
|
6168
|
+
const fullPath = path21.join(dir, entry.name);
|
|
6027
6169
|
const stat = fs7.statSync(fullPath);
|
|
6028
6170
|
return {
|
|
6029
6171
|
name: entry.name,
|
|
@@ -6038,7 +6180,7 @@ function windowsPathExtensions(pathext) {
|
|
|
6038
6180
|
return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
|
|
6039
6181
|
}
|
|
6040
6182
|
function resolveExecutableCandidate(dir, name, env) {
|
|
6041
|
-
const candidate =
|
|
6183
|
+
const candidate = path21.join(dir, name);
|
|
6042
6184
|
if (env.platform === "win32") {
|
|
6043
6185
|
const extensions = windowsPathExtensions(env.pathext);
|
|
6044
6186
|
const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
|
|
@@ -6087,13 +6229,13 @@ function resolveOwnExecutablePath(env) {
|
|
|
6087
6229
|
if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
|
|
6088
6230
|
return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
|
|
6089
6231
|
}
|
|
6090
|
-
const candidate = env.argv1 === void 0 ? env.execPath :
|
|
6091
|
-
const candidateDir =
|
|
6092
|
-
const candidateDirOnPath = env.pathDirs.some((dir) =>
|
|
6232
|
+
const candidate = env.argv1 === void 0 ? env.execPath : path21.resolve(env.cwd, env.argv1);
|
|
6233
|
+
const candidateDir = path21.dirname(candidate);
|
|
6234
|
+
const candidateDirOnPath = env.pathDirs.some((dir) => path21.resolve(dir) === candidateDir);
|
|
6093
6235
|
if (candidateDirOnPath) {
|
|
6094
6236
|
return candidate;
|
|
6095
6237
|
}
|
|
6096
|
-
const viaPath = searchPathForExecutable(env.pathDirs,
|
|
6238
|
+
const viaPath = searchPathForExecutable(env.pathDirs, path21.basename(candidate), env.findExecutableInDir);
|
|
6097
6239
|
return viaPath ?? candidate;
|
|
6098
6240
|
}
|
|
6099
6241
|
function realOwnExecutablePath() {
|
|
@@ -6101,21 +6243,21 @@ function realOwnExecutablePath() {
|
|
|
6101
6243
|
argv1: process.argv[1],
|
|
6102
6244
|
execPath: process.execPath,
|
|
6103
6245
|
cwd: process.cwd(),
|
|
6104
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
6246
|
+
pathDirs: (process.env.PATH ?? "").split(path21.delimiter).filter((dir) => dir !== ""),
|
|
6105
6247
|
findExecutableInDir
|
|
6106
6248
|
});
|
|
6107
6249
|
}
|
|
6108
6250
|
function realResolveClaudeBinary(ownInstallDirs) {
|
|
6109
6251
|
return () => discoverClaudeBinary({
|
|
6110
6252
|
listVersionsDir,
|
|
6111
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
6253
|
+
pathDirs: (process.env.PATH ?? "").split(path21.delimiter).filter((dir) => dir !== ""),
|
|
6112
6254
|
findExecutableInDir,
|
|
6113
6255
|
ownInstallDirs: [...ownInstallDirs]
|
|
6114
6256
|
});
|
|
6115
6257
|
}
|
|
6116
6258
|
|
|
6117
6259
|
// src/checkReport.ts
|
|
6118
|
-
import
|
|
6260
|
+
import path22 from "node:path";
|
|
6119
6261
|
import { z as z10 } from "zod";
|
|
6120
6262
|
|
|
6121
6263
|
// src/cli/bool.ts
|
|
@@ -6483,10 +6625,10 @@ function collectCheckReport(params) {
|
|
|
6483
6625
|
}).input;
|
|
6484
6626
|
const providerName = cascadeProviderName(cascade);
|
|
6485
6627
|
const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
|
|
6486
|
-
const farmRoot = identityDecision.name === void 0 ? void 0 :
|
|
6628
|
+
const farmRoot = identityDecision.name === void 0 ? void 0 : path22.join(paths.identitiesDir, identityDecision.name);
|
|
6487
6629
|
const settingsFiles = {
|
|
6488
|
-
"settings.json": realFsPort.readFileUtf8(
|
|
6489
|
-
"settings.local.json": realFsPort.readFileUtf8(
|
|
6630
|
+
"settings.json": realFsPort.readFileUtf8(path22.join(claudeHome, "settings.json")),
|
|
6631
|
+
"settings.local.json": realFsPort.readFileUtf8(path22.join(claudeHome, "settings.local.json"))
|
|
6490
6632
|
};
|
|
6491
6633
|
const report = runCheck({
|
|
6492
6634
|
cwd,
|
|
@@ -6516,7 +6658,7 @@ function collectCheckReport(params) {
|
|
|
6516
6658
|
|
|
6517
6659
|
// src/claudeShim.ts
|
|
6518
6660
|
import fs8 from "node:fs";
|
|
6519
|
-
import
|
|
6661
|
+
import path23 from "node:path";
|
|
6520
6662
|
import { z as z11 } from "zod";
|
|
6521
6663
|
var ClaudeShimStateSchema = z11.strictObject({
|
|
6522
6664
|
targetPath: z11.string().min(1),
|
|
@@ -6527,29 +6669,29 @@ function commandFilename(ownExecutablePath, commandName) {
|
|
|
6527
6669
|
return ownExecutablePath.toLowerCase().endsWith(".exe") ? `${commandName}.exe` : commandName;
|
|
6528
6670
|
}
|
|
6529
6671
|
function resolveOwnInstallDirs(paths, ownExecutablePath) {
|
|
6530
|
-
const dirs = [
|
|
6672
|
+
const dirs = [path23.dirname(ownExecutablePath)];
|
|
6531
6673
|
const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
6532
6674
|
if (state !== void 0) {
|
|
6533
|
-
dirs.push(
|
|
6675
|
+
dirs.push(path23.dirname(state.targetPath));
|
|
6534
6676
|
}
|
|
6535
6677
|
return dirs;
|
|
6536
6678
|
}
|
|
6537
6679
|
var nodeLinkFs = { link: fs8.linkSync, copyFile: fs8.copyFileSync, chmod: fs8.chmodSync };
|
|
6538
6680
|
function findPathShadow(params) {
|
|
6539
|
-
const resolvedTargetDir =
|
|
6681
|
+
const resolvedTargetDir = path23.resolve(params.targetDir);
|
|
6540
6682
|
for (const dir of params.pathDirs) {
|
|
6541
6683
|
const found = params.findExecutableInDir(dir, params.targetFilename);
|
|
6542
6684
|
if (found === void 0) {
|
|
6543
6685
|
continue;
|
|
6544
6686
|
}
|
|
6545
|
-
return
|
|
6687
|
+
return path23.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
|
|
6546
6688
|
}
|
|
6547
|
-
return params.pathDirs.some((dir) =>
|
|
6689
|
+
return params.pathDirs.some((dir) => path23.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
|
|
6548
6690
|
}
|
|
6549
6691
|
|
|
6550
6692
|
// src/doctorReport.ts
|
|
6551
6693
|
import fs9 from "node:fs";
|
|
6552
|
-
import
|
|
6694
|
+
import path24 from "node:path";
|
|
6553
6695
|
function refinePathShadow(status, ownExecutablePath, realpath) {
|
|
6554
6696
|
if (status.status !== "shadowed") {
|
|
6555
6697
|
return status;
|
|
@@ -6573,7 +6715,7 @@ function validateJson(schema, input) {
|
|
|
6573
6715
|
return { ok: true, data: result.data };
|
|
6574
6716
|
}
|
|
6575
6717
|
function pushPathResolution(push, resolution) {
|
|
6576
|
-
const ownDir =
|
|
6718
|
+
const ownDir = path24.dirname(resolution.ownExecutablePath);
|
|
6577
6719
|
switch (resolution.agentShim.status) {
|
|
6578
6720
|
case "ok":
|
|
6579
6721
|
push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
|
|
@@ -6641,14 +6783,14 @@ function pushProvider(push, entry) {
|
|
|
6641
6783
|
}
|
|
6642
6784
|
function pushLegacyName(push, params) {
|
|
6643
6785
|
const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
|
|
6644
|
-
if (legacyVariables.length === 0 &&
|
|
6786
|
+
if (legacyVariables.length === 0 && path24.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
|
|
6645
6787
|
push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
|
|
6646
6788
|
return;
|
|
6647
6789
|
}
|
|
6648
6790
|
for (const name of legacyVariables) {
|
|
6649
6791
|
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);
|
|
6650
6792
|
}
|
|
6651
|
-
if (
|
|
6793
|
+
if (path24.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
|
|
6652
6794
|
push(
|
|
6653
6795
|
"legacy-name",
|
|
6654
6796
|
"warn",
|
|
@@ -6838,7 +6980,7 @@ function runDoctor(params) {
|
|
|
6838
6980
|
"warn",
|
|
6839
6981
|
`Headroom state names supervisor pid ${String(state.supervisorPid)}, which is not running; the next launch through headroom will start a replacement.`
|
|
6840
6982
|
);
|
|
6841
|
-
} else if (state.headroomPid === void 0 || state.
|
|
6983
|
+
} else if (state.headroomPid === void 0 || state.socketPath === void 0) {
|
|
6842
6984
|
push(
|
|
6843
6985
|
"headroom",
|
|
6844
6986
|
"warn",
|
|
@@ -6854,7 +6996,7 @@ function runDoctor(params) {
|
|
|
6854
6996
|
push(
|
|
6855
6997
|
"headroom",
|
|
6856
6998
|
"pass",
|
|
6857
|
-
`Headroom daemon is up on
|
|
6999
|
+
`Headroom daemon is up on unix socket ${state.socketPath} (supervisor ${String(state.supervisorPid)}, daemon ${String(state.headroomPid)}).`
|
|
6858
7000
|
);
|
|
6859
7001
|
}
|
|
6860
7002
|
if (state.lastError !== void 0 && supervisorAlive) {
|
|
@@ -6956,18 +7098,18 @@ function collectDoctorReport(params) {
|
|
|
6956
7098
|
const { paths } = params;
|
|
6957
7099
|
const identityNames = fs9.existsSync(paths.identitiesDir) ? fs9.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
|
|
6958
7100
|
const identities = identityNames.map((name) => {
|
|
6959
|
-
const farmRoot =
|
|
6960
|
-
const identityPath =
|
|
7101
|
+
const farmRoot = path24.join(paths.identitiesDir, name);
|
|
7102
|
+
const identityPath = path24.join(farmRoot, "identity.json");
|
|
6961
7103
|
return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
|
|
6962
7104
|
});
|
|
6963
7105
|
const profileNames = fs9.existsSync(paths.configProfilesDir) ? fs9.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
6964
7106
|
const configProfiles = profileNames.map((name) => {
|
|
6965
|
-
const profilePath =
|
|
7107
|
+
const profilePath = path24.join(paths.configProfilesDir, `${name}.json`);
|
|
6966
7108
|
return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
|
|
6967
7109
|
});
|
|
6968
7110
|
const providerNames = fs9.existsSync(paths.providersDir) ? fs9.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
6969
7111
|
const providers = providerNames.map((name) => {
|
|
6970
|
-
const providerPath =
|
|
7112
|
+
const providerPath = path24.join(paths.providersDir, `${name}.json`);
|
|
6971
7113
|
return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
|
|
6972
7114
|
});
|
|
6973
7115
|
const ownExecutablePath = realOwnExecutablePath();
|
|
@@ -6979,12 +7121,12 @@ function collectDoctorReport(params) {
|
|
|
6979
7121
|
binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
|
|
6980
7122
|
}
|
|
6981
7123
|
const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
6982
|
-
const pathDirs = (params.env.PATH ?? "").split(
|
|
7124
|
+
const pathDirs = (params.env.PATH ?? "").split(path24.delimiter).filter((dir) => dir !== "");
|
|
6983
7125
|
const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
|
|
6984
7126
|
findPathShadow({
|
|
6985
7127
|
pathDirs,
|
|
6986
|
-
targetDir:
|
|
6987
|
-
targetFilename:
|
|
7128
|
+
targetDir: path24.dirname(shimState.targetPath),
|
|
7129
|
+
targetFilename: path24.basename(shimState.targetPath),
|
|
6988
7130
|
findExecutableInDir
|
|
6989
7131
|
}),
|
|
6990
7132
|
shimState.targetPath,
|
|
@@ -7007,7 +7149,7 @@ function collectDoctorReport(params) {
|
|
|
7007
7149
|
agentShim: refinePathShadow(
|
|
7008
7150
|
findPathShadow({
|
|
7009
7151
|
pathDirs,
|
|
7010
|
-
targetDir:
|
|
7152
|
+
targetDir: path24.dirname(ownExecutablePath),
|
|
7011
7153
|
targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
|
|
7012
7154
|
findExecutableInDir
|
|
7013
7155
|
}),
|
|
@@ -7028,7 +7170,7 @@ function collectDoctorReport(params) {
|
|
|
7028
7170
|
|
|
7029
7171
|
// src/launcher.ts
|
|
7030
7172
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
7031
|
-
import
|
|
7173
|
+
import path26 from "node:path";
|
|
7032
7174
|
|
|
7033
7175
|
// src/launcher/argv.ts
|
|
7034
7176
|
var ConflictingIdentityError = class extends UsageError {
|
|
@@ -7280,7 +7422,7 @@ function buildCliOverride(params) {
|
|
|
7280
7422
|
}
|
|
7281
7423
|
|
|
7282
7424
|
// src/launcher/flags.ts
|
|
7283
|
-
import
|
|
7425
|
+
import path25 from "node:path";
|
|
7284
7426
|
|
|
7285
7427
|
// src/headroom/headers.ts
|
|
7286
7428
|
function mergeAnthropicCustomHeaders(existing, additions) {
|
|
@@ -7350,7 +7492,7 @@ function buildEnv(params) {
|
|
|
7350
7492
|
const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
7351
7493
|
let providerCustomHeaders;
|
|
7352
7494
|
if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
|
|
7353
|
-
env.CLAUDE_CONFIG_DIR =
|
|
7495
|
+
env.CLAUDE_CONFIG_DIR = path25.join(params.identitiesDir, params.resolvedIdentityName);
|
|
7354
7496
|
}
|
|
7355
7497
|
if (params.provider !== void 0) {
|
|
7356
7498
|
const providerEnv = params.provider.definition.env ?? {};
|
|
@@ -7371,9 +7513,6 @@ function buildEnv(params) {
|
|
|
7371
7513
|
env[variable] = value;
|
|
7372
7514
|
}
|
|
7373
7515
|
}
|
|
7374
|
-
if (params.headroom !== void 0) {
|
|
7375
|
-
env.HEADROOM_PROXY_URL = `http://127.0.0.1:${String(params.headroom.port)}`;
|
|
7376
|
-
}
|
|
7377
7516
|
if (params.frontdoor !== void 0) {
|
|
7378
7517
|
env.ANTHROPIC_CUSTOM_HEADERS = mergeAnthropicCustomHeaders(
|
|
7379
7518
|
[
|
|
@@ -7514,7 +7653,7 @@ function prepareLaunch(params) {
|
|
|
7514
7653
|
identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
|
|
7515
7654
|
globalDefaultConfigProfile: params.globalDefaultConfigProfile
|
|
7516
7655
|
});
|
|
7517
|
-
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(
|
|
7656
|
+
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path26.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
|
|
7518
7657
|
log.error(
|
|
7519
7658
|
`agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
|
|
7520
7659
|
);
|
|
@@ -7650,7 +7789,7 @@ function prepareLaunch(params) {
|
|
|
7650
7789
|
if (resolvedFlags.headroom && headroomPort !== void 0) {
|
|
7651
7790
|
headroom = headroomPort.ensure();
|
|
7652
7791
|
const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
|
|
7653
|
-
log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor?.port ?? 0)} with headroom on
|
|
7792
|
+
log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor?.port ?? 0)} with headroom on unix socket ${headroom.socketPath} (${via}, project ${headroom.projectId})`);
|
|
7654
7793
|
} else if (resolvedFlags.headroom) {
|
|
7655
7794
|
log.error("agent-shim: headroom routing was requested but this launcher has no headroom port wired; refusing to launch without it.");
|
|
7656
7795
|
proc.exit(1);
|
|
@@ -7690,7 +7829,7 @@ import { randomUUID as randomUUID5 } from "node:crypto";
|
|
|
7690
7829
|
// src/realCredentialCache.ts
|
|
7691
7830
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
7692
7831
|
import fs10 from "node:fs";
|
|
7693
|
-
import
|
|
7832
|
+
import path27 from "node:path";
|
|
7694
7833
|
var KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
|
|
7695
7834
|
var CACHE_DIR_MODE = 448;
|
|
7696
7835
|
var CACHE_FILE_MODE = 384;
|
|
@@ -7717,8 +7856,8 @@ function security(args, stdin) {
|
|
|
7717
7856
|
return { status: result.status, stdout: result.stdout };
|
|
7718
7857
|
}
|
|
7719
7858
|
function createRealCredentialCache(root) {
|
|
7720
|
-
const dir =
|
|
7721
|
-
const filePath = (owner) =>
|
|
7859
|
+
const dir = path27.join(root, "credential-cache");
|
|
7860
|
+
const filePath = (owner) => path27.join(dir, cacheFileNameFor(owner));
|
|
7722
7861
|
return {
|
|
7723
7862
|
read(store, owner) {
|
|
7724
7863
|
if (store === "file") {
|
|
@@ -7834,11 +7973,11 @@ function probeFrontDoorSync(port, caPem) {
|
|
|
7834
7973
|
|
|
7835
7974
|
// src/frontdoor/trust.ts
|
|
7836
7975
|
import { createHash as createHash5 } from "node:crypto";
|
|
7837
|
-
import
|
|
7976
|
+
import path28 from "node:path";
|
|
7838
7977
|
var BUNDLE_NAME_HEX_DIGITS = 16;
|
|
7839
7978
|
function resolveTrustBundle(params) {
|
|
7840
7979
|
const { caCertFile, bundlesDir, inherited, fs: fs12 } = params;
|
|
7841
|
-
if (inherited === void 0 || inherited === "" ||
|
|
7980
|
+
if (inherited === void 0 || inherited === "" || path28.resolve(inherited) === path28.resolve(caCertFile)) {
|
|
7842
7981
|
return { path: caCertFile };
|
|
7843
7982
|
}
|
|
7844
7983
|
const caPem = fs12.readFileUtf8(caCertFile);
|
|
@@ -7856,7 +7995,7 @@ function resolveTrustBundle(params) {
|
|
|
7856
7995
|
}
|
|
7857
7996
|
const combined = `${inheritedPem.trimEnd()}
|
|
7858
7997
|
${caPem}`;
|
|
7859
|
-
const bundle =
|
|
7998
|
+
const bundle = path28.join(bundlesDir, `${createHash5("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
|
|
7860
7999
|
if (!fs12.exists(bundle)) {
|
|
7861
8000
|
fs12.mkdirp(bundlesDir);
|
|
7862
8001
|
fs12.writeFileAtomic(bundle, combined);
|