agent-shim 8.43.0 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2619,7 +2619,7 @@ var init_package = __esm({
2619
2619
  "package.json"() {
2620
2620
  package_default = {
2621
2621
  name: "agent-shim",
2622
- version: "8.43.0",
2622
+ version: "9.0.0",
2623
2623
  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.",
2624
2624
  license: "MIT",
2625
2625
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -2723,7 +2723,7 @@ var init_package = __esm({
2723
2723
 
2724
2724
  // src/headroom/state.ts
2725
2725
  import { createHash as createHash3 } from "node:crypto";
2726
- import path10 from "node:path";
2726
+ import path11 from "node:path";
2727
2727
  import { z as z5 } from "zod";
2728
2728
  function parseJson(raw, schema) {
2729
2729
  if (raw === void 0 || raw.trim() === "") {
@@ -2740,10 +2740,36 @@ function readHeadroomState(fs12, stateFile) {
2740
2740
  }
2741
2741
  }
2742
2742
  function writeHeadroomState(fs12, stateFile, state) {
2743
- fs12.mkdirp(path10.dirname(stateFile));
2743
+ fs12.mkdirp(path11.dirname(stateFile));
2744
2744
  fs12.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
2745
2745
  `);
2746
2746
  }
2747
+ function resolveServingHeadroomState(fs12, files, isRunning) {
2748
+ const current = readHeadroomState(fs12, files.stateFile);
2749
+ if (current !== void 0) {
2750
+ return { path: files.stateFile, state: current };
2751
+ }
2752
+ const legacy = readHeadroomState(fs12, files.legacyStateFile);
2753
+ if (legacy?.supervisorPid !== void 0 && isRunning(legacy.supervisorPid)) {
2754
+ return { path: files.legacyStateFile, state: legacy };
2755
+ }
2756
+ return void 0;
2757
+ }
2758
+ function migrateHeadroomState(fs12, files, isRunning) {
2759
+ const legacy = readHeadroomState(fs12, files.legacyStateFile);
2760
+ const legacyLive = legacy?.supervisorPid !== void 0 && isRunning(legacy.supervisorPid);
2761
+ const current = readHeadroomState(fs12, files.stateFile);
2762
+ if (current !== void 0 || legacyLive) {
2763
+ if (!legacyLive && fs12.readFileUtf8(files.legacyStateFile) !== void 0) {
2764
+ fs12.removeRecursive(files.legacyStateFile);
2765
+ }
2766
+ return;
2767
+ }
2768
+ if (legacy !== void 0) {
2769
+ writeHeadroomState(fs12, files.stateFile, legacy);
2770
+ }
2771
+ fs12.removeRecursive(files.legacyStateFile);
2772
+ }
2747
2773
  function headroomAllowlist(providers) {
2748
2774
  const urls = /* @__PURE__ */ new Set([HEADROOM_ANTHROPIC_UPSTREAM]);
2749
2775
  for (const provider of providers) {
@@ -2768,7 +2794,7 @@ function readAllProviders(fs12, providersDir) {
2768
2794
  continue;
2769
2795
  }
2770
2796
  try {
2771
- const parsed = parseJson(fs12.readFileUtf8(path10.join(providersDir, name)), ProviderSchema);
2797
+ const parsed = parseJson(fs12.readFileUtf8(path11.join(providersDir, name)), ProviderSchema);
2772
2798
  if (parsed !== void 0) {
2773
2799
  result.push({ name: name.slice(0, -".json".length), provider: parsed });
2774
2800
  }
@@ -2780,11 +2806,11 @@ function readAllProviders(fs12, providersDir) {
2780
2806
  }
2781
2807
  function writeSession(fs12, sessionsDir, session) {
2782
2808
  fs12.mkdirp(sessionsDir);
2783
- fs12.writeFileUtf8(path10.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
2809
+ fs12.writeFileUtf8(path11.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
2784
2810
  `);
2785
2811
  }
2786
2812
  function removeSession(fs12, sessionsDir, pid) {
2787
- fs12.removeRecursive(path10.join(sessionsDir, `${String(pid)}.json`));
2813
+ fs12.removeRecursive(path11.join(sessionsDir, `${String(pid)}.json`));
2788
2814
  }
2789
2815
  function listSessions(fs12, sessionsDir) {
2790
2816
  const sessions = [];
@@ -2793,7 +2819,7 @@ function listSessions(fs12, sessionsDir) {
2793
2819
  continue;
2794
2820
  }
2795
2821
  try {
2796
- const parsed = parseJson(fs12.readFileUtf8(path10.join(sessionsDir, name)), HeadroomSessionSchema);
2822
+ const parsed = parseJson(fs12.readFileUtf8(path11.join(sessionsDir, name)), HeadroomSessionSchema);
2797
2823
  if (parsed !== void 0) {
2798
2824
  sessions.push(parsed);
2799
2825
  }
@@ -2823,13 +2849,12 @@ function readStartLock(fs12, lockFile) {
2823
2849
  return void 0;
2824
2850
  }
2825
2851
  }
2826
- var HEADROOM_ANTHROPIC_UPSTREAM, HEADROOM_STATE_SCHEMA_VERSION, HeadroomStateSchema, HeadroomSessionSchema, HeadroomLockSchema;
2852
+ var HEADROOM_ANTHROPIC_UPSTREAM, HeadroomStateSchema, HeadroomSessionSchema, HeadroomLockSchema;
2827
2853
  var init_state2 = __esm({
2828
2854
  "src/headroom/state.ts"() {
2829
2855
  "use strict";
2830
2856
  init_schema();
2831
2857
  HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
2832
- HEADROOM_STATE_SCHEMA_VERSION = 2;
2833
2858
  HeadroomStateSchema = z5.strictObject({
2834
2859
  /** The supervisor process owning the daemon. Alive means someone is keeping headroom running. */
2835
2860
  supervisorPid: z5.number().int().positive().optional(),
@@ -2861,8 +2886,9 @@ function ensureHeadroom(params) {
2861
2886
  const deadline = ports.now() + HEADROOM_START_TIMEOUT_MS;
2862
2887
  let spawnedSupervisor = false;
2863
2888
  let awaitingAllowlist = false;
2889
+ migrateHeadroomState(ports.fs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning);
2864
2890
  for (; ; ) {
2865
- const state = readHeadroomState(ports.fs, paths.headroomStateFile);
2891
+ const state = resolveServingHeadroomState(ports.fs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning)?.state;
2866
2892
  if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
2867
2893
  const daemonUp = state.socketPath !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
2868
2894
  if (daemonUp && state.socketPath !== void 0) {
@@ -2963,9 +2989,9 @@ var init_settings = __esm({
2963
2989
  });
2964
2990
 
2965
2991
  // src/headroom/socket.ts
2966
- import path11 from "node:path";
2992
+ import path12 from "node:path";
2967
2993
  function headroomSocketPath(paths, supervisorPid) {
2968
- return path11.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
2994
+ return path12.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
2969
2995
  }
2970
2996
  function platformRefusal(platform) {
2971
2997
  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;
@@ -2994,7 +3020,7 @@ function verifyHeadroomSocket(socketPath, ports) {
2994
3020
  return { refused: unsupported };
2995
3021
  }
2996
3022
  const uid = ports.currentUid();
2997
- const directory = path11.dirname(socketPath);
3023
+ const directory = path12.dirname(socketPath);
2998
3024
  const refusal = ownerOnlyRefusal("socket directory", directory, ports.lstat(directory), "dir", uid) ?? ownerOnlyRefusal("socket", socketPath, ports.lstat(socketPath), "socket", uid);
2999
3025
  return refusal === void 0 ? { socketPath } : { refused: refusal };
3000
3026
  }
@@ -3024,7 +3050,7 @@ function pruneStaleHeadroomSockets(fs12, paths, isRunning) {
3024
3050
  if (pid === void 0 || isRunning(Number.parseInt(pid, 10))) {
3025
3051
  continue;
3026
3052
  }
3027
- fs12.removeRecursive(path11.join(paths.headroomSocketDir, name));
3053
+ fs12.removeRecursive(path12.join(paths.headroomSocketDir, name));
3028
3054
  removed.push(name);
3029
3055
  }
3030
3056
  return removed;
@@ -3131,7 +3157,8 @@ function compareVersions2(a, b) {
3131
3157
  async function runSupervisor(initialConfig, ports, options = {}) {
3132
3158
  const { fs: fs12, paths } = ports;
3133
3159
  let config = initialConfig;
3134
- const previousState = readHeadroomState(fs12, paths.headroomStateFile);
3160
+ migrateHeadroomState(fs12, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning);
3161
+ const previousState = resolveServingHeadroomState(fs12, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning)?.state;
3135
3162
  if (previousState?.supervisorPid !== void 0 && previousState.supervisorPid !== ports.ownPid && ports.isRunning(previousState.supervisorPid)) {
3136
3163
  ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: supervisor ${String(previousState.supervisorPid)} already owns the daemon; exiting`);
3137
3164
  return 0;
@@ -3334,7 +3361,7 @@ import { spawn, spawnSync } from "node:child_process";
3334
3361
  import { createHash as createHash5 } from "node:crypto";
3335
3362
  import fs3 from "node:fs";
3336
3363
  import os3 from "node:os";
3337
- import path12 from "node:path";
3364
+ import path13 from "node:path";
3338
3365
  import { isSea } from "node:sea";
3339
3366
  function isEnoent3(error) {
3340
3367
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
@@ -3361,7 +3388,7 @@ function realIsProcessRunning(pid) {
3361
3388
  return realIsProcessAlive(pid) && !realIsProcessZombie(pid);
3362
3389
  }
3363
3390
  function expandHome2(filePath) {
3364
- return filePath.startsWith("~/") ? path12.join(os3.homedir(), filePath.slice(1)) : filePath;
3391
+ return filePath.startsWith("~/") ? path13.join(os3.homedir(), filePath.slice(1)) : filePath;
3365
3392
  }
3366
3393
  function hasDesktopSession() {
3367
3394
  if (process.platform === "darwin") {
@@ -3405,7 +3432,7 @@ function spawnDaemonThroughScript(script) {
3405
3432
  return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: process.execPath, args: [script, subcommand] }, paths, subcommand, logPath);
3406
3433
  }
3407
3434
  function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
3408
- fs3.mkdirSync(path12.dirname(logPath), { recursive: true });
3435
+ fs3.mkdirSync(path13.dirname(logPath), { recursive: true });
3409
3436
  const logFd = fs3.openSync(logPath, "a");
3410
3437
  try {
3411
3438
  const child = spawn(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
@@ -3458,7 +3485,7 @@ function listVersionsDir(dir) {
3458
3485
  throw error;
3459
3486
  }
3460
3487
  return entries.filter((entry) => entry.isFile()).map((entry) => {
3461
- const fullPath = path12.join(dir, entry.name);
3488
+ const fullPath = path13.join(dir, entry.name);
3462
3489
  const stat = fs3.statSync(fullPath);
3463
3490
  return {
3464
3491
  name: entry.name,
@@ -3472,7 +3499,7 @@ function windowsPathExtensions(pathext) {
3472
3499
  return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
3473
3500
  }
3474
3501
  function resolveExecutableCandidate(dir, name, env) {
3475
- const candidate = path12.join(dir, name);
3502
+ const candidate = path13.join(dir, name);
3476
3503
  if (env.platform === "win32") {
3477
3504
  const extensions = windowsPathExtensions(env.pathext);
3478
3505
  const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
@@ -3521,13 +3548,13 @@ function resolveOwnExecutablePath(env) {
3521
3548
  if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
3522
3549
  return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
3523
3550
  }
3524
- const candidate = env.argv1 === void 0 ? env.execPath : path12.resolve(env.cwd, env.argv1);
3525
- const candidateDir = path12.dirname(candidate);
3526
- const candidateDirOnPath = env.pathDirs.some((dir) => path12.resolve(dir) === candidateDir);
3551
+ const candidate = env.argv1 === void 0 ? env.execPath : path13.resolve(env.cwd, env.argv1);
3552
+ const candidateDir = path13.dirname(candidate);
3553
+ const candidateDirOnPath = env.pathDirs.some((dir) => path13.resolve(dir) === candidateDir);
3527
3554
  if (candidateDirOnPath) {
3528
3555
  return candidate;
3529
3556
  }
3530
- const viaPath = searchPathForExecutable(env.pathDirs, path12.basename(candidate), env.findExecutableInDir);
3557
+ const viaPath = searchPathForExecutable(env.pathDirs, path13.basename(candidate), env.findExecutableInDir);
3531
3558
  return viaPath ?? candidate;
3532
3559
  }
3533
3560
  function realOwnExecutablePath() {
@@ -3535,7 +3562,7 @@ function realOwnExecutablePath() {
3535
3562
  argv1: process.argv[1],
3536
3563
  execPath: process.execPath,
3537
3564
  cwd: process.cwd(),
3538
- pathDirs: (process.env.PATH ?? "").split(path12.delimiter).filter((dir) => dir !== ""),
3565
+ pathDirs: (process.env.PATH ?? "").split(path13.delimiter).filter((dir) => dir !== ""),
3539
3566
  findExecutableInDir
3540
3567
  });
3541
3568
  }
@@ -3548,7 +3575,7 @@ function realContentSourcePath() {
3548
3575
  function realResolveClaudeBinary(isOwnBinary) {
3549
3576
  return (request4) => discoverClaudeBinary({
3550
3577
  listVersionsDir,
3551
- pathDirs: (process.env.PATH ?? "").split(path12.delimiter).filter((dir) => dir !== ""),
3578
+ pathDirs: (process.env.PATH ?? "").split(path13.delimiter).filter((dir) => dir !== ""),
3552
3579
  findExecutableInDir,
3553
3580
  isOwnBinary,
3554
3581
  ...request4?.version === void 0 ? {} : { version: request4.version }
@@ -3770,18 +3797,18 @@ var init_realPorts = __esm({
3770
3797
  });
3771
3798
 
3772
3799
  // src/pathNorm.ts
3773
- import path13 from "node:path";
3800
+ import path14 from "node:path";
3774
3801
  function expandTilde(value, home) {
3775
3802
  if (value === "~") {
3776
3803
  return home;
3777
3804
  }
3778
3805
  if (value.startsWith("~/")) {
3779
- return path13.join(home, value.slice(2));
3806
+ return path14.join(home, value.slice(2));
3780
3807
  }
3781
3808
  return value;
3782
3809
  }
3783
3810
  function normaliseRulePath(rulePath, home) {
3784
- return path13.resolve(expandTilde(rulePath, home));
3811
+ return path14.resolve(expandTilde(rulePath, home));
3785
3812
  }
3786
3813
  var init_pathNorm = __esm({
3787
3814
  "src/pathNorm.ts"() {
@@ -3790,12 +3817,12 @@ var init_pathNorm = __esm({
3790
3817
  });
3791
3818
 
3792
3819
  // src/launcher/cascade.ts
3793
- import path14 from "node:path";
3820
+ import path15 from "node:path";
3794
3821
  function loadCascadeInput(params) {
3795
3822
  const globalConfig = loadConfigFile(params.paths.globalConfigFile, GlobalConfigSchema, params.read);
3796
3823
  const directoryRules = loadConfigFile(params.paths.directoryRulesFile, DirectoryRulesSchema, params.read);
3797
3824
  const loadProfile = (name) => {
3798
- const filepath = path14.join(params.paths.configProfilesDir, `${name}.json`);
3825
+ const filepath = path15.join(params.paths.configProfilesDir, `${name}.json`);
3799
3826
  const loaded = loadConfigFile(filepath, ConfigProfileSchema, params.read);
3800
3827
  if (loaded === void 0) {
3801
3828
  return void 0;
@@ -3810,8 +3837,8 @@ function loadCascadeInput(params) {
3810
3837
  });
3811
3838
  const levels = [];
3812
3839
  for (const dir of dirs) {
3813
- const portable = loadConfigFile(path14.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path14.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
3814
- const portableLocal = loadConfigFile(path14.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path14.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
3840
+ const portable = loadConfigFile(path15.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path15.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
3841
+ const portableLocal = loadConfigFile(path15.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path15.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
3815
3842
  const rules = (directoryRules?.config.rules ?? []).map((rule, index) => ({ rule, index })).filter(({ rule }) => normaliseRulePath(rule.path, params.home) === dir).map(({ rule, index }) => {
3816
3843
  const entryOrder = directoryRules?.ruleEntryOrders[index];
3817
3844
  return {
@@ -3873,7 +3900,7 @@ var init_cascade = __esm({
3873
3900
  });
3874
3901
 
3875
3902
  // src/launcher/identity.ts
3876
- import path15 from "node:path";
3903
+ import path16 from "node:path";
3877
3904
  function poolNameOf(selector) {
3878
3905
  return selector.startsWith(POOL_SELECTOR_PREFIX) ? selector.slice(POOL_SELECTOR_PREFIX.length) : void 0;
3879
3906
  }
@@ -3926,7 +3953,7 @@ function decideConfigProfile(params) {
3926
3953
  return { source: "none" };
3927
3954
  }
3928
3955
  function loadIdentity(identitiesDir, name, fs12) {
3929
- return loadConfigFile(path15.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
3956
+ return loadConfigFile(path16.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
3930
3957
  }
3931
3958
  var IDENTITY_DECISION_SOURCES, CONFIG_PROFILE_DECISION_SOURCES;
3932
3959
  var init_identity = __esm({
@@ -4120,7 +4147,7 @@ var init_schema2 = __esm({
4120
4147
  });
4121
4148
 
4122
4149
  // src/usage/account.ts
4123
- import path16 from "node:path";
4150
+ import path17 from "node:path";
4124
4151
  function isObject(value) {
4125
4152
  return typeof value === "object" && value !== null && !Array.isArray(value);
4126
4153
  }
@@ -4128,7 +4155,7 @@ function isIdentityName(name) {
4128
4155
  return IdentitySchema.shape.name.safeParse(name).success;
4129
4156
  }
4130
4157
  function claudeJsonPath(identitiesDir, identity) {
4131
- return path16.join(identitiesDir, identity, CLAUDE_JSON);
4158
+ return path17.join(identitiesDir, identity, CLAUDE_JSON);
4132
4159
  }
4133
4160
  function readAccountMetadata(fs12, identitiesDir, identity) {
4134
4161
  if (!isIdentityName(identity)) {
@@ -4627,7 +4654,7 @@ var init_pick = __esm({
4627
4654
  });
4628
4655
 
4629
4656
  // src/usage/read.ts
4630
- import path17 from "node:path";
4657
+ import path18 from "node:path";
4631
4658
  function segmentDay(epochMs) {
4632
4659
  return new Date(epochMs).toISOString().slice(0, "YYYY-MM-DD".length);
4633
4660
  }
@@ -4652,7 +4679,7 @@ function readUsageLog(fs12, logDir, options = {}) {
4652
4679
  if (sinceMs !== void 0 && segment.endsAt <= sinceMs) {
4653
4680
  continue;
4654
4681
  }
4655
- const contents = fs12.readFileUtf8(path17.join(logDir, segment.name));
4682
+ const contents = fs12.readFileUtf8(path18.join(logDir, segment.name));
4656
4683
  if (contents === void 0) {
4657
4684
  continue;
4658
4685
  }
@@ -4686,7 +4713,7 @@ function snapshotPath(snapshotsDir, identity) {
4686
4713
  if (!isIdentityName(identity)) {
4687
4714
  throw new Error(`"${identity}" is not a valid identity name.`);
4688
4715
  }
4689
- return path17.join(snapshotsDir, `${identity}.json`);
4716
+ return path18.join(snapshotsDir, `${identity}.json`);
4690
4717
  }
4691
4718
  function readUsageSnapshot(fs12, snapshotsDir, identity) {
4692
4719
  const file = snapshotPath(snapshotsDir, identity);
@@ -4739,12 +4766,12 @@ var init_read = __esm({
4739
4766
  });
4740
4767
 
4741
4768
  // src/usage/store.ts
4742
- import path18 from "node:path";
4769
+ import path19 from "node:path";
4743
4770
  function pruneUsageLog(fs12, logDir, nowMs) {
4744
4771
  const cutoff = nowMs - USAGE_RETENTION_MS;
4745
4772
  for (const segment of listLogSegments(fs12, logDir)) {
4746
4773
  if (segment.endsAt <= cutoff) {
4747
- fs12.removeRecursive(path18.join(logDir, segment.name));
4774
+ fs12.removeRecursive(path19.join(logDir, segment.name));
4748
4775
  }
4749
4776
  }
4750
4777
  }
@@ -4826,7 +4853,7 @@ function createUsageStore(deps) {
4826
4853
  pruneUsageLog(fs12, paths.usageLogDir, nowMs);
4827
4854
  prunedDay = day;
4828
4855
  }
4829
- fs12.appendFilePrivate(path18.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record)}
4856
+ fs12.appendFilePrivate(path19.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record)}
4830
4857
  `);
4831
4858
  if (record.identity !== void 0) {
4832
4859
  rewriteSnapshot(record.identity, (current) => ({ ...current?.providers, [record.provider]: foldProviderState(current?.providers[record.provider], record) }));
@@ -4864,7 +4891,7 @@ var init_store2 = __esm({
4864
4891
  });
4865
4892
 
4866
4893
  // src/usage/poolPick.ts
4867
- import path19 from "node:path";
4894
+ import path20 from "node:path";
4868
4895
  import { z as z10 } from "zod";
4869
4896
  function errorMessage(error) {
4870
4897
  return error instanceof Error ? error.message : String(error);
@@ -4992,7 +5019,7 @@ function recordStickyPick(fs12, picksFile, directory, identity, nowMs) {
4992
5019
  const current = readPicksFile(fs12, picksFile).file.picks;
4993
5020
  const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
4994
5021
  const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
4995
- fs12.mkdirPrivate(path19.dirname(picksFile));
5022
+ fs12.mkdirPrivate(path20.dirname(picksFile));
4996
5023
  fs12.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
4997
5024
  `);
4998
5025
  }
@@ -5026,14 +5053,14 @@ var init_poolPick = __esm({
5026
5053
  // src/paths.ts
5027
5054
  import fs5 from "node:fs";
5028
5055
  import os5 from "node:os";
5029
- import path21 from "node:path";
5056
+ import path22 from "node:path";
5030
5057
  function resolveAgentShimHome(env = process.env, home = os5.homedir(), isDirectory = isExistingDirectory) {
5031
5058
  const fromEnv = env.AGENT_SHIM_HOME;
5032
5059
  if (fromEnv !== void 0 && fromEnv !== "") {
5033
5060
  return fromEnv;
5034
5061
  }
5035
- const current = path21.join(home, HOME_DIRNAME);
5036
- const legacy = path21.join(home, LEGACY_HOME_DIRNAME);
5062
+ const current = path22.join(home, HOME_DIRNAME);
5063
+ const legacy = path22.join(home, LEGACY_HOME_DIRNAME);
5037
5064
  return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
5038
5065
  }
5039
5066
  function isExistingDirectory(candidate) {
@@ -5044,42 +5071,43 @@ function resolveClaudeHome() {
5044
5071
  if (fromEnv !== void 0 && fromEnv !== "") {
5045
5072
  return fromEnv;
5046
5073
  }
5047
- return path21.join(os5.homedir(), ".claude");
5074
+ return path22.join(os5.homedir(), ".claude");
5048
5075
  }
5049
5076
  function buildLayoutPaths(root) {
5050
5077
  return {
5051
5078
  root,
5052
- identitiesDir: path21.join(root, "identities"),
5053
- configProfilesDir: path21.join(root, "config-profiles"),
5054
- providersDir: path21.join(root, "providers"),
5055
- directoryRulesFile: path21.join(root, "directory-rules.json"),
5056
- activeIdentityFile: path21.join(root, "active-identity"),
5057
- globalConfigFile: path21.join(root, "config.json"),
5058
- categoriesLocalFile: path21.join(root, "categories.local.json"),
5059
- claudeShimFile: path21.join(root, "claude-shim.json"),
5060
- headroomDir: path21.join(root, "headroom"),
5061
- headroomStateFile: path21.join(root, "headroom", `state.v${String(HEADROOM_STATE_SCHEMA_VERSION)}.json`),
5062
- headroomSocketDir: path21.join(root, "headroom", "run"),
5063
- headroomLockFile: path21.join(root, "headroom", "start.lock"),
5064
- headroomSessionsDir: path21.join(root, "headroom", "sessions"),
5065
- logsDir: path21.join(root, "logs"),
5066
- headroomLogPath: path21.join(root, "logs", "headroom.log"),
5067
- frontdoorDir: path21.join(root, "frontdoor"),
5068
- frontdoorCaDir: path21.join(root, "frontdoor", "ca"),
5069
- frontdoorCaCertFile: path21.join(root, "frontdoor", "ca", "ca.pem"),
5070
- frontdoorCaKeyFile: path21.join(root, "frontdoor", "ca", "ca.key"),
5071
- frontdoorCaBundlesDir: path21.join(root, "frontdoor", "ca", "bundles"),
5072
- chatgptSignInFile: path21.join(root, "codex", "chatgpt-sign-in.json"),
5073
- frontdoorStateFile: path21.join(root, "frontdoor", "state.json"),
5074
- frontdoorLockFile: path21.join(root, "frontdoor", "start.lock"),
5075
- frontdoorControlTokenFile: path21.join(root, "frontdoor", "control-token"),
5076
- frontdoorSessionsDir: path21.join(root, "frontdoor", "sessions"),
5077
- frontdoorRcCredentialsDir: path21.join(root, "frontdoor", "rc-credentials"),
5078
- frontdoorLogPath: path21.join(root, "logs", "frontdoor.log"),
5079
- usageDir: path21.join(root, "usage"),
5080
- usageLogDir: path21.join(root, "usage", "log"),
5081
- usageSnapshotsDir: path21.join(root, "usage", "snapshots"),
5082
- usagePicksFile: path21.join(root, "usage", "picks.json")
5079
+ identitiesDir: path22.join(root, "identities"),
5080
+ configProfilesDir: path22.join(root, "config-profiles"),
5081
+ providersDir: path22.join(root, "providers"),
5082
+ directoryRulesFile: path22.join(root, "directory-rules.json"),
5083
+ activeIdentityFile: path22.join(root, "active-identity"),
5084
+ globalConfigFile: path22.join(root, "config.json"),
5085
+ categoriesLocalFile: path22.join(root, "categories.local.json"),
5086
+ claudeShimFile: path22.join(root, "claude-shim.json"),
5087
+ headroomDir: path22.join(root, "headroom"),
5088
+ headroomStateFile: path22.join(root, "headroom", "state.json"),
5089
+ headroomLegacyStateFile: path22.join(root, "headroom", "state.v2.json"),
5090
+ headroomSocketDir: path22.join(root, "headroom", "run"),
5091
+ headroomLockFile: path22.join(root, "headroom", "start.lock"),
5092
+ headroomSessionsDir: path22.join(root, "headroom", "sessions"),
5093
+ logsDir: path22.join(root, "logs"),
5094
+ headroomLogPath: path22.join(root, "logs", "headroom.log"),
5095
+ frontdoorDir: path22.join(root, "frontdoor"),
5096
+ frontdoorCaDir: path22.join(root, "frontdoor", "ca"),
5097
+ frontdoorCaCertFile: path22.join(root, "frontdoor", "ca", "ca.pem"),
5098
+ frontdoorCaKeyFile: path22.join(root, "frontdoor", "ca", "ca.key"),
5099
+ frontdoorCaBundlesDir: path22.join(root, "frontdoor", "ca", "bundles"),
5100
+ chatgptSignInFile: path22.join(root, "codex", "chatgpt-sign-in.json"),
5101
+ frontdoorStateFile: path22.join(root, "frontdoor", "state.json"),
5102
+ frontdoorLockFile: path22.join(root, "frontdoor", "start.lock"),
5103
+ frontdoorControlTokenFile: path22.join(root, "frontdoor", "control-token"),
5104
+ frontdoorSessionsDir: path22.join(root, "frontdoor", "sessions"),
5105
+ frontdoorRcCredentialsDir: path22.join(root, "frontdoor", "rc-credentials"),
5106
+ frontdoorLogPath: path22.join(root, "logs", "frontdoor.log"),
5107
+ usageDir: path22.join(root, "usage"),
5108
+ usageLogDir: path22.join(root, "usage", "log"),
5109
+ usageSnapshotsDir: path22.join(root, "usage", "snapshots"),
5110
+ usagePicksFile: path22.join(root, "usage", "picks.json")
5083
5111
  };
5084
5112
  }
5085
5113
  function resolveLayoutPaths() {
@@ -5088,7 +5116,6 @@ function resolveLayoutPaths() {
5088
5116
  var init_paths = __esm({
5089
5117
  "src/paths.ts"() {
5090
5118
  "use strict";
5091
- init_state2();
5092
5119
  init_legacy();
5093
5120
  }
5094
5121
  });
@@ -5172,7 +5199,7 @@ var init_credentialCache = __esm({
5172
5199
  // src/realCredentialCache.ts
5173
5200
  import { spawnSync as spawnSync2 } from "node:child_process";
5174
5201
  import fs6 from "node:fs";
5175
- import path22 from "node:path";
5202
+ import path23 from "node:path";
5176
5203
  function cacheFileNameFor(owner) {
5177
5204
  return `${owner.replace(/[^A-Za-z0-9._-]/g, "_")}.json`;
5178
5205
  }
@@ -5196,8 +5223,8 @@ function security(args, stdin) {
5196
5223
  return { status: result.status, stdout: result.stdout };
5197
5224
  }
5198
5225
  function createRealCredentialCache(root) {
5199
- const dir = path22.join(root, "credential-cache");
5200
- const filePath = (owner) => path22.join(dir, cacheFileNameFor(owner));
5226
+ const dir = path23.join(root, "credential-cache");
5227
+ const filePath = (owner) => path23.join(dir, cacheFileNameFor(owner));
5201
5228
  return {
5202
5229
  read(store, owner) {
5203
5230
  if (store === "file") {
@@ -5429,9 +5456,9 @@ var init_credential = __esm({
5429
5456
 
5430
5457
  // src/providersStore.ts
5431
5458
  import fs7 from "node:fs";
5432
- import path23 from "node:path";
5459
+ import path24 from "node:path";
5433
5460
  function providerJsonPath(paths, name) {
5434
- return path23.join(paths.providersDir, `${name}.json`);
5461
+ return path24.join(paths.providersDir, `${name}.json`);
5435
5462
  }
5436
5463
  function providerExists(paths, name) {
5437
5464
  return fs7.existsSync(providerJsonPath(paths, name));
@@ -5491,7 +5518,7 @@ function readProvider(paths, name) {
5491
5518
  return parseProviderFile(filePath, raw);
5492
5519
  }
5493
5520
  function loadProvider(providersDir, name, port) {
5494
- const filePath = path23.join(providersDir, `${name}.json`);
5521
+ const filePath = path24.join(providersDir, `${name}.json`);
5495
5522
  const raw = port.readConfigFile(filePath);
5496
5523
  return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
5497
5524
  }
@@ -5856,17 +5883,17 @@ var init_commandDeps = __esm({
5856
5883
 
5857
5884
  // src/claudeShim.ts
5858
5885
  import fs8 from "node:fs";
5859
- import path25 from "node:path";
5886
+ import path26 from "node:path";
5860
5887
  import { z as z15 } from "zod";
5861
5888
  function commandFilename(ownExecutablePath, commandName) {
5862
5889
  return ownExecutablePath.toLowerCase().endsWith(".exe") ? `${commandName}.exe` : commandName;
5863
5890
  }
5864
5891
  function resolveOwnBinaryCheck(paths, contentSourcePath) {
5865
5892
  const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
5866
- const recordedTarget = state === void 0 ? void 0 : path25.resolve(state.targetPath);
5893
+ const recordedTarget = state === void 0 ? void 0 : path26.resolve(state.targetPath);
5867
5894
  let ownStat;
5868
5895
  return (candidate) => {
5869
- if (recordedTarget !== void 0 && path25.resolve(candidate) === recordedTarget) {
5896
+ if (recordedTarget !== void 0 && path26.resolve(candidate) === recordedTarget) {
5870
5897
  return true;
5871
5898
  }
5872
5899
  ownStat ??= statOrUndefined(contentSourcePath);
@@ -5889,15 +5916,15 @@ function statOrUndefined(target) {
5889
5916
  }
5890
5917
  }
5891
5918
  function findPathShadow(params) {
5892
- const resolvedTargetDir = path25.resolve(params.targetDir);
5919
+ const resolvedTargetDir = path26.resolve(params.targetDir);
5893
5920
  for (const dir of params.pathDirs) {
5894
5921
  const found = params.findExecutableInDir(dir, params.targetFilename);
5895
5922
  if (found === void 0) {
5896
5923
  continue;
5897
5924
  }
5898
- return path25.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
5925
+ return path26.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
5899
5926
  }
5900
- return params.pathDirs.some((dir) => path25.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
5927
+ return params.pathDirs.some((dir) => path26.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
5901
5928
  }
5902
5929
  var ClaudeShimStateSchema, nodeLinkFs;
5903
5930
  var init_claudeShim = __esm({
@@ -6321,7 +6348,7 @@ var init_headers = __esm({
6321
6348
  });
6322
6349
 
6323
6350
  // src/launcher/flags.ts
6324
- import path30 from "node:path";
6351
+ import path31 from "node:path";
6325
6352
  function resolveLaunchFlags(params) {
6326
6353
  return {
6327
6354
  skipPermissions: params.flags?.skipPermissions ?? parseEnvBool("AGENT_SHIM_SKIP_PERMISSIONS", params.env.AGENT_SHIM_SKIP_PERMISSIONS) ?? params.cascade?.skipPermissions ?? false,
@@ -6352,7 +6379,7 @@ function buildEnv(params) {
6352
6379
  const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
6353
6380
  let providerCustomHeaders;
6354
6381
  if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
6355
- env.CLAUDE_CONFIG_DIR = path30.join(params.identitiesDir, params.resolvedIdentityName);
6382
+ env.CLAUDE_CONFIG_DIR = path31.join(params.identitiesDir, params.resolvedIdentityName);
6356
6383
  }
6357
6384
  if (params.provider !== void 0) {
6358
6385
  const providerEnv = params.provider.definition.env ?? {};
@@ -6639,7 +6666,7 @@ var init_launchHook = __esm({
6639
6666
 
6640
6667
  // src/launcher.ts
6641
6668
  import { randomUUID as randomUUID4 } from "node:crypto";
6642
- import path31 from "node:path";
6669
+ import path32 from "node:path";
6643
6670
  function resolveIdentityCredential(identity, credential, env, port) {
6644
6671
  if (port === void 0) {
6645
6672
  return { ok: false, status: 1, message: `agent-shim: identity ${identity} needs its credential resolved, but this launcher has no credential port wired` };
@@ -6747,7 +6774,7 @@ function prepareLaunch(params) {
6747
6774
  identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
6748
6775
  globalDefaultConfigProfile: params.globalDefaultConfigProfile
6749
6776
  });
6750
- if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path31.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
6777
+ if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path32.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
6751
6778
  log.error(
6752
6779
  `agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
6753
6780
  );
@@ -6810,7 +6837,7 @@ function prepareLaunch(params) {
6810
6837
  );
6811
6838
  const updateCheck = runLaunchUpdateCheck({
6812
6839
  mode: params.updateMode ?? "off",
6813
- checkPath: path31.join(paths.root, "update.check"),
6840
+ checkPath: path32.join(paths.root, "update.check"),
6814
6841
  currentVersion: package_default.version,
6815
6842
  port: params.update
6816
6843
  });
@@ -6976,12 +7003,12 @@ var init_launcher = __esm({
6976
7003
  });
6977
7004
 
6978
7005
  // src/ownCli.ts
6979
- import path32 from "node:path";
7006
+ import path33 from "node:path";
6980
7007
  function agentShimCliPath(distDir = typeof __AGENT_SHIM_DIST_DIR__ === "string" ? __AGENT_SHIM_DIST_DIR__ : void 0) {
6981
7008
  if (distDir === void 0) {
6982
7009
  throw new OwnCliPathUnknownError();
6983
7010
  }
6984
- return path32.join(distDir, OWN_CLI_FILE_NAME);
7011
+ return path33.join(distDir, OWN_CLI_FILE_NAME);
6985
7012
  }
6986
7013
  var OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
6987
7014
  var init_ownCli = __esm({
@@ -7070,10 +7097,10 @@ request.on("error", (error) => finish(failed, (error.code ? error.code + ": " :
7070
7097
 
7071
7098
  // src/frontdoor/trust.ts
7072
7099
  import { createHash as createHash6 } from "node:crypto";
7073
- import path33 from "node:path";
7100
+ import path34 from "node:path";
7074
7101
  function resolveTrustBundle(params) {
7075
7102
  const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
7076
- if (inherited === void 0 || inherited === "" || path33.resolve(inherited) === path33.resolve(caCertFile)) {
7103
+ if (inherited === void 0 || inherited === "" || path34.resolve(inherited) === path34.resolve(caCertFile)) {
7077
7104
  return { path: caCertFile };
7078
7105
  }
7079
7106
  const caPem = fs12.readFileUtf8(caCertFile);
@@ -7091,7 +7118,7 @@ function resolveTrustBundle(params) {
7091
7118
  }
7092
7119
  const combined = `${inheritedPem.trimEnd()}
7093
7120
  ${caPem}`;
7094
- const bundle = path33.join(bundlesDir, `${createHash6("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7121
+ const bundle = path34.join(bundlesDir, `${createHash6("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7095
7122
  if (!fs12.exists(bundle)) {
7096
7123
  fs12.mkdirp(bundlesDir);
7097
7124
  fs12.writeFileAtomic(bundle, combined);
@@ -7897,11 +7924,21 @@ init_route();
7897
7924
 
7898
7925
  // src/frontdoor/supervisor.ts
7899
7926
  init_state();
7927
+ import path9 from "node:path";
7928
+ function watchedInstallEntry(resolvedOwnExecutablePath, siblingExists) {
7929
+ const parsed = path9.parse(resolvedOwnExecutablePath);
7930
+ if (parsed.name === "agent-shim") {
7931
+ return resolvedOwnExecutablePath;
7932
+ }
7933
+ const sibling = path9.join(parsed.dir, `agent-shim${parsed.ext}`);
7934
+ return siblingExists(sibling) ? sibling : resolvedOwnExecutablePath;
7935
+ }
7900
7936
  var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
7901
7937
  var FRONTDOOR_POLL_MS = 1e3;
7902
7938
  var MS_PER_MINUTE = 6e4;
7903
7939
  async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
7904
7940
  const { fs: fs12, paths } = ports;
7941
+ const servingBinary = ports.statOwnExecutable();
7905
7942
  const previous = readFrontDoorState(fs12, paths.frontdoorStateFile);
7906
7943
  let lastPort = previous?.lastPort;
7907
7944
  let lastConnectPort = previous?.lastConnectPort;
@@ -7964,6 +8001,18 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
7964
8001
  ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http3.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
7965
8002
  let idleSince;
7966
8003
  let ticks = 0;
8004
+ const binaryReplaced = () => {
8005
+ const current = ports.statOwnExecutable();
8006
+ return current !== void 0 && servingBinary !== void 0 && (current.dev !== servingBinary.dev || current.ino !== servingBinary.ino || current.size !== servingBinary.size || current.mtimeMs !== servingBinary.mtimeMs);
8007
+ };
8008
+ const shutdown = async () => {
8009
+ await direct.close();
8010
+ await connect3.close();
8011
+ await http3.close();
8012
+ ports.closeRcStreamHub();
8013
+ writeFrontDoorState(fs12, paths.frontdoorStateFile, sticky());
8014
+ return 0;
8015
+ };
7967
8016
  for (; ; ) {
7968
8017
  if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
7969
8018
  return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
@@ -7975,16 +8024,16 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
7975
8024
  ports.checkQuotaExpiry();
7976
8025
  const prunedPids = new Set(pruned);
7977
8026
  if (listed.filter((session) => !prunedPids.has(session.pid)).length === 0) {
8027
+ if (ticks > 1 && binaryReplaced()) {
8028
+ ports.log("agent-shim frontdoor supervisor: the installed binary changed and no sessions are live; turning the door over for the next launch");
8029
+ ports.doorHealth.binaryTurnover();
8030
+ return await shutdown();
8031
+ }
7978
8032
  idleSince ??= ports.now();
7979
8033
  if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
7980
8034
  ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
7981
8035
  ports.doorHealth.idleShutdown();
7982
- await direct.close();
7983
- await connect3.close();
7984
- await http3.close();
7985
- ports.closeRcStreamHub();
7986
- writeFrontDoorState(fs12, paths.frontdoorStateFile, sticky());
7987
- return 0;
8036
+ return await shutdown();
7988
8037
  }
7989
8038
  } else {
7990
8039
  idleSince = void 0;
@@ -8038,8 +8087,8 @@ function parseConnectTarget(authority) {
8038
8087
  function isInterceptedHost(host, interceptHosts) {
8039
8088
  return interceptHosts.includes(host);
8040
8089
  }
8041
- function servedByPipeline(path34) {
8042
- return path34?.startsWith(ROUTED_PATH_PREFIX) === true;
8090
+ function servedByPipeline(path35) {
8091
+ return path35?.startsWith(ROUTED_PATH_PREFIX) === true;
8043
8092
  }
8044
8093
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
8045
8094
  "connection",
@@ -8573,11 +8622,11 @@ function createRcSessionTracker(deps) {
8573
8622
  };
8574
8623
  const observeExchange = (request4) => {
8575
8624
  const method = (request4.method ?? "").toUpperCase();
8576
- const path34 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
8577
- if (!path34.startsWith(RC_SESSIONS_PATH_PREFIX)) {
8625
+ const path35 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
8626
+ if (!path35.startsWith(RC_SESSIONS_PATH_PREFIX)) {
8578
8627
  return void 0;
8579
8628
  }
8580
- const tail = path34.slice(RC_SESSIONS_PATH_PREFIX.length);
8629
+ const tail = path35.slice(RC_SESSIONS_PATH_PREFIX.length);
8581
8630
  const facts = {
8582
8631
  oauthAuthorization: oauthAuthorizationOf(request4.headers),
8583
8632
  anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
@@ -8959,8 +9008,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
8959
9008
  function isRcReadFileEncoding(value) {
8960
9009
  return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
8961
9010
  }
8962
- function buildRcReadFilePayload(requestId, path34, options) {
8963
- return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path34, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
9011
+ function buildRcReadFilePayload(requestId, path35, options) {
9012
+ return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path35, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
8964
9013
  }
8965
9014
  function buildRcFileSuggestionsPayload(requestId, query) {
8966
9015
  return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
@@ -9062,15 +9111,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
9062
9111
  const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
9063
9112
  return result.ok ? { ...result, requestId } : result;
9064
9113
  }
9065
- async function readRcSessionFile(deps, sessionId, path34, options) {
9066
- if (path34 === "") {
9114
+ async function readRcSessionFile(deps, sessionId, path35, options) {
9115
+ if (path35 === "") {
9067
9116
  return { ok: false, message: "a read-file write needs a non-empty path: the SDK's own field names the file the worker resolves against the session's cwd, and an empty string names none" };
9068
9117
  }
9069
9118
  if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
9070
9119
  return { ok: false, message: "a read-file write's max-bytes is a positive whole number of bytes: the SDK's own field caps the read, and a zero or negative cap reads nothing" };
9071
9120
  }
9072
9121
  const requestId = deps.newUuid();
9073
- const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path34, options), `read ${path34} from session ${sessionId}`);
9122
+ const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path35, options), `read ${path35} from session ${sessionId}`);
9074
9123
  return result.ok ? { ...result, requestId } : result;
9075
9124
  }
9076
9125
  async function suggestRcSessionFiles(deps, sessionId, query) {
@@ -9239,11 +9288,11 @@ function createRcControlHandler(deps) {
9239
9288
  path: "read-file",
9240
9289
  read: (body) => {
9241
9290
  const session = bodyString(body, "session");
9242
- const path34 = bodyString(body, "path");
9291
+ const path35 = bodyString(body, "path");
9243
9292
  const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
9244
9293
  const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
9245
- const refused2 = session === void 0 || path34 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
9246
- return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path34, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
9294
+ const refused2 = session === void 0 || path35 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
9295
+ return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path35, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
9247
9296
  }
9248
9297
  },
9249
9298
  {
@@ -9553,9 +9602,9 @@ function requestIdOfBody(body) {
9553
9602
  }
9554
9603
  function frontDoorRcControl(transport, token) {
9555
9604
  const headers = { authorization: `Bearer ${token}` };
9556
- const listAnswerOf = async (path34, what) => {
9605
+ const listAnswerOf = async (path35, what) => {
9557
9606
  try {
9558
- return await transport.request({ method: "GET", path: path34, headers });
9607
+ return await transport.request({ method: "GET", path: path35, headers });
9559
9608
  } catch (error) {
9560
9609
  throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
9561
9610
  }
@@ -9627,10 +9676,10 @@ function frontDoorRcControl(transport, token) {
9627
9676
  }
9628
9677
  return pending;
9629
9678
  };
9630
- const writeOf = async (path34, body, describeFailure) => {
9679
+ const writeOf = async (path35, body, describeFailure) => {
9631
9680
  let answer;
9632
9681
  try {
9633
- answer = await transport.request({ method: "POST", path: path34, headers: { ...headers, "content-type": "application/json" }, body });
9682
+ answer = await transport.request({ method: "POST", path: path35, headers: { ...headers, "content-type": "application/json" }, body });
9634
9683
  } catch (error) {
9635
9684
  return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
9636
9685
  }
@@ -9661,10 +9710,10 @@ function frontDoorRcControl(transport, token) {
9661
9710
  endSession: async (sessionId, reason) => await writeOf(`${CONTROL_PATH_PREFIX}/end-session`, JSON.stringify({ session: sessionId, ...reason === void 0 ? {} : { reason } }), (status, message) => `ending ${sessionId} failed (HTTP ${String(status)}): ${message}`),
9662
9711
  getUsage: async (sessionId, skipBehaviors) => await writeOf(`${CONTROL_PATH_PREFIX}/get-usage`, JSON.stringify({ session: sessionId, ...skipBehaviors === void 0 ? {} : { skipBehaviors } }), (status, message) => `requesting the usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
9663
9712
  getContextUsage: async (sessionId, detail) => await writeOf(`${CONTROL_PATH_PREFIX}/get-context-usage`, JSON.stringify({ session: sessionId, ...detail === void 0 ? {} : { detail } }), (status, message) => `requesting the context usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
9664
- readFile: async (sessionId, path34, options) => await writeOf(
9713
+ readFile: async (sessionId, path35, options) => await writeOf(
9665
9714
  `${CONTROL_PATH_PREFIX}/read-file`,
9666
- JSON.stringify({ session: sessionId, path: path34, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
9667
- (status, message) => `reading ${path34} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
9715
+ JSON.stringify({ session: sessionId, path: path35, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
9716
+ (status, message) => `reading ${path35} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
9668
9717
  ),
9669
9718
  fileSuggestions: async (sessionId, query) => await writeOf(`${CONTROL_PATH_PREFIX}/file-suggestions`, JSON.stringify({ session: sessionId, query }), (status, message) => `requesting file suggestions from ${sessionId} failed (HTTP ${String(status)}): ${message}`),
9670
9719
  keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
@@ -9819,12 +9868,12 @@ function tlsFacts(options) {
9819
9868
  }
9820
9869
  function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
9821
9870
  const agent = new ExemptTlsAgent();
9822
- const post = async (path34, headers, body) => await new Promise((resolve, reject) => {
9871
+ const post = async (path35, headers, body) => await new Promise((resolve, reject) => {
9823
9872
  const options = {
9824
9873
  host: target.host,
9825
9874
  port: target.port,
9826
9875
  method: "POST",
9827
- path: path34,
9876
+ path: path35,
9828
9877
  // The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
9829
9878
  headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
9830
9879
  agent
@@ -9889,12 +9938,12 @@ function lateRcStreamDial(resolve) {
9889
9938
  }
9890
9939
  function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
9891
9940
  const agent = new ExemptTlsAgent();
9892
- const request4 = async (method, path34, headers, body, signal) => await new Promise((resolve, reject) => {
9941
+ const request4 = async (method, path35, headers, body, signal) => await new Promise((resolve, reject) => {
9893
9942
  const options = {
9894
9943
  host: target.host,
9895
9944
  port: target.port,
9896
9945
  method,
9897
- path: path34,
9946
+ path: path35,
9898
9947
  // The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
9899
9948
  headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
9900
9949
  agent,
@@ -9936,9 +9985,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
9936
9985
  return { status, body: await readAll(response) };
9937
9986
  },
9938
9987
  openStream: async (sessionId, headers, resume, signal) => {
9939
- const path34 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
9988
+ const path35 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
9940
9989
  const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
9941
- const { status, response } = await request4("GET", path34, streamHeaders, void 0, signal);
9990
+ const { status, response } = await request4("GET", path35, streamHeaders, void 0, signal);
9942
9991
  if (!isSuccessful2(status)) {
9943
9992
  await readAll(response);
9944
9993
  return { status, chunks: NO_CHUNKS };
@@ -10150,7 +10199,7 @@ function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
10150
10199
  }
10151
10200
 
10152
10201
  // src/frontdoor/rcCredentialStore.ts
10153
- import path9 from "node:path";
10202
+ import path10 from "node:path";
10154
10203
  function isSafeSessionId(sessionId) {
10155
10204
  return /^[A-Za-z0-9_-]+$/.test(sessionId);
10156
10205
  }
@@ -10176,7 +10225,7 @@ function sequenceNumOfJson(value) {
10176
10225
  }
10177
10226
  function createRcCredentialStore(fs12, dir) {
10178
10227
  fs12.mkdirPrivate(dir);
10179
- const fileFor = (sessionId) => path9.join(dir, `${sessionId}.json`);
10228
+ const fileFor = (sessionId) => path10.join(dir, `${sessionId}.json`);
10180
10229
  const readParsed = (sessionId) => {
10181
10230
  const raw = fs12.readFileUtf8(fileFor(sessionId));
10182
10231
  if (raw === void 0) {
@@ -10636,7 +10685,7 @@ init_schema();
10636
10685
  init_cliError();
10637
10686
  init_load();
10638
10687
  import fs4 from "node:fs";
10639
- import path20 from "node:path";
10688
+ import path21 from "node:path";
10640
10689
  var ProfileNotFoundError = class extends CliError {
10641
10690
  constructor(profileName) {
10642
10691
  super(`No configuration profile named "${profileName}". Run \`agent-shim profile add ${profileName}\` first.`);
@@ -10662,7 +10711,7 @@ var InvalidCategoryNameError = class extends CliError {
10662
10711
  categoryName;
10663
10712
  };
10664
10713
  function profileJsonPath(paths, name) {
10665
- return path20.join(paths.configProfilesDir, `${name}.json`);
10714
+ return path21.join(paths.configProfilesDir, `${name}.json`);
10666
10715
  }
10667
10716
  function profileExists(paths, name) {
10668
10717
  return fs4.existsSync(profileJsonPath(paths, name));
@@ -10802,19 +10851,19 @@ function writePools(paths, pools) {
10802
10851
  applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
10803
10852
  }
10804
10853
  function poolCycleOf(pools, name) {
10805
- const walk = (current, path34) => {
10854
+ const walk = (current, path35) => {
10806
10855
  for (const entry of pools[current]?.identities ?? []) {
10807
10856
  const nested = poolNameOf(poolMemberIdentity(entry));
10808
10857
  if (nested === void 0) {
10809
10858
  continue;
10810
10859
  }
10811
10860
  if (nested === name) {
10812
- return [...path34, nested];
10861
+ return [...path35, nested];
10813
10862
  }
10814
- if (path34.includes(nested)) {
10863
+ if (path35.includes(nested)) {
10815
10864
  continue;
10816
10865
  }
10817
- const found = walk(nested, [...path34, nested]);
10866
+ const found = walk(nested, [...path35, nested]);
10818
10867
  if (found !== void 0) {
10819
10868
  return found;
10820
10869
  }
@@ -10924,7 +10973,7 @@ init_guard();
10924
10973
  init_providersStore();
10925
10974
  init_projects();
10926
10975
  init_pipeline();
10927
- import path24 from "node:path";
10976
+ import path25 from "node:path";
10928
10977
  import { z as z12 } from "zod";
10929
10978
  var HISTORY_PROJECTS_KEY_PREFIX = "history/projects/";
10930
10979
  function projectFragmentOf(rawKey) {
@@ -11262,10 +11311,10 @@ function collectCheckReport(params) {
11262
11311
  }).input;
11263
11312
  const providerName = cascadeProviderName(cascade);
11264
11313
  const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
11265
- const farmRoot = identityDecision.name === void 0 ? void 0 : path24.join(paths.identitiesDir, identityDecision.name);
11314
+ const farmRoot = identityDecision.name === void 0 ? void 0 : path25.join(paths.identitiesDir, identityDecision.name);
11266
11315
  const settingsFiles = {
11267
- "settings.json": realFsPort.readFileUtf8(path24.join(claudeHome, "settings.json")),
11268
- "settings.local.json": realFsPort.readFileUtf8(path24.join(claudeHome, "settings.local.json"))
11316
+ "settings.json": realFsPort.readFileUtf8(path25.join(claudeHome, "settings.json")),
11317
+ "settings.local.json": realFsPort.readFileUtf8(path25.join(claudeHome, "settings.local.json"))
11269
11318
  };
11270
11319
  const report = runCheck({
11271
11320
  cwd,
@@ -11485,7 +11534,7 @@ init_middleware();
11485
11534
  init_preflight();
11486
11535
 
11487
11536
  // src/frontdoor/controlSchemas.ts
11488
- import path28 from "node:path";
11537
+ import path29 from "node:path";
11489
11538
  import { z as z19 } from "zod";
11490
11539
 
11491
11540
  // src/doctorReport.ts
@@ -11499,7 +11548,7 @@ init_schema();
11499
11548
  init_cliError();
11500
11549
  init_identity();
11501
11550
  import fs9 from "node:fs";
11502
- import path26 from "node:path";
11551
+ import path27 from "node:path";
11503
11552
  init_lock();
11504
11553
  var IdentityNotFoundError = class extends CliError {
11505
11554
  constructor(name) {
@@ -11528,7 +11577,7 @@ var InvalidIdentityNameError = class extends CliError {
11528
11577
  attemptedName;
11529
11578
  };
11530
11579
  function identityJsonPath(paths, name) {
11531
- return path26.join(paths.identitiesDir, name, "identity.json");
11580
+ return path27.join(paths.identitiesDir, name, "identity.json");
11532
11581
  }
11533
11582
  function identityExists(paths, name) {
11534
11583
  return fs9.existsSync(identityJsonPath(paths, name));
@@ -11629,7 +11678,7 @@ function setIdentityCredential(paths, identityName, change) {
11629
11678
  });
11630
11679
  }
11631
11680
  function belongsToIdentity(entry, name) {
11632
- return entry === name || entry === path26.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
11681
+ return entry === name || entry === path27.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
11633
11682
  }
11634
11683
  function removeIdentity(paths, name) {
11635
11684
  if (!identityExists(paths, name)) {
@@ -11637,7 +11686,7 @@ function removeIdentity(paths, name) {
11637
11686
  }
11638
11687
  for (const entry of fs9.readdirSync(paths.identitiesDir)) {
11639
11688
  if (belongsToIdentity(entry, name)) {
11640
- fs9.rmSync(path26.join(paths.identitiesDir, entry), { recursive: true, force: true });
11689
+ fs9.rmSync(path27.join(paths.identitiesDir, entry), { recursive: true, force: true });
11641
11690
  }
11642
11691
  }
11643
11692
  if (readActiveIdentity2(paths) === name) {
@@ -11648,7 +11697,7 @@ function removeIdentity(paths, name) {
11648
11697
  // src/doctorReport.ts
11649
11698
  init_realPorts();
11650
11699
  import fs10 from "node:fs";
11651
- import path27 from "node:path";
11700
+ import path28 from "node:path";
11652
11701
 
11653
11702
  // src/codex/siwcStore.ts
11654
11703
  import { z as z18 } from "zod";
@@ -11780,8 +11829,18 @@ function validateJson(schema, input) {
11780
11829
  }
11781
11830
  return { ok: true, data: result.data };
11782
11831
  }
11832
+ function tcpPortEraRecord(raw) {
11833
+ let parsed;
11834
+ try {
11835
+ parsed = JSON.parse(raw);
11836
+ } catch {
11837
+ return false;
11838
+ }
11839
+ const has = (key) => typeof parsed === "object" && parsed !== null && key in parsed;
11840
+ return (has("port") || has("lastPort")) && !has("socketPath");
11841
+ }
11783
11842
  function pushPathResolution(push, resolution) {
11784
- const ownDir = path27.dirname(resolution.ownExecutablePath);
11843
+ const ownDir = path28.dirname(resolution.ownExecutablePath);
11785
11844
  switch (resolution.agentShim.status) {
11786
11845
  case "ok":
11787
11846
  push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
@@ -11880,14 +11939,14 @@ function pushProvider(push, entry, cacheEnv, signIn) {
11880
11939
  }
11881
11940
  function pushLegacyName(push, params) {
11882
11941
  const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
11883
- if (legacyVariables.length === 0 && path27.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
11942
+ if (legacyVariables.length === 0 && path28.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
11884
11943
  push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
11885
11944
  return;
11886
11945
  }
11887
11946
  for (const name of legacyVariables) {
11888
11947
  push("legacy-name", "warn", `${name} is the former name of ${name.replace(LEGACY_ENV_PREFIX, ENV_PREFIX)}. Rename it; the old name still works but is only a fallback.`, name);
11889
11948
  }
11890
- if (path27.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
11949
+ if (path28.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
11891
11950
  push(
11892
11951
  "legacy-name",
11893
11952
  "warn",
@@ -12089,6 +12148,8 @@ function runDoctor(params) {
12089
12148
  }
12090
12149
  if (params.headroom.state.raw === void 0) {
12091
12150
  push("headroom", "pass", "No headroom daemon has ever run; nothing to check.");
12151
+ } else if (tcpPortEraRecord(params.headroom.state.raw)) {
12152
+ push("headroom", "pass", `${params.headroom.state.path} holds a previous release's TCP-port state record; the next launch through headroom claims over it.`);
12092
12153
  } else {
12093
12154
  const validated2 = validateJson(HeadroomStateSchema, params.headroom.state);
12094
12155
  if (!validated2.ok) {
@@ -12227,18 +12288,18 @@ function collectDoctorReport(params) {
12227
12288
  const { paths } = params;
12228
12289
  const identityNames = fs10.existsSync(paths.identitiesDir) ? fs10.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
12229
12290
  const identities = identityNames.map((name) => {
12230
- const farmRoot = path27.join(paths.identitiesDir, name);
12231
- const identityPath = path27.join(farmRoot, "identity.json");
12291
+ const farmRoot = path28.join(paths.identitiesDir, name);
12292
+ const identityPath = path28.join(farmRoot, "identity.json");
12232
12293
  return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
12233
12294
  });
12234
12295
  const profileNames = fs10.existsSync(paths.configProfilesDir) ? fs10.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
12235
12296
  const configProfiles = profileNames.map((name) => {
12236
- const profilePath = path27.join(paths.configProfilesDir, `${name}.json`);
12297
+ const profilePath = path28.join(paths.configProfilesDir, `${name}.json`);
12237
12298
  return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
12238
12299
  });
12239
12300
  const providerNames = fs10.existsSync(paths.providersDir) ? fs10.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
12240
12301
  const providers = providerNames.map((name) => {
12241
- const providerPath = path27.join(paths.providersDir, `${name}.json`);
12302
+ const providerPath = path28.join(paths.providersDir, `${name}.json`);
12242
12303
  return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
12243
12304
  });
12244
12305
  const ownExecutablePath = realOwnExecutablePath();
@@ -12250,12 +12311,12 @@ function collectDoctorReport(params) {
12250
12311
  binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
12251
12312
  }
12252
12313
  const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
12253
- const pathDirs = (params.env.PATH ?? "").split(path27.delimiter).filter((dir) => dir !== "");
12314
+ const pathDirs = (params.env.PATH ?? "").split(path28.delimiter).filter((dir) => dir !== "");
12254
12315
  const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
12255
12316
  findPathShadow({
12256
12317
  pathDirs,
12257
- targetDir: path27.dirname(shimState.targetPath),
12258
- targetFilename: path27.basename(shimState.targetPath),
12318
+ targetDir: path28.dirname(shimState.targetPath),
12319
+ targetFilename: path28.basename(shimState.targetPath),
12259
12320
  findExecutableInDir
12260
12321
  }),
12261
12322
  shimState.targetPath,
@@ -12281,7 +12342,7 @@ function collectDoctorReport(params) {
12281
12342
  agentShim: refinePathShadow(
12282
12343
  findPathShadow({
12283
12344
  pathDirs,
12284
- targetDir: path27.dirname(ownExecutablePath),
12345
+ targetDir: path28.dirname(ownExecutablePath),
12285
12346
  targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
12286
12347
  findExecutableInDir
12287
12348
  }),
@@ -12293,7 +12354,12 @@ function collectDoctorReport(params) {
12293
12354
  run: realRunPort,
12294
12355
  platform: process.platform,
12295
12356
  headroom: {
12296
- state: { path: paths.headroomStateFile, raw: realFsPort.readFileUtf8(paths.headroomStateFile) },
12357
+ // Read-only resolution like `headroom status`: the doctor reports whichever record a launch would join, migrating nothing.
12358
+ state: (() => {
12359
+ const resolved = resolveServingHeadroomState(realFarmFs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, realIsProcessRunning);
12360
+ const statePath = resolved?.path ?? paths.headroomStateFile;
12361
+ return { path: statePath, raw: realFarmFs.readFileUtf8(statePath) };
12362
+ })(),
12297
12363
  isRunning: realIsProcessRunning
12298
12364
  }
12299
12365
  });
@@ -12350,11 +12416,11 @@ var FrontDoorSessionsOutputSchema = z19.strictObject({ sessions: z19.readonly(z1
12350
12416
  var CheckRunInputSchema = z19.strictObject({
12351
12417
  path: z19.string().min(1),
12352
12418
  identity: z19.string().min(1).optional()
12353
- }).refine((input) => path28.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
12419
+ }).refine((input) => path29.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
12354
12420
  var PoolPickInputSchema = z19.strictObject({
12355
12421
  pool: z19.string().min(1),
12356
12422
  path: z19.string().min(1)
12357
- }).refine((input) => path28.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
12423
+ }).refine((input) => path29.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
12358
12424
  var DoctorFindingSchema = z19.strictObject({
12359
12425
  section: z19.enum(DOCTOR_SECTIONS),
12360
12426
  subject: z19.string().optional(),
@@ -12396,6 +12462,7 @@ var LaunchLifecycleEventSchema = z20.strictObject({
12396
12462
  var DoorHealthEventSchema = z20.discriminatedUnion("kind", [
12397
12463
  z20.strictObject({ kind: z20.literal("generation"), pid: z20.number().int().positive(), providerPort: z20.number().int().positive(), connectPort: z20.number().int().positive(), directPort: z20.number().int().positive(), observedAt: z20.number() }),
12398
12464
  z20.strictObject({ kind: z20.literal("listenerFailed"), pid: z20.number().int().positive(), listener: z20.enum(["provider", "connect", "direct"]), message: z20.string(), observedAt: z20.number() }),
12465
+ z20.strictObject({ kind: z20.literal("binaryTurnover"), pid: z20.number().int().positive(), observedAt: z20.number() }),
12399
12466
  z20.strictObject({ kind: z20.literal("idleShutdown"), pid: z20.number().int().positive(), observedAt: z20.number() })
12400
12467
  ]);
12401
12468
  var QuotaExpiringEventSchema = z20.strictObject({
@@ -12559,7 +12626,7 @@ init_socket();
12559
12626
  init_state2();
12560
12627
  init_state();
12561
12628
  function headroomSocketTarget(fsPort, trust, paths) {
12562
- const socketPath = readHeadroomState(fsPort, paths.headroomStateFile)?.socketPath;
12629
+ const socketPath = readHeadroomState(fsPort, paths.headroomStateFile)?.socketPath ?? readHeadroomState(fsPort, paths.headroomLegacyStateFile)?.socketPath;
12563
12630
  return socketPath === void 0 ? void 0 : verifyHeadroomSocket(socketPath, trust);
12564
12631
  }
12565
12632
  function collectFrontDoorStatus(fsPort, socketTrust, paths, isRunning) {
@@ -12767,6 +12834,9 @@ function createDoorHealthPublisher(hub, now, pid) {
12767
12834
  },
12768
12835
  idleShutdown: () => {
12769
12836
  publisher.publish({ kind: "idleShutdown", pid, observedAt: now() });
12837
+ },
12838
+ binaryTurnover: () => {
12839
+ publisher.publish({ kind: "binaryTurnover", pid, observedAt: now() });
12770
12840
  }
12771
12841
  };
12772
12842
  }
@@ -14462,7 +14532,7 @@ data: ${JSON.stringify(envelope)}
14462
14532
 
14463
14533
  // src/frontdoor/rcSelfHostMint.ts
14464
14534
  init_account();
14465
- import path29 from "node:path";
14535
+ import path30 from "node:path";
14466
14536
  var CREDENTIALS_FILE = ".credentials.json";
14467
14537
  var CLAUDE_JSON2 = ".claude.json";
14468
14538
  var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
@@ -14486,7 +14556,7 @@ function readJsonObject(fs12, file) {
14486
14556
  return isRecord11(parsed) ? parsed : void 0;
14487
14557
  }
14488
14558
  function readRcSelfHostRecord(fs12, frontdoorDir) {
14489
- const parsed = readJsonObject(fs12, path29.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
14559
+ const parsed = readJsonObject(fs12, path30.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
14490
14560
  if (parsed === void 0) {
14491
14561
  return void 0;
14492
14562
  }
@@ -14500,11 +14570,11 @@ function mintRcSelfHostCredential(deps) {
14500
14570
  if (!isIdentityName(deps.identity)) {
14501
14571
  throw new Error(`"${deps.identity}" is not a valid identity name.`);
14502
14572
  }
14503
- const identityDir = path29.join(deps.identitiesDir, deps.identity);
14504
- const credentialsFile = path29.join(identityDir, CREDENTIALS_FILE);
14505
- const claudeJsonFile = path29.join(identityDir, CLAUDE_JSON2);
14506
- const recordDir = path29.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
14507
- const recordFile = path29.join(recordDir, RC_SELF_HOST_RECORD_FILE);
14573
+ const identityDir = path30.join(deps.identitiesDir, deps.identity);
14574
+ const credentialsFile = path30.join(identityDir, CREDENTIALS_FILE);
14575
+ const claudeJsonFile = path30.join(identityDir, CLAUDE_JSON2);
14576
+ const recordDir = path30.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
14577
+ const recordFile = path30.join(recordDir, RC_SELF_HOST_RECORD_FILE);
14508
14578
  const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
14509
14579
  const existingCredentials = readJsonObject(deps.fs, credentialsFile);
14510
14580
  const existingOauth = isRecord11(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
@@ -14520,7 +14590,7 @@ function mintRcSelfHostCredential(deps) {
14520
14590
  const organizationUuid = deps.newUuid();
14521
14591
  const accountUuid = deps.newUuid();
14522
14592
  const mintedAt = new Date(deps.now()).toISOString();
14523
- deps.fs.mkdirPrivate(path29.dirname(credentialsFile));
14593
+ deps.fs.mkdirPrivate(path30.dirname(credentialsFile));
14524
14594
  deps.fs.writeFilePrivate(credentialsFile, `${JSON.stringify({ ...existingCredentials, claudeAiOauth: { accessToken, refreshToken, expiresAt: null, scopes: [...RC_SELF_HOST_SCOPE_LIST], subscriptionType: SELF_HOST_SUBSCRIPTION_TYPE, rateLimitTier: null } }, null, 2)}
14525
14595
  `);
14526
14596
  const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
@@ -15052,5 +15122,6 @@ export {
15052
15122
  updateDirectoryRule,
15053
15123
  updateProvider,
15054
15124
  useIdentity,
15125
+ watchedInstallEntry,
15055
15126
  writeDirectoryRules
15056
15127
  };