agent-shim 7.12.0 → 7.13.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.cjs CHANGED
@@ -60,6 +60,7 @@ __export(index_exports, {
60
60
  InvalidCategoryNameError: () => InvalidCategoryNameError,
61
61
  InvalidIdentityNameError: () => InvalidIdentityNameError,
62
62
  InvalidProviderNameError: () => InvalidProviderNameError,
63
+ LaunchRefusedError: () => LaunchRefusedError,
63
64
  LegacyProviderFileError: () => LegacyProviderFileError,
64
65
  PoolNameSchema: () => PoolNameSchema,
65
66
  PoolNotFoundError: () => PoolNotFoundError,
@@ -110,6 +111,8 @@ __export(index_exports, {
110
111
  listUsageSnapshots: () => listUsageSnapshots,
111
112
  mintLeaf: () => mintLeaf,
112
113
  parseConnectTarget: () => parseConnectTarget,
114
+ prepareClaudeLaunch: () => prepareClaudeLaunch,
115
+ prepareLaunch: () => prepareLaunch,
113
116
  profileExists: () => profileExists,
114
117
  providerExists: () => providerExists,
115
118
  readActiveIdentity: () => readActiveIdentity,
@@ -1789,8 +1792,8 @@ var FarmManifestSchema = import_zod2.z.strictObject({
1789
1792
  materialised: import_zod2.z.array(import_zod2.z.string()),
1790
1793
  links: import_zod2.z.array(import_zod2.z.strictObject({ rel: import_zod2.z.string(), target: import_zod2.z.string() }))
1791
1794
  });
1792
- function readFarmManifest(fs10, farmRoot) {
1793
- const raw = fs10.readFileUtf8(import_node_path6.default.join(farmRoot, FARM_MANIFEST_FILENAME)) ?? fs10.readFileUtf8(import_node_path6.default.join(farmRoot, LEGACY_FARM_MANIFEST_FILENAME));
1795
+ function readFarmManifest(fs12, farmRoot) {
1796
+ const raw = fs12.readFileUtf8(import_node_path6.default.join(farmRoot, FARM_MANIFEST_FILENAME)) ?? fs12.readFileUtf8(import_node_path6.default.join(farmRoot, LEGACY_FARM_MANIFEST_FILENAME));
1794
1797
  if (raw === void 0) {
1795
1798
  return void 0;
1796
1799
  }
@@ -1848,9 +1851,9 @@ function buildEntryFacts(params) {
1848
1851
  entries
1849
1852
  };
1850
1853
  }
1851
- function listSubtree(fs10, root, rel) {
1854
+ function listSubtree(fs12, root, rel) {
1852
1855
  const absolute = import_node_path6.default.join(root, rel);
1853
- const stat = fs10.lstat(absolute);
1856
+ const stat = fs12.lstat(absolute);
1854
1857
  if (stat === void 0) {
1855
1858
  return [];
1856
1859
  }
@@ -1858,10 +1861,10 @@ function listSubtree(fs10, root, rel) {
1858
1861
  return [{ rel, kind: "symlink" }];
1859
1862
  }
1860
1863
  if (stat.kind === "dir") {
1861
- const children = [...fs10.readdir(absolute)].sort().flatMap((name) => listSubtree(fs10, root, `${rel}/${name}`));
1864
+ const children = [...fs12.readdir(absolute)].sort().flatMap((name) => listSubtree(fs12, root, `${rel}/${name}`));
1862
1865
  return [{ rel, kind: "dir" }, ...children];
1863
1866
  }
1864
- const contentHash = fs10.hashFile(absolute);
1867
+ const contentHash = fs12.hashFile(absolute);
1865
1868
  return [{ rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } }];
1866
1869
  }
1867
1870
  function topLevelScopeRoots(roots) {
@@ -1875,25 +1878,25 @@ function topLevelScopeRoots(roots) {
1875
1878
  }
1876
1879
  return kept;
1877
1880
  }
1878
- function reconciliationScope(fs10, farmRoot, manifest) {
1881
+ function reconciliationScope(fs12, farmRoot, manifest) {
1879
1882
  if (manifest !== void 0) {
1880
1883
  return topLevelScopeRoots(manifest.materialised);
1881
1884
  }
1882
- return [...fs10.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && name !== LEGACY_FARM_MANIFEST_FILENAME && fs10.lstat(import_node_path6.default.join(farmRoot, name))?.kind === "dir").sort();
1885
+ return [...fs12.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && name !== LEGACY_FARM_MANIFEST_FILENAME && fs12.lstat(import_node_path6.default.join(farmRoot, name))?.kind === "dir").sort();
1883
1886
  }
1884
- function collectFarmListing(fs10, farmRoot, scopeRoots) {
1885
- return scopeRoots.flatMap((root) => listSubtree(fs10, farmRoot, root));
1887
+ function collectFarmListing(fs12, farmRoot, scopeRoots) {
1888
+ return scopeRoots.flatMap((root) => listSubtree(fs12, farmRoot, root));
1886
1889
  }
1887
- function collectCanonicalCounterparts(fs10, claudeHome, farmListing) {
1890
+ function collectCanonicalCounterparts(fs12, claudeHome, farmListing) {
1888
1891
  const out = [];
1889
1892
  for (const entry of farmListing) {
1890
1893
  const absolute = import_node_path6.default.join(claudeHome, entry.rel);
1891
- const stat = fs10.lstat(absolute);
1894
+ const stat = fs12.lstat(absolute);
1892
1895
  if (stat === void 0) {
1893
1896
  continue;
1894
1897
  }
1895
1898
  if (stat.kind === "file") {
1896
- const contentHash = fs10.hashFile(absolute);
1899
+ const contentHash = fs12.hashFile(absolute);
1897
1900
  out.push({ rel: entry.rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } });
1898
1901
  continue;
1899
1902
  }
@@ -2577,8 +2580,12 @@ function pumpTapSession(secure, openUpstream, tap, prefix = Buffer.alloc(0)) {
2577
2580
  }
2578
2581
 
2579
2582
  // src/frontdoor/capability.ts
2583
+ var CONNECT_PROXY_USER = "agent-shim";
2580
2584
  var CONNECT_PROXY_REALM = "agent-shim front door";
2581
2585
  var BASIC_SCHEME = "basic";
2586
+ function connectProxyUrl(port, token) {
2587
+ return `http://${encodeURIComponent(CONNECT_PROXY_USER)}:${encodeURIComponent(token)}@127.0.0.1:${String(port)}`;
2588
+ }
2582
2589
  function capabilityFromProxyAuthorization(value) {
2583
2590
  const trimmed = value.trim();
2584
2591
  const space = trimmed.indexOf(" ");
@@ -2595,7 +2602,15 @@ function capabilityFromProxyAuthorization(value) {
2595
2602
  }
2596
2603
 
2597
2604
  // src/frontdoor/route.ts
2605
+ var IDENTITY_HEADER = "x-agent-shim-identity";
2606
+ var SESSION_HEADER = "x-agent-shim-session";
2607
+ var HEADROOM_FLAG_HEADER = "x-agent-shim-headroom";
2608
+ var PROJECT_ID_HEADER = "x-headroom-project-id";
2598
2609
  var AUTH_HEADER = "x-agent-shim-auth";
2610
+ var PROVIDER_PATH_PREFIX = "/providers/";
2611
+ function providerBaseUrl(port, provider) {
2612
+ return `https://127.0.0.1:${String(port)}${PROVIDER_PATH_PREFIX}${encodeURIComponent(provider)}`;
2613
+ }
2599
2614
 
2600
2615
  // src/frontdoor/state.ts
2601
2616
  var import_node_path7 = __toESM(require("node:path"), 1);
@@ -2632,10 +2647,10 @@ var FrontDoorStateSchema = import_zod3.z.strictObject({
2632
2647
  /** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
2633
2648
  lastError: import_zod3.z.string().optional()
2634
2649
  });
2635
- function readFrontDoorState(fs10, stateFile) {
2650
+ function readFrontDoorState(fs12, stateFile) {
2636
2651
  let raw;
2637
2652
  try {
2638
- raw = fs10.readFileUtf8(stateFile);
2653
+ raw = fs12.readFileUtf8(stateFile);
2639
2654
  } catch {
2640
2655
  return void 0;
2641
2656
  }
@@ -2649,28 +2664,28 @@ function readFrontDoorState(fs10, stateFile) {
2649
2664
  return void 0;
2650
2665
  }
2651
2666
  }
2652
- function writeFrontDoorState(fs10, stateFile, state) {
2653
- fs10.mkdirp(import_node_path7.default.dirname(stateFile));
2654
- fs10.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
2667
+ function writeFrontDoorState(fs12, stateFile, state) {
2668
+ fs12.mkdirp(import_node_path7.default.dirname(stateFile));
2669
+ fs12.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
2655
2670
  `);
2656
2671
  }
2657
2672
  function frontDoorOrigin(state) {
2658
2673
  const port = state?.directPort ?? state?.lastDirectPort;
2659
2674
  return port === void 0 ? void 0 : `http://127.0.0.1:${String(port)}`;
2660
2675
  }
2661
- function writeFrontDoorSession(fs10, sessionsDir, session) {
2662
- fs10.mkdirPrivate(sessionsDir);
2663
- fs10.writeFilePrivate(import_node_path7.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
2676
+ function writeFrontDoorSession(fs12, sessionsDir, session) {
2677
+ fs12.mkdirPrivate(sessionsDir);
2678
+ fs12.writeFilePrivate(import_node_path7.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
2664
2679
  `);
2665
2680
  }
2666
- function listFrontDoorSessions(fs10, sessionsDir) {
2681
+ function listFrontDoorSessions(fs12, sessionsDir) {
2667
2682
  const sessions = [];
2668
- for (const name of fs10.readdir(sessionsDir)) {
2683
+ for (const name of fs12.readdir(sessionsDir)) {
2669
2684
  if (!name.endsWith(".json")) {
2670
2685
  continue;
2671
2686
  }
2672
2687
  try {
2673
- const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs10.readFileUtf8(import_node_path7.default.join(sessionsDir, name)) ?? ""));
2688
+ const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs12.readFileUtf8(import_node_path7.default.join(sessionsDir, name)) ?? ""));
2674
2689
  if (parsed.success) {
2675
2690
  sessions.push({ pid: parsed.data.pid, startedAt: parsed.data.startedAt });
2676
2691
  }
@@ -2680,14 +2695,14 @@ function listFrontDoorSessions(fs10, sessionsDir) {
2680
2695
  }
2681
2696
  return sessions.sort((a, b) => a.pid - b.pid);
2682
2697
  }
2683
- function removeFrontDoorSession(fs10, sessionsDir, pid) {
2684
- fs10.removeRecursive(import_node_path7.default.join(sessionsDir, `${String(pid)}.json`));
2698
+ function removeFrontDoorSession(fs12, sessionsDir, pid) {
2699
+ fs12.removeRecursive(import_node_path7.default.join(sessionsDir, `${String(pid)}.json`));
2685
2700
  }
2686
- function pruneDeadFrontDoorSessions(fs10, sessionsDir, isRunning) {
2701
+ function pruneDeadFrontDoorSessions(fs12, sessionsDir, isRunning) {
2687
2702
  const removed = [];
2688
- for (const session of listFrontDoorSessions(fs10, sessionsDir)) {
2703
+ for (const session of listFrontDoorSessions(fs12, sessionsDir)) {
2689
2704
  if (!isRunning(session.pid)) {
2690
- removeFrontDoorSession(fs10, sessionsDir, session.pid);
2705
+ removeFrontDoorSession(fs12, sessionsDir, session.pid);
2691
2706
  removed.push(session.pid);
2692
2707
  }
2693
2708
  }
@@ -2699,8 +2714,8 @@ var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
2699
2714
  var FRONTDOOR_POLL_MS = 1e3;
2700
2715
  var MS_PER_MINUTE = 6e4;
2701
2716
  async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
2702
- const { fs: fs10, paths } = ports;
2703
- const previous = readFrontDoorState(fs10, paths.frontdoorStateFile);
2717
+ const { fs: fs12, paths } = ports;
2718
+ const previous = readFrontDoorState(fs12, paths.frontdoorStateFile);
2704
2719
  let lastPort = previous?.lastPort;
2705
2720
  let lastConnectPort = previous?.lastConnectPort;
2706
2721
  let lastDirectPort = previous?.lastDirectPort;
@@ -2710,12 +2725,12 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2710
2725
  ...lastDirectPort === void 0 ? {} : { lastDirectPort }
2711
2726
  });
2712
2727
  const fail = (message) => {
2713
- writeFrontDoorState(fs10, paths.frontdoorStateFile, { lastError: message, ...sticky() });
2714
- fs10.removeRecursive(paths.frontdoorLockFile);
2728
+ writeFrontDoorState(fs12, paths.frontdoorStateFile, { lastError: message, ...sticky() });
2729
+ fs12.removeRecursive(paths.frontdoorLockFile);
2715
2730
  ports.log(`agent-shim frontdoor supervisor: ${message}`);
2716
2731
  return 1;
2717
2732
  };
2718
- writeFrontDoorState(fs10, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
2733
+ writeFrontDoorState(fs12, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
2719
2734
  const previousSticky = lastPort;
2720
2735
  let http2;
2721
2736
  try {
@@ -2752,8 +2767,8 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2752
2767
  ports.log(`agent-shim frontdoor supervisor: sticky direct port ${String(previousStickyDirect)} was occupied; moving to ${String(direct.port)} (headroom must be restarted to admit the new address)`);
2753
2768
  }
2754
2769
  lastDirectPort = direct.port;
2755
- writeFrontDoorState(fs10, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http2.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
2756
- fs10.removeRecursive(paths.frontdoorLockFile);
2770
+ writeFrontDoorState(fs12, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http2.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
2771
+ fs12.removeRecursive(paths.frontdoorLockFile);
2757
2772
  ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http2.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
2758
2773
  let idleSince;
2759
2774
  let ticks = 0;
@@ -2762,15 +2777,15 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2762
2777
  return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
2763
2778
  }
2764
2779
  ticks += 1;
2765
- pruneDeadFrontDoorSessions(fs10, paths.frontdoorSessionsDir, ports.isRunning);
2766
- if (listFrontDoorSessions(fs10, paths.frontdoorSessionsDir).length === 0) {
2780
+ pruneDeadFrontDoorSessions(fs12, paths.frontdoorSessionsDir, ports.isRunning);
2781
+ if (listFrontDoorSessions(fs12, paths.frontdoorSessionsDir).length === 0) {
2767
2782
  idleSince ??= ports.now();
2768
2783
  if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
2769
2784
  ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
2770
2785
  await direct.close();
2771
2786
  await connect3.close();
2772
2787
  await http2.close();
2773
- writeFrontDoorState(fs10, paths.frontdoorStateFile, sticky());
2788
+ writeFrontDoorState(fs12, paths.frontdoorStateFile, sticky());
2774
2789
  return 0;
2775
2790
  }
2776
2791
  } else {
@@ -2825,8 +2840,8 @@ function parseConnectTarget(authority) {
2825
2840
  function isInterceptedHost(host, interceptHosts) {
2826
2841
  return interceptHosts.includes(host);
2827
2842
  }
2828
- function servedByPipeline(path23) {
2829
- return path23?.startsWith(ROUTED_PATH_PREFIX) === true;
2843
+ function servedByPipeline(path28) {
2844
+ return path28?.startsWith(ROUTED_PATH_PREFIX) === true;
2830
2845
  }
2831
2846
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
2832
2847
  "connection",
@@ -3360,16 +3375,16 @@ function parseJson(raw, schema) {
3360
3375
  const parsed = schema.safeParse(JSON.parse(raw));
3361
3376
  return parsed.success ? parsed.data : void 0;
3362
3377
  }
3363
- function readHeadroomState(fs10, stateFile) {
3378
+ function readHeadroomState(fs12, stateFile) {
3364
3379
  try {
3365
- return parseJson(fs10.readFileUtf8(stateFile), HeadroomStateSchema);
3380
+ return parseJson(fs12.readFileUtf8(stateFile), HeadroomStateSchema);
3366
3381
  } catch {
3367
3382
  return void 0;
3368
3383
  }
3369
3384
  }
3370
- function writeHeadroomState(fs10, stateFile, state) {
3371
- fs10.mkdirp(import_node_path8.default.dirname(stateFile));
3372
- fs10.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
3385
+ function writeHeadroomState(fs12, stateFile, state) {
3386
+ fs12.mkdirp(import_node_path8.default.dirname(stateFile));
3387
+ fs12.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
3373
3388
  `);
3374
3389
  }
3375
3390
  function headroomAllowlist(providers) {
@@ -3389,14 +3404,14 @@ function headroomUpstreams(providers, frontDoorOrigin2) {
3389
3404
  function hashAllowlist(allowlist) {
3390
3405
  return (0, import_node_crypto5.createHash)("sha256").update(allowlist.join("\n")).digest("hex");
3391
3406
  }
3392
- function readAllProviders(fs10, providersDir) {
3407
+ function readAllProviders(fs12, providersDir) {
3393
3408
  const result = [];
3394
- for (const name of fs10.readdir(providersDir)) {
3409
+ for (const name of fs12.readdir(providersDir)) {
3395
3410
  if (!name.endsWith(".json")) {
3396
3411
  continue;
3397
3412
  }
3398
3413
  try {
3399
- const parsed = parseJson(fs10.readFileUtf8(import_node_path8.default.join(providersDir, name)), ProviderSchema);
3414
+ const parsed = parseJson(fs12.readFileUtf8(import_node_path8.default.join(providersDir, name)), ProviderSchema);
3400
3415
  if (parsed !== void 0) {
3401
3416
  result.push({ name: name.slice(0, -".json".length), provider: parsed });
3402
3417
  }
@@ -3406,22 +3421,22 @@ function readAllProviders(fs10, providersDir) {
3406
3421
  }
3407
3422
  return result;
3408
3423
  }
3409
- function writeSession(fs10, sessionsDir, session) {
3410
- fs10.mkdirp(sessionsDir);
3411
- fs10.writeFileUtf8(import_node_path8.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
3424
+ function writeSession(fs12, sessionsDir, session) {
3425
+ fs12.mkdirp(sessionsDir);
3426
+ fs12.writeFileUtf8(import_node_path8.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
3412
3427
  `);
3413
3428
  }
3414
- function removeSession(fs10, sessionsDir, pid) {
3415
- fs10.removeRecursive(import_node_path8.default.join(sessionsDir, `${String(pid)}.json`));
3429
+ function removeSession(fs12, sessionsDir, pid) {
3430
+ fs12.removeRecursive(import_node_path8.default.join(sessionsDir, `${String(pid)}.json`));
3416
3431
  }
3417
- function listSessions(fs10, sessionsDir) {
3432
+ function listSessions(fs12, sessionsDir) {
3418
3433
  const sessions = [];
3419
- for (const name of fs10.readdir(sessionsDir)) {
3434
+ for (const name of fs12.readdir(sessionsDir)) {
3420
3435
  if (!name.endsWith(".json")) {
3421
3436
  continue;
3422
3437
  }
3423
3438
  try {
3424
- const parsed = parseJson(fs10.readFileUtf8(import_node_path8.default.join(sessionsDir, name)), HeadroomSessionSchema);
3439
+ const parsed = parseJson(fs12.readFileUtf8(import_node_path8.default.join(sessionsDir, name)), HeadroomSessionSchema);
3425
3440
  if (parsed !== void 0) {
3426
3441
  sessions.push(parsed);
3427
3442
  }
@@ -3431,22 +3446,22 @@ function listSessions(fs10, sessionsDir) {
3431
3446
  }
3432
3447
  return sessions.sort((a, b) => a.pid - b.pid);
3433
3448
  }
3434
- function sessionsForSupervisor(fs10, sessionsDir, supervisorPid) {
3435
- return listSessions(fs10, sessionsDir).filter((session) => session.supervisorPid === supervisorPid);
3449
+ function sessionsForSupervisor(fs12, sessionsDir, supervisorPid) {
3450
+ return listSessions(fs12, sessionsDir).filter((session) => session.supervisorPid === supervisorPid);
3436
3451
  }
3437
- function pruneDeadSessions(fs10, sessionsDir, isRunning) {
3452
+ function pruneDeadSessions(fs12, sessionsDir, isRunning) {
3438
3453
  const removed = [];
3439
- for (const session of listSessions(fs10, sessionsDir)) {
3454
+ for (const session of listSessions(fs12, sessionsDir)) {
3440
3455
  if (!isRunning(session.pid)) {
3441
- removeSession(fs10, sessionsDir, session.pid);
3456
+ removeSession(fs12, sessionsDir, session.pid);
3442
3457
  removed.push(session.pid);
3443
3458
  }
3444
3459
  }
3445
3460
  return removed;
3446
3461
  }
3447
- function readStartLock(fs10, lockFile) {
3462
+ function readStartLock(fs12, lockFile) {
3448
3463
  try {
3449
- return parseJson(fs10.readFileUtf8(lockFile), HeadroomLockSchema);
3464
+ return parseJson(fs12.readFileUtf8(lockFile), HeadroomLockSchema);
3450
3465
  } catch {
3451
3466
  return void 0;
3452
3467
  }
@@ -3697,12 +3712,12 @@ function isIdentityName(name) {
3697
3712
  function claudeJsonPath(identitiesDir, identity) {
3698
3713
  return import_node_path9.default.join(identitiesDir, identity, CLAUDE_JSON);
3699
3714
  }
3700
- function readAccountMetadata(fs10, identitiesDir, identity) {
3715
+ function readAccountMetadata(fs12, identitiesDir, identity) {
3701
3716
  if (!isIdentityName(identity)) {
3702
3717
  throw new Error(`"${identity}" is not a valid identity name.`);
3703
3718
  }
3704
3719
  const file = claudeJsonPath(identitiesDir, identity);
3705
- const raw = fs10.readFileUtf8(file);
3720
+ const raw = fs12.readFileUtf8(file);
3706
3721
  if (raw === void 0) {
3707
3722
  return void 0;
3708
3723
  }
@@ -3736,8 +3751,8 @@ function readAccountMetadata(fs10, identitiesDir, identity) {
3736
3751
  // src/usage/read.ts
3737
3752
  var SEGMENT_RE = /^(\d{4}-\d{2}-\d{2})\.(\d+)\.jsonl$/;
3738
3753
  var DAY_MS = 864e5;
3739
- function listLogSegments(fs10, logDir) {
3740
- return fs10.readdir(logDir).flatMap((name) => {
3754
+ function listLogSegments(fs12, logDir) {
3755
+ return fs12.readdir(logDir).flatMap((name) => {
3741
3756
  const match = SEGMENT_RE.exec(name);
3742
3757
  const day = match?.[1];
3743
3758
  if (day === void 0) {
@@ -3746,15 +3761,15 @@ function listLogSegments(fs10, logDir) {
3746
3761
  return [{ name, day, endsAt: Date.parse(`${day}T00:00:00.000Z`) + DAY_MS }];
3747
3762
  }).sort((left, right) => left.day.localeCompare(right.day) || left.name.localeCompare(right.name));
3748
3763
  }
3749
- function readUsageLog(fs10, logDir, options = {}) {
3764
+ function readUsageLog(fs12, logDir, options = {}) {
3750
3765
  const { sinceMs } = options;
3751
3766
  const records = [];
3752
3767
  let invalidLines = 0;
3753
- for (const segment of listLogSegments(fs10, logDir)) {
3768
+ for (const segment of listLogSegments(fs12, logDir)) {
3754
3769
  if (sinceMs !== void 0 && segment.endsAt <= sinceMs) {
3755
3770
  continue;
3756
3771
  }
3757
- const contents = fs10.readFileUtf8(import_node_path10.default.join(logDir, segment.name));
3772
+ const contents = fs12.readFileUtf8(import_node_path10.default.join(logDir, segment.name));
3758
3773
  if (contents === void 0) {
3759
3774
  continue;
3760
3775
  }
@@ -3798,9 +3813,9 @@ function snapshotPath(snapshotsDir, identity) {
3798
3813
  }
3799
3814
  return import_node_path10.default.join(snapshotsDir, `${identity}.json`);
3800
3815
  }
3801
- function readUsageSnapshot(fs10, snapshotsDir, identity) {
3816
+ function readUsageSnapshot(fs12, snapshotsDir, identity) {
3802
3817
  const file = snapshotPath(snapshotsDir, identity);
3803
- const raw = fs10.readFileUtf8(file);
3818
+ const raw = fs12.readFileUtf8(file);
3804
3819
  if (raw === void 0) {
3805
3820
  return void 0;
3806
3821
  }
@@ -3816,8 +3831,8 @@ function readUsageSnapshot(fs10, snapshotsDir, identity) {
3816
3831
  }
3817
3832
  return snapshot.data;
3818
3833
  }
3819
- function listUsageSnapshots(fs10, snapshotsDir) {
3820
- return fs10.readdir(snapshotsDir).flatMap((name) => {
3834
+ function listUsageSnapshots(fs12, snapshotsDir) {
3835
+ return fs12.readdir(snapshotsDir).flatMap((name) => {
3821
3836
  if (!name.endsWith(".json")) {
3822
3837
  return [];
3823
3838
  }
@@ -3825,7 +3840,7 @@ function listUsageSnapshots(fs10, snapshotsDir) {
3825
3840
  if (!isIdentityName(identity)) {
3826
3841
  return [];
3827
3842
  }
3828
- const snapshot = readUsageSnapshot(fs10, snapshotsDir, identity);
3843
+ const snapshot = readUsageSnapshot(fs12, snapshotsDir, identity);
3829
3844
  return snapshot === void 0 ? [] : [snapshot];
3830
3845
  }).sort((left, right) => left.identity.localeCompare(right.identity));
3831
3846
  }
@@ -4000,9 +4015,9 @@ function compareVersions(a, b) {
4000
4015
  }
4001
4016
  var HEADROOM_SUPERVISOR_STILL_RUNNING = -1;
4002
4017
  async function runSupervisor(initialConfig, ports, options = {}) {
4003
- const { fs: fs10, paths } = ports;
4018
+ const { fs: fs12, paths } = ports;
4004
4019
  let config = initialConfig;
4005
- const previousState = readHeadroomState(fs10, paths.headroomStateFile);
4020
+ const previousState = readHeadroomState(fs12, paths.headroomStateFile);
4006
4021
  if (previousState?.supervisorPid !== void 0 && previousState.supervisorPid !== ports.ownPid && ports.isRunning(previousState.supervisorPid)) {
4007
4022
  ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: supervisor ${String(previousState.supervisorPid)} already owns the daemon; exiting`);
4008
4023
  return 0;
@@ -4011,19 +4026,19 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4011
4026
  let lastPort = previousState?.lastPort;
4012
4027
  const sticky = () => lastPort === void 0 ? {} : { lastPort };
4013
4028
  const ownsState = () => {
4014
- const owner = readHeadroomState(fs10, paths.headroomStateFile)?.supervisorPid;
4029
+ const owner = readHeadroomState(fs12, paths.headroomStateFile)?.supervisorPid;
4015
4030
  return owner === void 0 || owner === ports.ownPid || !ports.isRunning(owner);
4016
4031
  };
4017
4032
  const writeOwnState = (state) => {
4018
4033
  if (!ownsState()) {
4019
4034
  return false;
4020
4035
  }
4021
- writeHeadroomState(fs10, paths.headroomStateFile, state);
4036
+ writeHeadroomState(fs12, paths.headroomStateFile, state);
4022
4037
  return true;
4023
4038
  };
4024
4039
  const fail = (message) => {
4025
4040
  if (writeOwnState({ lastError: message, ...sticky() })) {
4026
- fs10.removeRecursive(paths.headroomLockFile);
4041
+ fs12.removeRecursive(paths.headroomLockFile);
4027
4042
  }
4028
4043
  ports.log(`agent-shim headroom supervisor: ${message}`);
4029
4044
  return 1;
@@ -4072,7 +4087,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4072
4087
  const settingsHash = hashSettings(config.settings);
4073
4088
  const allowlist = allowlistOf(ports);
4074
4089
  const allowlistHash = hashAllowlist(allowlist);
4075
- pruneDeadSessions(fs10, paths.headroomSessionsDir, ports.isRunning);
4090
+ pruneDeadSessions(fs12, paths.headroomSessionsDir, ports.isRunning);
4076
4091
  const ownsNow = ownsState();
4077
4092
  if (!ownsNow && !superseded) {
4078
4093
  ports.log("agent-shim headroom supervisor: another supervisor now owns state.json; serving this daemon's own sessions until they end");
@@ -4124,7 +4139,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4124
4139
  ...sticky()
4125
4140
  });
4126
4141
  if (recorded) {
4127
- fs10.removeRecursive(paths.headroomLockFile);
4142
+ fs12.removeRecursive(paths.headroomLockFile);
4128
4143
  }
4129
4144
  idleSince = void 0;
4130
4145
  ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on 127.0.0.1:${String(port)}`);
@@ -4139,7 +4154,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4139
4154
  }
4140
4155
  } else {
4141
4156
  if (runningHash !== allowlistHash || runningSettingsHash !== settingsHash || installedSource !== config.source) {
4142
- if (sessionsForSupervisor(fs10, paths.headroomSessionsDir, ports.ownPid).length === 0) {
4157
+ if (sessionsForSupervisor(fs12, paths.headroomSessionsDir, ports.ownPid).length === 0) {
4143
4158
  ports.log("agent-shim headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
4144
4159
  ports.stopProcess(headroomPid);
4145
4160
  headroomPid = void 0;
@@ -4148,7 +4163,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4148
4163
  continue;
4149
4164
  }
4150
4165
  }
4151
- const sessions = sessionsForSupervisor(fs10, paths.headroomSessionsDir, ports.ownPid);
4166
+ const sessions = sessionsForSupervisor(fs12, paths.headroomSessionsDir, ports.ownPid);
4152
4167
  if (sessions.length === 0) {
4153
4168
  idleSince ??= ports.now();
4154
4169
  const idleMs = ports.now() - idleSince;
@@ -4170,9 +4185,9 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4170
4185
  await ports.sleep(HEADROOM_POLL_MS);
4171
4186
  }
4172
4187
  }
4173
- function currentHeadroomAllowlist(fs10, paths) {
4174
- const providers = readAllProviders(fs10, paths.providersDir).map((entry) => entry.provider);
4175
- return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(fs10, paths.frontdoorStateFile))));
4188
+ function currentHeadroomAllowlist(fs12, paths) {
4189
+ const providers = readAllProviders(fs12, paths.providersDir).map((entry) => entry.provider);
4190
+ return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile))));
4176
4191
  }
4177
4192
  function allowlistOf(ports) {
4178
4193
  return currentHeadroomAllowlist(ports.fs, ports.paths);
@@ -4349,8 +4364,8 @@ function decideConfigProfile(params) {
4349
4364
  }
4350
4365
  return { source: "none" };
4351
4366
  }
4352
- function loadIdentity(identitiesDir, name, fs10) {
4353
- return loadConfigFile(import_node_path12.default.join(identitiesDir, name, "identity.json"), IdentitySchema, fs10.readConfigFile);
4367
+ function loadIdentity(identitiesDir, name, fs12) {
4368
+ return loadConfigFile(import_node_path12.default.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
4354
4369
  }
4355
4370
 
4356
4371
  // src/configProfilesStore.ts
@@ -4692,13 +4707,59 @@ var import_node_path15 = __toESM(require("node:path"), 1);
4692
4707
 
4693
4708
  // src/credentialCache.ts
4694
4709
  var import_zod7 = require("zod");
4710
+ var MS_PER_UNIT = { s: 1e3, m: 6e4, h: 36e5, d: 864e5 };
4695
4711
  var CachedCredentialSchema = import_zod7.z.strictObject({
4696
4712
  token: import_zod7.z.string().min(1),
4697
4713
  fetchedAt: import_zod7.z.number().int().nonnegative(),
4698
4714
  source: CredentialSourceSchema
4699
4715
  });
4716
+ function effectiveStore(cache, platform) {
4717
+ return cache.store ?? (platform === "darwin" ? "keychain" : "file");
4718
+ }
4719
+ function ttlMs(cache) {
4720
+ if (cache.ttl === void 0) {
4721
+ return void 0;
4722
+ }
4723
+ const multiplier = MS_PER_UNIT[cache.ttl.slice(-1)];
4724
+ if (multiplier === void 0) {
4725
+ throw new Error(`credential cache ttl "${cache.ttl}" has no recognised unit`);
4726
+ }
4727
+ return Number(cache.ttl.slice(0, -1)) * multiplier;
4728
+ }
4729
+ function isFresh(entry, cache, now) {
4730
+ const limit = ttlMs(cache);
4731
+ if (entry.fetchedAt > now) {
4732
+ return false;
4733
+ }
4734
+ return limit === void 0 || now - entry.fetchedAt < limit;
4735
+ }
4700
4736
 
4701
4737
  // src/credential.ts
4738
+ var CREDENTIAL_UNAVAILABLE_EXIT = 64;
4739
+ var CREDENTIAL_COMMAND_TIMEOUT_MS = 1e4;
4740
+ var CREDENTIAL_INTERACTIVE_TIMEOUT_MS = 12e4;
4741
+ var GROUP_OTHER_PERMISSION_BITS = 63;
4742
+ var PERMISSION_BITS = 511;
4743
+ var OCTAL_RADIX = 8;
4744
+ function commandArgv(source) {
4745
+ if ("command" in source) {
4746
+ return source.command;
4747
+ }
4748
+ if ("op" in source) {
4749
+ return ["op", "read", source.op];
4750
+ }
4751
+ const account = source.keychain.account;
4752
+ return ["security", "find-generic-password", "-s", source.keychain.service, ...account === void 0 ? [] : ["-a", account], "-w"];
4753
+ }
4754
+ function isInteractiveSource(source, env) {
4755
+ if ("command" in source || "keychain" in source) {
4756
+ return source.interactive ?? false;
4757
+ }
4758
+ if ("op" in source) {
4759
+ return source.interactive ?? (env.OP_SERVICE_ACCOUNT_TOKEN ?? "") === "";
4760
+ }
4761
+ return false;
4762
+ }
4702
4763
  function summariseSource(source) {
4703
4764
  if ("env" in source) {
4704
4765
  return { kind: "env", variable: source.env };
@@ -4746,6 +4807,9 @@ function formatSourceSummary(summary) {
4746
4807
  return summary;
4747
4808
  }
4748
4809
  }
4810
+ function describeSource(source) {
4811
+ return formatSourceSummary(summariseSource(source));
4812
+ }
4749
4813
  function formatCredentialSummary(summary) {
4750
4814
  const cache = summary.cache === void 0 ? "" : `, cached ${summary.cache.ttl === void 0 ? "with no expiry" : `for ${summary.cache.ttl}`}${summary.cache.store === void 0 ? "" : ` in the ${summary.cache.store} store`}`;
4751
4815
  return `${summary.target} from ${summary.sources.map(formatSourceSummary).join(", then ")}${cache}`;
@@ -4753,6 +4817,88 @@ function formatCredentialSummary(summary) {
4753
4817
  function describeCredential(credential) {
4754
4818
  return formatCredentialSummary(summariseCredential(credential));
4755
4819
  }
4820
+ function trySource(source, params) {
4821
+ const none = (reason, warn = false) => ({ ok: false, reason, warn });
4822
+ if ("env" in source) {
4823
+ const value = params.env[source.env];
4824
+ return value === void 0 || value === "" ? none("is unset or empty") : { ok: true, token: value };
4825
+ }
4826
+ if ("literal" in source) {
4827
+ return { ok: true, token: source.literal };
4828
+ }
4829
+ if ("file" in source) {
4830
+ const read = params.port.readSecretFile(source.file);
4831
+ if (!read.found) {
4832
+ return none("does not exist");
4833
+ }
4834
+ if (read.mode !== void 0 && (read.mode & GROUP_OTHER_PERMISSION_BITS) !== 0) {
4835
+ return none(
4836
+ `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS).toString(OCTAL_RADIX)}); run \`chmod 600 ${source.file}\``,
4837
+ true
4838
+ );
4839
+ }
4840
+ const token2 = read.content.trim();
4841
+ return token2 === "" ? none("is empty") : { ok: true, token: token2 };
4842
+ }
4843
+ const argv = commandArgv(source);
4844
+ const interactive = isInteractiveSource(source, params.env);
4845
+ if (interactive && !params.port.personPresent()) {
4846
+ return none("needs a person to approve it, but there is no terminal or desktop session");
4847
+ }
4848
+ const timeoutMs = source.timeoutMs ?? (interactive ? CREDENTIAL_INTERACTIVE_TIMEOUT_MS : CREDENTIAL_COMMAND_TIMEOUT_MS);
4849
+ const result = params.port.runCommand(argv, { timeoutMs, interactive });
4850
+ if (result.timedOut) {
4851
+ return none(`timed out after ${String(timeoutMs)}ms`);
4852
+ }
4853
+ if (result.status !== 0) {
4854
+ const stderr = result.stderr.trim();
4855
+ const outcome = result.status === null ? "could not be run or was killed by a signal" : `exited with status ${String(result.status)}`;
4856
+ return none(`${outcome}${stderr === "" ? "" : `: ${stderr}`}`);
4857
+ }
4858
+ const token = result.stdout.trim();
4859
+ return token === "" ? none("printed no token") : { ok: true, token };
4860
+ }
4861
+ function warmCommandFor(subject) {
4862
+ const [kind, name] = subject.split(" ");
4863
+ return kind === "provider" ? `agent-shim credential warm --provider ${name ?? ""}` : `agent-shim credential warm ${name ?? ""}`;
4864
+ }
4865
+ function resolveCredential(params) {
4866
+ const target = params.credential.target ?? "bearer";
4867
+ const cacheBlock = params.credential.cache;
4868
+ const cache = cacheBlock === void 0 ? void 0 : params.port.cache;
4869
+ const store = cacheBlock === void 0 || cache === void 0 ? void 0 : effectiveStore(cacheBlock, cache.platform);
4870
+ if (cacheBlock !== void 0 && cache !== void 0 && store !== void 0 && params.refresh !== true) {
4871
+ const entry = cache.port.read(store, params.subject);
4872
+ if (entry !== void 0 && isFresh(entry, cacheBlock, cache.now())) {
4873
+ return { ok: true, credential: { target, token: entry.token, source: entry.source, warnings: [], cachedAt: entry.fetchedAt } };
4874
+ }
4875
+ }
4876
+ const attempts = [];
4877
+ const warnings = [];
4878
+ for (const source of params.credential.sources) {
4879
+ const outcome = trySource(source, params);
4880
+ if (outcome.ok) {
4881
+ if (cache !== void 0 && store !== void 0) {
4882
+ cache.port.write(store, params.subject, { token: outcome.token, fetchedAt: cache.now(), source });
4883
+ }
4884
+ return { ok: true, credential: { target, token: outcome.token, source, warnings } };
4885
+ }
4886
+ const line = `${describeSource(source)} ${outcome.reason}`;
4887
+ attempts.push(line);
4888
+ if (outcome.warn) {
4889
+ warnings.push(`agent-shim: ${params.subject}: skipped ${line}`);
4890
+ }
4891
+ }
4892
+ const hint = cacheBlock === void 0 ? "" : `; fill the cache from a terminal with \`${warmCommandFor(params.subject)}\``;
4893
+ return { ok: false, message: `agent-shim: ${params.subject} has no usable credential: ${attempts.join("; ")}${hint}` };
4894
+ }
4895
+ function credentialVariables(target, token) {
4896
+ return {
4897
+ ANTHROPIC_AUTH_TOKEN: target === "bearer" ? token : void 0,
4898
+ ANTHROPIC_API_KEY: target === "apiKey" ? token : void 0,
4899
+ CLAUDE_CODE_OAUTH_TOKEN: target === "oauthToken" ? token : void 0
4900
+ };
4901
+ }
4756
4902
 
4757
4903
  // src/providersStore.ts
4758
4904
  var ProviderNotFoundError = class extends CliError {
@@ -4858,6 +5004,11 @@ function readProvider(paths, name) {
4858
5004
  const raw = JSON.parse(import_node_fs5.default.readFileSync(filePath, "utf8"));
4859
5005
  return parseProviderFile(filePath, raw);
4860
5006
  }
5007
+ function loadProvider(providersDir, name, port) {
5008
+ const filePath = import_node_path15.default.join(providersDir, `${name}.json`);
5009
+ const raw = port.readConfigFile(filePath);
5010
+ return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
5011
+ }
4861
5012
  function listProviders(paths) {
4862
5013
  const names = listProviderNames(
4863
5014
  (dir) => import_node_fs5.default.readdirSync(dir),
@@ -4990,6 +5141,30 @@ function cascadeProviderName(cascade) {
4990
5141
  }
4991
5142
  return name;
4992
5143
  }
5144
+ function resolveProvider(params) {
5145
+ const cliName = params.cliProvider !== void 0 && params.cliProvider !== "" ? params.cliProvider : void 0;
5146
+ const name = cliName ?? (params.cascade === void 0 ? void 0 : cascadeProviderName(params.cascade));
5147
+ if (name === void 0) {
5148
+ return void 0;
5149
+ }
5150
+ const definition = loadProvider(params.paths.providersDir, name, params.port);
5151
+ if (definition === void 0) {
5152
+ const known = listProviderNames(params.port.readdir, params.paths.providersDir);
5153
+ return {
5154
+ ok: false,
5155
+ status: 1,
5156
+ message: `agent-shim: no provider named "${name}". ` + (known.length > 0 ? `Known providers: ${known.join(", ")}.` : "No providers are defined yet; run `agent-shim provider add`.")
5157
+ };
5158
+ }
5159
+ if (params.credentials === void 0) {
5160
+ return { ok: false, status: 1, message: `agent-shim: provider ${name} needs its credential resolved, but this launcher has no credential port wired` };
5161
+ }
5162
+ const resolution = resolveCredential({ credential: definition.credential, env: params.env, port: params.credentials, subject: `provider ${name}` });
5163
+ if (!resolution.ok) {
5164
+ return { ok: false, status: CREDENTIAL_UNAVAILABLE_EXIT, message: resolution.message };
5165
+ }
5166
+ return { ok: true, provider: { name, definition, credential: resolution.credential }, warnings: resolution.credential.warnings };
5167
+ }
4993
5168
 
4994
5169
  // src/directoryRulesStore.ts
4995
5170
  var DirectoryRuleNotFoundError = class extends CliError {
@@ -5082,7 +5257,7 @@ function removeDirectoryRule(paths, rulePath) {
5082
5257
  }
5083
5258
 
5084
5259
  // src/checkReport.ts
5085
- var import_node_os3 = __toESM(require("node:os"), 1);
5260
+ var import_node_os4 = __toESM(require("node:os"), 1);
5086
5261
 
5087
5262
  // src/launcher/cascade.ts
5088
5263
  var import_node_path17 = __toESM(require("node:path"), 1);
@@ -5178,6 +5353,7 @@ var MS_PER_SECOND2 = 1e3;
5178
5353
  var SECONDS_PER_MINUTE = 60;
5179
5354
  var MINUTES_PER_HOUR = 60;
5180
5355
  var HOURS_PER_DAY = 24;
5356
+ var WARNING_STATUSES = /* @__PURE__ */ new Set(["allowed_warning", "rejected"]);
5181
5357
  function formatAge(ms) {
5182
5358
  const minutes = Math.floor(ms / (MS_PER_SECOND2 * SECONDS_PER_MINUTE));
5183
5359
  if (minutes < MINUTES_PER_HOUR) {
@@ -5198,8 +5374,30 @@ function effectiveWindow(window, nowMs) {
5198
5374
  ...window.status === void 0 ? {} : { status: window.status }
5199
5375
  };
5200
5376
  }
5377
+ function quotaWarnings(snapshot, provider, nowMs) {
5378
+ const rateLimit = snapshot?.providers[provider]?.rateLimit;
5379
+ const unified = rateLimit?.unified;
5380
+ if (snapshot === void 0 || rateLimit === void 0 || unified === void 0) {
5381
+ return [];
5382
+ }
5383
+ const age = formatAge(nowMs - Date.parse(rateLimit.observedAt));
5384
+ const windows = [
5385
+ { name: "five-hour", window: unified.fiveHour },
5386
+ { name: "seven-day", window: unified.sevenDay }
5387
+ ];
5388
+ return windows.flatMap(({ name, window }) => {
5389
+ const effective = window === void 0 ? void 0 : effectiveWindow(window, nowMs);
5390
+ if (window === void 0 || effective?.status === void 0 || !WARNING_STATUSES.has(effective.status)) {
5391
+ return [];
5392
+ }
5393
+ const reset = window.resetsAt === void 0 ? "" : `, resets ${window.resetsAt}`;
5394
+ const verdict = effective.status === "rejected" ? "exhausted" : "nearly used";
5395
+ return [`agent-shim: identity ${snapshot.identity}: the ${name} quota is ${verdict}${reset} (last seen ${age} ago)`];
5396
+ });
5397
+ }
5201
5398
 
5202
5399
  // src/usage/poolPick.ts
5400
+ var import_node_path18 = __toESM(require("node:path"), 1);
5203
5401
  var import_zod9 = require("zod");
5204
5402
 
5205
5403
  // src/usage/plan.ts
@@ -5452,14 +5650,14 @@ var PicksFileSchema = import_zod9.z.strictObject({
5452
5650
  function errorMessage(error) {
5453
5651
  return error instanceof Error ? error.message : String(error);
5454
5652
  }
5455
- function loadPoolMembers(fs10, paths, identities, nowMs) {
5653
+ function loadPoolMembers(fs12, paths, identities, nowMs) {
5456
5654
  const windowStartMs = nowMs - FIVE_HOUR_WINDOW_MS;
5457
- const log = readUsageLog(fs10, paths.usageLogDir, { sinceMs: windowStartMs });
5655
+ const log = readUsageLog(fs12, paths.usageLogDir, { sinceMs: windowStartMs });
5458
5656
  return identities.map((identity) => {
5459
5657
  const records = log.records.filter((record) => record.identity === identity && record.provider === ANTHROPIC_PROVIDER && Date.parse(record.at) >= windowStartMs);
5460
5658
  try {
5461
- const snapshot = readUsageSnapshot(fs10, paths.usageSnapshotsDir, identity);
5462
- const account = readAccountMetadata(fs10, paths.identitiesDir, identity) ?? snapshot?.account;
5659
+ const snapshot = readUsageSnapshot(fs12, paths.usageSnapshotsDir, identity);
5660
+ const account = readAccountMetadata(fs12, paths.identitiesDir, identity) ?? snapshot?.account;
5463
5661
  return { identity, records, ...snapshot === void 0 ? {} : { snapshot }, ...account === void 0 ? {} : { account } };
5464
5662
  } catch (error) {
5465
5663
  if (error instanceof UsageSnapshotError || error instanceof AccountMetadataError) {
@@ -5477,9 +5675,9 @@ function rankPoolFromStore(params) {
5477
5675
  ...params.sticky === void 0 ? {} : { sticky: params.sticky }
5478
5676
  });
5479
5677
  }
5480
- function readPicksFile(fs10, file) {
5678
+ function readPicksFile(fs12, file) {
5481
5679
  const empty = { schemaVersion: SCHEMA_VERSION, picks: {} };
5482
- const raw = fs10.readFileUtf8(file);
5680
+ const raw = fs12.readFileUtf8(file);
5483
5681
  if (raw === void 0) {
5484
5682
  return { file: empty };
5485
5683
  }
@@ -5492,17 +5690,72 @@ function readPicksFile(fs10, file) {
5492
5690
  const result = PicksFileSchema.safeParse(parsed);
5493
5691
  return result.success ? { file: result.data } : { file: empty, problem: `${file} is not a picks file this agent-shim can read` };
5494
5692
  }
5495
- function readStickyPick(fs10, picksFile, directory) {
5496
- const read = readPicksFile(fs10, picksFile);
5693
+ function readStickyPick(fs12, picksFile, directory) {
5694
+ const read = readPicksFile(fs12, picksFile);
5497
5695
  const entry = read.file.picks[directory];
5498
5696
  return { ...entry === void 0 ? {} : { sticky: entry }, ...read.problem === void 0 ? {} : { problem: read.problem } };
5499
5697
  }
5698
+ function recordStickyPick(fs12, picksFile, directory, identity, nowMs) {
5699
+ const current = readPicksFile(fs12, picksFile).file.picks;
5700
+ const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
5701
+ const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
5702
+ fs12.mkdirPrivate(import_node_path18.default.dirname(picksFile));
5703
+ fs12.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
5704
+ `);
5705
+ }
5500
5706
 
5501
5707
  // src/launcher/pool.ts
5502
- function splitMembers(pool, paths, fs10) {
5503
- const exists = (name) => loadIdentity(paths.identitiesDir, name, fs10) !== void 0;
5708
+ var RESUME_FLAGS = /* @__PURE__ */ new Set(["--continue", "-c", "--resume", "-r"]);
5709
+ var TERMINATOR = "--";
5710
+ var REASONS_LOGGED = 3;
5711
+ function splitMembers(pool, paths, fs12) {
5712
+ const exists = (name) => loadIdentity(paths.identitiesDir, name, fs12) !== void 0;
5504
5713
  return { present: pool.identities.filter(exists), missing: pool.identities.filter((name) => !exists(name)) };
5505
5714
  }
5715
+ function isResuming(passthrough) {
5716
+ const end = passthrough.indexOf(TERMINATOR);
5717
+ return (end === -1 ? passthrough : passthrough.slice(0, end)).some((token) => RESUME_FLAGS.has(token));
5718
+ }
5719
+ function resolvePoolLaunch(params) {
5720
+ const { poolName, log } = params;
5721
+ const pool = params.pools?.[poolName];
5722
+ if (pool === void 0) {
5723
+ return { ok: false, message: `agent-shim: no pool named "${poolName}" (selected via ${params.selectedVia}). Run \`agent-shim pool add ${poolName} --identity <name>...\` first.` };
5724
+ }
5725
+ const { present: identities, missing } = splitMembers(pool, params.paths, params.fs);
5726
+ for (const name of missing) {
5727
+ log.warn(`agent-shim: pool "${poolName}" names identity "${name}", which does not exist; skipping it`);
5728
+ }
5729
+ if (identities.length === 0) {
5730
+ return { ok: false, message: `agent-shim: no member of pool "${poolName}" is an existing identity.` };
5731
+ }
5732
+ const resuming = isResuming(params.passthrough);
5733
+ const stickyRead = readStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd);
5734
+ if (stickyRead.problem !== void 0) {
5735
+ log.warn(`agent-shim: ${stickyRead.problem}; ignoring the last-pick record`);
5736
+ }
5737
+ for (; ; ) {
5738
+ const nowMs = params.now();
5739
+ const ranking = rankPoolFromStore({ fs: params.usageFs, paths: params.paths, identities, nowMs, resuming, ...stickyRead.sticky === void 0 ? {} : { sticky: stickyRead.sticky } });
5740
+ const { pick, earliestReturn } = ranking;
5741
+ if (pick !== void 0) {
5742
+ recordStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd, pick.identity, nowMs);
5743
+ return { ok: true, identity: pick.identity, explanation: `pool ${poolName}: ${pick.reasons.slice(0, REASONS_LOGGED).join("; ")}` };
5744
+ }
5745
+ if (earliestReturn === void 0) {
5746
+ return { ok: false, message: `agent-shim: no member of pool "${poolName}" can be picked.` };
5747
+ }
5748
+ const until = new Date(earliestReturn.atMs).toISOString();
5749
+ if (!params.wait) {
5750
+ return {
5751
+ ok: false,
5752
+ message: `agent-shim: every member of pool "${poolName}" is refused right now; the earliest, ${earliestReturn.identity}, returns at ${until} (in ${formatAge(earliestReturn.atMs - nowMs)}). Pass --wait to sleep until then.`
5753
+ };
5754
+ }
5755
+ log.info(`agent-shim: every member of pool "${poolName}" is refused; waiting until ${until} for ${earliestReturn.identity}`);
5756
+ params.sleep(Math.max(earliestReturn.atMs - nowMs, 0));
5757
+ }
5758
+ }
5506
5759
 
5507
5760
  // src/poolPickReport.ts
5508
5761
  function candidateView(candidate) {
@@ -5542,14 +5795,15 @@ function collectPoolPick(params) {
5542
5795
  var import_node_child_process = require("node:child_process");
5543
5796
  var import_node_crypto8 = require("node:crypto");
5544
5797
  var import_node_fs6 = __toESM(require("node:fs"), 1);
5545
- var import_node_path19 = __toESM(require("node:path"), 1);
5798
+ var import_node_os3 = __toESM(require("node:os"), 1);
5799
+ var import_node_path20 = __toESM(require("node:path"), 1);
5546
5800
  var import_node_sea = require("node:sea");
5547
5801
 
5548
5802
  // src/versionDiscovery.ts
5549
5803
  var import_node_os2 = __toESM(require("node:os"), 1);
5550
- var import_node_path18 = __toESM(require("node:path"), 1);
5804
+ var import_node_path19 = __toESM(require("node:path"), 1);
5551
5805
  function defaultVersionsDir() {
5552
- return import_node_path18.default.join(import_node_os2.default.homedir(), ".local", "share", "claude", "versions");
5806
+ return import_node_path19.default.join(import_node_os2.default.homedir(), ".local", "share", "claude", "versions");
5553
5807
  }
5554
5808
  var NUMERIC_DOTTED_VERSION_RE = /^\d+(?:\.\d+)*$/;
5555
5809
  function isNumericDottedVersion(name) {
@@ -5591,14 +5845,14 @@ function discoverClaudeBinary(options) {
5591
5845
  const highestVersion = pickHighestVersion(entries);
5592
5846
  if (highestVersion !== void 0) {
5593
5847
  return {
5594
- path: import_node_path18.default.join(versionsDir, highestVersion),
5848
+ path: import_node_path19.default.join(versionsDir, highestVersion),
5595
5849
  source: "versions-dir",
5596
5850
  version: highestVersion
5597
5851
  };
5598
5852
  }
5599
- const ownInstallDirs = new Set(options.ownInstallDirs.map((dir) => import_node_path18.default.resolve(dir)));
5853
+ const ownInstallDirs = new Set(options.ownInstallDirs.map((dir) => import_node_path19.default.resolve(dir)));
5600
5854
  for (const dir of options.pathDirs) {
5601
- if (ownInstallDirs.has(import_node_path18.default.resolve(dir))) {
5855
+ if (ownInstallDirs.has(import_node_path19.default.resolve(dir))) {
5602
5856
  continue;
5603
5857
  }
5604
5858
  const found = options.findExecutableInDir(dir, "claude");
@@ -5643,7 +5897,7 @@ function isErrorWithCode(error, code) {
5643
5897
  }
5644
5898
  var OWNER_ONLY_DIR_MODE = 448;
5645
5899
  var OWNER_ONLY_FILE_MODE = 384;
5646
- var PERMISSION_BITS = 511;
5900
+ var PERMISSION_BITS2 = 511;
5647
5901
  var realFarmFs = {
5648
5902
  lstat(filePath) {
5649
5903
  let stat;
@@ -5709,7 +5963,7 @@ var realFarmFs = {
5709
5963
  appendFilePrivate(filePath, contents) {
5710
5964
  const descriptor = import_node_fs6.default.openSync(filePath, "a", OWNER_ONLY_FILE_MODE);
5711
5965
  try {
5712
- if ((import_node_fs6.default.fstatSync(descriptor).mode & PERMISSION_BITS) !== OWNER_ONLY_FILE_MODE) {
5966
+ if ((import_node_fs6.default.fstatSync(descriptor).mode & PERMISSION_BITS2) !== OWNER_ONLY_FILE_MODE) {
5713
5967
  import_node_fs6.default.fchmodSync(descriptor, OWNER_ONLY_FILE_MODE);
5714
5968
  }
5715
5969
  const bytes = Buffer.from(contents, "utf8");
@@ -5743,6 +5997,10 @@ var realFarmFs = {
5743
5997
  }
5744
5998
  }
5745
5999
  };
6000
+ var INT32_BYTE_LENGTH = 4;
6001
+ function realSleepSync(ms) {
6002
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(INT32_BYTE_LENGTH)), 0, 0, ms);
6003
+ }
5746
6004
  function realIsProcessAlive(pid) {
5747
6005
  try {
5748
6006
  process.kill(pid, 0);
@@ -5764,6 +6022,51 @@ var realRunPort = {
5764
6022
  return { status: result.status, stdout: result.stdout, stderr: result.stderr };
5765
6023
  }
5766
6024
  };
6025
+ function expandHome2(filePath) {
6026
+ return filePath.startsWith("~/") ? import_node_path20.default.join(import_node_os3.default.homedir(), filePath.slice(1)) : filePath;
6027
+ }
6028
+ var MACOS_GUI_SESSION_MANAGER = "Aqua";
6029
+ function hasDesktopSession() {
6030
+ if (process.platform === "darwin") {
6031
+ const result = (0, import_node_child_process.spawnSync)("launchctl", ["managername"], { encoding: "utf8" });
6032
+ return result.status === 0 && result.stdout.trim() === MACOS_GUI_SESSION_MANAGER;
6033
+ }
6034
+ if (process.platform === "win32") {
6035
+ return false;
6036
+ }
6037
+ return (process.env.DISPLAY ?? "") !== "" || (process.env.WAYLAND_DISPLAY ?? "") !== "";
6038
+ }
6039
+ var realCredentialPort = {
6040
+ readSecretFile(filePath) {
6041
+ const resolved = expandHome2(filePath);
6042
+ let content;
6043
+ let stat;
6044
+ try {
6045
+ stat = import_node_fs6.default.statSync(resolved);
6046
+ content = import_node_fs6.default.readFileSync(resolved, "utf8");
6047
+ } catch (error) {
6048
+ if (isEnoent3(error)) {
6049
+ return { found: false };
6050
+ }
6051
+ throw error;
6052
+ }
6053
+ return { found: true, content, mode: process.platform === "win32" ? void 0 : stat.mode };
6054
+ },
6055
+ runCommand(argv, options) {
6056
+ const [command, ...args] = argv;
6057
+ const result = (0, import_node_child_process.spawnSync)(command, args, {
6058
+ encoding: "utf8",
6059
+ timeout: options.timeoutMs,
6060
+ stdio: options.interactive ? ["inherit", "pipe", "inherit"] : ["ignore", "pipe", "pipe"]
6061
+ });
6062
+ if (result.error !== void 0) {
6063
+ const timedOut = isErrorWithCode(result.error, "ETIMEDOUT");
6064
+ return { status: result.status, stdout: "", stderr: timedOut ? "" : result.error.message, timedOut };
6065
+ }
6066
+ return { status: result.status, stdout: result.stdout, stderr: options.interactive ? "" : result.stderr, timedOut: false };
6067
+ },
6068
+ personPresent: () => process.stdin.isTTY || hasDesktopSession()
6069
+ };
5767
6070
  function resolveGitBranch(run, cwd) {
5768
6071
  const result = run.run("git", ["-C", cwd, "rev-parse", "--abbrev-ref", "HEAD"]);
5769
6072
  if (result.status !== 0) {
@@ -5778,6 +6081,62 @@ function resolveGitBranch(run, cwd) {
5778
6081
  }
5779
6082
  return { branch: name, branchDetached: false };
5780
6083
  }
6084
+ function resolveGitRoot(run, cwd) {
6085
+ const result = run.run("git", ["-C", cwd, "rev-parse", "--show-toplevel"]);
6086
+ if (result.status !== 0) {
6087
+ return void 0;
6088
+ }
6089
+ const root = result.stdout.trim();
6090
+ return root === "" ? void 0 : root;
6091
+ }
6092
+ function detachedDaemonSpawnOptions(logFd, env) {
6093
+ return { detached: true, stdio: ["ignore", logFd, logFd], env };
6094
+ }
6095
+ function spawnDaemonThrough(executable) {
6096
+ return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: executable, args: [subcommand] }, paths, subcommand, logPath);
6097
+ }
6098
+ function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
6099
+ import_node_fs6.default.mkdirSync(import_node_path20.default.dirname(logPath), { recursive: true });
6100
+ const logFd = import_node_fs6.default.openSync(logPath, "a");
6101
+ try {
6102
+ const child = (0, import_node_child_process.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
6103
+ child.unref();
6104
+ if (child.pid === void 0) {
6105
+ throw new Error(`spawning ${subcommand} returned no pid`);
6106
+ }
6107
+ return child.pid;
6108
+ } finally {
6109
+ import_node_fs6.default.closeSync(logFd);
6110
+ }
6111
+ }
6112
+ function spawnHeadroomSupervisor(paths, spawnDaemon) {
6113
+ return spawnDaemon(paths, "__headroom-supervisor", paths.headroomLogPath);
6114
+ }
6115
+ function realHeadroomPort(paths, options) {
6116
+ return {
6117
+ ensure: () => {
6118
+ const up = ensureHeadroom({
6119
+ paths,
6120
+ launcherPid: process.pid,
6121
+ ports: {
6122
+ fs: realFarmFs,
6123
+ // 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.
6124
+ isRunning: realIsProcessRunning,
6125
+ now: () => Date.now(),
6126
+ sleep: realSleepSync,
6127
+ spawnSupervisor: (layout) => spawnHeadroomSupervisor(layout, options.spawnDaemon)
6128
+ }
6129
+ });
6130
+ return {
6131
+ port: up.port,
6132
+ projectId: resolveGitRoot(realRunPort, options.cwd) ?? options.cwd
6133
+ };
6134
+ },
6135
+ release: () => {
6136
+ removeSession(realFarmFs, paths.headroomSessionsDir, process.pid);
6137
+ }
6138
+ };
6139
+ }
5781
6140
  var realProcPort = {
5782
6141
  env: process.env,
5783
6142
  argv: process.argv.slice(2),
@@ -5795,7 +6154,7 @@ function listVersionsDir(dir) {
5795
6154
  throw error;
5796
6155
  }
5797
6156
  return entries.filter((entry) => entry.isFile()).map((entry) => {
5798
- const fullPath = import_node_path19.default.join(dir, entry.name);
6157
+ const fullPath = import_node_path20.default.join(dir, entry.name);
5799
6158
  const stat = import_node_fs6.default.statSync(fullPath);
5800
6159
  return {
5801
6160
  name: entry.name,
@@ -5810,7 +6169,7 @@ function windowsPathExtensions(pathext) {
5810
6169
  return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
5811
6170
  }
5812
6171
  function resolveExecutableCandidate(dir, name, env) {
5813
- const candidate = import_node_path19.default.join(dir, name);
6172
+ const candidate = import_node_path20.default.join(dir, name);
5814
6173
  if (env.platform === "win32") {
5815
6174
  const extensions = windowsPathExtensions(env.pathext);
5816
6175
  const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
@@ -5859,13 +6218,13 @@ function resolveOwnExecutablePath(env) {
5859
6218
  if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
5860
6219
  return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
5861
6220
  }
5862
- const candidate = env.argv1 === void 0 ? env.execPath : import_node_path19.default.resolve(env.cwd, env.argv1);
5863
- const candidateDir = import_node_path19.default.dirname(candidate);
5864
- const candidateDirOnPath = env.pathDirs.some((dir) => import_node_path19.default.resolve(dir) === candidateDir);
6221
+ const candidate = env.argv1 === void 0 ? env.execPath : import_node_path20.default.resolve(env.cwd, env.argv1);
6222
+ const candidateDir = import_node_path20.default.dirname(candidate);
6223
+ const candidateDirOnPath = env.pathDirs.some((dir) => import_node_path20.default.resolve(dir) === candidateDir);
5865
6224
  if (candidateDirOnPath) {
5866
6225
  return candidate;
5867
6226
  }
5868
- const viaPath = searchPathForExecutable(env.pathDirs, import_node_path19.default.basename(candidate), env.findExecutableInDir);
6227
+ const viaPath = searchPathForExecutable(env.pathDirs, import_node_path20.default.basename(candidate), env.findExecutableInDir);
5869
6228
  return viaPath ?? candidate;
5870
6229
  }
5871
6230
  function realOwnExecutablePath() {
@@ -5873,21 +6232,21 @@ function realOwnExecutablePath() {
5873
6232
  argv1: process.argv[1],
5874
6233
  execPath: process.execPath,
5875
6234
  cwd: process.cwd(),
5876
- pathDirs: (process.env.PATH ?? "").split(import_node_path19.default.delimiter).filter((dir) => dir !== ""),
6235
+ pathDirs: (process.env.PATH ?? "").split(import_node_path20.default.delimiter).filter((dir) => dir !== ""),
5877
6236
  findExecutableInDir
5878
6237
  });
5879
6238
  }
5880
6239
  function realResolveClaudeBinary(ownInstallDirs) {
5881
6240
  return () => discoverClaudeBinary({
5882
6241
  listVersionsDir,
5883
- pathDirs: (process.env.PATH ?? "").split(import_node_path19.default.delimiter).filter((dir) => dir !== ""),
6242
+ pathDirs: (process.env.PATH ?? "").split(import_node_path20.default.delimiter).filter((dir) => dir !== ""),
5884
6243
  findExecutableInDir,
5885
6244
  ownInstallDirs: [...ownInstallDirs]
5886
6245
  });
5887
6246
  }
5888
6247
 
5889
6248
  // src/checkReport.ts
5890
- var import_node_path20 = __toESM(require("node:path"), 1);
6249
+ var import_node_path21 = __toESM(require("node:path"), 1);
5891
6250
  var import_zod10 = require("zod");
5892
6251
 
5893
6252
  // src/cli/bool.ts
@@ -6209,7 +6568,7 @@ function loadCheckProvider(paths, name) {
6209
6568
  }
6210
6569
  function collectCheckReport(params) {
6211
6570
  const { paths, cwd } = params;
6212
- const home = import_node_os3.default.homedir();
6571
+ const home = import_node_os4.default.homedir();
6213
6572
  const claudeHome = resolveClaudeHome();
6214
6573
  const read = cosmiconfigReader();
6215
6574
  const classification = loadClassification(paths);
@@ -6254,10 +6613,10 @@ function collectCheckReport(params) {
6254
6613
  }).input;
6255
6614
  const providerName = cascadeProviderName(cascade);
6256
6615
  const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
6257
- const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path20.default.join(paths.identitiesDir, identityDecision.name);
6616
+ const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path21.default.join(paths.identitiesDir, identityDecision.name);
6258
6617
  const settingsFiles = {
6259
- "settings.json": realFsPort.readFileUtf8(import_node_path20.default.join(claudeHome, "settings.json")),
6260
- "settings.local.json": realFsPort.readFileUtf8(import_node_path20.default.join(claudeHome, "settings.local.json"))
6618
+ "settings.json": realFsPort.readFileUtf8(import_node_path21.default.join(claudeHome, "settings.json")),
6619
+ "settings.local.json": realFsPort.readFileUtf8(import_node_path21.default.join(claudeHome, "settings.local.json"))
6261
6620
  };
6262
6621
  const report = runCheck({
6263
6622
  cwd,
@@ -6287,7 +6646,7 @@ function collectCheckReport(params) {
6287
6646
 
6288
6647
  // src/claudeShim.ts
6289
6648
  var import_node_fs7 = __toESM(require("node:fs"), 1);
6290
- var import_node_path21 = __toESM(require("node:path"), 1);
6649
+ var import_node_path22 = __toESM(require("node:path"), 1);
6291
6650
  var import_zod11 = require("zod");
6292
6651
  var ClaudeShimStateSchema = import_zod11.z.strictObject({
6293
6652
  targetPath: import_zod11.z.string().min(1),
@@ -6298,29 +6657,29 @@ function commandFilename(ownExecutablePath, commandName) {
6298
6657
  return ownExecutablePath.toLowerCase().endsWith(".exe") ? `${commandName}.exe` : commandName;
6299
6658
  }
6300
6659
  function resolveOwnInstallDirs(paths, ownExecutablePath) {
6301
- const dirs = [import_node_path21.default.dirname(ownExecutablePath)];
6660
+ const dirs = [import_node_path22.default.dirname(ownExecutablePath)];
6302
6661
  const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
6303
6662
  if (state !== void 0) {
6304
- dirs.push(import_node_path21.default.dirname(state.targetPath));
6663
+ dirs.push(import_node_path22.default.dirname(state.targetPath));
6305
6664
  }
6306
6665
  return dirs;
6307
6666
  }
6308
6667
  var nodeLinkFs = { link: import_node_fs7.default.linkSync, copyFile: import_node_fs7.default.copyFileSync, chmod: import_node_fs7.default.chmodSync };
6309
6668
  function findPathShadow(params) {
6310
- const resolvedTargetDir = import_node_path21.default.resolve(params.targetDir);
6669
+ const resolvedTargetDir = import_node_path22.default.resolve(params.targetDir);
6311
6670
  for (const dir of params.pathDirs) {
6312
6671
  const found = params.findExecutableInDir(dir, params.targetFilename);
6313
6672
  if (found === void 0) {
6314
6673
  continue;
6315
6674
  }
6316
- return import_node_path21.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
6675
+ return import_node_path22.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
6317
6676
  }
6318
- return params.pathDirs.some((dir) => import_node_path21.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
6677
+ return params.pathDirs.some((dir) => import_node_path22.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
6319
6678
  }
6320
6679
 
6321
6680
  // src/doctorReport.ts
6322
6681
  var import_node_fs8 = __toESM(require("node:fs"), 1);
6323
- var import_node_path22 = __toESM(require("node:path"), 1);
6682
+ var import_node_path23 = __toESM(require("node:path"), 1);
6324
6683
  function refinePathShadow(status, ownExecutablePath, realpath) {
6325
6684
  if (status.status !== "shadowed") {
6326
6685
  return status;
@@ -6344,7 +6703,7 @@ function validateJson(schema, input) {
6344
6703
  return { ok: true, data: result.data };
6345
6704
  }
6346
6705
  function pushPathResolution(push, resolution) {
6347
- const ownDir = import_node_path22.default.dirname(resolution.ownExecutablePath);
6706
+ const ownDir = import_node_path23.default.dirname(resolution.ownExecutablePath);
6348
6707
  switch (resolution.agentShim.status) {
6349
6708
  case "ok":
6350
6709
  push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
@@ -6412,14 +6771,14 @@ function pushProvider(push, entry) {
6412
6771
  }
6413
6772
  function pushLegacyName(push, params) {
6414
6773
  const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
6415
- if (legacyVariables.length === 0 && import_node_path22.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
6774
+ if (legacyVariables.length === 0 && import_node_path23.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
6416
6775
  push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
6417
6776
  return;
6418
6777
  }
6419
6778
  for (const name of legacyVariables) {
6420
6779
  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);
6421
6780
  }
6422
- if (import_node_path22.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
6781
+ if (import_node_path23.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
6423
6782
  push(
6424
6783
  "legacy-name",
6425
6784
  "warn",
@@ -6727,18 +7086,18 @@ function collectDoctorReport(params) {
6727
7086
  const { paths } = params;
6728
7087
  const identityNames = import_node_fs8.default.existsSync(paths.identitiesDir) ? import_node_fs8.default.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
6729
7088
  const identities = identityNames.map((name) => {
6730
- const farmRoot = import_node_path22.default.join(paths.identitiesDir, name);
6731
- const identityPath = import_node_path22.default.join(farmRoot, "identity.json");
7089
+ const farmRoot = import_node_path23.default.join(paths.identitiesDir, name);
7090
+ const identityPath = import_node_path23.default.join(farmRoot, "identity.json");
6732
7091
  return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
6733
7092
  });
6734
7093
  const profileNames = import_node_fs8.default.existsSync(paths.configProfilesDir) ? import_node_fs8.default.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
6735
7094
  const configProfiles = profileNames.map((name) => {
6736
- const profilePath = import_node_path22.default.join(paths.configProfilesDir, `${name}.json`);
7095
+ const profilePath = import_node_path23.default.join(paths.configProfilesDir, `${name}.json`);
6737
7096
  return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
6738
7097
  });
6739
7098
  const providerNames = import_node_fs8.default.existsSync(paths.providersDir) ? import_node_fs8.default.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
6740
7099
  const providers = providerNames.map((name) => {
6741
- const providerPath = import_node_path22.default.join(paths.providersDir, `${name}.json`);
7100
+ const providerPath = import_node_path23.default.join(paths.providersDir, `${name}.json`);
6742
7101
  return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
6743
7102
  });
6744
7103
  const ownExecutablePath = realOwnExecutablePath();
@@ -6750,12 +7109,12 @@ function collectDoctorReport(params) {
6750
7109
  binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
6751
7110
  }
6752
7111
  const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
6753
- const pathDirs = (params.env.PATH ?? "").split(import_node_path22.default.delimiter).filter((dir) => dir !== "");
7112
+ const pathDirs = (params.env.PATH ?? "").split(import_node_path23.default.delimiter).filter((dir) => dir !== "");
6754
7113
  const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
6755
7114
  findPathShadow({
6756
7115
  pathDirs,
6757
- targetDir: import_node_path22.default.dirname(shimState.targetPath),
6758
- targetFilename: import_node_path22.default.basename(shimState.targetPath),
7116
+ targetDir: import_node_path23.default.dirname(shimState.targetPath),
7117
+ targetFilename: import_node_path23.default.basename(shimState.targetPath),
6759
7118
  findExecutableInDir
6760
7119
  }),
6761
7120
  shimState.targetPath,
@@ -6778,7 +7137,7 @@ function collectDoctorReport(params) {
6778
7137
  agentShim: refinePathShadow(
6779
7138
  findPathShadow({
6780
7139
  pathDirs,
6781
- targetDir: import_node_path22.default.dirname(ownExecutablePath),
7140
+ targetDir: import_node_path23.default.dirname(ownExecutablePath),
6782
7141
  targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
6783
7142
  findExecutableInDir
6784
7143
  }),
@@ -6796,6 +7155,975 @@ function collectDoctorReport(params) {
6796
7155
  });
6797
7156
  return report;
6798
7157
  }
7158
+
7159
+ // src/launcher.ts
7160
+ var import_node_crypto9 = require("node:crypto");
7161
+ var import_node_path25 = __toESM(require("node:path"), 1);
7162
+
7163
+ // src/launcher/argv.ts
7164
+ var ConflictingIdentityError = class extends UsageError {
7165
+ constructor(positional, flag) {
7166
+ super(`The launch names two identities: "@${positional}" and "--identity ${flag}". Pass only one.`);
7167
+ this.positional = positional;
7168
+ this.flag = flag;
7169
+ this.name = "ConflictingIdentityError";
7170
+ }
7171
+ positional;
7172
+ flag;
7173
+ };
7174
+ var VALUED_FLAGS = ["--identity", "--config-profile", "--provider", "--category", "--share", "--hide"];
7175
+ var BOOLEAN_FLAGS = [
7176
+ { flag: "--headroom", key: "headroom" },
7177
+ { flag: "--track-usage", key: "trackUsage" },
7178
+ { flag: "--skip-permissions", key: "skipPermissions" },
7179
+ { flag: "--remote-control", key: "remoteControl" },
7180
+ { flag: "--wait", key: "wait" }
7181
+ ];
7182
+ var LAUNCHER_FLAG_NAMES = [
7183
+ ...VALUED_FLAGS,
7184
+ "--no-provider",
7185
+ ...BOOLEAN_FLAGS.flatMap(({ flag }) => [flag, `--no-${flag.slice(2)}`])
7186
+ ];
7187
+ var TERMINATOR2 = "--";
7188
+ function matchValuedFlag(token) {
7189
+ for (const flag of VALUED_FLAGS) {
7190
+ if (token === flag) {
7191
+ return { flag };
7192
+ }
7193
+ if (token.startsWith(`${flag}=`)) {
7194
+ return { flag, inlineValue: token.slice(flag.length + 1) };
7195
+ }
7196
+ }
7197
+ return void 0;
7198
+ }
7199
+ function matchBooleanFlag(token) {
7200
+ for (const { flag, key } of BOOLEAN_FLAGS) {
7201
+ if (token === flag) {
7202
+ return { key, value: true };
7203
+ }
7204
+ if (token === `--no-${flag.slice(2)}`) {
7205
+ return { key, value: false };
7206
+ }
7207
+ }
7208
+ return void 0;
7209
+ }
7210
+ function parseLauncherArgv(argv) {
7211
+ const first = argv[0];
7212
+ const positionalIdentity = first !== void 0 && first.startsWith("@") && first.length > 1 ? first.slice(1) : void 0;
7213
+ const remaining = positionalIdentity === void 0 ? argv : argv.slice(1);
7214
+ let flagIdentity;
7215
+ let configProfile;
7216
+ let provider;
7217
+ const booleans = {};
7218
+ const categoryFlags = [];
7219
+ const shareFlags = [];
7220
+ const hideFlags = [];
7221
+ const rest = [];
7222
+ for (let index = 0; index < remaining.length; index += 1) {
7223
+ const token = remaining[index];
7224
+ if (token === void 0) {
7225
+ continue;
7226
+ }
7227
+ if (token === TERMINATOR2) {
7228
+ rest.push(...remaining.slice(index));
7229
+ break;
7230
+ }
7231
+ if (token === "--no-provider") {
7232
+ provider = false;
7233
+ continue;
7234
+ }
7235
+ const booleanFlag = matchBooleanFlag(token);
7236
+ if (booleanFlag !== void 0) {
7237
+ booleans[booleanFlag.key] = booleanFlag.value;
7238
+ continue;
7239
+ }
7240
+ const matched = matchValuedFlag(token);
7241
+ if (matched === void 0) {
7242
+ rest.push(token);
7243
+ continue;
7244
+ }
7245
+ let value;
7246
+ if (matched.inlineValue !== void 0) {
7247
+ value = matched.inlineValue;
7248
+ } else {
7249
+ const next = remaining[index + 1];
7250
+ if (next === void 0 || next === TERMINATOR2) {
7251
+ rest.push(token);
7252
+ continue;
7253
+ }
7254
+ value = next;
7255
+ index += 1;
7256
+ }
7257
+ switch (matched.flag) {
7258
+ case "--identity":
7259
+ flagIdentity = value;
7260
+ break;
7261
+ case "--config-profile":
7262
+ configProfile = value;
7263
+ break;
7264
+ case "--provider":
7265
+ provider = value;
7266
+ break;
7267
+ case "--category":
7268
+ categoryFlags.push(value);
7269
+ break;
7270
+ case "--share":
7271
+ shareFlags.push(value);
7272
+ break;
7273
+ case "--hide":
7274
+ hideFlags.push(value);
7275
+ break;
7276
+ default:
7277
+ matched.flag;
7278
+ }
7279
+ }
7280
+ if (positionalIdentity !== void 0 && flagIdentity !== void 0 && positionalIdentity !== flagIdentity) {
7281
+ throw new ConflictingIdentityError(positionalIdentity, flagIdentity);
7282
+ }
7283
+ const identity = flagIdentity ?? positionalIdentity;
7284
+ return {
7285
+ ...identity === void 0 ? {} : { identity },
7286
+ ...configProfile === void 0 ? {} : { configProfile },
7287
+ ...provider === void 0 ? {} : { provider },
7288
+ ...booleans,
7289
+ categoryFlags,
7290
+ shareFlags,
7291
+ hideFlags,
7292
+ rest
7293
+ };
7294
+ }
7295
+
7296
+ // src/cli/pairs.ts
7297
+ function splitCommas(input) {
7298
+ if (input === "") {
7299
+ return [];
7300
+ }
7301
+ return input.split(",");
7302
+ }
7303
+ function parsePair(input) {
7304
+ const eqIndex = input.indexOf("=");
7305
+ if (eqIndex === -1) {
7306
+ throw new Error(`Expected "<key>=<value>", got "${input}" (no "=" found)`);
7307
+ }
7308
+ const key = input.slice(0, eqIndex);
7309
+ const value = input.slice(eqIndex + 1);
7310
+ if (key === "") {
7311
+ throw new Error(`Expected a non-empty key before "=" in "${input}"`);
7312
+ }
7313
+ return { key, value };
7314
+ }
7315
+ function parseBool(input) {
7316
+ const parsed = parseBoolWord(input);
7317
+ if (parsed === void 0) {
7318
+ throw new Error(`Expected "true", "false", "1" or "0", got "${input}"`);
7319
+ }
7320
+ return parsed;
7321
+ }
7322
+ function parseBoolPairList(input) {
7323
+ const result = {};
7324
+ for (const piece of splitCommas(input)) {
7325
+ const { key, value } = parsePair(piece);
7326
+ result[key] = parseBool(value);
7327
+ }
7328
+ return result;
7329
+ }
7330
+
7331
+ // src/launcher/cliOverride.ts
7332
+ var InvalidCliCategoryError = class extends CliError {
7333
+ constructor(categoryName) {
7334
+ super(`"${categoryName}" is not a category this launch may toggle (runtime, history, knowledge, settings).`);
7335
+ this.categoryName = categoryName;
7336
+ this.name = "InvalidCliCategoryError";
7337
+ }
7338
+ categoryName;
7339
+ };
7340
+ var InvalidCliEntryKeyError = class extends CliError {
7341
+ constructor(key) {
7342
+ super(`"${key}" is not a valid entries key \u2014 it must start with "<category>/", e.g. "knowledge/skills/commit".`);
7343
+ this.key = key;
7344
+ this.name = "InvalidCliEntryKeyError";
7345
+ }
7346
+ key;
7347
+ };
7348
+ function toCategoryMap(pairs) {
7349
+ const expanded = expandAllCategoryKey(pairs);
7350
+ const result = {};
7351
+ for (const [key, value] of Object.entries(expanded)) {
7352
+ if (!isOverridableCategory(key)) {
7353
+ throw new InvalidCliCategoryError(key);
7354
+ }
7355
+ result[key] = value;
7356
+ }
7357
+ return result;
7358
+ }
7359
+ function toEntries(pairs) {
7360
+ for (const key of Object.keys(pairs)) {
7361
+ if (!ENTRY_KEY_RE.test(key)) {
7362
+ throw new InvalidCliEntryKeyError(key);
7363
+ }
7364
+ }
7365
+ return pairs;
7366
+ }
7367
+ function parseOverride(source, raw, parse) {
7368
+ try {
7369
+ return parse(raw);
7370
+ } catch (error) {
7371
+ if (error instanceof Error && !(error instanceof CliError)) {
7372
+ throw new UsageError(`Invalid ${source} value "${raw}": ${error.message}.`);
7373
+ }
7374
+ throw error;
7375
+ }
7376
+ }
7377
+ function buildCliOverride(params) {
7378
+ let categoryPairs = {};
7379
+ if (params.env.AGENT_SHIM_CATEGORY_OVERRIDE !== void 0 && params.env.AGENT_SHIM_CATEGORY_OVERRIDE !== "") {
7380
+ categoryPairs = parseOverride("AGENT_SHIM_CATEGORY_OVERRIDE", params.env.AGENT_SHIM_CATEGORY_OVERRIDE, parseBoolPairList);
7381
+ }
7382
+ for (const flagValue of params.categoryFlags) {
7383
+ const pair = parseOverride("--category", flagValue, (raw) => {
7384
+ const { key, value } = parsePair(raw);
7385
+ return { key, value: parseBool(value) };
7386
+ });
7387
+ categoryPairs[pair.key] = pair.value;
7388
+ }
7389
+ let entryPairs = {};
7390
+ if (params.env.AGENT_SHIM_ENTRY_OVERRIDE !== void 0 && params.env.AGENT_SHIM_ENTRY_OVERRIDE !== "") {
7391
+ entryPairs = parseOverride("AGENT_SHIM_ENTRY_OVERRIDE", params.env.AGENT_SHIM_ENTRY_OVERRIDE, parseBoolPairList);
7392
+ }
7393
+ for (const entryPath of params.shareFlags) {
7394
+ entryPairs[entryPath] = true;
7395
+ }
7396
+ for (const entryPath of params.hideFlags) {
7397
+ entryPairs[entryPath] = false;
7398
+ }
7399
+ const hasCategories = Object.keys(categoryPairs).length > 0;
7400
+ const hasEntries = Object.keys(entryPairs).length > 0;
7401
+ const hasProvider = params.providerFlag !== void 0 && params.providerFlag !== "";
7402
+ if (!hasCategories && !hasEntries && !hasProvider) {
7403
+ return void 0;
7404
+ }
7405
+ return {
7406
+ ...hasCategories ? { categories: toCategoryMap(categoryPairs) } : {},
7407
+ ...hasEntries ? { entries: toEntries(entryPairs) } : {},
7408
+ ...hasProvider ? { launch: { provider: params.providerFlag } } : {}
7409
+ };
7410
+ }
7411
+
7412
+ // src/launcher/flags.ts
7413
+ var import_node_path24 = __toESM(require("node:path"), 1);
7414
+
7415
+ // src/headroom/headers.ts
7416
+ function mergeAnthropicCustomHeaders(existing, additions) {
7417
+ const merged = /* @__PURE__ */ new Map();
7418
+ for (const block of existing) {
7419
+ if (block === void 0) {
7420
+ continue;
7421
+ }
7422
+ for (const line of block.split("\n")) {
7423
+ const entry = parseCustomHeaderLine(line);
7424
+ if (entry === void 0) {
7425
+ continue;
7426
+ }
7427
+ merged.set(entry.name, entry.value);
7428
+ }
7429
+ }
7430
+ for (const entry of additions) {
7431
+ merged.set(entry.name, entry.value);
7432
+ }
7433
+ return [...merged].map(([name, value]) => `${name}: ${value}`).join("\n");
7434
+ }
7435
+ function parseCustomHeaderLine(line) {
7436
+ const trimmed = line.trim();
7437
+ if (trimmed === "") {
7438
+ return void 0;
7439
+ }
7440
+ const colon = trimmed.indexOf(":");
7441
+ if (colon <= 0) {
7442
+ return void 0;
7443
+ }
7444
+ return { name: trimmed.slice(0, colon).trim(), value: trimmed.slice(colon + 1).trim() };
7445
+ }
7446
+
7447
+ // src/launcher/flags.ts
7448
+ function resolveLaunchFlags(params) {
7449
+ return {
7450
+ skipPermissions: params.flags?.skipPermissions ?? parseEnvBool("AGENT_SHIM_SKIP_PERMISSIONS", params.env.AGENT_SHIM_SKIP_PERMISSIONS) ?? params.cascade?.skipPermissions ?? false,
7451
+ remoteControl: params.flags?.remoteControl ?? parseEnvBool("AGENT_SHIM_REMOTE_CONTROL", params.env.AGENT_SHIM_REMOTE_CONTROL) ?? params.cascade?.remoteControl ?? false,
7452
+ headroom: params.flags?.headroom ?? parseEnvBool("AGENT_SHIM_HEADROOM", params.env.AGENT_SHIM_HEADROOM) ?? params.cascade?.headroom ?? false,
7453
+ trackUsage: params.flags?.trackUsage ?? parseEnvBool("AGENT_SHIM_TRACK_USAGE", params.env.AGENT_SHIM_TRACK_USAGE) ?? params.cascade?.trackUsage ?? params.trackUsageDefault ?? false
7454
+ };
7455
+ }
7456
+ function buildFlagArgs(flags) {
7457
+ const args = [];
7458
+ if (flags.skipPermissions) {
7459
+ args.push("--dangerously-skip-permissions");
7460
+ }
7461
+ if (flags.remoteControl) {
7462
+ args.push("--remote-control=");
7463
+ }
7464
+ return args;
7465
+ }
7466
+ function buildArgv(params) {
7467
+ return [...params.toolFlags, ...params.extraFlags, ...params.passthrough];
7468
+ }
7469
+ var LOOPBACK_HOSTS = ["127.0.0.1", "localhost", "::1"];
7470
+ function isLoopbackUrl(baseUrl) {
7471
+ const host = new URL(baseUrl).hostname.replace(/^\[|\]$/g, "");
7472
+ return LOOPBACK_HOSTS.some((loopback) => loopback === host);
7473
+ }
7474
+ function withLoopbackHosts(existing) {
7475
+ const listed = (existing ?? "").split(",").map((entry) => entry.trim()).filter((entry) => entry !== "");
7476
+ return [...listed, ...LOOPBACK_HOSTS.filter((host) => !listed.includes(host))].join(",");
7477
+ }
7478
+ function buildEnv(params) {
7479
+ const env = { ...params.baseEnv };
7480
+ const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
7481
+ let providerCustomHeaders;
7482
+ if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
7483
+ env.CLAUDE_CONFIG_DIR = import_node_path24.default.join(params.identitiesDir, params.resolvedIdentityName);
7484
+ }
7485
+ if (params.provider !== void 0) {
7486
+ const providerEnv = params.provider.definition.env ?? {};
7487
+ providerCustomHeaders = providerEnv.ANTHROPIC_CUSTOM_HEADERS;
7488
+ env.ANTHROPIC_BASE_URL = params.provider.baseUrl;
7489
+ if (isLoopbackUrl(params.provider.baseUrl)) {
7490
+ env.NO_PROXY = withLoopbackHosts(params.baseEnv.NO_PROXY);
7491
+ env.no_proxy = withLoopbackHosts(params.baseEnv.no_proxy);
7492
+ }
7493
+ env.AGENT_SHIM_PROVIDER = params.provider.definition.displayName;
7494
+ for (const [key, value] of Object.entries(providerEnv)) {
7495
+ env[key] = value;
7496
+ }
7497
+ }
7498
+ const credential = params.provider?.credential ?? params.identityCredential;
7499
+ if (credential !== void 0) {
7500
+ for (const [variable, value] of Object.entries(credentialVariables(credential.target, credential.token))) {
7501
+ env[variable] = value;
7502
+ }
7503
+ }
7504
+ if (params.headroom !== void 0) {
7505
+ env.HEADROOM_PROXY_URL = `http://127.0.0.1:${String(params.headroom.port)}`;
7506
+ }
7507
+ if (params.frontdoor !== void 0) {
7508
+ env.ANTHROPIC_CUSTOM_HEADERS = mergeAnthropicCustomHeaders(
7509
+ [
7510
+ ...parentCustomHeaders === void 0 ? [] : [parentCustomHeaders],
7511
+ ...providerCustomHeaders === void 0 ? [] : [providerCustomHeaders]
7512
+ ],
7513
+ [
7514
+ ...params.resolvedIdentityName === void 0 ? [] : [{ name: IDENTITY_HEADER, value: params.resolvedIdentityName }],
7515
+ { name: SESSION_HEADER, value: params.sessionId },
7516
+ { name: AUTH_HEADER, value: params.frontdoor.sessionToken },
7517
+ ...params.headroom === void 0 ? [] : [
7518
+ { name: HEADROOM_FLAG_HEADER, value: "1" },
7519
+ { name: PROJECT_ID_HEADER, value: params.headroom.projectId }
7520
+ ]
7521
+ ]
7522
+ );
7523
+ env.NODE_EXTRA_CA_CERTS = params.frontdoor.trustBundlePath;
7524
+ if (params.provider === void 0) {
7525
+ env.HTTPS_PROXY = connectProxyUrl(params.frontdoor.connectPort, params.frontdoor.sessionToken);
7526
+ }
7527
+ }
7528
+ return env;
7529
+ }
7530
+
7531
+ // src/launcher/extraFlags.ts
7532
+ function splitExtraFlags(value) {
7533
+ if (value === void 0) {
7534
+ return [];
7535
+ }
7536
+ const trimmed = value.trim();
7537
+ if (trimmed === "") {
7538
+ return [];
7539
+ }
7540
+ return trimmed.split(/\s+/);
7541
+ }
7542
+
7543
+ // src/launcher.ts
7544
+ function resolveIdentityCredential(identity, credential, env, port) {
7545
+ if (port === void 0) {
7546
+ return { ok: false, status: 1, message: `agent-shim: identity ${identity} needs its credential resolved, but this launcher has no credential port wired` };
7547
+ }
7548
+ const resolution = resolveCredential({ credential, env, port, subject: `identity ${identity}` });
7549
+ return resolution.ok ? resolution : { ok: false, status: CREDENTIAL_UNAVAILABLE_EXIT, message: resolution.message };
7550
+ }
7551
+ function pickFromPool(decided, params, parsedArgv) {
7552
+ const { paths, fs: fs12, proc, log } = params;
7553
+ if (decided.pool === void 0) {
7554
+ return { identityDecision: decided };
7555
+ }
7556
+ const farmRuntime = params.farm;
7557
+ if (farmRuntime === void 0) {
7558
+ log.error(`agent-shim: pool "${decided.pool}" was selected, but this launcher has no farm wired to read usage and pick a member with.`);
7559
+ return proc.exit(1);
7560
+ }
7561
+ const resolution = resolvePoolLaunch({
7562
+ poolName: decided.pool,
7563
+ selectedVia: decided.source,
7564
+ pools: params.pools,
7565
+ paths,
7566
+ fs: fs12,
7567
+ usageFs: farmRuntime.fs,
7568
+ cwd: farmRuntime.cwd,
7569
+ now: farmRuntime.now,
7570
+ sleep: farmRuntime.lock.sleep,
7571
+ passthrough: parsedArgv.rest,
7572
+ wait: parsedArgv.wait === true,
7573
+ log
7574
+ });
7575
+ if (!resolution.ok) {
7576
+ log.error(resolution.message);
7577
+ return proc.exit(1);
7578
+ }
7579
+ return { identityDecision: { ...decided, name: resolution.identity }, poolExplanation: resolution.explanation };
7580
+ }
7581
+ function prepareLaunch(params) {
7582
+ const { paths, fs: fs12, proc, log } = params;
7583
+ const { env, argv } = proc;
7584
+ const parsedArgv = parseLauncherArgv(argv);
7585
+ const cliOverride = buildCliOverride({
7586
+ env,
7587
+ categoryFlags: parsedArgv.categoryFlags,
7588
+ shareFlags: parsedArgv.shareFlags,
7589
+ hideFlags: parsedArgv.hideFlags
7590
+ });
7591
+ const configDirEscapeHatchApplies = env.CLAUDE_CONFIG_DIR !== void 0 && env.CLAUDE_CONFIG_DIR !== "";
7592
+ const decidedIdentity = decideIdentity({
7593
+ env,
7594
+ argv0Identity: parsedArgv.identity,
7595
+ directoryPinnedIdentity: params.directoryPinnedIdentity,
7596
+ readActiveIdentityFile: () => {
7597
+ const raw = fs12.readFileUtf8(paths.activeIdentityFile);
7598
+ if (raw === void 0) {
7599
+ return void 0;
7600
+ }
7601
+ const trimmed = raw.trim();
7602
+ return trimmed === "" ? void 0 : trimmed;
7603
+ }
7604
+ });
7605
+ const { identityDecision, poolExplanation } = pickFromPool(decidedIdentity, params, parsedArgv);
7606
+ const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
7607
+ const farm = farmIdentity === void 0 ? void 0 : params.farm;
7608
+ if (farm !== void 0 && farmIdentity !== void 0) {
7609
+ let recovery;
7610
+ try {
7611
+ recovery = recoverFarm({
7612
+ fs: farm.fs,
7613
+ identitiesDir: paths.identitiesDir,
7614
+ identity: farmIdentity,
7615
+ now: farm.now,
7616
+ lock: farm.lock,
7617
+ classification: farm.classification
7618
+ });
7619
+ } catch (error) {
7620
+ if (error instanceof IdentityLockBusyError) {
7621
+ log.error(error.message);
7622
+ proc.exit(1);
7623
+ }
7624
+ throw error;
7625
+ }
7626
+ for (const diagnostic of recoveryDiagnostics(recovery, farmIdentity)) {
7627
+ log.warn(`agent-shim: ${diagnostic.code}: ${diagnostic.message}`);
7628
+ }
7629
+ }
7630
+ let loadedIdentity;
7631
+ if (identityDecision.name !== void 0) {
7632
+ loadedIdentity = loadIdentity(paths.identitiesDir, identityDecision.name, fs12);
7633
+ if (loadedIdentity === void 0) {
7634
+ log.error(
7635
+ `agent-shim: no identity named "${identityDecision.name}" (selected via ${identityDecision.source}). Run \`agent-shim identity add ${identityDecision.name}\` first.`
7636
+ );
7637
+ proc.exit(1);
7638
+ }
7639
+ }
7640
+ const configProfileDecision = decideConfigProfile({
7641
+ env,
7642
+ cliFlagConfigProfile: params.cliFlagConfigProfile ?? parsedArgv.configProfile,
7643
+ directoryRuleConfigProfile: params.directoryRuleConfigProfile,
7644
+ identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
7645
+ globalDefaultConfigProfile: params.globalDefaultConfigProfile
7646
+ });
7647
+ if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(import_node_path25.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
7648
+ log.error(
7649
+ `agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
7650
+ );
7651
+ proc.exit(1);
7652
+ }
7653
+ const farmContext = farm !== void 0 && farmIdentity !== void 0 ? { farm, identity: farmIdentity, cascade: farm.loadCascade(configProfileDecision.name, cliOverride) } : void 0;
7654
+ const provider = parsedArgv.provider === false ? void 0 : resolveProvider({
7655
+ paths,
7656
+ port: fs12,
7657
+ env,
7658
+ ...params.credentials === void 0 ? {} : { credentials: params.credentials },
7659
+ ...parsedArgv.provider === void 0 ? {} : { cliProvider: parsedArgv.provider },
7660
+ ...farmContext === void 0 ? {} : { cascade: farmContext.cascade }
7661
+ });
7662
+ if (provider !== void 0 && !provider.ok) {
7663
+ log.error(provider.message);
7664
+ proc.exit(provider.status);
7665
+ }
7666
+ const resolvedProvider = provider?.ok === true ? provider.provider : void 0;
7667
+ for (const warning of provider?.ok === true ? provider.warnings : []) {
7668
+ log.warn(warning);
7669
+ }
7670
+ if (farm !== void 0 && farmIdentity !== void 0) {
7671
+ try {
7672
+ const snapshot = readUsageSnapshot(farm.fs, paths.usageSnapshotsDir, farmIdentity);
7673
+ for (const warning of quotaWarnings(snapshot, resolvedProvider?.name ?? ANTHROPIC_PROVIDER, farm.now())) {
7674
+ log.warn(warning);
7675
+ }
7676
+ } catch (error) {
7677
+ if (!(error instanceof UsageSnapshotError)) {
7678
+ throw error;
7679
+ }
7680
+ log.warn(`agent-shim: ${error.message}`);
7681
+ }
7682
+ }
7683
+ const identityCredentialBlock = loadedIdentity?.config.credential;
7684
+ const identityResolution = resolvedProvider === void 0 && farmIdentity !== void 0 && identityCredentialBlock !== void 0 ? resolveIdentityCredential(farmIdentity, identityCredentialBlock, env, params.credentials) : void 0;
7685
+ if (identityResolution !== void 0 && !identityResolution.ok) {
7686
+ log.error(identityResolution.message);
7687
+ proc.exit(identityResolution.status);
7688
+ }
7689
+ const identityCredential = identityResolution?.ok === true ? identityResolution.credential : void 0;
7690
+ for (const warning of identityCredential?.warnings ?? []) {
7691
+ log.warn(warning);
7692
+ }
7693
+ const guardResult = evaluateAmbientCredentialGuard({
7694
+ env,
7695
+ allowAmbientCredential: loadedIdentity?.config.allowAmbientCredential ?? false,
7696
+ allowAmbientCredentialOverride: parseEnvBool("AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL", env.AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL) === true,
7697
+ identityName: identityDecision.name,
7698
+ providerSelected: resolvedProvider !== void 0,
7699
+ ...identityCredential === void 0 ? {} : { injectedCredential: { variable: CREDENTIAL_TARGET_VARS[identityCredential.target], token: identityCredential.token } }
7700
+ });
7701
+ if (!guardResult.ok) {
7702
+ log.error(guardResult.message);
7703
+ proc.exit(1);
7704
+ }
7705
+ log.info(
7706
+ `agent-shim: identity ${identityDecision.name ?? "(none)"} (${identityDecision.source}${poolExplanation === void 0 ? "" : `, ${poolExplanation}`}), config profile ${configProfileDecision.name ?? "(none)"} (${configProfileDecision.source})` + (resolvedProvider === void 0 ? "" : `, provider ${resolvedProvider.name} (credential ${resolvedProvider.credential.target} from ${describeSource(resolvedProvider.credential.source)})`) + (identityCredential === void 0 ? "" : `, identity credential ${identityCredential.target} from ${describeSource(identityCredential.source)}`)
7707
+ );
7708
+ let cascadeLaunch;
7709
+ if (farmContext !== void 0) {
7710
+ const { farm: resyncFarmRuntime, identity: resyncIdentity, cascade } = farmContext;
7711
+ let result;
7712
+ try {
7713
+ result = resyncFarm({
7714
+ fs: resyncFarmRuntime.fs,
7715
+ identitiesDir: paths.identitiesDir,
7716
+ identity: resyncIdentity,
7717
+ ...configProfileDecision.name === void 0 ? {} : { configProfile: configProfileDecision.name },
7718
+ claudeHome: resyncFarmRuntime.claudeHome,
7719
+ home: resyncFarmRuntime.home,
7720
+ cwd: resyncFarmRuntime.cwd,
7721
+ env,
7722
+ ...resyncFarmRuntime.branch === void 0 ? {} : { branch: resyncFarmRuntime.branch },
7723
+ ...resyncFarmRuntime.branchDetached === void 0 ? {} : { branchDetached: resyncFarmRuntime.branchDetached },
7724
+ cascade,
7725
+ classification: resyncFarmRuntime.classification,
7726
+ now: resyncFarmRuntime.now,
7727
+ uniqueSuffix: resyncFarmRuntime.uniqueSuffix,
7728
+ lock: resyncFarmRuntime.lock
7729
+ });
7730
+ } catch (error) {
7731
+ if (error instanceof IdentityLockBusyError) {
7732
+ log.error(error.message);
7733
+ proc.exit(1);
7734
+ }
7735
+ throw error;
7736
+ }
7737
+ for (const diagnostic of result.diagnostics) {
7738
+ if (diagnostic.severity === "error") {
7739
+ log.error(`agent-shim: ${diagnostic.code}: ${diagnostic.message}`);
7740
+ } else if (diagnostic.severity === "warning") {
7741
+ log.warn(`agent-shim: ${diagnostic.code}: ${diagnostic.message}`);
7742
+ }
7743
+ }
7744
+ log.info(
7745
+ result.noOp ? `agent-shim: farm at ${result.farmRoot} already matches the resolved cascade` : `agent-shim: farm at ${result.farmRoot} resynced (${String(result.manifest.links.length)} link(s), ${String(result.manifest.materialised.length)} built director(ies)${result.adopted.length === 0 ? "" : `, ${String(result.adopted.length)} adopted into ${resyncFarmRuntime.claudeHome}`})`
7746
+ );
7747
+ cascadeLaunch = result.resolved.flattened.launch;
7748
+ } else if (params.farm !== void 0) {
7749
+ cascadeLaunch = flattenLayers(assembleCascade(params.farm.loadCascade(configProfileDecision.name, cliOverride)).layers, { home: params.farm.home }).launch;
7750
+ }
7751
+ const discovered = params.resolveClaudeBinary();
7752
+ const resolvedFlags = resolveLaunchFlags({
7753
+ env,
7754
+ // A pool pick reads the usage the front door records, so a pool launch records its own unless something says otherwise.
7755
+ ...poolExplanation === void 0 ? {} : { trackUsageDefault: true },
7756
+ ...cascadeLaunch === void 0 ? {} : { cascade: cascadeLaunch },
7757
+ flags: {
7758
+ ...parsedArgv.skipPermissions === void 0 ? {} : { skipPermissions: parsedArgv.skipPermissions },
7759
+ ...parsedArgv.remoteControl === void 0 ? {} : { remoteControl: parsedArgv.remoteControl },
7760
+ ...parsedArgv.headroom === void 0 ? {} : { headroom: parsedArgv.headroom },
7761
+ ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage }
7762
+ }
7763
+ });
7764
+ const frontDoorPort = params.frontdoor;
7765
+ const frontDoorEngaged = resolvedProvider !== void 0 || resolvedFlags.headroom || resolvedFlags.trackUsage;
7766
+ if (frontDoorEngaged && frontDoorPort === void 0) {
7767
+ log.error("agent-shim: this launch routes through the front-door daemon, but this launcher has no front-door port wired; refusing to launch without it.");
7768
+ proc.exit(1);
7769
+ }
7770
+ const frontDoor = frontDoorEngaged && frontDoorPort !== void 0 ? frontDoorPort.ensure(env.NODE_EXTRA_CA_CERTS) : void 0;
7771
+ if (frontDoor?.trustWarning !== void 0) {
7772
+ log.warn(frontDoor.trustWarning);
7773
+ }
7774
+ let routedProvider;
7775
+ if (resolvedProvider !== void 0 && frontDoor !== void 0) {
7776
+ routedProvider = { ...resolvedProvider, baseUrl: providerBaseUrl(frontDoor.port, resolvedProvider.name) };
7777
+ }
7778
+ let headroom;
7779
+ const headroomPort = params.headroom;
7780
+ if (resolvedFlags.headroom && headroomPort !== void 0) {
7781
+ headroom = headroomPort.ensure();
7782
+ const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
7783
+ log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor?.port ?? 0)} with headroom on 127.0.0.1:${String(headroom.port)} (${via}, project ${headroom.projectId})`);
7784
+ } else if (resolvedFlags.headroom) {
7785
+ log.error("agent-shim: headroom routing was requested but this launcher has no headroom port wired; refusing to launch without it.");
7786
+ proc.exit(1);
7787
+ } else if (frontDoor !== void 0) {
7788
+ log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor.port)}${resolvedProvider === void 0 ? ` (OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor.connectPort)}, usage recorded)` : ` (provider ${resolvedProvider.name})`}`);
7789
+ }
7790
+ const frontDoorRelease = frontDoor === void 0 ? void 0 : frontDoorPort?.release;
7791
+ const finalArgv = buildArgv({
7792
+ toolFlags: buildFlagArgs(resolvedFlags),
7793
+ extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
7794
+ passthrough: parsedArgv.rest
7795
+ });
7796
+ const finalEnv = buildEnv({
7797
+ baseEnv: env,
7798
+ configDirEscapeHatch: configDirEscapeHatchApplies,
7799
+ resolvedIdentityName: identityDecision.name,
7800
+ identitiesDir: paths.identitiesDir,
7801
+ ...routedProvider === void 0 ? {} : { provider: routedProvider },
7802
+ ...identityCredential === void 0 ? {} : { identityCredential },
7803
+ ...frontDoor === void 0 ? {} : { frontdoor: frontDoor },
7804
+ ...headroom === void 0 ? {} : { headroom },
7805
+ sessionId: (0, import_node_crypto9.randomUUID)()
7806
+ });
7807
+ const releases = [...headroom === void 0 || headroomPort === void 0 ? [] : [headroomPort.release], ...frontDoorRelease === void 0 ? [] : [frontDoorRelease]];
7808
+ const release = () => {
7809
+ for (const registered of releases) {
7810
+ registered();
7811
+ }
7812
+ };
7813
+ return { bin: discovered.path, args: finalArgv, env: finalEnv, release };
7814
+ }
7815
+
7816
+ // src/launchWiring.ts
7817
+ var import_node_os5 = __toESM(require("node:os"), 1);
7818
+ var import_node_crypto11 = require("node:crypto");
7819
+
7820
+ // src/realCredentialCache.ts
7821
+ var import_node_child_process2 = require("node:child_process");
7822
+ var import_node_fs9 = __toESM(require("node:fs"), 1);
7823
+ var import_node_path26 = __toESM(require("node:path"), 1);
7824
+ var KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
7825
+ var CACHE_DIR_MODE = 448;
7826
+ var CACHE_FILE_MODE = 384;
7827
+ function cacheFileNameFor(owner) {
7828
+ return `${owner.replace(/[^A-Za-z0-9._-]/g, "_")}.json`;
7829
+ }
7830
+ function parseEntry(raw) {
7831
+ let json;
7832
+ try {
7833
+ json = JSON.parse(raw);
7834
+ } catch {
7835
+ return void 0;
7836
+ }
7837
+ const parsed = CachedCredentialSchema.safeParse(json);
7838
+ return parsed.success ? parsed.data : void 0;
7839
+ }
7840
+ function requireKeychain() {
7841
+ if (process.platform !== "darwin") {
7842
+ throw new Error("the keychain credential store needs macOS; use --credential-cache-store file");
7843
+ }
7844
+ }
7845
+ function security(args, stdin) {
7846
+ const result = (0, import_node_child_process2.spawnSync)("security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
7847
+ return { status: result.status, stdout: result.stdout };
7848
+ }
7849
+ function createRealCredentialCache(root) {
7850
+ const dir = import_node_path26.default.join(root, "credential-cache");
7851
+ const filePath = (owner) => import_node_path26.default.join(dir, cacheFileNameFor(owner));
7852
+ return {
7853
+ read(store, owner) {
7854
+ if (store === "file") {
7855
+ try {
7856
+ return parseEntry(import_node_fs9.default.readFileSync(filePath(owner), "utf8"));
7857
+ } catch {
7858
+ return void 0;
7859
+ }
7860
+ }
7861
+ requireKeychain();
7862
+ const result = security(["find-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner, "-w"]);
7863
+ return result.status === 0 ? parseEntry(Buffer.from(result.stdout.trim(), "base64").toString("utf8")) : void 0;
7864
+ },
7865
+ write(store, owner, entry) {
7866
+ const serialised = JSON.stringify(entry);
7867
+ if (store === "file") {
7868
+ import_node_fs9.default.mkdirSync(dir, { recursive: true, mode: CACHE_DIR_MODE });
7869
+ import_node_fs9.default.chmodSync(dir, CACHE_DIR_MODE);
7870
+ const target = filePath(owner);
7871
+ const temp = `${target}.${String(process.pid)}.tmp`;
7872
+ import_node_fs9.default.writeFileSync(temp, serialised, { mode: CACHE_FILE_MODE });
7873
+ import_node_fs9.default.renameSync(temp, target);
7874
+ return;
7875
+ }
7876
+ requireKeychain();
7877
+ const encoded = Buffer.from(serialised, "utf8").toString("base64");
7878
+ const result = security(["-i"], `add-generic-password -U -s ${KEYCHAIN_CACHE_SERVICE} -a ${JSON.stringify(owner)} -w ${encoded}
7879
+ `);
7880
+ if (result.status !== 0) {
7881
+ throw new Error(`could not write the keychain credential cache for ${owner}`);
7882
+ }
7883
+ },
7884
+ remove(store, owner) {
7885
+ if (store === "file") {
7886
+ import_node_fs9.default.rmSync(filePath(owner), { force: true });
7887
+ return;
7888
+ }
7889
+ requireKeychain();
7890
+ security(["delete-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner]);
7891
+ }
7892
+ };
7893
+ }
7894
+ function realCredentialCacheEnv(paths) {
7895
+ return { port: createRealCredentialCache(paths.root), platform: process.platform, now: () => Date.now() };
7896
+ }
7897
+
7898
+ // src/frontdoor/realFrontDoorPort.ts
7899
+ var import_node_fs10 = __toESM(require("node:fs"), 1);
7900
+
7901
+ // src/frontdoor/probe.ts
7902
+ var import_node_worker_threads = require("node:worker_threads");
7903
+ var PROBE_TIMEOUT_MS = 2e3;
7904
+ var PROBE_WAIT_MARGIN_MS = 1e3;
7905
+ var REASON_BYTES = 1024;
7906
+ var HEADER_SLOTS = 2;
7907
+ var INT32_BYTES = 4;
7908
+ var VERDICT_PENDING = 0;
7909
+ var VERDICT_OK = 1;
7910
+ var VERDICT_FAILED = 2;
7911
+ var PROBE_SOURCE = `
7912
+ const { workerData } = require("node:worker_threads");
7913
+ const https = require("node:https");
7914
+ const { port, ca, timeoutMs, shared, ok, failed, headerSlots } = workerData;
7915
+ const header = new Int32Array(shared, 0, headerSlots);
7916
+ const reason = new Uint8Array(shared, headerSlots * 4);
7917
+ let done = false;
7918
+ const finish = (verdict, message) => {
7919
+ if (done) return;
7920
+ done = true;
7921
+ const bytes = Buffer.from(String(message), "utf8").subarray(0, reason.length);
7922
+ reason.set(bytes);
7923
+ Atomics.store(header, 1, bytes.length);
7924
+ Atomics.store(header, 0, verdict);
7925
+ Atomics.notify(header, 0);
7926
+ };
7927
+ const request = https.get({ host: "127.0.0.1", port, path: "/healthz", ca: [ca], agent: false }, (response) => {
7928
+ let body = "";
7929
+ response.setEncoding("utf8");
7930
+ response.on("data", (chunk) => { body += chunk; });
7931
+ response.on("end", () => {
7932
+ if (response.statusCode === 200 && body === "ok") finish(ok, "");
7933
+ else finish(failed, "the listener answered its health probe with HTTP " + String(response.statusCode));
7934
+ });
7935
+ response.on("error", (error) => finish(failed, error.message));
7936
+ });
7937
+ // A hard deadline over the whole exchange, handshake included: a listener that accepts the connection and then says nothing must still fail the probe.
7938
+ setTimeout(() => { request.destroy(new Error("no answer within " + String(timeoutMs) + "ms")); }, timeoutMs);
7939
+ request.on("error", (error) => finish(failed, (error.code ? error.code + ": " : "") + error.message));
7940
+ `;
7941
+ function probeFrontDoorSync(port, caPem) {
7942
+ const shared = new SharedArrayBuffer(HEADER_SLOTS * INT32_BYTES + REASON_BYTES);
7943
+ const header = new Int32Array(shared, 0, HEADER_SLOTS);
7944
+ const worker = new import_node_worker_threads.Worker(PROBE_SOURCE, {
7945
+ eval: true,
7946
+ workerData: { port, ca: caPem, timeoutMs: PROBE_TIMEOUT_MS, shared, ok: VERDICT_OK, failed: VERDICT_FAILED, headerSlots: HEADER_SLOTS }
7947
+ });
7948
+ worker.unref();
7949
+ try {
7950
+ const waited = Atomics.wait(header, 0, VERDICT_PENDING, PROBE_TIMEOUT_MS + PROBE_WAIT_MARGIN_MS);
7951
+ const verdict = Atomics.load(header, 0);
7952
+ if (waited === "timed-out" || verdict === VERDICT_PENDING) {
7953
+ return { ok: false, reason: `the probe did not finish within ${String(PROBE_TIMEOUT_MS + PROBE_WAIT_MARGIN_MS)}ms` };
7954
+ }
7955
+ if (verdict === VERDICT_OK) {
7956
+ return { ok: true };
7957
+ }
7958
+ const length = Atomics.load(header, 1);
7959
+ return { ok: false, reason: Buffer.from(new Uint8Array(shared, HEADER_SLOTS * INT32_BYTES, length)).toString("utf8") };
7960
+ } finally {
7961
+ void worker.terminate();
7962
+ }
7963
+ }
7964
+
7965
+ // src/frontdoor/trust.ts
7966
+ var import_node_crypto10 = require("node:crypto");
7967
+ var import_node_path27 = __toESM(require("node:path"), 1);
7968
+ var BUNDLE_NAME_HEX_DIGITS = 16;
7969
+ function resolveTrustBundle(params) {
7970
+ const { caCertFile, bundlesDir, inherited, fs: fs12 } = params;
7971
+ if (inherited === void 0 || inherited === "" || import_node_path27.default.resolve(inherited) === import_node_path27.default.resolve(caCertFile)) {
7972
+ return { path: caCertFile };
7973
+ }
7974
+ const caPem = fs12.readFileUtf8(caCertFile);
7975
+ let inheritedPem;
7976
+ try {
7977
+ inheritedPem = fs12.readFileUtf8(inherited);
7978
+ } catch (error) {
7979
+ return {
7980
+ path: caCertFile,
7981
+ warning: `agent-shim: NODE_EXTRA_CA_CERTS names ${inherited}, which could not be read (${error instanceof Error ? error.message : String(error)}); the child trusts agent-shim's front-door CA on top of the system store, and nothing from that file`
7982
+ };
7983
+ }
7984
+ if (inheritedPem.includes(caPem.trim())) {
7985
+ return { path: inherited };
7986
+ }
7987
+ const combined = `${inheritedPem.trimEnd()}
7988
+ ${caPem}`;
7989
+ const bundle = import_node_path27.default.join(bundlesDir, `${(0, import_node_crypto10.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7990
+ if (!fs12.exists(bundle)) {
7991
+ fs12.mkdirp(bundlesDir);
7992
+ fs12.writeFileAtomic(bundle, combined);
7993
+ }
7994
+ return { path: bundle };
7995
+ }
7996
+
7997
+ // src/frontdoor/realFrontDoorPort.ts
7998
+ var realTrustBundleFs = {
7999
+ readFileUtf8: (file) => import_node_fs10.default.readFileSync(file, "utf8"),
8000
+ exists: (file) => import_node_fs10.default.existsSync(file),
8001
+ mkdirp: (dir) => {
8002
+ import_node_fs10.default.mkdirSync(dir, { recursive: true });
8003
+ },
8004
+ writeFileAtomic: (file, contents) => {
8005
+ realFarmFs.writeFilePrivate(file, contents);
8006
+ }
8007
+ };
8008
+ function realFrontDoorPort(paths, spawnDaemon) {
8009
+ return {
8010
+ ensure: (inheritedExtraCaCerts) => {
8011
+ const up = ensureFrontDoor({
8012
+ paths,
8013
+ launcherPid: process.pid,
8014
+ ports: {
8015
+ fs: realFarmFs,
8016
+ isRunning: realIsProcessRunning,
8017
+ now: () => Date.now(),
8018
+ sleep: realSleepSync,
8019
+ spawnSupervisor: (layout) => spawnDaemon(layout, "__frontdoor-supervisor", layout.frontdoorLogPath),
8020
+ stopSupervisor: (pid) => {
8021
+ process.kill(pid, "SIGTERM");
8022
+ },
8023
+ // Read fresh for each probe: a replacement supervisor may have regenerated an unparseable CA, and the probe must trust exactly what the serving door's leaf chains to.
8024
+ verifyListener: (port) => probeFrontDoorSync(port, import_node_fs10.default.readFileSync(paths.frontdoorCaCertFile, "utf8"))
8025
+ }
8026
+ });
8027
+ const trust = resolveTrustBundle({ caCertFile: paths.frontdoorCaCertFile, bundlesDir: paths.frontdoorCaBundlesDir, inherited: inheritedExtraCaCerts, fs: realTrustBundleFs });
8028
+ return {
8029
+ port: up.port,
8030
+ connectPort: up.connectPort,
8031
+ trustBundlePath: trust.path,
8032
+ ...trust.warning === void 0 ? {} : { trustWarning: trust.warning },
8033
+ sessionToken: up.token
8034
+ };
8035
+ },
8036
+ release: () => {
8037
+ removeFrontDoorSession(realFarmFs, paths.frontdoorSessionsDir, process.pid);
8038
+ }
8039
+ };
8040
+ }
8041
+
8042
+ // src/launchWiring.ts
8043
+ function buildFarmRuntime(paths, cwd) {
8044
+ const home = import_node_os5.default.homedir();
8045
+ const read = cosmiconfigReader();
8046
+ const classification = loadClassification(paths);
8047
+ const loaded = loadCascadeInput({ paths, home, cwd, read });
8048
+ const selections = readDirectorySelections(loaded);
8049
+ const git = resolveGitBranch(realRunPort, cwd);
8050
+ return {
8051
+ runtime: {
8052
+ fs: realFarmFs,
8053
+ claudeHome: resolveClaudeHome(),
8054
+ home,
8055
+ cwd,
8056
+ ...git.branch === void 0 ? {} : { branch: git.branch },
8057
+ ...git.branchDetached === void 0 ? {} : { branchDetached: git.branchDetached },
8058
+ classification,
8059
+ loadCascade: (baseConfigProfile, cliOverride) => loadCascadeInput({
8060
+ paths,
8061
+ home,
8062
+ cwd,
8063
+ read,
8064
+ ...baseConfigProfile === void 0 ? {} : { baseConfigProfile },
8065
+ ...cliOverride === void 0 ? {} : { cliOverride }
8066
+ }).input,
8067
+ now: () => Date.now(),
8068
+ uniqueSuffix: `${String(process.pid)}.${(0, import_node_crypto11.randomUUID)()}`,
8069
+ // Zombie-aware on purpose: a previous launcher that crashed out of a resync without releasing the lock may sit unreaped, still answering signal 0 as alive, and must read as a dead holder so this launch takes the lock over instead of timing out.
8070
+ lock: { pid: process.pid, isRunning: realIsProcessRunning, sleep: realSleepSync }
8071
+ },
8072
+ ...selections.identity === void 0 ? {} : { directoryIdentity: selections.identity },
8073
+ ...selections.configProfile === void 0 ? {} : { directoryConfigProfile: selections.configProfile },
8074
+ ...loaded.globalConfig?.defaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: loaded.globalConfig.defaultConfigProfile },
8075
+ ...loaded.globalConfig?.pools === void 0 ? {} : { pools: loaded.globalConfig.pools }
8076
+ };
8077
+ }
8078
+ function realPrepareLaunchParams(paths, options) {
8079
+ const { farm } = options;
8080
+ return {
8081
+ paths,
8082
+ fs: realFsPort,
8083
+ proc: options.proc,
8084
+ log: options.log,
8085
+ resolveClaudeBinary: realResolveClaudeBinary(resolveOwnInstallDirs(paths, realOwnExecutablePath())),
8086
+ farm: farm.runtime,
8087
+ headroom: realHeadroomPort(paths, { spawnDaemon: options.spawnDaemon, cwd: farm.runtime.cwd }),
8088
+ frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
8089
+ credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
8090
+ ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
8091
+ ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
8092
+ ...farm.globalDefaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: farm.globalDefaultConfigProfile },
8093
+ ...farm.pools === void 0 ? {} : { pools: farm.pools },
8094
+ ...options.allowMissingConfigProfile === void 0 ? {} : { allowMissingConfigProfile: options.allowMissingConfigProfile }
8095
+ };
8096
+ }
8097
+ var LaunchRefusedError = class extends CliError {
8098
+ exitCode;
8099
+ constructor(message, exitCode) {
8100
+ super(message);
8101
+ this.name = "LaunchRefusedError";
8102
+ this.exitCode = exitCode;
8103
+ }
8104
+ };
8105
+ function prepareClaudeLaunch(options) {
8106
+ const paths = options.paths ?? resolveLayoutPaths();
8107
+ const refusals = [];
8108
+ const log = {
8109
+ info: () => void 0,
8110
+ warn: () => void 0,
8111
+ error: (message) => {
8112
+ refusals.push(message);
8113
+ }
8114
+ };
8115
+ const proc = {
8116
+ env: options.env,
8117
+ argv: options.argv,
8118
+ exit: (code) => {
8119
+ throw new LaunchRefusedError(refusals.join("\n") || `the launch was refused (exit ${String(code)})`, code);
8120
+ }
8121
+ };
8122
+ const spawnDaemon = options.agentShim === void 0 ? () => {
8123
+ throw new LaunchRefusedError("this launch routes through the front door or headroom, which need `agentShim`, the path of the agent-shim executable, to start their daemons", 1);
8124
+ } : spawnDaemonThrough(options.agentShim);
8125
+ return prepareLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) }));
8126
+ }
6799
8127
  // Annotate the CommonJS export names for ESM import in node:
6800
8128
  0 && (module.exports = {
6801
8129
  AMBIENT_CREDENTIAL_VARS,
@@ -6828,6 +8156,7 @@ function collectDoctorReport(params) {
6828
8156
  InvalidCategoryNameError,
6829
8157
  InvalidIdentityNameError,
6830
8158
  InvalidProviderNameError,
8159
+ LaunchRefusedError,
6831
8160
  LegacyProviderFileError,
6832
8161
  PoolNameSchema,
6833
8162
  PoolNotFoundError,
@@ -6878,6 +8207,8 @@ function collectDoctorReport(params) {
6878
8207
  listUsageSnapshots,
6879
8208
  mintLeaf,
6880
8209
  parseConnectTarget,
8210
+ prepareClaudeLaunch,
8211
+ prepareLaunch,
6881
8212
  profileExists,
6882
8213
  providerExists,
6883
8214
  readActiveIdentity,