agent-shim 8.5.2 → 8.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -35184,7 +35184,7 @@ function debugEnabled(env) {
35184
35184
 
35185
35185
  // src/claudeShim.ts
35186
35186
  var import_node_fs4 = __toESM(require("node:fs"), 1);
35187
- var import_node_path7 = __toESM(require("node:path"), 1);
35187
+ var import_node_path9 = __toESM(require("node:path"), 1);
35188
35188
 
35189
35189
  // node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/external.js
35190
35190
  var external_exports = {};
@@ -55050,10 +55050,10 @@ function applyPatch(filePath, schema, patch, options = {}) {
55050
55050
 
55051
55051
  // src/realPorts.ts
55052
55052
  var import_node_child_process2 = require("node:child_process");
55053
- var import_node_crypto3 = require("node:crypto");
55053
+ var import_node_crypto4 = require("node:crypto");
55054
55054
  var import_node_fs3 = __toESM(require("node:fs"), 1);
55055
55055
  var import_node_os2 = __toESM(require("node:os"), 1);
55056
- var import_node_path6 = __toESM(require("node:path"), 1);
55056
+ var import_node_path8 = __toESM(require("node:path"), 1);
55057
55057
  var import_node_sea = require("node:sea");
55058
55058
 
55059
55059
  // src/versionDiscovery.ts
@@ -55505,13 +55505,24 @@ function ensureHeadroom(params) {
55505
55505
  const { paths, ports } = params;
55506
55506
  const deadline = ports.now() + HEADROOM_START_TIMEOUT_MS;
55507
55507
  let spawnedSupervisor = false;
55508
+ let awaitingAllowlist = false;
55508
55509
  for (; ; ) {
55509
55510
  const state = readHeadroomState(ports.fs, paths.headroomStateFile);
55510
55511
  if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
55511
55512
  const daemonUp = state.socketPath !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
55512
55513
  if (daemonUp && state.socketPath !== void 0) {
55513
- writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
55514
- return { socketPath: state.socketPath };
55514
+ const required2 = params.requiredAllowlistHash?.();
55515
+ if (required2 === void 0 || state.allowlistHash === required2) {
55516
+ writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
55517
+ return { socketPath: state.socketPath };
55518
+ }
55519
+ const holders = sessionsForSupervisor(ports.fs, paths.headroomSessionsDir, state.supervisorPid).filter((session) => ports.isRunning(session.pid));
55520
+ if (holders.length > 0) {
55521
+ throw new HeadroomStartError(
55522
+ `agent-shim: the running headroom daemon was started before this launch's front door address and would refuse every request this launch sends through it. It restarts once the launches using it end (pid ${holders.map((session) => String(session.pid)).join(", ")}); end them and launch again, or launch with --no-headroom.`
55523
+ );
55524
+ }
55525
+ awaitingAllowlist = true;
55515
55526
  }
55516
55527
  if (state.lastError !== void 0) {
55517
55528
  throw new HeadroomStartError(
@@ -55539,13 +55550,535 @@ function ensureHeadroom(params) {
55539
55550
  if (ports.now() >= deadline) {
55540
55551
  const lastError = state?.lastError;
55541
55552
  throw new HeadroomStartError(
55542
- `agent-shim: the headroom daemon did not become ready within ${String(HEADROOM_START_TIMEOUT_MS)}ms` + (lastError === void 0 ? "" : ` (last error: ${lastError})`) + `. Daemon log: ${paths.headroomLogPath}`
55553
+ `agent-shim: the headroom daemon did not become ready within ${String(HEADROOM_START_TIMEOUT_MS)}ms` + (lastError === void 0 ? "" : ` (last error: ${lastError})`) + (awaitingAllowlist ? " (the running daemon's allowlist does not admit this launch's front door, and it did not restart)" : "") + `. Daemon log: ${paths.headroomLogPath}`
55543
55554
  );
55544
55555
  }
55545
55556
  ports.sleep(HEADROOM_LAUNCHER_POLL_MS);
55546
55557
  }
55547
55558
  }
55548
55559
 
55560
+ // src/frontdoor/state.ts
55561
+ var import_node_path6 = __toESM(require("node:path"), 1);
55562
+ var FRONT_DOOR_PROTOCOL = 2;
55563
+ var FrontDoorSessionSchema = external_exports.strictObject({ pid: external_exports.number().int().positive(), startedAt: external_exports.number(), token: external_exports.string().min(1) });
55564
+ var FrontDoorStateSchema = external_exports.strictObject({
55565
+ /**
55566
+ * The launcher-to-door wire protocol this supervisor speaks, written once it is serving; absent in state written by a release that predates the field, which `ensureFrontDoor` reads as protocol 0. A launcher replaces a door whose protocol is lower than its own (see `FRONT_DOOR_PROTOCOL`).
55567
+ */
55568
+ protocol: external_exports.number().int().nonnegative().optional(),
55569
+ /** The supervisor process serving the front door. Alive means both listeners are up in that process. */
55570
+ supervisorPid: external_exports.number().int().positive().optional(),
55571
+ /** The loopback port the HTTPS provider listener serves on. Absent until the listener has bound and answered its health probe, so "port is set" is itself the ready signal a launcher polls for. */
55572
+ port: external_exports.number().int().positive().optional(),
55573
+ /**
55574
+ * The sticky port preference for the provider listener: kept across crashes, restarts and idle shutdowns so every provider session, whose base URL was frozen at launch, keeps finding the front door at the same address.
55575
+ */
55576
+ lastPort: external_exports.number().int().positive().optional(),
55577
+ /**
55578
+ * The loopback port the CONNECT surface listens on. Absent whenever no supervisor is serving it, so "connectPort is set" is the ready signal an OAuth launch polls for alongside `port`.
55579
+ */
55580
+ connectPort: external_exports.number().int().positive().optional(),
55581
+ /**
55582
+ * The sticky port preference for the CONNECT surface, the exact analogue of `lastPort` for the second listener: it survives every shutdown, because every OAuth session's environment was frozen at launch with HTTPS_PROXY pointing at this address and a restart that moves strands them.
55583
+ */
55584
+ lastConnectPort: external_exports.number().int().positive().optional(),
55585
+ /**
55586
+ * The loopback port the direct listener serves on: the listener a headroom hop tells the daemon to forward routed traffic back to. Sticky like the others, because headroom's allowlist admits its exact origin and an ephemeral port would invalidate the allowlist on every restart.
55587
+ */
55588
+ directPort: external_exports.number().int().positive().optional(),
55589
+ /** The sticky port preference for the direct listener, for the reason `directPort` gives. */
55590
+ lastDirectPort: external_exports.number().int().positive().optional(),
55591
+ /** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
55592
+ lastError: external_exports.string().optional()
55593
+ });
55594
+ function readFrontDoorState(fs19, stateFile) {
55595
+ let raw;
55596
+ try {
55597
+ raw = fs19.readFileUtf8(stateFile);
55598
+ } catch {
55599
+ return void 0;
55600
+ }
55601
+ if (raw === void 0 || raw.trim() === "") {
55602
+ return void 0;
55603
+ }
55604
+ try {
55605
+ const parsed = FrontDoorStateSchema.safeParse(JSON.parse(raw));
55606
+ return parsed.success ? parsed.data : void 0;
55607
+ } catch {
55608
+ return void 0;
55609
+ }
55610
+ }
55611
+ function writeFrontDoorState(fs19, stateFile, state) {
55612
+ fs19.mkdirp(import_node_path6.default.dirname(stateFile));
55613
+ fs19.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
55614
+ `);
55615
+ }
55616
+ function frontDoorOrigin(state) {
55617
+ const port = state?.directPort ?? state?.lastDirectPort;
55618
+ return port === void 0 ? void 0 : `http://127.0.0.1:${String(port)}`;
55619
+ }
55620
+ function writeFrontDoorSession(fs19, sessionsDir, session) {
55621
+ fs19.mkdirPrivate(sessionsDir);
55622
+ fs19.writeFilePrivate(import_node_path6.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
55623
+ `);
55624
+ }
55625
+ function listFrontDoorSessions(fs19, sessionsDir) {
55626
+ const sessions = [];
55627
+ for (const name of fs19.readdir(sessionsDir)) {
55628
+ if (!name.endsWith(".json")) {
55629
+ continue;
55630
+ }
55631
+ try {
55632
+ const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs19.readFileUtf8(import_node_path6.default.join(sessionsDir, name)) ?? ""));
55633
+ if (parsed.success) {
55634
+ sessions.push({ pid: parsed.data.pid, startedAt: parsed.data.startedAt });
55635
+ }
55636
+ } catch {
55637
+ continue;
55638
+ }
55639
+ }
55640
+ return sessions.sort((a2, b) => a2.pid - b.pid);
55641
+ }
55642
+ function removeFrontDoorSession(fs19, sessionsDir, pid) {
55643
+ fs19.removeRecursive(import_node_path6.default.join(sessionsDir, `${String(pid)}.json`));
55644
+ }
55645
+ function pruneDeadFrontDoorSessions(fs19, sessionsDir, isRunning) {
55646
+ const removed = [];
55647
+ for (const session of listFrontDoorSessions(fs19, sessionsDir)) {
55648
+ if (!isRunning(session.pid)) {
55649
+ removeFrontDoorSession(fs19, sessionsDir, session.pid);
55650
+ removed.push(session.pid);
55651
+ }
55652
+ }
55653
+ return removed;
55654
+ }
55655
+ function liveSessionTokens(fs19, sessionsDir) {
55656
+ const tokens = /* @__PURE__ */ new Set();
55657
+ for (const name of fs19.readdir(sessionsDir)) {
55658
+ if (!name.endsWith(".json")) {
55659
+ continue;
55660
+ }
55661
+ try {
55662
+ const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs19.readFileUtf8(import_node_path6.default.join(sessionsDir, name)) ?? ""));
55663
+ if (parsed.success) {
55664
+ tokens.add(parsed.data.token);
55665
+ }
55666
+ } catch {
55667
+ continue;
55668
+ }
55669
+ }
55670
+ return tokens;
55671
+ }
55672
+
55673
+ // src/headroom/settings.ts
55674
+ var import_node_crypto3 = require("node:crypto");
55675
+ function settingsOf(config2) {
55676
+ return {
55677
+ ...config2.mode === void 0 ? {} : { mode: config2.mode },
55678
+ ...config2.targetRatio === void 0 ? {} : { targetRatio: config2.targetRatio },
55679
+ ...config2.ccr === void 0 ? {} : { ccr: config2.ccr },
55680
+ ...config2.rolloutChannel === void 0 ? {} : { rolloutChannel: config2.rolloutChannel },
55681
+ ...config2.interceptToolResults === void 0 ? {} : { interceptToolResults: config2.interceptToolResults },
55682
+ ...config2.readMaturation === void 0 ? {} : { readMaturation: config2.readMaturation }
55683
+ };
55684
+ }
55685
+ function settingsArgs(settings2) {
55686
+ return [
55687
+ ...settings2.mode === void 0 ? [] : ["--mode", settings2.mode],
55688
+ ...settings2.targetRatio === void 0 ? [] : ["--target-ratio", String(settings2.targetRatio)],
55689
+ ...settings2.ccr === "lossless" ? ["--lossless"] : [],
55690
+ ...settings2.ccr === "none" ? ["--no-ccr"] : [],
55691
+ ...settings2.interceptToolResults === true ? ["--intercept-tool-results"] : [],
55692
+ ...settings2.readMaturation === true ? ["--read-maturation"] : []
55693
+ ];
55694
+ }
55695
+ function settingsEnv(settings2) {
55696
+ return settings2.rolloutChannel === void 0 ? {} : { HEADROOM_ROLLOUT_CHANNEL: settings2.rolloutChannel };
55697
+ }
55698
+ function hashSettings(settings2) {
55699
+ return (0, import_node_crypto3.createHash)("sha256").update(JSON.stringify([...settingsArgs(settings2), JSON.stringify(settingsEnv(settings2))])).digest("hex");
55700
+ }
55701
+
55702
+ // src/headroom/socket.ts
55703
+ var import_node_path7 = __toESM(require("node:path"), 1);
55704
+ var GROUP_OR_OTHER_BITS = 63;
55705
+ var OCTAL_RADIX = 8;
55706
+ var MODE_DIGITS = 4;
55707
+ var HEADROOM_SOCKET_SUFFIX = ".sock";
55708
+ var HEADROOM_SOCKET_NAME = /^(\d+)\.sock$/;
55709
+ var UNIX_SOCKET_PATH_MAX_BYTES = 103;
55710
+ var PLATFORMS_WITHOUT_UNIX_SOCKETS = ["win32"];
55711
+ function headroomSocketPath(paths, supervisorPid) {
55712
+ return import_node_path7.default.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
55713
+ }
55714
+ function platformRefusal(platform) {
55715
+ 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;
55716
+ }
55717
+ function ownerOnlyRefusal(label, target, stat, expected, uid) {
55718
+ if (stat === void 0) {
55719
+ return `the headroom ${label} ${target} does not exist`;
55720
+ }
55721
+ if (stat.kind === "symlink") {
55722
+ return `the headroom ${label} ${target} is a symlink; it must be the real ${expected === "dir" ? "directory" : "socket"}`;
55723
+ }
55724
+ if (stat.kind !== expected) {
55725
+ return `the headroom ${label} ${target} is not a ${expected === "dir" ? "directory" : "socket"}`;
55726
+ }
55727
+ if (stat.uid !== uid) {
55728
+ return `the headroom ${label} ${target} is owned by uid ${String(stat.uid)}, not by this user (uid ${String(uid)})`;
55729
+ }
55730
+ if ((stat.mode & GROUP_OR_OTHER_BITS) !== 0) {
55731
+ 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`;
55732
+ }
55733
+ return void 0;
55734
+ }
55735
+ function verifyHeadroomSocket(socketPath, ports) {
55736
+ const unsupported = platformRefusal(ports.platform);
55737
+ if (unsupported !== void 0) {
55738
+ return { refused: unsupported };
55739
+ }
55740
+ const uid = ports.currentUid();
55741
+ const directory = import_node_path7.default.dirname(socketPath);
55742
+ const refusal = ownerOnlyRefusal("socket directory", directory, ports.lstat(directory), "dir", uid) ?? ownerOnlyRefusal("socket", socketPath, ports.lstat(socketPath), "socket", uid);
55743
+ return refusal === void 0 ? { socketPath } : { refused: refusal };
55744
+ }
55745
+ function prepareHeadroomSocket(fs19, ports, paths, supervisorPid) {
55746
+ const unsupported = platformRefusal(ports.platform);
55747
+ if (unsupported !== void 0) {
55748
+ return { refused: unsupported };
55749
+ }
55750
+ const socketPath = headroomSocketPath(paths, supervisorPid);
55751
+ const length = Buffer.byteLength(socketPath, "utf8");
55752
+ if (length > UNIX_SOCKET_PATH_MAX_BYTES) {
55753
+ return {
55754
+ 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`
55755
+ };
55756
+ }
55757
+ if (ports.lstat(paths.headroomSocketDir)?.kind === "symlink") {
55758
+ return { refused: `the headroom socket directory ${paths.headroomSocketDir} is a symlink; it must be the real directory` };
55759
+ }
55760
+ fs19.mkdirPrivate(paths.headroomSocketDir);
55761
+ const refusal = ownerOnlyRefusal("socket directory", paths.headroomSocketDir, ports.lstat(paths.headroomSocketDir), "dir", ports.currentUid());
55762
+ return refusal === void 0 ? { socketPath } : { refused: refusal };
55763
+ }
55764
+ function pruneStaleHeadroomSockets(fs19, paths, isRunning) {
55765
+ const removed = [];
55766
+ for (const name of fs19.readdir(paths.headroomSocketDir)) {
55767
+ const pid = HEADROOM_SOCKET_NAME.exec(name)?.[1];
55768
+ if (pid === void 0 || isRunning(Number.parseInt(pid, 10))) {
55769
+ continue;
55770
+ }
55771
+ fs19.removeRecursive(import_node_path7.default.join(paths.headroomSocketDir, name));
55772
+ removed.push(name);
55773
+ }
55774
+ return removed;
55775
+ }
55776
+
55777
+ // src/headroom/source.ts
55778
+ var GIT_SPEC_RE = /git\+[^@\s]+(?:@([^\s#]+))?/;
55779
+ var COMMIT_SHA_RE = /^[0-9a-f]{40}$/i;
55780
+ var DirectUrlSchema = external_exports.object({ vcs_info: external_exports.object({ commit_id: external_exports.string() }) });
55781
+ function isMovingGitSource(spec) {
55782
+ const match = GIT_SPEC_RE.exec(spec);
55783
+ if (match === null) {
55784
+ return false;
55785
+ }
55786
+ const ref = match[1];
55787
+ return ref === void 0 || !COMMIT_SHA_RE.test(ref);
55788
+ }
55789
+ function pinnedGitCommit(spec) {
55790
+ const ref = GIT_SPEC_RE.exec(spec)?.[1];
55791
+ return ref !== void 0 && COMMIT_SHA_RE.test(ref) ? ref.toLowerCase() : void 0;
55792
+ }
55793
+ function parseInstalledCommit(directUrlJson) {
55794
+ try {
55795
+ const parsed = DirectUrlSchema.safeParse(JSON.parse(directUrlJson));
55796
+ return parsed.success ? parsed.data.vcs_info.commit_id.toLowerCase() : void 0;
55797
+ } catch {
55798
+ return void 0;
55799
+ }
55800
+ }
55801
+
55802
+ // src/headroom/supervisor.ts
55803
+ function resolveSupervisorConfig(configured) {
55804
+ return {
55805
+ source: configured.source ?? HEADROOM_DEFAULT_SOURCE,
55806
+ idleShutdownMinutes: configured.idleShutdownMinutes ?? HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES,
55807
+ settings: settingsOf(configured)
55808
+ };
55809
+ }
55810
+ var HEADROOM_BACKOFF_BASE_MS = 500;
55811
+ var HEADROOM_BACKOFF_CAP_MS = 3e4;
55812
+ var HEADROOM_START_RETRY_BUDGET = 5;
55813
+ var HEADROOM_READY_TIMEOUT_MS = 15e3;
55814
+ var HEADROOM_POLL_MS = 1e3;
55815
+ var MS_PER_MINUTE = 6e4;
55816
+ var STOP_POLL_MS = 100;
55817
+ var TERM_GRACE_MS = 1500;
55818
+ var KILL_GRACE_MS = 1500;
55819
+ function stopSupervisedProcess(pid, primitives) {
55820
+ const send = (signal) => {
55821
+ try {
55822
+ primitives.signal(pid, signal);
55823
+ } catch {
55824
+ }
55825
+ };
55826
+ send("SIGTERM");
55827
+ if (awaitExit(pid, primitives, TERM_GRACE_MS)) {
55828
+ return "exited-on-term";
55829
+ }
55830
+ send("SIGKILL");
55831
+ if (awaitExit(pid, primitives, KILL_GRACE_MS)) {
55832
+ return "killed";
55833
+ }
55834
+ return "still-running";
55835
+ }
55836
+ function awaitExit(pid, primitives, budgetMs) {
55837
+ const deadline = primitives.now() + budgetMs;
55838
+ while (primitives.isRunning(pid)) {
55839
+ if (primitives.now() >= deadline) {
55840
+ return false;
55841
+ }
55842
+ primitives.waitMs(STOP_POLL_MS);
55843
+ }
55844
+ return true;
55845
+ }
55846
+ function backoffForAttempt(attempt) {
55847
+ return Math.min(HEADROOM_BACKOFF_CAP_MS, HEADROOM_BACKOFF_BASE_MS * 2 ** (attempt - 1));
55848
+ }
55849
+ function versionSatisfies(version2, source) {
55850
+ if (version2 === void 0) {
55851
+ return false;
55852
+ }
55853
+ const specifier = /==|>=|<=|!=|>|<|~=/.exec(source);
55854
+ if (specifier === null) {
55855
+ return true;
55856
+ }
55857
+ const installed = parseVersion(version2);
55858
+ const wanted = parseVersion(source.slice(specifier.index + specifier[0].length));
55859
+ if (installed === void 0 || wanted === void 0) {
55860
+ return true;
55861
+ }
55862
+ const cmp = compareVersions2(installed, wanted);
55863
+ switch (specifier[0]) {
55864
+ case "==":
55865
+ return cmp === 0;
55866
+ case "!=":
55867
+ return cmp !== 0;
55868
+ case ">=":
55869
+ return cmp >= 0;
55870
+ case "<=":
55871
+ return cmp <= 0;
55872
+ case ">":
55873
+ return cmp > 0;
55874
+ case "<":
55875
+ return cmp < 0;
55876
+ case "~=":
55877
+ return compareVersions2(installed.slice(0, Math.max(0, wanted.length - 1)), wanted.slice(0, Math.max(0, wanted.length - 1))) === 0 && cmp >= 0;
55878
+ default:
55879
+ return true;
55880
+ }
55881
+ }
55882
+ function parseVersion(input2) {
55883
+ const match = /(\d+)(\.\d+)*/.exec(input2);
55884
+ if (match === null) {
55885
+ return void 0;
55886
+ }
55887
+ return match[0].split(".").map((part) => Number.parseInt(part, 10));
55888
+ }
55889
+ function compareVersions2(a2, b) {
55890
+ for (let index = 0; index < Math.max(a2.length, b.length); index += 1) {
55891
+ const left = a2[index] ?? 0;
55892
+ const right = b[index] ?? 0;
55893
+ if (left !== right) {
55894
+ return left - right;
55895
+ }
55896
+ }
55897
+ return 0;
55898
+ }
55899
+ var HEADROOM_SUPERVISOR_STILL_RUNNING = -1;
55900
+ async function runSupervisor(initialConfig, ports, options = {}) {
55901
+ const { fs: fs19, paths } = ports;
55902
+ let config2 = initialConfig;
55903
+ const previousState = readHeadroomState(fs19, paths.headroomStateFile);
55904
+ if (previousState?.supervisorPid !== void 0 && previousState.supervisorPid !== ports.ownPid && ports.isRunning(previousState.supervisorPid)) {
55905
+ ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: supervisor ${String(previousState.supervisorPid)} already owns the daemon; exiting`);
55906
+ return 0;
55907
+ }
55908
+ let installedSource = previousState?.installedSource;
55909
+ const ownsState = () => {
55910
+ const owner = readHeadroomState(fs19, paths.headroomStateFile)?.supervisorPid;
55911
+ return owner === void 0 || owner === ports.ownPid || !ports.isRunning(owner);
55912
+ };
55913
+ const writeOwnState = (state) => {
55914
+ if (!ownsState()) {
55915
+ return false;
55916
+ }
55917
+ writeHeadroomState(fs19, paths.headroomStateFile, state);
55918
+ return true;
55919
+ };
55920
+ const fail = (message) => {
55921
+ if (writeOwnState({ lastError: message })) {
55922
+ fs19.removeRecursive(paths.headroomLockFile);
55923
+ }
55924
+ ports.log(`agent-shim headroom supervisor: ${message}`);
55925
+ return 1;
55926
+ };
55927
+ const ensureInstalled = () => {
55928
+ const version3 = ports.headroomVersion();
55929
+ const versionOk = version3 !== void 0 && versionSatisfies(version3, config2.source);
55930
+ const pinned = pinnedGitCommit(config2.source);
55931
+ const commitOk = pinned === void 0 || ports.installedCommit() === pinned;
55932
+ if (versionOk && commitOk && (installedSource === void 0 || installedSource === config2.source)) {
55933
+ installedSource = config2.source;
55934
+ return true;
55935
+ }
55936
+ ports.log(`agent-shim headroom supervisor: installing headroom from ${config2.source}`);
55937
+ const result = ports.install(config2.source);
55938
+ if (!result.ok) {
55939
+ return false;
55940
+ }
55941
+ installedSource = config2.source;
55942
+ return true;
55943
+ };
55944
+ const socket = prepareHeadroomSocket(fs19, ports.socketTrust, paths, ports.ownPid);
55945
+ if (socket.refused !== void 0) {
55946
+ return fail(socket.refused);
55947
+ }
55948
+ const { socketPath } = socket;
55949
+ pruneStaleHeadroomSockets(fs19, paths, ports.isRunning);
55950
+ if (!ensureInstalled()) {
55951
+ return fail(`could not install headroom from ${config2.source}: install failed (is uv installed and on PATH?)`);
55952
+ }
55953
+ const version2 = ports.headroomVersion() ?? "unknown";
55954
+ writeOwnState({ supervisorPid: ports.ownPid, version: version2, installedSource });
55955
+ ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${allowlistOf(ports).join(", ")}]`);
55956
+ const orphanPid = previousState?.headroomPid;
55957
+ if (orphanPid !== void 0 && ports.isRunning(orphanPid)) {
55958
+ ports.log(`agent-shim headroom supervisor: stopping daemon pid ${String(orphanPid)} left behind by the previous supervisor`);
55959
+ ports.stopProcess(orphanPid);
55960
+ }
55961
+ let headroomPid;
55962
+ let runningHash;
55963
+ let runningSettingsHash;
55964
+ let consecutiveFailures = 0;
55965
+ let idleSince;
55966
+ let superseded = false;
55967
+ let ticks = 0;
55968
+ for (; ; ) {
55969
+ if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
55970
+ return HEADROOM_SUPERVISOR_STILL_RUNNING;
55971
+ }
55972
+ ticks += 1;
55973
+ config2 = ports.readConfig();
55974
+ const settingsHash = hashSettings(config2.settings);
55975
+ const allowlist = allowlistOf(ports);
55976
+ const allowlistHash = hashAllowlist(allowlist);
55977
+ pruneDeadSessions(fs19, paths.headroomSessionsDir, ports.isRunning);
55978
+ const ownsNow = ownsState();
55979
+ if (!ownsNow && !superseded) {
55980
+ ports.log("agent-shim headroom supervisor: another supervisor now owns the state file; serving this daemon's own sessions until they end");
55981
+ }
55982
+ superseded = !ownsNow;
55983
+ const crashed = headroomPid !== void 0 && !ports.isRunning(headroomPid);
55984
+ if (headroomPid === void 0 || crashed) {
55985
+ if (crashed) {
55986
+ ports.log(`agent-shim headroom supervisor: headroom pid ${String(headroomPid)} died`);
55987
+ headroomPid = void 0;
55988
+ runningHash = void 0;
55989
+ runningSettingsHash = void 0;
55990
+ writeOwnState({
55991
+ supervisorPid: ports.ownPid,
55992
+ version: version2,
55993
+ installedSource
55994
+ });
55995
+ }
55996
+ if (consecutiveFailures >= HEADROOM_START_RETRY_BUDGET) {
55997
+ return fail(`headroom failed to become ready ${String(consecutiveFailures)} times in a row; giving up`);
55998
+ }
55999
+ if (installedSource !== config2.source && !ensureInstalled()) {
56000
+ return fail(`could not install headroom from ${config2.source}: install failed (is uv installed and on PATH?)`);
56001
+ }
56002
+ const pid = ports.spawnHeadroom(socketPath, allowlist, config2.settings);
56003
+ const ready = await waitUntilReady(ports, socketPath);
56004
+ if (ready) {
56005
+ consecutiveFailures = 0;
56006
+ headroomPid = pid;
56007
+ runningHash = allowlistHash;
56008
+ runningSettingsHash = settingsHash;
56009
+ const recorded = writeOwnState({
56010
+ supervisorPid: ports.ownPid,
56011
+ headroomPid: pid,
56012
+ socketPath,
56013
+ version: version2,
56014
+ allowlistHash,
56015
+ settingsHash,
56016
+ installedSource: config2.source
56017
+ });
56018
+ if (recorded) {
56019
+ fs19.removeRecursive(paths.headroomLockFile);
56020
+ }
56021
+ idleSince = void 0;
56022
+ ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on unix socket ${socketPath}`);
56023
+ } else {
56024
+ ports.stopProcess(pid);
56025
+ consecutiveFailures += 1;
56026
+ ports.log(
56027
+ `agent-shim headroom supervisor: headroom did not become ready on unix socket ${socketPath} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
56028
+ );
56029
+ await ports.sleep(backoffForAttempt(consecutiveFailures));
56030
+ continue;
56031
+ }
56032
+ } else {
56033
+ if (runningHash !== allowlistHash || runningSettingsHash !== settingsHash || installedSource !== config2.source) {
56034
+ if (sessionsForSupervisor(fs19, paths.headroomSessionsDir, ports.ownPid).length === 0) {
56035
+ ports.log("agent-shim headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
56036
+ ports.stopProcess(headroomPid);
56037
+ headroomPid = void 0;
56038
+ runningHash = void 0;
56039
+ runningSettingsHash = void 0;
56040
+ continue;
56041
+ }
56042
+ }
56043
+ const sessions = sessionsForSupervisor(fs19, paths.headroomSessionsDir, ports.ownPid);
56044
+ if (sessions.length === 0) {
56045
+ idleSince ??= ports.now();
56046
+ const idleMs = ports.now() - idleSince;
56047
+ if (idleMs >= config2.idleShutdownMinutes * MS_PER_MINUTE) {
56048
+ ports.log(
56049
+ `agent-shim headroom supervisor: no sessions for ${String(config2.idleShutdownMinutes)} minute(s); stopping headroom and exiting`
56050
+ );
56051
+ ports.stopProcess(headroomPid);
56052
+ writeOwnState({ version: version2 });
56053
+ return 0;
56054
+ }
56055
+ } else {
56056
+ idleSince = void 0;
56057
+ }
56058
+ }
56059
+ await ports.sleep(HEADROOM_POLL_MS);
56060
+ }
56061
+ }
56062
+ function currentHeadroomAllowlist(fs19, paths) {
56063
+ const providers = readAllProviders(fs19, paths.providersDir).map((entry) => entry.provider);
56064
+ return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(fs19, paths.frontdoorStateFile))));
56065
+ }
56066
+ function allowlistOf(ports) {
56067
+ return currentHeadroomAllowlist(ports.fs, ports.paths);
56068
+ }
56069
+ async function waitUntilReady(ports, socketPath) {
56070
+ const deadline = ports.now() + HEADROOM_READY_TIMEOUT_MS;
56071
+ for (; ; ) {
56072
+ if (await ports.ready(socketPath)) {
56073
+ return true;
56074
+ }
56075
+ if (ports.now() >= deadline) {
56076
+ return false;
56077
+ }
56078
+ await ports.sleep(HEADROOM_POLL_MS);
56079
+ }
56080
+ }
56081
+
55549
56082
  // src/realPorts.ts
55550
56083
  function isEnoent2(error62) {
55551
56084
  return typeof error62 === "object" && error62 !== null && "code" in error62 && error62.code === "ENOENT";
@@ -55669,7 +56202,7 @@ var realFarmFs = {
55669
56202
  },
55670
56203
  hashFile(filePath) {
55671
56204
  try {
55672
- return (0, import_node_crypto3.createHash)("sha256").update(import_node_fs3.default.readFileSync(filePath)).digest("hex");
56205
+ return (0, import_node_crypto4.createHash)("sha256").update(import_node_fs3.default.readFileSync(filePath)).digest("hex");
55673
56206
  } catch (error62) {
55674
56207
  if (isEnoent2(error62) || isErrorWithCode(error62, "EISDIR")) {
55675
56208
  return void 0;
@@ -55704,7 +56237,7 @@ var realRunPort = {
55704
56237
  }
55705
56238
  };
55706
56239
  function expandHome(filePath) {
55707
- return filePath.startsWith("~/") ? import_node_path6.default.join(import_node_os2.default.homedir(), filePath.slice(1)) : filePath;
56240
+ return filePath.startsWith("~/") ? import_node_path8.default.join(import_node_os2.default.homedir(), filePath.slice(1)) : filePath;
55708
56241
  }
55709
56242
  var MACOS_GUI_SESSION_MANAGER = "Aqua";
55710
56243
  function hasDesktopSession() {
@@ -55780,7 +56313,7 @@ function spawnDetachedSupervisor(paths, subcommand, logPath) {
55780
56313
  return spawnDetachedDaemon(selfInvocation([subcommand]), paths, subcommand, logPath);
55781
56314
  }
55782
56315
  function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
55783
- import_node_fs3.default.mkdirSync(import_node_path6.default.dirname(logPath), { recursive: true });
56316
+ import_node_fs3.default.mkdirSync(import_node_path8.default.dirname(logPath), { recursive: true });
55784
56317
  const logFd = import_node_fs3.default.openSync(logPath, "a");
55785
56318
  try {
55786
56319
  const child = (0, import_node_child_process2.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
@@ -55821,10 +56354,11 @@ var realHeadroomSocketTrust = {
55821
56354
  };
55822
56355
  function realHeadroomPort(paths, options) {
55823
56356
  return {
55824
- ensure: () => {
56357
+ ensure: ({ routesProvider }) => {
55825
56358
  const up = ensureHeadroom({
55826
56359
  paths,
55827
56360
  launcherPid: process.pid,
56361
+ ...routesProvider ? { requiredAllowlistHash: () => hashAllowlist(currentHeadroomAllowlist(realFarmFs, paths)) } : {},
55828
56362
  ports: {
55829
56363
  fs: realFarmFs,
55830
56364
  // Zombie-aware on purpose: a supervisor that died while still a child of this launcher sits unreaped until the launcher itself exits, and a defunct supervisor answering signal 0 as alive would stretch every launch to the full start timeout.
@@ -55878,7 +56412,7 @@ function listVersionsDir(dir) {
55878
56412
  throw error62;
55879
56413
  }
55880
56414
  return entries.filter((entry) => entry.isFile()).map((entry) => {
55881
- const fullPath = import_node_path6.default.join(dir, entry.name);
56415
+ const fullPath = import_node_path8.default.join(dir, entry.name);
55882
56416
  const stat = import_node_fs3.default.statSync(fullPath);
55883
56417
  return {
55884
56418
  name: entry.name,
@@ -55893,7 +56427,7 @@ function windowsPathExtensions(pathext) {
55893
56427
  return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
55894
56428
  }
55895
56429
  function resolveExecutableCandidate(dir, name, env) {
55896
- const candidate = import_node_path6.default.join(dir, name);
56430
+ const candidate = import_node_path8.default.join(dir, name);
55897
56431
  if (env.platform === "win32") {
55898
56432
  const extensions = windowsPathExtensions(env.pathext);
55899
56433
  const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
@@ -55942,13 +56476,13 @@ function resolveOwnExecutablePath(env) {
55942
56476
  if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
55943
56477
  return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
55944
56478
  }
55945
- const candidate = env.argv1 === void 0 ? env.execPath : import_node_path6.default.resolve(env.cwd, env.argv1);
55946
- const candidateDir = import_node_path6.default.dirname(candidate);
55947
- const candidateDirOnPath = env.pathDirs.some((dir) => import_node_path6.default.resolve(dir) === candidateDir);
56479
+ const candidate = env.argv1 === void 0 ? env.execPath : import_node_path8.default.resolve(env.cwd, env.argv1);
56480
+ const candidateDir = import_node_path8.default.dirname(candidate);
56481
+ const candidateDirOnPath = env.pathDirs.some((dir) => import_node_path8.default.resolve(dir) === candidateDir);
55948
56482
  if (candidateDirOnPath) {
55949
56483
  return candidate;
55950
56484
  }
55951
- const viaPath = searchPathForExecutable(env.pathDirs, import_node_path6.default.basename(candidate), env.findExecutableInDir);
56485
+ const viaPath = searchPathForExecutable(env.pathDirs, import_node_path8.default.basename(candidate), env.findExecutableInDir);
55952
56486
  return viaPath ?? candidate;
55953
56487
  }
55954
56488
  function realOwnExecutablePath() {
@@ -55956,7 +56490,7 @@ function realOwnExecutablePath() {
55956
56490
  argv1: process.argv[1],
55957
56491
  execPath: process.execPath,
55958
56492
  cwd: process.cwd(),
55959
- pathDirs: (process.env.PATH ?? "").split(import_node_path6.default.delimiter).filter((dir) => dir !== ""),
56493
+ pathDirs: (process.env.PATH ?? "").split(import_node_path8.default.delimiter).filter((dir) => dir !== ""),
55960
56494
  findExecutableInDir
55961
56495
  });
55962
56496
  }
@@ -55969,7 +56503,7 @@ function realContentSourcePath() {
55969
56503
  function realResolveClaudeBinary(isOwnBinary) {
55970
56504
  return () => discoverClaudeBinary({
55971
56505
  listVersionsDir,
55972
- pathDirs: (process.env.PATH ?? "").split(import_node_path6.default.delimiter).filter((dir) => dir !== ""),
56506
+ pathDirs: (process.env.PATH ?? "").split(import_node_path8.default.delimiter).filter((dir) => dir !== ""),
55973
56507
  findExecutableInDir,
55974
56508
  isOwnBinary
55975
56509
  });
@@ -56015,10 +56549,10 @@ function isInvokedAsClaude(invokedName) {
56015
56549
  }
56016
56550
  function resolveOwnBinaryCheck(paths, contentSourcePath) {
56017
56551
  const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
56018
- const recordedTarget = state === void 0 ? void 0 : import_node_path7.default.resolve(state.targetPath);
56552
+ const recordedTarget = state === void 0 ? void 0 : import_node_path9.default.resolve(state.targetPath);
56019
56553
  let ownStat;
56020
56554
  return (candidate) => {
56021
- if (recordedTarget !== void 0 && import_node_path7.default.resolve(candidate) === recordedTarget) {
56555
+ if (recordedTarget !== void 0 && import_node_path9.default.resolve(candidate) === recordedTarget) {
56022
56556
  return true;
56023
56557
  }
56024
56558
  ownStat ??= statOrUndefined(contentSourcePath);
@@ -56028,7 +56562,7 @@ function resolveOwnBinaryCheck(paths, contentSourcePath) {
56028
56562
  };
56029
56563
  }
56030
56564
  function resolveClaudeTargetPath(ownExecutablePath, dir) {
56031
- return import_node_path7.default.join(dir ?? import_node_path7.default.dirname(ownExecutablePath), claudeTargetFilename(ownExecutablePath));
56565
+ return import_node_path9.default.join(dir ?? import_node_path9.default.dirname(ownExecutablePath), claudeTargetFilename(ownExecutablePath));
56032
56566
  }
56033
56567
  function isEnoent3(error62) {
56034
56568
  return typeof error62 === "object" && error62 !== null && "code" in error62 && error62.code === "ENOENT";
@@ -56063,13 +56597,13 @@ function enableClaudeShim(params, linkFs = nodeLinkFs) {
56063
56597
  throw new UnsupportedShimSourceError(realContentPath);
56064
56598
  }
56065
56599
  const targetPath = resolveClaudeTargetPath(params.ownExecutablePath, params.dir);
56066
- import_node_fs4.default.mkdirSync(import_node_path7.default.dirname(targetPath), { recursive: true });
56600
+ import_node_fs4.default.mkdirSync(import_node_path9.default.dirname(targetPath), { recursive: true });
56067
56601
  const existing = lstatOrUndefined(targetPath);
56068
56602
  if (existing !== void 0) {
56069
56603
  const ownStat = import_node_fs4.default.statSync(realContentPath);
56070
56604
  const state = readJson(params.paths.claudeShimFile, ClaudeShimStateSchema);
56071
56605
  const sameInode = existing.dev === ownStat.dev && existing.ino === ownStat.ino;
56072
- const markerMatches = state !== void 0 && import_node_path7.default.resolve(state.targetPath) === targetPath;
56606
+ const markerMatches = state !== void 0 && import_node_path9.default.resolve(state.targetPath) === targetPath;
56073
56607
  if (!sameInode && !markerMatches && !params.force) {
56074
56608
  throw new ForeignClaudeEntryError(targetPath, "enable");
56075
56609
  }
@@ -56094,7 +56628,7 @@ function enableClaudeShim(params, linkFs = nodeLinkFs) {
56094
56628
  function disableClaudeShim(params) {
56095
56629
  const realContentPath = import_node_fs4.default.realpathSync(params.contentSourcePath);
56096
56630
  const state = readJson(params.paths.claudeShimFile, ClaudeShimStateSchema);
56097
- const targetPath = params.dir !== void 0 ? import_node_path7.default.join(params.dir, claudeTargetFilename(params.ownExecutablePath)) : state?.targetPath ?? resolveClaudeTargetPath(params.ownExecutablePath);
56631
+ const targetPath = params.dir !== void 0 ? import_node_path9.default.join(params.dir, claudeTargetFilename(params.ownExecutablePath)) : state?.targetPath ?? resolveClaudeTargetPath(params.ownExecutablePath);
56098
56632
  const existing = lstatOrUndefined(targetPath);
56099
56633
  if (existing === void 0) {
56100
56634
  if (state !== void 0) {
@@ -56104,7 +56638,7 @@ function disableClaudeShim(params) {
56104
56638
  }
56105
56639
  const ownStat = import_node_fs4.default.statSync(realContentPath);
56106
56640
  const sameInode = existing.dev === ownStat.dev && existing.ino === ownStat.ino;
56107
- const markerMatches = state !== void 0 && import_node_path7.default.resolve(state.targetPath) === targetPath;
56641
+ const markerMatches = state !== void 0 && import_node_path9.default.resolve(state.targetPath) === targetPath;
56108
56642
  if (!sameInode && !markerMatches && !params.force) {
56109
56643
  throw new ForeignClaudeEntryError(targetPath, "disable");
56110
56644
  }
@@ -56113,15 +56647,15 @@ function disableClaudeShim(params) {
56113
56647
  return { action: "disabled", targetPath };
56114
56648
  }
56115
56649
  function findPathShadow(params) {
56116
- const resolvedTargetDir = import_node_path7.default.resolve(params.targetDir);
56650
+ const resolvedTargetDir = import_node_path9.default.resolve(params.targetDir);
56117
56651
  for (const dir of params.pathDirs) {
56118
56652
  const found = params.findExecutableInDir(dir, params.targetFilename);
56119
56653
  if (found === void 0) {
56120
56654
  continue;
56121
56655
  }
56122
- return import_node_path7.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
56656
+ return import_node_path9.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
56123
56657
  }
56124
- return params.pathDirs.some((dir) => import_node_path7.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
56658
+ return params.pathDirs.some((dir) => import_node_path9.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
56125
56659
  }
56126
56660
  function registerShimCommand(program2, deps) {
56127
56661
  const { paths } = deps;
@@ -56139,21 +56673,21 @@ function registerShimCommand(program2, deps) {
56139
56673
  ownExecutablePath,
56140
56674
  contentSourcePath,
56141
56675
  platform: process.platform,
56142
- ...options.dir === void 0 ? {} : { dir: import_node_path7.default.resolve(options.dir) },
56676
+ ...options.dir === void 0 ? {} : { dir: import_node_path9.default.resolve(options.dir) },
56143
56677
  force: options.force ?? false
56144
56678
  });
56145
56679
  console.log(`${result.action === "enabled" ? "Installed" : "Reinstalled"} \`claude\` at ${result.targetPath} (${result.method}).`);
56146
56680
  const shadow = findPathShadow({
56147
- pathDirs: (process.env.PATH ?? "").split(import_node_path7.default.delimiter).filter((dir) => dir !== ""),
56148
- targetDir: import_node_path7.default.dirname(result.targetPath),
56149
- targetFilename: import_node_path7.default.basename(result.targetPath),
56681
+ pathDirs: (process.env.PATH ?? "").split(import_node_path9.default.delimiter).filter((dir) => dir !== ""),
56682
+ targetDir: import_node_path9.default.dirname(result.targetPath),
56683
+ targetFilename: import_node_path9.default.basename(result.targetPath),
56150
56684
  findExecutableInDir
56151
56685
  });
56152
56686
  if (shadow.status === "not-on-path") {
56153
- console.warn(`warning: ${import_node_path7.default.dirname(result.targetPath)} is not on PATH \u2014 add it, or use \`agent-shim run\` instead.`);
56687
+ console.warn(`warning: ${import_node_path9.default.dirname(result.targetPath)} is not on PATH \u2014 add it, or use \`agent-shim run\` instead.`);
56154
56688
  } else if (shadow.status === "shadowed") {
56155
56689
  console.warn(
56156
- `warning: 'claude' on PATH currently resolves to ${shadow.by}, not ${result.targetPath}. Put ${import_node_path7.default.dirname(result.targetPath)} ahead of it on PATH.`
56690
+ `warning: 'claude' on PATH currently resolves to ${shadow.by}, not ${result.targetPath}. Put ${import_node_path9.default.dirname(result.targetPath)} ahead of it on PATH.`
56157
56691
  );
56158
56692
  }
56159
56693
  });
@@ -56165,7 +56699,7 @@ function registerShimCommand(program2, deps) {
56165
56699
  paths,
56166
56700
  ownExecutablePath,
56167
56701
  contentSourcePath,
56168
- ...options.dir === void 0 ? {} : { dir: import_node_path7.default.resolve(options.dir) },
56702
+ ...options.dir === void 0 ? {} : { dir: import_node_path9.default.resolve(options.dir) },
56169
56703
  force: options.force ?? false
56170
56704
  });
56171
56705
  console.log(
@@ -56221,7 +56755,7 @@ function aliasLegacyWireHeaders(headers) {
56221
56755
  // src/configure.ts
56222
56756
  var import_node_fs8 = __toESM(require("node:fs"), 1);
56223
56757
  var import_node_os4 = __toESM(require("node:os"), 1);
56224
- var import_node_path18 = __toESM(require("node:path"), 1);
56758
+ var import_node_path20 = __toESM(require("node:path"), 1);
56225
56759
 
56226
56760
  // node_modules/.pnpm/@clack+core@1.5.1/node_modules/@clack/core/dist/index.mjs
56227
56761
  var import_node_util3 = require("node:util");
@@ -57490,10 +58024,10 @@ function classifyEntries(names, options) {
57490
58024
 
57491
58025
  // src/identityStore.ts
57492
58026
  var import_node_fs6 = __toESM(require("node:fs"), 1);
57493
- var import_node_path11 = __toESM(require("node:path"), 1);
58027
+ var import_node_path13 = __toESM(require("node:path"), 1);
57494
58028
 
57495
58029
  // src/launcher/identity.ts
57496
- var import_node_path8 = __toESM(require("node:path"), 1);
58030
+ var import_node_path10 = __toESM(require("node:path"), 1);
57497
58031
  function poolNameOf(selector) {
57498
58032
  return selector.startsWith(POOL_SELECTOR_PREFIX) ? selector.slice(POOL_SELECTOR_PREFIX.length) : void 0;
57499
58033
  }
@@ -57542,12 +58076,12 @@ function decideConfigProfile(params) {
57542
58076
  return { source: "none" };
57543
58077
  }
57544
58078
  function loadIdentity(identitiesDir, name, fs19) {
57545
- return loadConfigFile(import_node_path8.default.join(identitiesDir, name, "identity.json"), IdentitySchema, fs19.readConfigFile);
58079
+ return loadConfigFile(import_node_path10.default.join(identitiesDir, name, "identity.json"), IdentitySchema, fs19.readConfigFile);
57546
58080
  }
57547
58081
 
57548
58082
  // src/configProfilesStore.ts
57549
58083
  var import_node_fs5 = __toESM(require("node:fs"), 1);
57550
- var import_node_path9 = __toESM(require("node:path"), 1);
58084
+ var import_node_path11 = __toESM(require("node:path"), 1);
57551
58085
  var ProfileNotFoundError = class extends CliError {
57552
58086
  constructor(profileName) {
57553
58087
  super(`No configuration profile named "${profileName}". Run \`agent-shim profile add ${profileName}\` first.`);
@@ -57573,7 +58107,7 @@ var InvalidCategoryNameError = class extends CliError {
57573
58107
  categoryName;
57574
58108
  };
57575
58109
  function profileJsonPath(paths, name) {
57576
- return import_node_path9.default.join(paths.configProfilesDir, `${name}.json`);
58110
+ return import_node_path11.default.join(paths.configProfilesDir, `${name}.json`);
57577
58111
  }
57578
58112
  function profileExists(paths, name) {
57579
58113
  return import_node_fs5.default.existsSync(profileJsonPath(paths, name));
@@ -57734,8 +58268,8 @@ function removePool(paths, name) {
57734
58268
  }
57735
58269
 
57736
58270
  // src/launcher/lock.ts
57737
- var import_node_crypto4 = require("node:crypto");
57738
- var import_node_path10 = __toESM(require("node:path"), 1);
58271
+ var import_node_crypto5 = require("node:crypto");
58272
+ var import_node_path12 = __toESM(require("node:path"), 1);
57739
58273
  var DEFAULT_STALE_AFTER_MS = 12e4;
57740
58274
  var DEFAULT_RETRY_DELAY_MS = 50;
57741
58275
  var DEFAULT_MAX_ATTEMPTS = 200;
@@ -57754,7 +58288,7 @@ var IdentityLockBusyError = class extends CliError {
57754
58288
  holderPid;
57755
58289
  };
57756
58290
  function identityLockPath(dir, identity) {
57757
- return import_node_path10.default.join(dir, `.${identity}.lock`);
58291
+ return import_node_path12.default.join(dir, `.${identity}.lock`);
57758
58292
  }
57759
58293
  function parseLockRecord(raw) {
57760
58294
  if (raw === void 0) {
@@ -57783,7 +58317,7 @@ function acquireIdentityLock(params) {
57783
58317
  const staleAfterMs = params.staleAfterMs ?? DEFAULT_STALE_AFTER_MS;
57784
58318
  const retryDelayMs = params.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
57785
58319
  const maxAttempts = params.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
57786
- const token = (0, import_node_crypto4.randomUUID)();
58320
+ const token = (0, import_node_crypto5.randomUUID)();
57787
58321
  if (params.fs.lstat(params.dir) === void 0) {
57788
58322
  params.fs.mkdirp(params.dir);
57789
58323
  }
@@ -57848,7 +58382,7 @@ var InvalidIdentityNameError = class extends CliError {
57848
58382
  attemptedName;
57849
58383
  };
57850
58384
  function identityJsonPath(paths, name) {
57851
- return import_node_path11.default.join(paths.identitiesDir, name, "identity.json");
58385
+ return import_node_path13.default.join(paths.identitiesDir, name, "identity.json");
57852
58386
  }
57853
58387
  function identityExists(paths, name) {
57854
58388
  return import_node_fs6.default.existsSync(identityJsonPath(paths, name));
@@ -57949,7 +58483,7 @@ function setIdentityCredential(paths, identityName, change) {
57949
58483
  });
57950
58484
  }
57951
58485
  function belongsToIdentity(entry, name) {
57952
- return entry === name || entry === import_node_path11.default.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
58486
+ return entry === name || entry === import_node_path13.default.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
57953
58487
  }
57954
58488
  function removeIdentity(paths, name) {
57955
58489
  if (!identityExists(paths, name)) {
@@ -57957,7 +58491,7 @@ function removeIdentity(paths, name) {
57957
58491
  }
57958
58492
  for (const entry of import_node_fs6.default.readdirSync(paths.identitiesDir)) {
57959
58493
  if (belongsToIdentity(entry, name)) {
57960
- import_node_fs6.default.rmSync(import_node_path11.default.join(paths.identitiesDir, entry), { recursive: true, force: true });
58494
+ import_node_fs6.default.rmSync(import_node_path13.default.join(paths.identitiesDir, entry), { recursive: true, force: true });
57961
58495
  }
57962
58496
  }
57963
58497
  if (readActiveIdentity(paths) === name) {
@@ -58056,32 +58590,32 @@ function removeDirectoryRule(paths, rulePath) {
58056
58590
  }
58057
58591
 
58058
58592
  // src/launcher/cascade.ts
58059
- var import_node_path14 = __toESM(require("node:path"), 1);
58593
+ var import_node_path16 = __toESM(require("node:path"), 1);
58060
58594
 
58061
58595
  // src/pathNorm.ts
58062
- var import_node_path12 = __toESM(require("node:path"), 1);
58596
+ var import_node_path14 = __toESM(require("node:path"), 1);
58063
58597
  function expandTilde(value, home) {
58064
58598
  if (value === "~") {
58065
58599
  return home;
58066
58600
  }
58067
58601
  if (value.startsWith("~/")) {
58068
- return import_node_path12.default.join(home, value.slice(2));
58602
+ return import_node_path14.default.join(home, value.slice(2));
58069
58603
  }
58070
58604
  return value;
58071
58605
  }
58072
58606
  function normaliseRulePath(rulePath, home) {
58073
- return import_node_path12.default.resolve(expandTilde(rulePath, home));
58607
+ return import_node_path14.default.resolve(expandTilde(rulePath, home));
58074
58608
  }
58075
58609
  function isAncestorOrSelf(ancestor, descendant) {
58076
58610
  if (ancestor === descendant) {
58077
58611
  return true;
58078
58612
  }
58079
- const withSeparator = ancestor.endsWith(import_node_path12.default.sep) ? ancestor : `${ancestor}${import_node_path12.default.sep}`;
58613
+ const withSeparator = ancestor.endsWith(import_node_path14.default.sep) ? ancestor : `${ancestor}${import_node_path14.default.sep}`;
58080
58614
  return descendant.startsWith(withSeparator);
58081
58615
  }
58082
58616
 
58083
58617
  // src/resolve/walk.ts
58084
- var import_node_path13 = __toESM(require("node:path"), 1);
58618
+ var import_node_path15 = __toESM(require("node:path"), 1);
58085
58619
 
58086
58620
  // src/resolve/extends.ts
58087
58621
  function lineariseProfile(rootName, load) {
@@ -58149,10 +58683,10 @@ function profileLayers(rootName, load, startId) {
58149
58683
 
58150
58684
  // src/resolve/walk.ts
58151
58685
  function walkDirectoryAncestors(cwd, options) {
58152
- const limit = import_node_path13.default.resolve(options.limit ?? options.home);
58686
+ const limit = import_node_path15.default.resolve(options.limit ?? options.home);
58153
58687
  const isReadable = options.isReadable ?? (() => true);
58154
58688
  const collected = [];
58155
- let current = import_node_path13.default.resolve(cwd);
58689
+ let current = import_node_path15.default.resolve(cwd);
58156
58690
  for (; ; ) {
58157
58691
  if (!isReadable(current)) {
58158
58692
  break;
@@ -58161,7 +58695,7 @@ function walkDirectoryAncestors(cwd, options) {
58161
58695
  if (current === limit) {
58162
58696
  break;
58163
58697
  }
58164
- const parent = import_node_path13.default.dirname(current);
58698
+ const parent = import_node_path15.default.dirname(current);
58165
58699
  if (parent === current) {
58166
58700
  break;
58167
58701
  }
@@ -58254,7 +58788,7 @@ function loadCascadeInput(params) {
58254
58788
  const globalConfig2 = loadConfigFile(params.paths.globalConfigFile, GlobalConfigSchema, params.read);
58255
58789
  const directoryRules = loadConfigFile(params.paths.directoryRulesFile, DirectoryRulesSchema, params.read);
58256
58790
  const loadProfile = (name) => {
58257
- const filepath = import_node_path14.default.join(params.paths.configProfilesDir, `${name}.json`);
58791
+ const filepath = import_node_path16.default.join(params.paths.configProfilesDir, `${name}.json`);
58258
58792
  const loaded = loadConfigFile(filepath, ConfigProfileSchema, params.read);
58259
58793
  if (loaded === void 0) {
58260
58794
  return void 0;
@@ -58269,8 +58803,8 @@ function loadCascadeInput(params) {
58269
58803
  });
58270
58804
  const levels = [];
58271
58805
  for (const dir of dirs) {
58272
- const portable = loadConfigFile(import_node_path14.default.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path14.default.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
58273
- const portableLocal = loadConfigFile(import_node_path14.default.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path14.default.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
58806
+ const portable = loadConfigFile(import_node_path16.default.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path16.default.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
58807
+ const portableLocal = loadConfigFile(import_node_path16.default.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path16.default.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
58274
58808
  const rules = (directoryRules?.config.rules ?? []).map((rule, index) => ({ rule, index })).filter(({ rule }) => normaliseRulePath(rule.path, params.home) === dir).map(({ rule, index }) => {
58275
58809
  const entryOrder = directoryRules?.ruleEntryOrders[index];
58276
58810
  return {
@@ -58319,7 +58853,7 @@ function readDirectorySelections(loaded) {
58319
58853
  }
58320
58854
 
58321
58855
  // src/launcher/farm.ts
58322
- var import_node_path16 = __toESM(require("node:path"), 1);
58856
+ var import_node_path18 = __toESM(require("node:path"), 1);
58323
58857
 
58324
58858
  // src/resolve/reconcile.ts
58325
58859
  function parentOf(rel) {
@@ -58987,7 +59521,7 @@ function dedupeDiagnostics(diagnostics) {
58987
59521
  }
58988
59522
 
58989
59523
  // src/resolve/plan.ts
58990
- var import_node_path15 = __toESM(require("node:path"), 1);
59524
+ var import_node_path17 = __toESM(require("node:path"), 1);
58991
59525
  function parentOf2(rel) {
58992
59526
  const index = rel.lastIndexOf("/");
58993
59527
  return index === -1 ? "" : rel.slice(0, index);
@@ -59037,7 +59571,7 @@ function planFarm(params) {
59037
59571
  }
59038
59572
  return value;
59039
59573
  };
59040
- const linkTarget = (rel) => import_node_path15.default.join(params.facts.claudeHome, rel);
59574
+ const linkTarget = (rel) => import_node_path17.default.join(params.facts.claudeHome, rel);
59041
59575
  const visit2 = (rel) => {
59042
59576
  const fact = params.facts.entries.get(rel);
59043
59577
  const decision = params.decisions.get(rel);
@@ -59170,7 +59704,7 @@ var FarmManifestSchema = external_exports.strictObject({
59170
59704
  links: external_exports.array(external_exports.strictObject({ rel: external_exports.string(), target: external_exports.string() }))
59171
59705
  });
59172
59706
  function readFarmManifest(fs19, farmRoot) {
59173
- const raw = fs19.readFileUtf8(import_node_path16.default.join(farmRoot, FARM_MANIFEST_FILENAME)) ?? fs19.readFileUtf8(import_node_path16.default.join(farmRoot, LEGACY_FARM_MANIFEST_FILENAME));
59707
+ const raw = fs19.readFileUtf8(import_node_path18.default.join(farmRoot, FARM_MANIFEST_FILENAME)) ?? fs19.readFileUtf8(import_node_path18.default.join(farmRoot, LEGACY_FARM_MANIFEST_FILENAME));
59174
59708
  if (raw === void 0) {
59175
59709
  return void 0;
59176
59710
  }
@@ -59186,7 +59720,7 @@ function readFarmManifest(fs19, farmRoot) {
59186
59720
  function buildEntryFacts(params) {
59187
59721
  const entries = /* @__PURE__ */ new Map();
59188
59722
  const visit2 = (rel) => {
59189
- const absolute = import_node_path16.default.join(params.claudeHome, rel);
59723
+ const absolute = import_node_path18.default.join(params.claudeHome, rel);
59190
59724
  const stat = params.fs.lstat(absolute);
59191
59725
  if (stat === void 0) {
59192
59726
  return void 0;
@@ -59229,7 +59763,7 @@ function buildEntryFacts(params) {
59229
59763
  };
59230
59764
  }
59231
59765
  function listSubtree(fs19, root, rel) {
59232
- const absolute = import_node_path16.default.join(root, rel);
59766
+ const absolute = import_node_path18.default.join(root, rel);
59233
59767
  const stat = fs19.lstat(absolute);
59234
59768
  if (stat === void 0) {
59235
59769
  return [];
@@ -59259,7 +59793,7 @@ function reconciliationScope(fs19, farmRoot, manifest) {
59259
59793
  if (manifest !== void 0) {
59260
59794
  return topLevelScopeRoots(manifest.materialised);
59261
59795
  }
59262
- return [...fs19.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && name !== LEGACY_FARM_MANIFEST_FILENAME && fs19.lstat(import_node_path16.default.join(farmRoot, name))?.kind === "dir").sort();
59796
+ return [...fs19.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && name !== LEGACY_FARM_MANIFEST_FILENAME && fs19.lstat(import_node_path18.default.join(farmRoot, name))?.kind === "dir").sort();
59263
59797
  }
59264
59798
  function collectFarmListing(fs19, farmRoot, scopeRoots) {
59265
59799
  return scopeRoots.flatMap((root) => listSubtree(fs19, farmRoot, root));
@@ -59267,7 +59801,7 @@ function collectFarmListing(fs19, farmRoot, scopeRoots) {
59267
59801
  function collectCanonicalCounterparts(fs19, claudeHome, farmListing) {
59268
59802
  const out = [];
59269
59803
  for (const entry of farmListing) {
59270
- const absolute = import_node_path16.default.join(claudeHome, entry.rel);
59804
+ const absolute = import_node_path18.default.join(claudeHome, entry.rel);
59271
59805
  const stat = fs19.lstat(absolute);
59272
59806
  if (stat === void 0) {
59273
59807
  continue;
@@ -59297,21 +59831,21 @@ function carryOver(params) {
59297
59831
  if (accounted.has(name)) {
59298
59832
  continue;
59299
59833
  }
59300
- const stat = params.fs.lstat(import_node_path16.default.join(params.previousRoot, name));
59834
+ const stat = params.fs.lstat(import_node_path18.default.join(params.previousRoot, name));
59301
59835
  if (stat === void 0 || stat.kind === "symlink") {
59302
59836
  continue;
59303
59837
  }
59304
- if (params.fs.lstat(import_node_path16.default.join(params.farmRoot, name)) !== void 0) {
59838
+ if (params.fs.lstat(import_node_path18.default.join(params.farmRoot, name)) !== void 0) {
59305
59839
  const category = params.classification === void 0 ? void 0 : classifyEntries([name], params.classification).classification.get(name);
59306
59840
  if (category === "runtime") {
59307
- params.fs.removeRecursive(import_node_path16.default.join(params.previousRoot, name));
59841
+ params.fs.removeRecursive(import_node_path18.default.join(params.previousRoot, name));
59308
59842
  autoResolved.push(name);
59309
59843
  continue;
59310
59844
  }
59311
59845
  collided.push(name);
59312
59846
  continue;
59313
59847
  }
59314
- params.fs.rename(import_node_path16.default.join(params.previousRoot, name), import_node_path16.default.join(params.farmRoot, name));
59848
+ params.fs.rename(import_node_path18.default.join(params.previousRoot, name), import_node_path18.default.join(params.farmRoot, name));
59315
59849
  carried.push(name);
59316
59850
  }
59317
59851
  return { carried, autoResolved, collided };
@@ -59319,9 +59853,9 @@ function carryOver(params) {
59319
59853
  function buildScratchTree(params) {
59320
59854
  params.fs.mkdirp(params.scratchRoot);
59321
59855
  for (const entry of params.plan.entries) {
59322
- const absolute = import_node_path16.default.join(params.scratchRoot, entry.rel);
59856
+ const absolute = import_node_path18.default.join(params.scratchRoot, entry.rel);
59323
59857
  if (entry.kind === "link") {
59324
- params.fs.mkdirp(import_node_path16.default.dirname(absolute));
59858
+ params.fs.mkdirp(import_node_path18.default.dirname(absolute));
59325
59859
  params.fs.symlink(entry.target, absolute);
59326
59860
  continue;
59327
59861
  }
@@ -59330,14 +59864,14 @@ function buildScratchTree(params) {
59330
59864
  }
59331
59865
  }
59332
59866
  params.fs.writeFileUtf8(
59333
- import_node_path16.default.join(params.scratchRoot, FARM_MANIFEST_FILENAME),
59867
+ import_node_path18.default.join(params.scratchRoot, FARM_MANIFEST_FILENAME),
59334
59868
  `${JSON.stringify(params.manifest, null, 2)}
59335
59869
  `
59336
59870
  );
59337
59871
  }
59338
59872
  function swapIn(params) {
59339
59873
  if (params.fs.lstat(params.farmRoot) === void 0) {
59340
- params.fs.mkdirp(import_node_path16.default.dirname(params.farmRoot));
59874
+ params.fs.mkdirp(import_node_path18.default.dirname(params.farmRoot));
59341
59875
  params.fs.rename(params.scratchRoot, params.farmRoot);
59342
59876
  return { carried: [], autoResolved: [], collided: [] };
59343
59877
  }
@@ -59361,14 +59895,14 @@ function recoverInterruptedSwap(params) {
59361
59895
  const names = [...params.fs.readdir(params.identitiesDir)].sort();
59362
59896
  const removedScratch = [];
59363
59897
  for (const name of names.filter((candidate) => candidate.startsWith(scratchPrefix))) {
59364
- params.fs.removeRecursive(import_node_path16.default.join(params.identitiesDir, name));
59898
+ params.fs.removeRecursive(import_node_path18.default.join(params.identitiesDir, name));
59365
59899
  removedScratch.push(name);
59366
59900
  }
59367
59901
  let previous = names.filter((candidate) => candidate.startsWith(previousPrefix));
59368
59902
  let restoredFrom;
59369
59903
  const first = previous[0];
59370
59904
  if (first !== void 0 && params.fs.lstat(params.farmRoot) === void 0) {
59371
- params.fs.rename(import_node_path16.default.join(params.identitiesDir, first), params.farmRoot);
59905
+ params.fs.rename(import_node_path18.default.join(params.identitiesDir, first), params.farmRoot);
59372
59906
  restoredFrom = first;
59373
59907
  previous = previous.slice(1);
59374
59908
  }
@@ -59376,7 +59910,7 @@ function recoverInterruptedSwap(params) {
59376
59910
  const autoResolved = [];
59377
59911
  const retained = [];
59378
59912
  for (const name of previous) {
59379
- const previousRoot = import_node_path16.default.join(params.identitiesDir, name);
59913
+ const previousRoot = import_node_path18.default.join(params.identitiesDir, name);
59380
59914
  const result = carryOver({
59381
59915
  fs: params.fs,
59382
59916
  previousRoot,
@@ -59401,7 +59935,7 @@ function recoverInterruptedSwap(params) {
59401
59935
  };
59402
59936
  }
59403
59937
  function recoverFarm(params) {
59404
- const farmRoot = import_node_path16.default.join(params.identitiesDir, params.identity);
59938
+ const farmRoot = import_node_path18.default.join(params.identitiesDir, params.identity);
59405
59939
  const lock = acquireIdentityLock({
59406
59940
  identity: params.identity,
59407
59941
  dir: params.identitiesDir,
@@ -59460,16 +59994,16 @@ function executeReconciliation(params) {
59460
59994
  });
59461
59995
  continue;
59462
59996
  }
59463
- const from = import_node_path16.default.join(params.farmRoot, action.rel);
59464
- const canonical = import_node_path16.default.join(params.claudeHome, action.rel);
59997
+ const from = import_node_path18.default.join(params.farmRoot, action.rel);
59998
+ const canonical = import_node_path18.default.join(params.claudeHome, action.rel);
59465
59999
  if (action.kind === "adopt") {
59466
- params.fs.mkdirp(import_node_path16.default.dirname(canonical));
60000
+ params.fs.mkdirp(import_node_path18.default.dirname(canonical));
59467
60001
  params.fs.copyRecursive(from, canonical);
59468
60002
  adopted.push(action.rel);
59469
60003
  continue;
59470
60004
  }
59471
60005
  const preserved = `${canonical}.farm-conflict-${String(params.nowMs)}`;
59472
- params.fs.mkdirp(import_node_path16.default.dirname(canonical));
60006
+ params.fs.mkdirp(import_node_path18.default.dirname(canonical));
59473
60007
  params.fs.copyRecursive(from, preserved);
59474
60008
  conflicts.push(action.rel);
59475
60009
  }
@@ -59494,7 +60028,7 @@ function farmAlreadyMatches(existing, next) {
59494
60028
  return existing.identity === next.identity && existing.claudeHome === next.claudeHome && sameStrings(existing.materialised, next.materialised) && sameLinks(existing.links, next.links);
59495
60029
  }
59496
60030
  function resyncFarm(params) {
59497
- const farmRoot = import_node_path16.default.join(params.identitiesDir, params.identity);
60031
+ const farmRoot = import_node_path18.default.join(params.identitiesDir, params.identity);
59498
60032
  const lock = acquireIdentityLock({
59499
60033
  identity: params.identity,
59500
60034
  dir: params.identitiesDir,
@@ -59574,8 +60108,8 @@ function resyncFarm(params) {
59574
60108
  diagnostics
59575
60109
  };
59576
60110
  }
59577
- const scratchRoot = import_node_path16.default.join(params.identitiesDir, `.${params.identity}.scratch.${params.uniqueSuffix}`);
59578
- const previousRoot = import_node_path16.default.join(params.identitiesDir, `.${params.identity}.previous.${params.uniqueSuffix}`);
60111
+ const scratchRoot = import_node_path18.default.join(params.identitiesDir, `.${params.identity}.scratch.${params.uniqueSuffix}`);
60112
+ const previousRoot = import_node_path18.default.join(params.identitiesDir, `.${params.identity}.previous.${params.uniqueSuffix}`);
59579
60113
  buildScratchTree({ fs: params.fs, scratchRoot, plan: resolved.farm, manifest });
59580
60114
  const swap = swapIn({ fs: params.fs, farmRoot, scratchRoot, previousRoot, classification: params.classification });
59581
60115
  if (swap.retainedPrevious !== void 0) {
@@ -59634,14 +60168,14 @@ function recoveryDiagnostics(recovery, identity) {
59634
60168
  // src/paths.ts
59635
60169
  var import_node_fs7 = __toESM(require("node:fs"), 1);
59636
60170
  var import_node_os3 = __toESM(require("node:os"), 1);
59637
- var import_node_path17 = __toESM(require("node:path"), 1);
60171
+ var import_node_path19 = __toESM(require("node:path"), 1);
59638
60172
  function resolveAgentShimHome(env = process.env, home = import_node_os3.default.homedir(), isDirectory = isExistingDirectory) {
59639
60173
  const fromEnv = env.AGENT_SHIM_HOME;
59640
60174
  if (fromEnv !== void 0 && fromEnv !== "") {
59641
60175
  return fromEnv;
59642
60176
  }
59643
- const current = import_node_path17.default.join(home, HOME_DIRNAME);
59644
- const legacy = import_node_path17.default.join(home, LEGACY_HOME_DIRNAME);
60177
+ const current = import_node_path19.default.join(home, HOME_DIRNAME);
60178
+ const legacy = import_node_path19.default.join(home, LEGACY_HOME_DIRNAME);
59645
60179
  return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
59646
60180
  }
59647
60181
  function isExistingDirectory(candidate) {
@@ -59652,40 +60186,40 @@ function resolveClaudeHome() {
59652
60186
  if (fromEnv !== void 0 && fromEnv !== "") {
59653
60187
  return fromEnv;
59654
60188
  }
59655
- return import_node_path17.default.join(import_node_os3.default.homedir(), ".claude");
60189
+ return import_node_path19.default.join(import_node_os3.default.homedir(), ".claude");
59656
60190
  }
59657
60191
  function buildLayoutPaths(root) {
59658
60192
  return {
59659
60193
  root,
59660
- identitiesDir: import_node_path17.default.join(root, "identities"),
59661
- configProfilesDir: import_node_path17.default.join(root, "config-profiles"),
59662
- providersDir: import_node_path17.default.join(root, "providers"),
59663
- directoryRulesFile: import_node_path17.default.join(root, "directory-rules.json"),
59664
- activeIdentityFile: import_node_path17.default.join(root, "active-identity"),
59665
- globalConfigFile: import_node_path17.default.join(root, "config.json"),
59666
- categoriesLocalFile: import_node_path17.default.join(root, "categories.local.json"),
59667
- claudeShimFile: import_node_path17.default.join(root, "claude-shim.json"),
59668
- headroomDir: import_node_path17.default.join(root, "headroom"),
59669
- headroomStateFile: import_node_path17.default.join(root, "headroom", `state.v${String(HEADROOM_STATE_SCHEMA_VERSION)}.json`),
59670
- headroomSocketDir: import_node_path17.default.join(root, "headroom", "run"),
59671
- headroomLockFile: import_node_path17.default.join(root, "headroom", "start.lock"),
59672
- headroomSessionsDir: import_node_path17.default.join(root, "headroom", "sessions"),
59673
- logsDir: import_node_path17.default.join(root, "logs"),
59674
- headroomLogPath: import_node_path17.default.join(root, "logs", "headroom.log"),
59675
- frontdoorDir: import_node_path17.default.join(root, "frontdoor"),
59676
- frontdoorCaDir: import_node_path17.default.join(root, "frontdoor", "ca"),
59677
- frontdoorCaCertFile: import_node_path17.default.join(root, "frontdoor", "ca", "ca.pem"),
59678
- frontdoorCaKeyFile: import_node_path17.default.join(root, "frontdoor", "ca", "ca.key"),
59679
- frontdoorCaBundlesDir: import_node_path17.default.join(root, "frontdoor", "ca", "bundles"),
59680
- frontdoorStateFile: import_node_path17.default.join(root, "frontdoor", "state.json"),
59681
- frontdoorLockFile: import_node_path17.default.join(root, "frontdoor", "start.lock"),
59682
- frontdoorControlTokenFile: import_node_path17.default.join(root, "frontdoor", "control-token"),
59683
- frontdoorSessionsDir: import_node_path17.default.join(root, "frontdoor", "sessions"),
59684
- frontdoorLogPath: import_node_path17.default.join(root, "logs", "frontdoor.log"),
59685
- usageDir: import_node_path17.default.join(root, "usage"),
59686
- usageLogDir: import_node_path17.default.join(root, "usage", "log"),
59687
- usageSnapshotsDir: import_node_path17.default.join(root, "usage", "snapshots"),
59688
- usagePicksFile: import_node_path17.default.join(root, "usage", "picks.json")
60194
+ identitiesDir: import_node_path19.default.join(root, "identities"),
60195
+ configProfilesDir: import_node_path19.default.join(root, "config-profiles"),
60196
+ providersDir: import_node_path19.default.join(root, "providers"),
60197
+ directoryRulesFile: import_node_path19.default.join(root, "directory-rules.json"),
60198
+ activeIdentityFile: import_node_path19.default.join(root, "active-identity"),
60199
+ globalConfigFile: import_node_path19.default.join(root, "config.json"),
60200
+ categoriesLocalFile: import_node_path19.default.join(root, "categories.local.json"),
60201
+ claudeShimFile: import_node_path19.default.join(root, "claude-shim.json"),
60202
+ headroomDir: import_node_path19.default.join(root, "headroom"),
60203
+ headroomStateFile: import_node_path19.default.join(root, "headroom", `state.v${String(HEADROOM_STATE_SCHEMA_VERSION)}.json`),
60204
+ headroomSocketDir: import_node_path19.default.join(root, "headroom", "run"),
60205
+ headroomLockFile: import_node_path19.default.join(root, "headroom", "start.lock"),
60206
+ headroomSessionsDir: import_node_path19.default.join(root, "headroom", "sessions"),
60207
+ logsDir: import_node_path19.default.join(root, "logs"),
60208
+ headroomLogPath: import_node_path19.default.join(root, "logs", "headroom.log"),
60209
+ frontdoorDir: import_node_path19.default.join(root, "frontdoor"),
60210
+ frontdoorCaDir: import_node_path19.default.join(root, "frontdoor", "ca"),
60211
+ frontdoorCaCertFile: import_node_path19.default.join(root, "frontdoor", "ca", "ca.pem"),
60212
+ frontdoorCaKeyFile: import_node_path19.default.join(root, "frontdoor", "ca", "ca.key"),
60213
+ frontdoorCaBundlesDir: import_node_path19.default.join(root, "frontdoor", "ca", "bundles"),
60214
+ frontdoorStateFile: import_node_path19.default.join(root, "frontdoor", "state.json"),
60215
+ frontdoorLockFile: import_node_path19.default.join(root, "frontdoor", "start.lock"),
60216
+ frontdoorControlTokenFile: import_node_path19.default.join(root, "frontdoor", "control-token"),
60217
+ frontdoorSessionsDir: import_node_path19.default.join(root, "frontdoor", "sessions"),
60218
+ frontdoorLogPath: import_node_path19.default.join(root, "logs", "frontdoor.log"),
60219
+ usageDir: import_node_path19.default.join(root, "usage"),
60220
+ usageLogDir: import_node_path19.default.join(root, "usage", "log"),
60221
+ usageSnapshotsDir: import_node_path19.default.join(root, "usage", "snapshots"),
60222
+ usagePicksFile: import_node_path19.default.join(root, "usage", "picks.json")
59689
60223
  };
59690
60224
  }
59691
60225
  function resolveLayoutPaths() {
@@ -59767,7 +60301,7 @@ function chooseWriteTarget(params) {
59767
60301
  for (let index = params.levels.length - 1; index >= 0; index -= 1) {
59768
60302
  const level = params.levels[index];
59769
60303
  if (level !== void 0 && (level.hasPortable || level.hasPortableLocal)) {
59770
- return { tier: "portable-local", localConfigPath: import_node_path18.default.join(level.dir, level.portableLocalFilename) };
60304
+ return { tier: "portable-local", localConfigPath: import_node_path20.default.join(level.dir, level.portableLocalFilename) };
59771
60305
  }
59772
60306
  }
59773
60307
  const normalisedCwd = normaliseRulePath(params.cwd, params.home);
@@ -59860,11 +60394,11 @@ function buildWriteTargetLevels(cwd, home, walkUpLimit) {
59860
60394
  const limit = walkUpLimit === void 0 ? void 0 : expandTilde(walkUpLimit, home);
59861
60395
  const dirs = walkDirectoryAncestors(cwd, { home, ...limit === void 0 ? {} : { limit } });
59862
60396
  return dirs.map((dir) => {
59863
- const hasLocal = import_node_fs8.default.existsSync(import_node_path18.default.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME));
59864
- const hasLegacyLocal = import_node_fs8.default.existsSync(import_node_path18.default.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME));
60397
+ const hasLocal = import_node_fs8.default.existsSync(import_node_path20.default.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME));
60398
+ const hasLegacyLocal = import_node_fs8.default.existsSync(import_node_path20.default.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME));
59865
60399
  return {
59866
60400
  dir,
59867
- hasPortable: import_node_fs8.default.existsSync(import_node_path18.default.join(dir, PORTABLE_CONFIG_FILENAME)) || import_node_fs8.default.existsSync(import_node_path18.default.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME)),
60401
+ hasPortable: import_node_fs8.default.existsSync(import_node_path20.default.join(dir, PORTABLE_CONFIG_FILENAME)) || import_node_fs8.default.existsSync(import_node_path20.default.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME)),
59868
60402
  hasPortableLocal: hasLocal || hasLegacyLocal,
59869
60403
  portableLocalFilename: !hasLocal && hasLegacyLocal ? LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME : PORTABLE_LOCAL_CONFIG_FILENAME
59870
60404
  };
@@ -60208,7 +60742,7 @@ function resolveLaunchIdentity(paths, cwd) {
60208
60742
  }
60209
60743
 
60210
60744
  // src/identityManager.ts
60211
- var import_node_path20 = __toESM(require("node:path"), 1);
60745
+ var import_node_path22 = __toESM(require("node:path"), 1);
60212
60746
 
60213
60747
  // src/cli/credentialOption.ts
60214
60748
  var CREDENTIAL_SOURCE_SYNTAX = "env:<VAR>, file:<path>, command:<program and arguments>, op:<op://reference>, keychain:<service>[:<account>], literal:<placeholder>, or a JSON source object";
@@ -60316,7 +60850,7 @@ var CREDENTIAL_COMMAND_TIMEOUT_MS = 1e4;
60316
60850
  var CREDENTIAL_INTERACTIVE_TIMEOUT_MS = 12e4;
60317
60851
  var GROUP_OTHER_PERMISSION_BITS = 63;
60318
60852
  var PERMISSION_BITS2 = 511;
60319
- var OCTAL_RADIX = 8;
60853
+ var OCTAL_RADIX2 = 8;
60320
60854
  function commandArgv(source) {
60321
60855
  if ("command" in source) {
60322
60856
  return source.command;
@@ -60409,7 +60943,7 @@ function trySource(source, params) {
60409
60943
  }
60410
60944
  if (read.mode !== void 0 && (read.mode & GROUP_OTHER_PERMISSION_BITS) !== 0) {
60411
60945
  return none(
60412
- `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS2).toString(OCTAL_RADIX)}); run \`chmod 600 ${source.file}\``,
60946
+ `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS2).toString(OCTAL_RADIX2)}); run \`chmod 600 ${source.file}\``,
60413
60947
  true
60414
60948
  );
60415
60949
  }
@@ -60477,11 +61011,11 @@ function credentialVariables(target, token) {
60477
61011
  }
60478
61012
 
60479
61013
  // src/launcher/farmResolve.ts
60480
- var import_node_path19 = __toESM(require("node:path"), 1);
61014
+ var import_node_path21 = __toESM(require("node:path"), 1);
60481
61015
  async function resolveFarmConflicts(params) {
60482
- const farmRoot = import_node_path19.default.join(params.identitiesDir, params.identity);
61016
+ const farmRoot = import_node_path21.default.join(params.identitiesDir, params.identity);
60483
61017
  const previousPrefix = `.${params.identity}.previous.`;
60484
- const previousRoots = [...params.fs.readdir(params.identitiesDir)].filter((name) => name.startsWith(previousPrefix)).sort().map((name) => import_node_path19.default.join(params.identitiesDir, name));
61018
+ const previousRoots = [...params.fs.readdir(params.identitiesDir)].filter((name) => name.startsWith(previousPrefix)).sort().map((name) => import_node_path21.default.join(params.identitiesDir, name));
60485
61019
  const resolved = [];
60486
61020
  const autoResolved = [];
60487
61021
  const removed = [];
@@ -60504,11 +61038,11 @@ async function resolveFarmConflicts(params) {
60504
61038
  continue;
60505
61039
  }
60506
61040
  if (choice === "keep-new") {
60507
- params.fs.removeRecursive(import_node_path19.default.join(previousRoot, name));
61041
+ params.fs.removeRecursive(import_node_path21.default.join(previousRoot, name));
60508
61042
  continue;
60509
61043
  }
60510
- params.fs.removeRecursive(import_node_path19.default.join(farmRoot, name));
60511
- params.fs.rename(import_node_path19.default.join(previousRoot, name), import_node_path19.default.join(farmRoot, name));
61044
+ params.fs.removeRecursive(import_node_path21.default.join(farmRoot, name));
61045
+ params.fs.rename(import_node_path21.default.join(previousRoot, name), import_node_path21.default.join(farmRoot, name));
60512
61046
  }
60513
61047
  if (anySkipped) {
60514
61048
  retained.push(previousRoot);
@@ -60847,7 +61381,7 @@ function toIdentityView(paths, entry) {
60847
61381
  return {
60848
61382
  name: entry.name,
60849
61383
  active: entry.isActive,
60850
- directory: import_node_path20.default.join(paths.identitiesDir, entry.name),
61384
+ directory: import_node_path22.default.join(paths.identitiesDir, entry.name),
60851
61385
  ...entry.problem === void 0 ? {
60852
61386
  ...entry.identity.defaultConfigProfile === void 0 ? {} : { defaultConfigProfile: entry.identity.defaultConfigProfile },
60853
61387
  allowAmbientCredential: entry.identity.allowAmbientCredential,
@@ -60994,7 +61528,7 @@ function registerIdentityCommand(program2, deps) {
60994
61528
  if (!identityExists(paths, name)) {
60995
61529
  throw new IdentityNotFoundError(name);
60996
61530
  }
60997
- await confirmRemoval(deps, options.yes, `identity "${name}" and its directory ${import_node_path20.default.join(paths.identitiesDir, name)}`);
61531
+ await confirmRemoval(deps, options.yes, `identity "${name}" and its directory ${import_node_path22.default.join(paths.identitiesDir, name)}`);
60998
61532
  removeIdentity(paths, name);
60999
61533
  reportMutation(options.json, { action: "removed", kind: "identity", name }, () => {
61000
61534
  console.log(`Removed identity "${name}".`);
@@ -61052,7 +61586,7 @@ function registerIdentityCommand(program2, deps) {
61052
61586
  // package.json
61053
61587
  var package_default = {
61054
61588
  name: "agent-shim",
61055
- version: "8.5.2",
61589
+ version: "8.5.3",
61056
61590
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
61057
61591
  license: "MIT",
61058
61592
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -61148,7 +61682,7 @@ var package_default = {
61148
61682
  };
61149
61683
 
61150
61684
  // src/check.ts
61151
- var import_node_path27 = __toESM(require("node:path"), 1);
61685
+ var import_node_path29 = __toESM(require("node:path"), 1);
61152
61686
 
61153
61687
  // src/checkReport.ts
61154
61688
  var import_node_os5 = __toESM(require("node:os"), 1);
@@ -61202,10 +61736,10 @@ function quotaWarnings(snapshot, provider, nowMs) {
61202
61736
  }
61203
61737
 
61204
61738
  // src/usage/poolPick.ts
61205
- var import_node_path24 = __toESM(require("node:path"), 1);
61739
+ var import_node_path26 = __toESM(require("node:path"), 1);
61206
61740
 
61207
61741
  // src/usage/account.ts
61208
- var import_node_path21 = __toESM(require("node:path"), 1);
61742
+ var import_node_path23 = __toESM(require("node:path"), 1);
61209
61743
 
61210
61744
  // src/usage/schema.ts
61211
61745
  var USAGE_SCHEMA_VERSION = 1;
@@ -61374,7 +61908,7 @@ function isIdentityName(name) {
61374
61908
  return IdentitySchema.shape.name.safeParse(name).success;
61375
61909
  }
61376
61910
  function claudeJsonPath(identitiesDir, identity) {
61377
- return import_node_path21.default.join(identitiesDir, identity, CLAUDE_JSON);
61911
+ return import_node_path23.default.join(identitiesDir, identity, CLAUDE_JSON);
61378
61912
  }
61379
61913
  function readAccountMetadata(fs19, identitiesDir, identity) {
61380
61914
  if (!isIdentityName(identity)) {
@@ -62182,7 +62716,7 @@ function rankPool(input2) {
62182
62716
  }
62183
62717
 
62184
62718
  // src/usage/read.ts
62185
- var import_node_path22 = __toESM(require("node:path"), 1);
62719
+ var import_node_path24 = __toESM(require("node:path"), 1);
62186
62720
  var SEGMENT_RE = /^(\d{4}-\d{2}-\d{2})\.(\d+)\.jsonl$/;
62187
62721
  var DAY_MS = 864e5;
62188
62722
  function segmentDay(epochMs) {
@@ -62209,7 +62743,7 @@ function readUsageLog(fs19, logDir, options = {}) {
62209
62743
  if (sinceMs !== void 0 && segment.endsAt <= sinceMs) {
62210
62744
  continue;
62211
62745
  }
62212
- const contents = fs19.readFileUtf8(import_node_path22.default.join(logDir, segment.name));
62746
+ const contents = fs19.readFileUtf8(import_node_path24.default.join(logDir, segment.name));
62213
62747
  if (contents === void 0) {
62214
62748
  continue;
62215
62749
  }
@@ -62251,7 +62785,7 @@ function snapshotPath(snapshotsDir, identity) {
62251
62785
  if (!isIdentityName(identity)) {
62252
62786
  throw new Error(`"${identity}" is not a valid identity name.`);
62253
62787
  }
62254
- return import_node_path22.default.join(snapshotsDir, `${identity}.json`);
62788
+ return import_node_path24.default.join(snapshotsDir, `${identity}.json`);
62255
62789
  }
62256
62790
  function readUsageSnapshot(fs19, snapshotsDir, identity) {
62257
62791
  const file2 = snapshotPath(snapshotsDir, identity);
@@ -62335,7 +62869,7 @@ function summariseUsage(records) {
62335
62869
  }
62336
62870
 
62337
62871
  // src/usage/store.ts
62338
- var import_node_path23 = __toESM(require("node:path"), 1);
62872
+ var import_node_path25 = __toESM(require("node:path"), 1);
62339
62873
  var DAY_MS2 = 864e5;
62340
62874
  var DAYS_IN_WEEK = 7;
62341
62875
  var USAGE_RETENTION_MS = DAYS_IN_WEEK * DAY_MS2;
@@ -62343,7 +62877,7 @@ function pruneUsageLog(fs19, logDir, nowMs) {
62343
62877
  const cutoff = nowMs - USAGE_RETENTION_MS;
62344
62878
  for (const segment of listLogSegments(fs19, logDir)) {
62345
62879
  if (segment.endsAt <= cutoff) {
62346
- fs19.removeRecursive(import_node_path23.default.join(logDir, segment.name));
62880
+ fs19.removeRecursive(import_node_path25.default.join(logDir, segment.name));
62347
62881
  }
62348
62882
  }
62349
62883
  }
@@ -62424,7 +62958,7 @@ function createUsageStore(deps) {
62424
62958
  pruneUsageLog(fs19, paths.usageLogDir, nowMs);
62425
62959
  prunedDay = day;
62426
62960
  }
62427
- fs19.appendFilePrivate(import_node_path23.default.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record2)}
62961
+ fs19.appendFilePrivate(import_node_path25.default.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record2)}
62428
62962
  `);
62429
62963
  if (record2.identity !== void 0) {
62430
62964
  rewriteSnapshot(record2.identity, (current) => ({ ...current?.providers, [record2.provider]: foldProviderState(current?.providers[record2.provider], record2) }));
@@ -62500,7 +63034,7 @@ function recordStickyPick(fs19, picksFile, directory, identity, nowMs) {
62500
63034
  const current = readPicksFile(fs19, picksFile).file.picks;
62501
63035
  const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
62502
63036
  const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
62503
- fs19.mkdirPrivate(import_node_path24.default.dirname(picksFile));
63037
+ fs19.mkdirPrivate(import_node_path26.default.dirname(picksFile));
62504
63038
  fs19.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
62505
63039
  `);
62506
63040
  }
@@ -62594,7 +63128,7 @@ function collectPoolPick(params) {
62594
63128
 
62595
63129
  // src/providersStore.ts
62596
63130
  var import_node_fs9 = __toESM(require("node:fs"), 1);
62597
- var import_node_path25 = __toESM(require("node:path"), 1);
63131
+ var import_node_path27 = __toESM(require("node:path"), 1);
62598
63132
  var ProviderNotFoundError = class extends CliError {
62599
63133
  constructor(name) {
62600
63134
  super(`No provider named "${name}". Run \`agent-shim provider add ${name}\` first.`);
@@ -62623,7 +63157,7 @@ var InvalidProviderNameError = class extends CliError {
62623
63157
  };
62624
63158
  var PROVIDER_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._@-]*$/;
62625
63159
  function providerJsonPath(paths, name) {
62626
- return import_node_path25.default.join(paths.providersDir, `${name}.json`);
63160
+ return import_node_path27.default.join(paths.providersDir, `${name}.json`);
62627
63161
  }
62628
63162
  function providerExists(paths, name) {
62629
63163
  return import_node_fs9.default.existsSync(providerJsonPath(paths, name));
@@ -62699,7 +63233,7 @@ function readProvider(paths, name) {
62699
63233
  return parseProviderFile(filePath, raw);
62700
63234
  }
62701
63235
  function loadProvider(providersDir, name, port) {
62702
- const filePath = import_node_path25.default.join(providersDir, `${name}.json`);
63236
+ const filePath = import_node_path27.default.join(providersDir, `${name}.json`);
62703
63237
  const raw = port.readConfigFile(filePath);
62704
63238
  return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
62705
63239
  }
@@ -62861,7 +63395,7 @@ function resolveProvider(params) {
62861
63395
  }
62862
63396
 
62863
63397
  // src/checkReport.ts
62864
- var import_node_path26 = __toESM(require("node:path"), 1);
63398
+ var import_node_path28 = __toESM(require("node:path"), 1);
62865
63399
 
62866
63400
  // src/cli/envBool.ts
62867
63401
  var InvalidEnvBoolError = class extends UsageError {
@@ -63261,10 +63795,10 @@ function collectCheckReport(params) {
63261
63795
  }).input;
63262
63796
  const providerName = cascadeProviderName(cascade);
63263
63797
  const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
63264
- const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path26.default.join(paths.identitiesDir, identityDecision.name);
63798
+ const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path28.default.join(paths.identitiesDir, identityDecision.name);
63265
63799
  const settingsFiles = {
63266
- "settings.json": realFsPort.readFileUtf8(import_node_path26.default.join(claudeHome, "settings.json")),
63267
- "settings.local.json": realFsPort.readFileUtf8(import_node_path26.default.join(claudeHome, "settings.local.json"))
63800
+ "settings.json": realFsPort.readFileUtf8(import_node_path28.default.join(claudeHome, "settings.json")),
63801
+ "settings.local.json": realFsPort.readFileUtf8(import_node_path28.default.join(claudeHome, "settings.local.json"))
63268
63802
  };
63269
63803
  const report = runCheck({
63270
63804
  cwd,
@@ -63298,7 +63832,7 @@ function registerCheckCommand(program2, deps) {
63298
63832
  const command = program2.command("check [path]").description(
63299
63833
  "Show what a launch in a directory would share or hide and why, plus credential and settings diagnostics. Never touches the farm or spawns claude."
63300
63834
  ).option("--identity <name>", "Identity to check (defaults to the identity a launch there would resolve).").option("--json", "Print the report as JSON.").option("--strict", "Exit 1 when the report carries any warning, not only on errors.").action((pathArg, options) => {
63301
- const cwd = pathArg === void 0 ? process.cwd() : import_node_path27.default.resolve(pathArg);
63835
+ const cwd = pathArg === void 0 ? process.cwd() : import_node_path29.default.resolve(pathArg);
63302
63836
  const report = collectCheckReport({ paths, cwd, ...options.identity === void 0 ? {} : { identity: options.identity }, env: process.env });
63303
63837
  if (options.json === true) {
63304
63838
  printJson(checkReportToJson(report));
@@ -63315,123 +63849,10 @@ function registerCheckCommand(program2, deps) {
63315
63849
  }
63316
63850
 
63317
63851
  // src/codex/commands.ts
63318
- var import_node_crypto6 = require("node:crypto");
63852
+ var import_node_crypto7 = require("node:crypto");
63319
63853
  var import_node_fs10 = __toESM(require("node:fs"), 1);
63320
63854
  var import_node_os6 = __toESM(require("node:os"), 1);
63321
- var import_node_path29 = __toESM(require("node:path"), 1);
63322
-
63323
- // src/frontdoor/state.ts
63324
- var import_node_path28 = __toESM(require("node:path"), 1);
63325
- var FRONT_DOOR_PROTOCOL = 2;
63326
- var FrontDoorSessionSchema = external_exports.strictObject({ pid: external_exports.number().int().positive(), startedAt: external_exports.number(), token: external_exports.string().min(1) });
63327
- var FrontDoorStateSchema = external_exports.strictObject({
63328
- /**
63329
- * The launcher-to-door wire protocol this supervisor speaks, written once it is serving; absent in state written by a release that predates the field, which `ensureFrontDoor` reads as protocol 0. A launcher replaces a door whose protocol is lower than its own (see `FRONT_DOOR_PROTOCOL`).
63330
- */
63331
- protocol: external_exports.number().int().nonnegative().optional(),
63332
- /** The supervisor process serving the front door. Alive means both listeners are up in that process. */
63333
- supervisorPid: external_exports.number().int().positive().optional(),
63334
- /** The loopback port the HTTPS provider listener serves on. Absent until the listener has bound and answered its health probe, so "port is set" is itself the ready signal a launcher polls for. */
63335
- port: external_exports.number().int().positive().optional(),
63336
- /**
63337
- * The sticky port preference for the provider listener: kept across crashes, restarts and idle shutdowns so every provider session, whose base URL was frozen at launch, keeps finding the front door at the same address.
63338
- */
63339
- lastPort: external_exports.number().int().positive().optional(),
63340
- /**
63341
- * The loopback port the CONNECT surface listens on. Absent whenever no supervisor is serving it, so "connectPort is set" is the ready signal an OAuth launch polls for alongside `port`.
63342
- */
63343
- connectPort: external_exports.number().int().positive().optional(),
63344
- /**
63345
- * The sticky port preference for the CONNECT surface, the exact analogue of `lastPort` for the second listener: it survives every shutdown, because every OAuth session's environment was frozen at launch with HTTPS_PROXY pointing at this address and a restart that moves strands them.
63346
- */
63347
- lastConnectPort: external_exports.number().int().positive().optional(),
63348
- /**
63349
- * The loopback port the direct listener serves on: the listener a headroom hop tells the daemon to forward routed traffic back to. Sticky like the others, because headroom's allowlist admits its exact origin and an ephemeral port would invalidate the allowlist on every restart.
63350
- */
63351
- directPort: external_exports.number().int().positive().optional(),
63352
- /** The sticky port preference for the direct listener, for the reason `directPort` gives. */
63353
- lastDirectPort: external_exports.number().int().positive().optional(),
63354
- /** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
63355
- lastError: external_exports.string().optional()
63356
- });
63357
- function readFrontDoorState(fs19, stateFile) {
63358
- let raw;
63359
- try {
63360
- raw = fs19.readFileUtf8(stateFile);
63361
- } catch {
63362
- return void 0;
63363
- }
63364
- if (raw === void 0 || raw.trim() === "") {
63365
- return void 0;
63366
- }
63367
- try {
63368
- const parsed = FrontDoorStateSchema.safeParse(JSON.parse(raw));
63369
- return parsed.success ? parsed.data : void 0;
63370
- } catch {
63371
- return void 0;
63372
- }
63373
- }
63374
- function writeFrontDoorState(fs19, stateFile, state) {
63375
- fs19.mkdirp(import_node_path28.default.dirname(stateFile));
63376
- fs19.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
63377
- `);
63378
- }
63379
- function frontDoorOrigin(state) {
63380
- const port = state?.directPort ?? state?.lastDirectPort;
63381
- return port === void 0 ? void 0 : `http://127.0.0.1:${String(port)}`;
63382
- }
63383
- function writeFrontDoorSession(fs19, sessionsDir, session) {
63384
- fs19.mkdirPrivate(sessionsDir);
63385
- fs19.writeFilePrivate(import_node_path28.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
63386
- `);
63387
- }
63388
- function listFrontDoorSessions(fs19, sessionsDir) {
63389
- const sessions = [];
63390
- for (const name of fs19.readdir(sessionsDir)) {
63391
- if (!name.endsWith(".json")) {
63392
- continue;
63393
- }
63394
- try {
63395
- const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs19.readFileUtf8(import_node_path28.default.join(sessionsDir, name)) ?? ""));
63396
- if (parsed.success) {
63397
- sessions.push({ pid: parsed.data.pid, startedAt: parsed.data.startedAt });
63398
- }
63399
- } catch {
63400
- continue;
63401
- }
63402
- }
63403
- return sessions.sort((a2, b) => a2.pid - b.pid);
63404
- }
63405
- function removeFrontDoorSession(fs19, sessionsDir, pid) {
63406
- fs19.removeRecursive(import_node_path28.default.join(sessionsDir, `${String(pid)}.json`));
63407
- }
63408
- function pruneDeadFrontDoorSessions(fs19, sessionsDir, isRunning) {
63409
- const removed = [];
63410
- for (const session of listFrontDoorSessions(fs19, sessionsDir)) {
63411
- if (!isRunning(session.pid)) {
63412
- removeFrontDoorSession(fs19, sessionsDir, session.pid);
63413
- removed.push(session.pid);
63414
- }
63415
- }
63416
- return removed;
63417
- }
63418
- function liveSessionTokens(fs19, sessionsDir) {
63419
- const tokens = /* @__PURE__ */ new Set();
63420
- for (const name of fs19.readdir(sessionsDir)) {
63421
- if (!name.endsWith(".json")) {
63422
- continue;
63423
- }
63424
- try {
63425
- const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs19.readFileUtf8(import_node_path28.default.join(sessionsDir, name)) ?? ""));
63426
- if (parsed.success) {
63427
- tokens.add(parsed.data.token);
63428
- }
63429
- } catch {
63430
- continue;
63431
- }
63432
- }
63433
- return tokens;
63434
- }
63855
+ var import_node_path30 = __toESM(require("node:path"), 1);
63435
63856
 
63436
63857
  // src/codex/agent.ts
63437
63858
  var import_undici = __toESM(require_undici(), 1);
@@ -63580,7 +64001,7 @@ function createCodexAuthStore(authPath, ports) {
63580
64001
  }
63581
64002
 
63582
64003
  // src/codex/upstream.ts
63583
- var import_node_crypto5 = require("node:crypto");
64004
+ var import_node_crypto6 = require("node:crypto");
63584
64005
 
63585
64006
  // src/codex/http.ts
63586
64007
  var HTTP_STATUS = {
@@ -63634,7 +64055,7 @@ function sessionIdFor(userId, randomId) {
63634
64055
  if (userId === void 0 || userId === "") {
63635
64056
  return randomId();
63636
64057
  }
63637
- const hex3 = (0, import_node_crypto5.createHash)("sha256").update(`agent-shim codex session
64058
+ const hex3 = (0, import_node_crypto6.createHash)("sha256").update(`agent-shim codex session
63638
64059
  ${userId}`).digest("hex");
63639
64060
  let next = 0;
63640
64061
  return UUID_TEMPLATE.replace(/x/g, () => hex3.charAt(next++));
@@ -63670,10 +64091,10 @@ async function callCodex(ports, request7, sessionId, signal) {
63670
64091
  // src/codex/commands.ts
63671
64092
  function codexHome(env, home) {
63672
64093
  const fromEnv = env.CODEX_HOME;
63673
- return fromEnv !== void 0 && fromEnv !== "" ? fromEnv : import_node_path29.default.join(home, ".codex");
64094
+ return fromEnv !== void 0 && fromEnv !== "" ? fromEnv : import_node_path30.default.join(home, ".codex");
63674
64095
  }
63675
64096
  function codexUsageSnapshotPath() {
63676
- return import_node_path29.default.join(resolveClaudeHome(), "codex-quota.json");
64097
+ return import_node_path30.default.join(resolveClaudeHome(), "codex-quota.json");
63677
64098
  }
63678
64099
  function isEnoent4(error62) {
63679
64100
  return typeof error62 === "object" && error62 !== null && "code" in error62 && error62.code === "ENOENT";
@@ -63702,7 +64123,7 @@ function writeUsageSnapshot(log, snapshot) {
63702
64123
  const target = codexUsageSnapshotPath();
63703
64124
  const temp = `${target}.${String(process.pid)}.tmp`;
63704
64125
  try {
63705
- import_node_fs10.default.mkdirSync(import_node_path29.default.dirname(target), { recursive: true });
64126
+ import_node_fs10.default.mkdirSync(import_node_path30.default.dirname(target), { recursive: true });
63706
64127
  import_node_fs10.default.writeFileSync(temp, `${JSON.stringify(snapshot, null, 2)}
63707
64128
  `);
63708
64129
  import_node_fs10.default.renameSync(temp, target);
@@ -63713,14 +64134,14 @@ function writeUsageSnapshot(log, snapshot) {
63713
64134
  function createCodexRoutePorts(log) {
63714
64135
  const agent = createUpstreamAgent();
63715
64136
  const upstreamFetch = createUpstreamFetch(agent);
63716
- const auth = createCodexAuthStore(import_node_path29.default.join(codexHome(process.env, import_node_os6.default.homedir()), "auth.json"), {
64137
+ const auth = createCodexAuthStore(import_node_path30.default.join(codexHome(process.env, import_node_os6.default.homedir()), "auth.json"), {
63717
64138
  fs: realCodexAuthFs,
63718
64139
  fetch: upstreamFetch,
63719
64140
  now: () => /* @__PURE__ */ new Date(),
63720
- tempSuffix: `${String(process.pid)}.${(0, import_node_crypto6.randomUUID)()}`
64141
+ tempSuffix: `${String(process.pid)}.${(0, import_node_crypto7.randomUUID)()}`
63721
64142
  });
63722
64143
  return {
63723
- upstream: { fetch: upstreamFetch, auth, timers: realTimers, randomId: import_node_crypto6.randomUUID },
64144
+ upstream: { fetch: upstreamFetch, auth, timers: realTimers, randomId: import_node_crypto7.randomUUID },
63724
64145
  writeUsageSnapshot: (snapshot) => {
63725
64146
  writeUsageSnapshot(log, snapshot);
63726
64147
  },
@@ -63787,85 +64208,10 @@ function registerCodexCommand(program2, deps) {
63787
64208
  }
63788
64209
 
63789
64210
  // src/frontdoor/commands.ts
63790
- var import_node_crypto11 = require("node:crypto");
64211
+ var import_node_crypto12 = require("node:crypto");
63791
64212
  var import_node_path31 = __toESM(require("node:path"), 1);
63792
64213
  var import_node_fs11 = __toESM(require("node:fs"), 1);
63793
64214
 
63794
- // src/headroom/socket.ts
63795
- var import_node_path30 = __toESM(require("node:path"), 1);
63796
- var GROUP_OR_OTHER_BITS = 63;
63797
- var OCTAL_RADIX2 = 8;
63798
- var MODE_DIGITS = 4;
63799
- var HEADROOM_SOCKET_SUFFIX = ".sock";
63800
- var HEADROOM_SOCKET_NAME = /^(\d+)\.sock$/;
63801
- var UNIX_SOCKET_PATH_MAX_BYTES = 103;
63802
- var PLATFORMS_WITHOUT_UNIX_SOCKETS = ["win32"];
63803
- function headroomSocketPath(paths, supervisorPid) {
63804
- return import_node_path30.default.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
63805
- }
63806
- function platformRefusal(platform) {
63807
- 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;
63808
- }
63809
- function ownerOnlyRefusal(label, target, stat, expected, uid) {
63810
- if (stat === void 0) {
63811
- return `the headroom ${label} ${target} does not exist`;
63812
- }
63813
- if (stat.kind === "symlink") {
63814
- return `the headroom ${label} ${target} is a symlink; it must be the real ${expected === "dir" ? "directory" : "socket"}`;
63815
- }
63816
- if (stat.kind !== expected) {
63817
- return `the headroom ${label} ${target} is not a ${expected === "dir" ? "directory" : "socket"}`;
63818
- }
63819
- if (stat.uid !== uid) {
63820
- return `the headroom ${label} ${target} is owned by uid ${String(stat.uid)}, not by this user (uid ${String(uid)})`;
63821
- }
63822
- if ((stat.mode & GROUP_OR_OTHER_BITS) !== 0) {
63823
- return `the headroom ${label} ${target} has mode ${stat.mode.toString(OCTAL_RADIX2).padStart(MODE_DIGITS, "0")}, which lets other users reach it; it must be accessible to its owner only`;
63824
- }
63825
- return void 0;
63826
- }
63827
- function verifyHeadroomSocket(socketPath, ports) {
63828
- const unsupported = platformRefusal(ports.platform);
63829
- if (unsupported !== void 0) {
63830
- return { refused: unsupported };
63831
- }
63832
- const uid = ports.currentUid();
63833
- const directory = import_node_path30.default.dirname(socketPath);
63834
- const refusal = ownerOnlyRefusal("socket directory", directory, ports.lstat(directory), "dir", uid) ?? ownerOnlyRefusal("socket", socketPath, ports.lstat(socketPath), "socket", uid);
63835
- return refusal === void 0 ? { socketPath } : { refused: refusal };
63836
- }
63837
- function prepareHeadroomSocket(fs19, ports, paths, supervisorPid) {
63838
- const unsupported = platformRefusal(ports.platform);
63839
- if (unsupported !== void 0) {
63840
- return { refused: unsupported };
63841
- }
63842
- const socketPath = headroomSocketPath(paths, supervisorPid);
63843
- const length = Buffer.byteLength(socketPath, "utf8");
63844
- if (length > UNIX_SOCKET_PATH_MAX_BYTES) {
63845
- return {
63846
- 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`
63847
- };
63848
- }
63849
- if (ports.lstat(paths.headroomSocketDir)?.kind === "symlink") {
63850
- return { refused: `the headroom socket directory ${paths.headroomSocketDir} is a symlink; it must be the real directory` };
63851
- }
63852
- fs19.mkdirPrivate(paths.headroomSocketDir);
63853
- const refusal = ownerOnlyRefusal("socket directory", paths.headroomSocketDir, ports.lstat(paths.headroomSocketDir), "dir", ports.currentUid());
63854
- return refusal === void 0 ? { socketPath } : { refused: refusal };
63855
- }
63856
- function pruneStaleHeadroomSockets(fs19, paths, isRunning) {
63857
- const removed = [];
63858
- for (const name of fs19.readdir(paths.headroomSocketDir)) {
63859
- const pid = HEADROOM_SOCKET_NAME.exec(name)?.[1];
63860
- if (pid === void 0 || isRunning(Number.parseInt(pid, 10))) {
63861
- continue;
63862
- }
63863
- fs19.removeRecursive(import_node_path30.default.join(paths.headroomSocketDir, name));
63864
- removed.push(name);
63865
- }
63866
- return removed;
63867
- }
63868
-
63869
64215
  // src/frontdoor/custody.ts
63870
64216
  var CREDENTIAL_HEADERS = ["authorization", "x-api-key"];
63871
64217
  var SEQUESTERED_CREDENTIAL = "agent-shim-sequestered";
@@ -63967,7 +64313,7 @@ function createDoorPipelines(deps) {
63967
64313
  }
63968
64314
 
63969
64315
  // src/frontdoor/capability.ts
63970
- var import_node_crypto7 = require("node:crypto");
64316
+ var import_node_crypto8 = require("node:crypto");
63971
64317
  var CONNECT_PROXY_USER = "agent-shim";
63972
64318
  var CONNECT_PROXY_REALM = "agent-shim front door";
63973
64319
  var BASIC_SCHEME = "basic";
@@ -63989,13 +64335,13 @@ function capabilityFromProxyAuthorization(value) {
63989
64335
  return password === "" ? void 0 : password;
63990
64336
  }
63991
64337
  function digest(token) {
63992
- return (0, import_node_crypto7.createHash)("sha256").update(token, "utf8").digest();
64338
+ return (0, import_node_crypto8.createHash)("sha256").update(token, "utf8").digest();
63993
64339
  }
63994
64340
  function isLiveCapability(presented, live) {
63995
64341
  const presentedDigest = digest(presented);
63996
64342
  let matched = false;
63997
64343
  for (const token of live) {
63998
- const equal = (0, import_node_crypto7.timingSafeEqual)(presentedDigest, digest(token));
64344
+ const equal = (0, import_node_crypto8.timingSafeEqual)(presentedDigest, digest(token));
63999
64345
  matched = equal || matched;
64000
64346
  }
64001
64347
  return matched;
@@ -64139,11 +64485,11 @@ function createFileCapture(file2, now = () => /* @__PURE__ */ new Date()) {
64139
64485
  }
64140
64486
 
64141
64487
  // src/frontdoor/connect.ts
64142
- var import_node_crypto9 = require("node:crypto");
64488
+ var import_node_crypto10 = require("node:crypto");
64143
64489
  var fs12 = __toESM(require("node:fs"), 1);
64144
64490
 
64145
64491
  // src/frontdoor/x509.ts
64146
- var import_node_crypto8 = require("node:crypto");
64492
+ var import_node_crypto9 = require("node:crypto");
64147
64493
  var import_node_net = __toESM(require("node:net"), 1);
64148
64494
  var TAG_BOOLEAN = 1;
64149
64495
  var TAG_INTEGER = 2;
@@ -64295,7 +64641,7 @@ function ipBytes(address) {
64295
64641
  return bytes;
64296
64642
  }
64297
64643
  function keyIdentifier(publicKey) {
64298
- return (0, import_node_crypto8.createHash)("sha1").update(publicKey.export({ type: "pkcs1", format: "der" })).digest();
64644
+ return (0, import_node_crypto9.createHash)("sha1").update(publicKey.export({ type: "pkcs1", format: "der" })).digest();
64299
64645
  }
64300
64646
  function readElement(buffer, offset) {
64301
64647
  const tag = buffer[offset];
@@ -64341,7 +64687,7 @@ ${body.join("\n")}
64341
64687
  `;
64342
64688
  }
64343
64689
  function randomSerial() {
64344
- const bytes = (0, import_node_crypto8.randomBytes)(SERIAL_NUMBER_BYTES);
64690
+ const bytes = (0, import_node_crypto9.randomBytes)(SERIAL_NUMBER_BYTES);
64345
64691
  bytes[0] = (bytes[0] ?? 0) & BASE_128_PAYLOAD_MASK | HIGH_BIT >> 1;
64346
64692
  return bytes;
64347
64693
  }
@@ -64356,7 +64702,7 @@ function assemble(spec) {
64356
64702
  spec.subjectPublicKey.export({ type: "spki", format: "der" }),
64357
64703
  tlv(TAG_EXTENSIONS, sequence(...spec.extensions))
64358
64704
  );
64359
- const signature = (0, import_node_crypto8.sign)("sha256", tbs, spec.signingKey);
64705
+ const signature = (0, import_node_crypto9.sign)("sha256", tbs, spec.signingKey);
64360
64706
  return sequence(tbs, SIGNATURE_ALGORITHM, wholeBitString(signature));
64361
64707
  }
64362
64708
  function subjectKeyIdentifierExtension(publicKey) {
@@ -64366,7 +64712,7 @@ function basicConstraintsExtension(isCa) {
64366
64712
  return extension(OID_BASIC_CONSTRAINTS, true, sequence(...isCa ? [boolean4(true)] : []));
64367
64713
  }
64368
64714
  function rsaKeyPair() {
64369
- return (0, import_node_crypto8.generateKeyPairSync)("rsa", { modulusLength: RSA_MODULUS_BITS });
64715
+ return (0, import_node_crypto9.generateKeyPairSync)("rsa", { modulusLength: RSA_MODULUS_BITS });
64370
64716
  }
64371
64717
  function keyPem(privateKey) {
64372
64718
  return privateKey.export({ type: "pkcs8", format: "pem" });
@@ -64390,8 +64736,8 @@ function issueLeafCertificate(ca, names, notBefore, notAfter) {
64390
64736
  if (commonName === void 0) {
64391
64737
  throw new Error("a leaf certificate needs at least one name");
64392
64738
  }
64393
- const caCertificate = new import_node_crypto8.X509Certificate(ca.certPem);
64394
- const caPrivateKey = (0, import_node_crypto8.createPrivateKey)(ca.keyPem);
64739
+ const caCertificate = new import_node_crypto9.X509Certificate(ca.certPem);
64740
+ const caPrivateKey = (0, import_node_crypto9.createPrivateKey)(ca.keyPem);
64395
64741
  const { publicKey, privateKey } = rsaKeyPair();
64396
64742
  const generalNames = names.map((name) => import_node_net.default.isIP(name) === 0 ? tlv(TAG_GENERAL_NAME_DNS, Buffer.from(name, "ascii")) : tlv(TAG_GENERAL_NAME_IP, ipBytes(name)));
64397
64743
  const der = assemble({
@@ -64467,7 +64813,7 @@ function pumpTapSession(secure, openUpstream, tap, prefix = Buffer.alloc(0)) {
64467
64813
  // src/frontdoor/supervisor.ts
64468
64814
  var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
64469
64815
  var FRONTDOOR_POLL_MS = 1e3;
64470
- var MS_PER_MINUTE = 6e4;
64816
+ var MS_PER_MINUTE2 = 6e4;
64471
64817
  async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
64472
64818
  const { fs: fs19, paths } = ports;
64473
64819
  const previous = readFrontDoorState(fs19, paths.frontdoorStateFile);
@@ -64535,7 +64881,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
64535
64881
  pruneDeadFrontDoorSessions(fs19, paths.frontdoorSessionsDir, ports.isRunning);
64536
64882
  if (listFrontDoorSessions(fs19, paths.frontdoorSessionsDir).length === 0) {
64537
64883
  idleSince ??= ports.now();
64538
- if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
64884
+ if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE2) {
64539
64885
  ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
64540
64886
  await direct.close();
64541
64887
  await connect3.close();
@@ -64654,8 +65000,8 @@ function ensureCa(store, generate) {
64654
65000
  }
64655
65001
  function caParses(ca) {
64656
65002
  try {
64657
- new import_node_crypto9.X509Certificate(ca.certPem);
64658
- (0, import_node_crypto9.createPrivateKey)(ca.keyPem);
65003
+ new import_node_crypto10.X509Certificate(ca.certPem);
65004
+ (0, import_node_crypto10.createPrivateKey)(ca.keyPem);
64659
65005
  return true;
64660
65006
  } catch {
64661
65007
  return false;
@@ -66030,7 +66376,7 @@ async function serveRouted(request7, deps) {
66030
66376
  }
66031
66377
 
66032
66378
  // src/codex/translate.ts
66033
- var import_node_crypto10 = require("node:crypto");
66379
+ var import_node_crypto11 = require("node:crypto");
66034
66380
 
66035
66381
  // src/codex/anthropic.ts
66036
66382
  var TextBlockSchema = external_exports.looseObject({ type: external_exports.literal("text"), text: external_exports.string() });
@@ -66142,7 +66488,7 @@ function shortToolName(name, names) {
66142
66488
  if (name.length <= CODEX_TOOL_NAME_LIMIT) {
66143
66489
  return name;
66144
66490
  }
66145
- const hash2 = (0, import_node_crypto10.createHash)("sha256").update(name).digest("hex").slice(0, TOOL_NAME_HASH_CHARS);
66491
+ const hash2 = (0, import_node_crypto11.createHash)("sha256").update(name).digest("hex").slice(0, TOOL_NAME_HASH_CHARS);
66146
66492
  const shortened = `${name.slice(0, CODEX_TOOL_NAME_LIMIT - TOOL_NAME_HASH_CHARS - 1)}_${hash2}`;
66147
66493
  names.set(shortened, name);
66148
66494
  return shortened;
@@ -67000,6 +67346,11 @@ function singleHeader(headers, name) {
67000
67346
  const value = headers[name];
67001
67347
  return typeof value === "string" ? value : void 0;
67002
67348
  }
67349
+ var OAUTH_AUTHORIZATION_PREFIX = "Bearer sk-ant-oat";
67350
+ function oauthAuthorizationOf(headers) {
67351
+ const value = singleHeader(headers, "authorization");
67352
+ return value?.startsWith(OAUTH_AUTHORIZATION_PREFIX) === true ? value : void 0;
67353
+ }
67003
67354
  function sessionCreateId(body) {
67004
67355
  let parsed;
67005
67356
  try {
@@ -67143,7 +67494,7 @@ function createRcSessionTracker(deps) {
67143
67494
  }
67144
67495
  const tail = path41.slice(RC_SESSIONS_PATH_PREFIX.length);
67145
67496
  const facts = {
67146
- authorization: singleHeader(request7.headers, "authorization"),
67497
+ oauthAuthorization: oauthAuthorizationOf(request7.headers),
67147
67498
  anthropicVersion: singleHeader(request7.headers, "anthropic-version"),
67148
67499
  anthropicClientPlatform: singleHeader(request7.headers, "anthropic-client-platform")
67149
67500
  };
@@ -67185,7 +67536,7 @@ function createRcSessionTracker(deps) {
67185
67536
  }
67186
67537
  const entry = entries.get(id) ?? birth(id, facts);
67187
67538
  entry.lastSeenAt = deps.now();
67188
- entry.authorization = facts.authorization ?? entry.authorization;
67539
+ entry.oauthAuthorization = facts.oauthAuthorization ?? entry.oauthAuthorization;
67189
67540
  entry.anthropicVersion = facts.anthropicVersion ?? entry.anthropicVersion;
67190
67541
  entry.anthropicClientPlatform = facts.anthropicClientPlatform ?? entry.anthropicClientPlatform;
67191
67542
  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;
@@ -67273,7 +67624,7 @@ function createRcSessionTracker(deps) {
67273
67624
  },
67274
67625
  credentialOf: (sessionId) => {
67275
67626
  const entry = entries.get(sessionId);
67276
- return entry === void 0 ? void 0 : { authorization: entry.authorization, anthropicVersion: entry.anthropicVersion, anthropicClientPlatform: entry.anthropicClientPlatform };
67627
+ return entry === void 0 ? void 0 : { authorization: entry.oauthAuthorization, anthropicVersion: entry.anthropicVersion, anthropicClientPlatform: entry.anthropicClientPlatform };
67277
67628
  },
67278
67629
  completePending: (sessionId, requestId) => {
67279
67630
  entries.get(sessionId)?.pending.delete(requestId);
@@ -67375,6 +67726,9 @@ function rcEventWriteResultFromAnswer(answer) {
67375
67726
  }
67376
67727
  return { ok: true, sequenceNums };
67377
67728
  }
67729
+ function noOAuthCredentialResult(sessionId) {
67730
+ return { ok: false, message: `no claude.ai OAuth bearer has been observed for session ${sessionId}: only worker calls crossed this door, and the worker JWT they carry is answered 401 on the client half. Reconnect Remote Control through this door and the create's own bearer will be observed` };
67731
+ }
67378
67732
  function rcWriteHeaders(credential) {
67379
67733
  const headers = { "content-type": "application/json" };
67380
67734
  if (credential.authorization !== void 0) {
@@ -67393,6 +67747,9 @@ async function injectRcUserMessage(deps, sessionId, text2) {
67393
67747
  if (credential === void 0) {
67394
67748
  return { ok: false, message: `the front door has not observed Remote Control session ${sessionId}: it may never have passed through this door, or it ended or expired (an entry lives only a bounded idle period past its last observed traffic)` };
67395
67749
  }
67750
+ if (credential.authorization === void 0) {
67751
+ return noOAuthCredentialResult(sessionId);
67752
+ }
67396
67753
  const body = JSON.stringify(buildRcEventWriteBody(buildRcUserMessagePayload(deps.newUuid(), sessionId, text2)));
67397
67754
  let answer;
67398
67755
  try {
@@ -67411,6 +67768,9 @@ async function answerRcControlRequest(deps, sessionId, requestId, decision) {
67411
67768
  if (credential === void 0) {
67412
67769
  return { ok: false, message: `the front door has not observed Remote Control session ${sessionId}: it may never have passed through this door, or it ended or expired (an entry lives only a bounded idle period past its last observed traffic)` };
67413
67770
  }
67771
+ if (credential.authorization === void 0) {
67772
+ return noOAuthCredentialResult(sessionId);
67773
+ }
67414
67774
  if (!deps.pendingOf(sessionId).some((pending) => pending.requestId === requestId)) {
67415
67775
  return { ok: false, message: `the front door has not observed control request ${requestId} pending on session ${sessionId}: it was answered already (by this door or by an attached client), it passed its answer deadline (the protocol's permission round-trip bound), or it never passed through this door` };
67416
67776
  }
@@ -67732,7 +68092,7 @@ function realFrontDoorSupervisorPorts(paths) {
67732
68092
  let directPort = 0;
67733
68093
  const codexPorts = createCodexRoutePorts(log);
67734
68094
  const rcTracker = createRcSessionTracker({ now: () => Date.now(), idleMs: RC_IDLE_EXPIRY_MS });
67735
- const rcControlToken = (0, import_node_crypto11.randomUUID)();
68095
+ const rcControlToken = (0, import_node_crypto12.randomUUID)();
67736
68096
  const resolveRoute = rcObservingResolver(createProviderRouteResolver({ fs: realFsPort, providersDir: paths.providersDir, codexPorts, directPort: () => directPort }), rcTracker);
67737
68097
  const isLiveToken = (token) => isLiveCapability(token, liveSessionTokens(realFarmFs, paths.frontdoorSessionsDir));
67738
68098
  const usageStore = createUsageStore({
@@ -67759,8 +68119,8 @@ function realFrontDoorSupervisorPorts(paths) {
67759
68119
  now: () => Date.now(),
67760
68120
  headroomSocket: () => headroomSocketTarget(realFarmFs, realHeadroomSocketTrust, paths),
67761
68121
  // The per-generation capability the direct listener demands: held only in this process's memory, so a loopback process that discovers the direct port still cannot use it.
67762
- hopSecret: (0, import_node_crypto11.randomUUID)(),
67763
- custody: createCredentialCustody(() => (0, import_node_crypto11.randomUUID)()),
68122
+ hopSecret: (0, import_node_crypto12.randomUUID)(),
68123
+ custody: createCredentialCustody(() => (0, import_node_crypto12.randomUUID)()),
67764
68124
  log
67765
68125
  });
67766
68126
  let ca;
@@ -67786,7 +68146,7 @@ function realFrontDoorSupervisorPorts(paths) {
67786
68146
  startProviderListener: async (preferredPort) => {
67787
68147
  const authority = loadCa();
67788
68148
  const rcDial = realRcEventDial();
67789
- const rcInject = async (sessionId, text2) => await injectRcUserMessage({ credentialOf: rcTracker.credentialOf, dial: rcDial, newUuid: import_node_crypto11.randomUUID }, sessionId, text2);
68149
+ const rcInject = async (sessionId, text2) => await injectRcUserMessage({ credentialOf: rcTracker.credentialOf, dial: rcDial, newUuid: import_node_crypto12.randomUUID }, sessionId, text2);
67790
68150
  const rcAnswer = async (sessionId, requestId, decision) => await answerRcControlRequest({ credentialOf: rcTracker.credentialOf, pendingOf: (id) => rcTracker.pendingOf(id), completePending: rcTracker.completePending, dial: rcDial }, sessionId, requestId, decision);
67791
68151
  realFarmFs.mkdirp(paths.frontdoorDir);
67792
68152
  realFarmFs.writeFilePrivate(paths.frontdoorControlTokenFile, `${rcControlToken}
@@ -67810,7 +68170,7 @@ function realFrontDoorSupervisorPorts(paths) {
67810
68170
  },
67811
68171
  startConnectListener: async (preferredPort) => {
67812
68172
  const transparentPort = process.env.AGENT_SHIM_TRANSPARENT_SURFACE === void 0 ? void 0 : Number(process.env.AGENT_SHIM_TRANSPARENT_SURFACE);
67813
- const transparentCapability = transparentPort === void 0 || Number.isNaN(transparentPort) ? void 0 : (0, import_node_crypto11.randomUUID)();
68173
+ const transparentCapability = transparentPort === void 0 || Number.isNaN(transparentPort) ? void 0 : (0, import_node_crypto12.randomUUID)();
67814
68174
  if (transparentCapability !== void 0) {
67815
68175
  writeFrontDoorSession(realFarmFs, paths.frontdoorSessionsDir, { pid: process.pid, startedAt: Date.now(), token: transparentCapability });
67816
68176
  }
@@ -68596,33 +68956,6 @@ function subjectName(positional, provider) {
68596
68956
  // src/doctorReport.ts
68597
68957
  var import_node_fs14 = __toESM(require("node:fs"), 1);
68598
68958
  var import_node_path34 = __toESM(require("node:path"), 1);
68599
-
68600
- // src/headroom/source.ts
68601
- var GIT_SPEC_RE = /git\+[^@\s]+(?:@([^\s#]+))?/;
68602
- var COMMIT_SHA_RE = /^[0-9a-f]{40}$/i;
68603
- var DirectUrlSchema = external_exports.object({ vcs_info: external_exports.object({ commit_id: external_exports.string() }) });
68604
- function isMovingGitSource(spec) {
68605
- const match = GIT_SPEC_RE.exec(spec);
68606
- if (match === null) {
68607
- return false;
68608
- }
68609
- const ref = match[1];
68610
- return ref === void 0 || !COMMIT_SHA_RE.test(ref);
68611
- }
68612
- function pinnedGitCommit(spec) {
68613
- const ref = GIT_SPEC_RE.exec(spec)?.[1];
68614
- return ref !== void 0 && COMMIT_SHA_RE.test(ref) ? ref.toLowerCase() : void 0;
68615
- }
68616
- function parseInstalledCommit(directUrlJson) {
68617
- try {
68618
- const parsed = DirectUrlSchema.safeParse(JSON.parse(directUrlJson));
68619
- return parsed.success ? parsed.data.vcs_info.commit_id.toLowerCase() : void 0;
68620
- } catch {
68621
- return void 0;
68622
- }
68623
- }
68624
-
68625
- // src/doctorReport.ts
68626
68959
  function refinePathShadow(status, ownExecutablePath, realpath) {
68627
68960
  if (status.status !== "shadowed") {
68628
68961
  return status;
@@ -69130,7 +69463,7 @@ var import_node_child_process5 = require("node:child_process");
69130
69463
  var import_node_fs15 = __toESM(require("node:fs"), 1);
69131
69464
 
69132
69465
  // src/frontdoor/ensure.ts
69133
- var import_node_crypto12 = require("node:crypto");
69466
+ var import_node_crypto13 = require("node:crypto");
69134
69467
  var FRONTDOOR_START_TIMEOUT_MS = 3e4;
69135
69468
  var FRONTDOOR_LAUNCHER_POLL_MS = 100;
69136
69469
  var FrontDoorStartError = class extends CliError {
@@ -69164,7 +69497,7 @@ function ensureFrontDoor(params) {
69164
69497
  continue;
69165
69498
  }
69166
69499
  if (verdict.ok) {
69167
- const token = (0, import_node_crypto12.randomUUID)();
69500
+ const token = (0, import_node_crypto13.randomUUID)();
69168
69501
  writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token });
69169
69502
  return { port: state.port, connectPort: state.connectPort, token };
69170
69503
  }
@@ -69268,7 +69601,7 @@ function probeFrontDoorSync(port, caPem) {
69268
69601
  }
69269
69602
 
69270
69603
  // src/frontdoor/trust.ts
69271
- var import_node_crypto13 = require("node:crypto");
69604
+ var import_node_crypto14 = require("node:crypto");
69272
69605
  var import_node_path35 = __toESM(require("node:path"), 1);
69273
69606
  var BUNDLE_NAME_HEX_DIGITS = 16;
69274
69607
  function resolveTrustBundle(params) {
@@ -69291,7 +69624,7 @@ function resolveTrustBundle(params) {
69291
69624
  }
69292
69625
  const combined = `${inheritedPem.trimEnd()}
69293
69626
  ${caPem}`;
69294
- const bundle = import_node_path35.default.join(bundlesDir, `${(0, import_node_crypto13.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
69627
+ const bundle = import_node_path35.default.join(bundlesDir, `${(0, import_node_crypto14.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
69295
69628
  if (!fs19.exists(bundle)) {
69296
69629
  fs19.mkdirp(bundlesDir);
69297
69630
  fs19.writeFileAtomic(bundle, combined);
@@ -69344,315 +69677,6 @@ function realFrontDoorPort(paths, spawnDaemon) {
69344
69677
  };
69345
69678
  }
69346
69679
 
69347
- // src/headroom/settings.ts
69348
- var import_node_crypto14 = require("node:crypto");
69349
- function settingsOf(config2) {
69350
- return {
69351
- ...config2.mode === void 0 ? {} : { mode: config2.mode },
69352
- ...config2.targetRatio === void 0 ? {} : { targetRatio: config2.targetRatio },
69353
- ...config2.ccr === void 0 ? {} : { ccr: config2.ccr },
69354
- ...config2.rolloutChannel === void 0 ? {} : { rolloutChannel: config2.rolloutChannel },
69355
- ...config2.interceptToolResults === void 0 ? {} : { interceptToolResults: config2.interceptToolResults },
69356
- ...config2.readMaturation === void 0 ? {} : { readMaturation: config2.readMaturation }
69357
- };
69358
- }
69359
- function settingsArgs(settings2) {
69360
- return [
69361
- ...settings2.mode === void 0 ? [] : ["--mode", settings2.mode],
69362
- ...settings2.targetRatio === void 0 ? [] : ["--target-ratio", String(settings2.targetRatio)],
69363
- ...settings2.ccr === "lossless" ? ["--lossless"] : [],
69364
- ...settings2.ccr === "none" ? ["--no-ccr"] : [],
69365
- ...settings2.interceptToolResults === true ? ["--intercept-tool-results"] : [],
69366
- ...settings2.readMaturation === true ? ["--read-maturation"] : []
69367
- ];
69368
- }
69369
- function settingsEnv(settings2) {
69370
- return settings2.rolloutChannel === void 0 ? {} : { HEADROOM_ROLLOUT_CHANNEL: settings2.rolloutChannel };
69371
- }
69372
- function hashSettings(settings2) {
69373
- return (0, import_node_crypto14.createHash)("sha256").update(JSON.stringify([...settingsArgs(settings2), JSON.stringify(settingsEnv(settings2))])).digest("hex");
69374
- }
69375
-
69376
- // src/headroom/supervisor.ts
69377
- function resolveSupervisorConfig(configured) {
69378
- return {
69379
- source: configured.source ?? HEADROOM_DEFAULT_SOURCE,
69380
- idleShutdownMinutes: configured.idleShutdownMinutes ?? HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES,
69381
- settings: settingsOf(configured)
69382
- };
69383
- }
69384
- var HEADROOM_BACKOFF_BASE_MS = 500;
69385
- var HEADROOM_BACKOFF_CAP_MS = 3e4;
69386
- var HEADROOM_START_RETRY_BUDGET = 5;
69387
- var HEADROOM_READY_TIMEOUT_MS = 15e3;
69388
- var HEADROOM_POLL_MS = 1e3;
69389
- var MS_PER_MINUTE2 = 6e4;
69390
- var STOP_POLL_MS = 100;
69391
- var TERM_GRACE_MS = 1500;
69392
- var KILL_GRACE_MS = 1500;
69393
- function stopSupervisedProcess(pid, primitives) {
69394
- const send = (signal) => {
69395
- try {
69396
- primitives.signal(pid, signal);
69397
- } catch {
69398
- }
69399
- };
69400
- send("SIGTERM");
69401
- if (awaitExit(pid, primitives, TERM_GRACE_MS)) {
69402
- return "exited-on-term";
69403
- }
69404
- send("SIGKILL");
69405
- if (awaitExit(pid, primitives, KILL_GRACE_MS)) {
69406
- return "killed";
69407
- }
69408
- return "still-running";
69409
- }
69410
- function awaitExit(pid, primitives, budgetMs) {
69411
- const deadline = primitives.now() + budgetMs;
69412
- while (primitives.isRunning(pid)) {
69413
- if (primitives.now() >= deadline) {
69414
- return false;
69415
- }
69416
- primitives.waitMs(STOP_POLL_MS);
69417
- }
69418
- return true;
69419
- }
69420
- function backoffForAttempt(attempt) {
69421
- return Math.min(HEADROOM_BACKOFF_CAP_MS, HEADROOM_BACKOFF_BASE_MS * 2 ** (attempt - 1));
69422
- }
69423
- function versionSatisfies(version2, source) {
69424
- if (version2 === void 0) {
69425
- return false;
69426
- }
69427
- const specifier = /==|>=|<=|!=|>|<|~=/.exec(source);
69428
- if (specifier === null) {
69429
- return true;
69430
- }
69431
- const installed = parseVersion(version2);
69432
- const wanted = parseVersion(source.slice(specifier.index + specifier[0].length));
69433
- if (installed === void 0 || wanted === void 0) {
69434
- return true;
69435
- }
69436
- const cmp = compareVersions2(installed, wanted);
69437
- switch (specifier[0]) {
69438
- case "==":
69439
- return cmp === 0;
69440
- case "!=":
69441
- return cmp !== 0;
69442
- case ">=":
69443
- return cmp >= 0;
69444
- case "<=":
69445
- return cmp <= 0;
69446
- case ">":
69447
- return cmp > 0;
69448
- case "<":
69449
- return cmp < 0;
69450
- case "~=":
69451
- return compareVersions2(installed.slice(0, Math.max(0, wanted.length - 1)), wanted.slice(0, Math.max(0, wanted.length - 1))) === 0 && cmp >= 0;
69452
- default:
69453
- return true;
69454
- }
69455
- }
69456
- function parseVersion(input2) {
69457
- const match = /(\d+)(\.\d+)*/.exec(input2);
69458
- if (match === null) {
69459
- return void 0;
69460
- }
69461
- return match[0].split(".").map((part) => Number.parseInt(part, 10));
69462
- }
69463
- function compareVersions2(a2, b) {
69464
- for (let index = 0; index < Math.max(a2.length, b.length); index += 1) {
69465
- const left = a2[index] ?? 0;
69466
- const right = b[index] ?? 0;
69467
- if (left !== right) {
69468
- return left - right;
69469
- }
69470
- }
69471
- return 0;
69472
- }
69473
- var HEADROOM_SUPERVISOR_STILL_RUNNING = -1;
69474
- async function runSupervisor(initialConfig, ports, options = {}) {
69475
- const { fs: fs19, paths } = ports;
69476
- let config2 = initialConfig;
69477
- const previousState = readHeadroomState(fs19, paths.headroomStateFile);
69478
- if (previousState?.supervisorPid !== void 0 && previousState.supervisorPid !== ports.ownPid && ports.isRunning(previousState.supervisorPid)) {
69479
- ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: supervisor ${String(previousState.supervisorPid)} already owns the daemon; exiting`);
69480
- return 0;
69481
- }
69482
- let installedSource = previousState?.installedSource;
69483
- const ownsState = () => {
69484
- const owner = readHeadroomState(fs19, paths.headroomStateFile)?.supervisorPid;
69485
- return owner === void 0 || owner === ports.ownPid || !ports.isRunning(owner);
69486
- };
69487
- const writeOwnState = (state) => {
69488
- if (!ownsState()) {
69489
- return false;
69490
- }
69491
- writeHeadroomState(fs19, paths.headroomStateFile, state);
69492
- return true;
69493
- };
69494
- const fail = (message) => {
69495
- if (writeOwnState({ lastError: message })) {
69496
- fs19.removeRecursive(paths.headroomLockFile);
69497
- }
69498
- ports.log(`agent-shim headroom supervisor: ${message}`);
69499
- return 1;
69500
- };
69501
- const ensureInstalled = () => {
69502
- const version3 = ports.headroomVersion();
69503
- const versionOk = version3 !== void 0 && versionSatisfies(version3, config2.source);
69504
- const pinned = pinnedGitCommit(config2.source);
69505
- const commitOk = pinned === void 0 || ports.installedCommit() === pinned;
69506
- if (versionOk && commitOk && (installedSource === void 0 || installedSource === config2.source)) {
69507
- installedSource = config2.source;
69508
- return true;
69509
- }
69510
- ports.log(`agent-shim headroom supervisor: installing headroom from ${config2.source}`);
69511
- const result = ports.install(config2.source);
69512
- if (!result.ok) {
69513
- return false;
69514
- }
69515
- installedSource = config2.source;
69516
- return true;
69517
- };
69518
- const socket = prepareHeadroomSocket(fs19, ports.socketTrust, paths, ports.ownPid);
69519
- if (socket.refused !== void 0) {
69520
- return fail(socket.refused);
69521
- }
69522
- const { socketPath } = socket;
69523
- pruneStaleHeadroomSockets(fs19, paths, ports.isRunning);
69524
- if (!ensureInstalled()) {
69525
- return fail(`could not install headroom from ${config2.source}: install failed (is uv installed and on PATH?)`);
69526
- }
69527
- const version2 = ports.headroomVersion() ?? "unknown";
69528
- writeOwnState({ supervisorPid: ports.ownPid, version: version2, installedSource });
69529
- ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${allowlistOf(ports).join(", ")}]`);
69530
- const orphanPid = previousState?.headroomPid;
69531
- if (orphanPid !== void 0 && ports.isRunning(orphanPid)) {
69532
- ports.log(`agent-shim headroom supervisor: stopping daemon pid ${String(orphanPid)} left behind by the previous supervisor`);
69533
- ports.stopProcess(orphanPid);
69534
- }
69535
- let headroomPid;
69536
- let runningHash;
69537
- let runningSettingsHash;
69538
- let consecutiveFailures = 0;
69539
- let idleSince;
69540
- let superseded = false;
69541
- let ticks = 0;
69542
- for (; ; ) {
69543
- if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
69544
- return HEADROOM_SUPERVISOR_STILL_RUNNING;
69545
- }
69546
- ticks += 1;
69547
- config2 = ports.readConfig();
69548
- const settingsHash = hashSettings(config2.settings);
69549
- const allowlist = allowlistOf(ports);
69550
- const allowlistHash = hashAllowlist(allowlist);
69551
- pruneDeadSessions(fs19, paths.headroomSessionsDir, ports.isRunning);
69552
- const ownsNow = ownsState();
69553
- if (!ownsNow && !superseded) {
69554
- ports.log("agent-shim headroom supervisor: another supervisor now owns the state file; serving this daemon's own sessions until they end");
69555
- }
69556
- superseded = !ownsNow;
69557
- const crashed = headroomPid !== void 0 && !ports.isRunning(headroomPid);
69558
- if (headroomPid === void 0 || crashed) {
69559
- if (crashed) {
69560
- ports.log(`agent-shim headroom supervisor: headroom pid ${String(headroomPid)} died`);
69561
- headroomPid = void 0;
69562
- runningHash = void 0;
69563
- runningSettingsHash = void 0;
69564
- writeOwnState({
69565
- supervisorPid: ports.ownPid,
69566
- version: version2,
69567
- installedSource
69568
- });
69569
- }
69570
- if (consecutiveFailures >= HEADROOM_START_RETRY_BUDGET) {
69571
- return fail(`headroom failed to become ready ${String(consecutiveFailures)} times in a row; giving up`);
69572
- }
69573
- if (installedSource !== config2.source && !ensureInstalled()) {
69574
- return fail(`could not install headroom from ${config2.source}: install failed (is uv installed and on PATH?)`);
69575
- }
69576
- const pid = ports.spawnHeadroom(socketPath, allowlist, config2.settings);
69577
- const ready = await waitUntilReady(ports, socketPath);
69578
- if (ready) {
69579
- consecutiveFailures = 0;
69580
- headroomPid = pid;
69581
- runningHash = allowlistHash;
69582
- runningSettingsHash = settingsHash;
69583
- const recorded = writeOwnState({
69584
- supervisorPid: ports.ownPid,
69585
- headroomPid: pid,
69586
- socketPath,
69587
- version: version2,
69588
- allowlistHash,
69589
- settingsHash,
69590
- installedSource: config2.source
69591
- });
69592
- if (recorded) {
69593
- fs19.removeRecursive(paths.headroomLockFile);
69594
- }
69595
- idleSince = void 0;
69596
- ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on unix socket ${socketPath}`);
69597
- } else {
69598
- ports.stopProcess(pid);
69599
- consecutiveFailures += 1;
69600
- ports.log(
69601
- `agent-shim headroom supervisor: headroom did not become ready on unix socket ${socketPath} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
69602
- );
69603
- await ports.sleep(backoffForAttempt(consecutiveFailures));
69604
- continue;
69605
- }
69606
- } else {
69607
- if (runningHash !== allowlistHash || runningSettingsHash !== settingsHash || installedSource !== config2.source) {
69608
- if (sessionsForSupervisor(fs19, paths.headroomSessionsDir, ports.ownPid).length === 0) {
69609
- ports.log("agent-shim headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
69610
- ports.stopProcess(headroomPid);
69611
- headroomPid = void 0;
69612
- runningHash = void 0;
69613
- runningSettingsHash = void 0;
69614
- continue;
69615
- }
69616
- }
69617
- const sessions = sessionsForSupervisor(fs19, paths.headroomSessionsDir, ports.ownPid);
69618
- if (sessions.length === 0) {
69619
- idleSince ??= ports.now();
69620
- const idleMs = ports.now() - idleSince;
69621
- if (idleMs >= config2.idleShutdownMinutes * MS_PER_MINUTE2) {
69622
- ports.log(
69623
- `agent-shim headroom supervisor: no sessions for ${String(config2.idleShutdownMinutes)} minute(s); stopping headroom and exiting`
69624
- );
69625
- ports.stopProcess(headroomPid);
69626
- writeOwnState({ version: version2 });
69627
- return 0;
69628
- }
69629
- } else {
69630
- idleSince = void 0;
69631
- }
69632
- }
69633
- await ports.sleep(HEADROOM_POLL_MS);
69634
- }
69635
- }
69636
- function currentHeadroomAllowlist(fs19, paths) {
69637
- const providers = readAllProviders(fs19, paths.providersDir).map((entry) => entry.provider);
69638
- return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(fs19, paths.frontdoorStateFile))));
69639
- }
69640
- function allowlistOf(ports) {
69641
- return currentHeadroomAllowlist(ports.fs, ports.paths);
69642
- }
69643
- async function waitUntilReady(ports, socketPath) {
69644
- const deadline = ports.now() + HEADROOM_READY_TIMEOUT_MS;
69645
- for (; ; ) {
69646
- if (await ports.ready(socketPath)) {
69647
- return true;
69648
- }
69649
- if (ports.now() >= deadline) {
69650
- return false;
69651
- }
69652
- await ports.sleep(HEADROOM_POLL_MS);
69653
- }
69654
- }
69655
-
69656
69680
  // src/headroom/commands.ts
69657
69681
  function collectHeadroomStatus(fsPort, paths, isRunning) {
69658
69682
  const state = readHeadroomState(fsPort, paths.headroomStateFile) ?? {};
@@ -71040,7 +71064,7 @@ function prepareLaunch(params) {
71040
71064
  let headroom;
71041
71065
  const headroomPort = params.headroom;
71042
71066
  if (resolvedFlags.headroom && headroomPort !== void 0) {
71043
- headroom = headroomPort.ensure();
71067
+ headroom = headroomPort.ensure({ routesProvider: resolvedProvider !== void 0 });
71044
71068
  const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
71045
71069
  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})`);
71046
71070
  } else if (resolvedFlags.headroom) {