claude-use 7.12.1 → 7.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1223,6 +1223,37 @@ function planFarm(params) {
1223
1223
  return { entries, materialised, links };
1224
1224
  }
1225
1225
 
1226
+ // src/resolve/walkPolicy.ts
1227
+ var ENTER_EVERYTHING = () => true;
1228
+ function readsSubtreeAggregates(rule) {
1229
+ const when = rule.when;
1230
+ return when !== void 0 && (when.newerThan !== void 0 || when.olderThan !== void 0 || when.maxSizeBytes !== void 0);
1231
+ }
1232
+ function hasUnboundedDepth(pattern) {
1233
+ return pattern.includes("**") || /[{(]/.test(pattern);
1234
+ }
1235
+ function couldMatchBeneath(rule, dirRel) {
1236
+ if (rule.matches(dirRel)) {
1237
+ return rule.when !== void 0;
1238
+ }
1239
+ if (rule.isExact) {
1240
+ return rule.canonicalPattern.startsWith(`${dirRel}/`);
1241
+ }
1242
+ const depth = dirRel.split("/").length;
1243
+ if (!hasUnboundedDepth(rule.canonicalPattern) && rule.segmentCount <= depth) {
1244
+ return false;
1245
+ }
1246
+ const prefix = rule.literalPrefix;
1247
+ return prefix === "" || prefix.startsWith(`${dirRel}/`) || dirRel.startsWith(prefix);
1248
+ }
1249
+ function descendPolicy(rules) {
1250
+ const all = [...rules];
1251
+ if (all.some(readsSubtreeAggregates)) {
1252
+ return ENTER_EVERYTHING;
1253
+ }
1254
+ return (dirRel) => all.some((rule) => couldMatchBeneath(rule, dirRel));
1255
+ }
1256
+
1226
1257
  // src/resolve/walk.ts
1227
1258
  import path4 from "node:path";
1228
1259
 
@@ -1401,6 +1432,9 @@ function topLevelNames(facts) {
1401
1432
  }
1402
1433
  return [...names].sort();
1403
1434
  }
1435
+ function descendPolicyFor(cascade, home) {
1436
+ return descendPolicy(flattenLayers(assembleCascade(cascade).layers, { home }).rules.values());
1437
+ }
1404
1438
  function resolveDecisions(input) {
1405
1439
  const assembled = assembleCascade(input.cascade);
1406
1440
  const flattened = flattenLayers(assembled.layers, { home: input.facts.home });
@@ -1626,8 +1660,8 @@ var FarmManifestSchema = z2.strictObject({
1626
1660
  materialised: z2.array(z2.string()),
1627
1661
  links: z2.array(z2.strictObject({ rel: z2.string(), target: z2.string() }))
1628
1662
  });
1629
- function readFarmManifest(fs10, farmRoot) {
1630
- const raw = fs10.readFileUtf8(path6.join(farmRoot, FARM_MANIFEST_FILENAME)) ?? fs10.readFileUtf8(path6.join(farmRoot, LEGACY_FARM_MANIFEST_FILENAME));
1663
+ function readFarmManifest(fs12, farmRoot) {
1664
+ const raw = fs12.readFileUtf8(path6.join(farmRoot, FARM_MANIFEST_FILENAME)) ?? fs12.readFileUtf8(path6.join(farmRoot, LEGACY_FARM_MANIFEST_FILENAME));
1631
1665
  if (raw === void 0) {
1632
1666
  return void 0;
1633
1667
  }
@@ -1651,7 +1685,7 @@ function buildEntryFacts(params) {
1651
1685
  const isDirectory = stat.kind === "dir";
1652
1686
  let latestMtimeMs = stat.mtimeMs;
1653
1687
  let totalSizeBytes = stat.sizeBytes;
1654
- if (isDirectory) {
1688
+ if (isDirectory && params.descend(rel)) {
1655
1689
  for (const name of [...params.fs.readdir(absolute)].sort()) {
1656
1690
  const child = visit(`${rel}/${name}`);
1657
1691
  if (child !== void 0) {
@@ -1685,9 +1719,9 @@ function buildEntryFacts(params) {
1685
1719
  entries
1686
1720
  };
1687
1721
  }
1688
- function listSubtree(fs10, root, rel) {
1722
+ function listSubtree(fs12, root, rel) {
1689
1723
  const absolute = path6.join(root, rel);
1690
- const stat = fs10.lstat(absolute);
1724
+ const stat = fs12.lstat(absolute);
1691
1725
  if (stat === void 0) {
1692
1726
  return [];
1693
1727
  }
@@ -1695,10 +1729,10 @@ function listSubtree(fs10, root, rel) {
1695
1729
  return [{ rel, kind: "symlink" }];
1696
1730
  }
1697
1731
  if (stat.kind === "dir") {
1698
- const children = [...fs10.readdir(absolute)].sort().flatMap((name) => listSubtree(fs10, root, `${rel}/${name}`));
1732
+ const children = [...fs12.readdir(absolute)].sort().flatMap((name) => listSubtree(fs12, root, `${rel}/${name}`));
1699
1733
  return [{ rel, kind: "dir" }, ...children];
1700
1734
  }
1701
- const contentHash = fs10.hashFile(absolute);
1735
+ const contentHash = fs12.hashFile(absolute);
1702
1736
  return [{ rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } }];
1703
1737
  }
1704
1738
  function topLevelScopeRoots(roots) {
@@ -1712,25 +1746,25 @@ function topLevelScopeRoots(roots) {
1712
1746
  }
1713
1747
  return kept;
1714
1748
  }
1715
- function reconciliationScope(fs10, farmRoot, manifest) {
1749
+ function reconciliationScope(fs12, farmRoot, manifest) {
1716
1750
  if (manifest !== void 0) {
1717
1751
  return topLevelScopeRoots(manifest.materialised);
1718
1752
  }
1719
- return [...fs10.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && name !== LEGACY_FARM_MANIFEST_FILENAME && fs10.lstat(path6.join(farmRoot, name))?.kind === "dir").sort();
1753
+ return [...fs12.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && name !== LEGACY_FARM_MANIFEST_FILENAME && fs12.lstat(path6.join(farmRoot, name))?.kind === "dir").sort();
1720
1754
  }
1721
- function collectFarmListing(fs10, farmRoot, scopeRoots) {
1722
- return scopeRoots.flatMap((root) => listSubtree(fs10, farmRoot, root));
1755
+ function collectFarmListing(fs12, farmRoot, scopeRoots) {
1756
+ return scopeRoots.flatMap((root) => listSubtree(fs12, farmRoot, root));
1723
1757
  }
1724
- function collectCanonicalCounterparts(fs10, claudeHome, farmListing) {
1758
+ function collectCanonicalCounterparts(fs12, claudeHome, farmListing) {
1725
1759
  const out = [];
1726
1760
  for (const entry of farmListing) {
1727
1761
  const absolute = path6.join(claudeHome, entry.rel);
1728
- const stat = fs10.lstat(absolute);
1762
+ const stat = fs12.lstat(absolute);
1729
1763
  if (stat === void 0) {
1730
1764
  continue;
1731
1765
  }
1732
1766
  if (stat.kind === "file") {
1733
- const contentHash = fs10.hashFile(absolute);
1767
+ const contentHash = fs12.hashFile(absolute);
1734
1768
  out.push({ rel: entry.rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } });
1735
1769
  continue;
1736
1770
  }
@@ -1998,7 +2032,8 @@ function resyncFarm(params) {
1998
2032
  nowMs,
1999
2033
  env: params.env,
2000
2034
  ...params.branch === void 0 ? {} : { branch: params.branch },
2001
- ...params.branchDetached === void 0 ? {} : { branchDetached: params.branchDetached }
2035
+ ...params.branchDetached === void 0 ? {} : { branchDetached: params.branchDetached },
2036
+ descend: descendPolicyFor(params.cascade, params.home)
2002
2037
  });
2003
2038
  const resolved = resolveDecisions({ facts, cascade: params.cascade, classification: params.classification });
2004
2039
  const manifest = {
@@ -2414,8 +2449,12 @@ function pumpTapSession(secure, openUpstream, tap, prefix = Buffer.alloc(0)) {
2414
2449
  }
2415
2450
 
2416
2451
  // src/frontdoor/capability.ts
2452
+ var CONNECT_PROXY_USER = "agent-shim";
2417
2453
  var CONNECT_PROXY_REALM = "agent-shim front door";
2418
2454
  var BASIC_SCHEME = "basic";
2455
+ function connectProxyUrl(port, token) {
2456
+ return `http://${encodeURIComponent(CONNECT_PROXY_USER)}:${encodeURIComponent(token)}@127.0.0.1:${String(port)}`;
2457
+ }
2419
2458
  function capabilityFromProxyAuthorization(value) {
2420
2459
  const trimmed = value.trim();
2421
2460
  const space = trimmed.indexOf(" ");
@@ -2432,7 +2471,15 @@ function capabilityFromProxyAuthorization(value) {
2432
2471
  }
2433
2472
 
2434
2473
  // src/frontdoor/route.ts
2474
+ var IDENTITY_HEADER = "x-agent-shim-identity";
2475
+ var SESSION_HEADER = "x-agent-shim-session";
2476
+ var HEADROOM_FLAG_HEADER = "x-agent-shim-headroom";
2477
+ var PROJECT_ID_HEADER = "x-headroom-project-id";
2435
2478
  var AUTH_HEADER = "x-agent-shim-auth";
2479
+ var PROVIDER_PATH_PREFIX = "/providers/";
2480
+ function providerBaseUrl(port, provider) {
2481
+ return `https://127.0.0.1:${String(port)}${PROVIDER_PATH_PREFIX}${encodeURIComponent(provider)}`;
2482
+ }
2436
2483
 
2437
2484
  // src/frontdoor/state.ts
2438
2485
  import path7 from "node:path";
@@ -2469,10 +2516,10 @@ var FrontDoorStateSchema = z3.strictObject({
2469
2516
  /** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
2470
2517
  lastError: z3.string().optional()
2471
2518
  });
2472
- function readFrontDoorState(fs10, stateFile) {
2519
+ function readFrontDoorState(fs12, stateFile) {
2473
2520
  let raw;
2474
2521
  try {
2475
- raw = fs10.readFileUtf8(stateFile);
2522
+ raw = fs12.readFileUtf8(stateFile);
2476
2523
  } catch {
2477
2524
  return void 0;
2478
2525
  }
@@ -2486,28 +2533,28 @@ function readFrontDoorState(fs10, stateFile) {
2486
2533
  return void 0;
2487
2534
  }
2488
2535
  }
2489
- function writeFrontDoorState(fs10, stateFile, state) {
2490
- fs10.mkdirp(path7.dirname(stateFile));
2491
- fs10.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
2536
+ function writeFrontDoorState(fs12, stateFile, state) {
2537
+ fs12.mkdirp(path7.dirname(stateFile));
2538
+ fs12.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
2492
2539
  `);
2493
2540
  }
2494
2541
  function frontDoorOrigin(state) {
2495
2542
  const port = state?.directPort ?? state?.lastDirectPort;
2496
2543
  return port === void 0 ? void 0 : `http://127.0.0.1:${String(port)}`;
2497
2544
  }
2498
- function writeFrontDoorSession(fs10, sessionsDir, session) {
2499
- fs10.mkdirPrivate(sessionsDir);
2500
- fs10.writeFilePrivate(path7.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
2545
+ function writeFrontDoorSession(fs12, sessionsDir, session) {
2546
+ fs12.mkdirPrivate(sessionsDir);
2547
+ fs12.writeFilePrivate(path7.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
2501
2548
  `);
2502
2549
  }
2503
- function listFrontDoorSessions(fs10, sessionsDir) {
2550
+ function listFrontDoorSessions(fs12, sessionsDir) {
2504
2551
  const sessions = [];
2505
- for (const name of fs10.readdir(sessionsDir)) {
2552
+ for (const name of fs12.readdir(sessionsDir)) {
2506
2553
  if (!name.endsWith(".json")) {
2507
2554
  continue;
2508
2555
  }
2509
2556
  try {
2510
- const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs10.readFileUtf8(path7.join(sessionsDir, name)) ?? ""));
2557
+ const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs12.readFileUtf8(path7.join(sessionsDir, name)) ?? ""));
2511
2558
  if (parsed.success) {
2512
2559
  sessions.push({ pid: parsed.data.pid, startedAt: parsed.data.startedAt });
2513
2560
  }
@@ -2517,14 +2564,14 @@ function listFrontDoorSessions(fs10, sessionsDir) {
2517
2564
  }
2518
2565
  return sessions.sort((a, b) => a.pid - b.pid);
2519
2566
  }
2520
- function removeFrontDoorSession(fs10, sessionsDir, pid) {
2521
- fs10.removeRecursive(path7.join(sessionsDir, `${String(pid)}.json`));
2567
+ function removeFrontDoorSession(fs12, sessionsDir, pid) {
2568
+ fs12.removeRecursive(path7.join(sessionsDir, `${String(pid)}.json`));
2522
2569
  }
2523
- function pruneDeadFrontDoorSessions(fs10, sessionsDir, isRunning) {
2570
+ function pruneDeadFrontDoorSessions(fs12, sessionsDir, isRunning) {
2524
2571
  const removed = [];
2525
- for (const session of listFrontDoorSessions(fs10, sessionsDir)) {
2572
+ for (const session of listFrontDoorSessions(fs12, sessionsDir)) {
2526
2573
  if (!isRunning(session.pid)) {
2527
- removeFrontDoorSession(fs10, sessionsDir, session.pid);
2574
+ removeFrontDoorSession(fs12, sessionsDir, session.pid);
2528
2575
  removed.push(session.pid);
2529
2576
  }
2530
2577
  }
@@ -2536,8 +2583,8 @@ var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
2536
2583
  var FRONTDOOR_POLL_MS = 1e3;
2537
2584
  var MS_PER_MINUTE = 6e4;
2538
2585
  async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
2539
- const { fs: fs10, paths } = ports;
2540
- const previous = readFrontDoorState(fs10, paths.frontdoorStateFile);
2586
+ const { fs: fs12, paths } = ports;
2587
+ const previous = readFrontDoorState(fs12, paths.frontdoorStateFile);
2541
2588
  let lastPort = previous?.lastPort;
2542
2589
  let lastConnectPort = previous?.lastConnectPort;
2543
2590
  let lastDirectPort = previous?.lastDirectPort;
@@ -2547,12 +2594,12 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2547
2594
  ...lastDirectPort === void 0 ? {} : { lastDirectPort }
2548
2595
  });
2549
2596
  const fail = (message) => {
2550
- writeFrontDoorState(fs10, paths.frontdoorStateFile, { lastError: message, ...sticky() });
2551
- fs10.removeRecursive(paths.frontdoorLockFile);
2597
+ writeFrontDoorState(fs12, paths.frontdoorStateFile, { lastError: message, ...sticky() });
2598
+ fs12.removeRecursive(paths.frontdoorLockFile);
2552
2599
  ports.log(`agent-shim frontdoor supervisor: ${message}`);
2553
2600
  return 1;
2554
2601
  };
2555
- writeFrontDoorState(fs10, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
2602
+ writeFrontDoorState(fs12, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
2556
2603
  const previousSticky = lastPort;
2557
2604
  let http2;
2558
2605
  try {
@@ -2589,8 +2636,8 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2589
2636
  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)`);
2590
2637
  }
2591
2638
  lastDirectPort = direct.port;
2592
- writeFrontDoorState(fs10, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http2.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
2593
- fs10.removeRecursive(paths.frontdoorLockFile);
2639
+ writeFrontDoorState(fs12, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http2.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
2640
+ fs12.removeRecursive(paths.frontdoorLockFile);
2594
2641
  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)}`);
2595
2642
  let idleSince;
2596
2643
  let ticks = 0;
@@ -2599,15 +2646,15 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2599
2646
  return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
2600
2647
  }
2601
2648
  ticks += 1;
2602
- pruneDeadFrontDoorSessions(fs10, paths.frontdoorSessionsDir, ports.isRunning);
2603
- if (listFrontDoorSessions(fs10, paths.frontdoorSessionsDir).length === 0) {
2649
+ pruneDeadFrontDoorSessions(fs12, paths.frontdoorSessionsDir, ports.isRunning);
2650
+ if (listFrontDoorSessions(fs12, paths.frontdoorSessionsDir).length === 0) {
2604
2651
  idleSince ??= ports.now();
2605
2652
  if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
2606
2653
  ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
2607
2654
  await direct.close();
2608
2655
  await connect3.close();
2609
2656
  await http2.close();
2610
- writeFrontDoorState(fs10, paths.frontdoorStateFile, sticky());
2657
+ writeFrontDoorState(fs12, paths.frontdoorStateFile, sticky());
2611
2658
  return 0;
2612
2659
  }
2613
2660
  } else {
@@ -2662,8 +2709,8 @@ function parseConnectTarget(authority) {
2662
2709
  function isInterceptedHost(host, interceptHosts) {
2663
2710
  return interceptHosts.includes(host);
2664
2711
  }
2665
- function servedByPipeline(path23) {
2666
- return path23?.startsWith(ROUTED_PATH_PREFIX) === true;
2712
+ function servedByPipeline(path28) {
2713
+ return path28?.startsWith(ROUTED_PATH_PREFIX) === true;
2667
2714
  }
2668
2715
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
2669
2716
  "connection",
@@ -3197,16 +3244,16 @@ function parseJson(raw, schema) {
3197
3244
  const parsed = schema.safeParse(JSON.parse(raw));
3198
3245
  return parsed.success ? parsed.data : void 0;
3199
3246
  }
3200
- function readHeadroomState(fs10, stateFile) {
3247
+ function readHeadroomState(fs12, stateFile) {
3201
3248
  try {
3202
- return parseJson(fs10.readFileUtf8(stateFile), HeadroomStateSchema);
3249
+ return parseJson(fs12.readFileUtf8(stateFile), HeadroomStateSchema);
3203
3250
  } catch {
3204
3251
  return void 0;
3205
3252
  }
3206
3253
  }
3207
- function writeHeadroomState(fs10, stateFile, state) {
3208
- fs10.mkdirp(path8.dirname(stateFile));
3209
- fs10.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
3254
+ function writeHeadroomState(fs12, stateFile, state) {
3255
+ fs12.mkdirp(path8.dirname(stateFile));
3256
+ fs12.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
3210
3257
  `);
3211
3258
  }
3212
3259
  function headroomAllowlist(providers) {
@@ -3226,14 +3273,14 @@ function headroomUpstreams(providers, frontDoorOrigin2) {
3226
3273
  function hashAllowlist(allowlist) {
3227
3274
  return createHash2("sha256").update(allowlist.join("\n")).digest("hex");
3228
3275
  }
3229
- function readAllProviders(fs10, providersDir) {
3276
+ function readAllProviders(fs12, providersDir) {
3230
3277
  const result = [];
3231
- for (const name of fs10.readdir(providersDir)) {
3278
+ for (const name of fs12.readdir(providersDir)) {
3232
3279
  if (!name.endsWith(".json")) {
3233
3280
  continue;
3234
3281
  }
3235
3282
  try {
3236
- const parsed = parseJson(fs10.readFileUtf8(path8.join(providersDir, name)), ProviderSchema);
3283
+ const parsed = parseJson(fs12.readFileUtf8(path8.join(providersDir, name)), ProviderSchema);
3237
3284
  if (parsed !== void 0) {
3238
3285
  result.push({ name: name.slice(0, -".json".length), provider: parsed });
3239
3286
  }
@@ -3243,22 +3290,22 @@ function readAllProviders(fs10, providersDir) {
3243
3290
  }
3244
3291
  return result;
3245
3292
  }
3246
- function writeSession(fs10, sessionsDir, session) {
3247
- fs10.mkdirp(sessionsDir);
3248
- fs10.writeFileUtf8(path8.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
3293
+ function writeSession(fs12, sessionsDir, session) {
3294
+ fs12.mkdirp(sessionsDir);
3295
+ fs12.writeFileUtf8(path8.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
3249
3296
  `);
3250
3297
  }
3251
- function removeSession(fs10, sessionsDir, pid) {
3252
- fs10.removeRecursive(path8.join(sessionsDir, `${String(pid)}.json`));
3298
+ function removeSession(fs12, sessionsDir, pid) {
3299
+ fs12.removeRecursive(path8.join(sessionsDir, `${String(pid)}.json`));
3253
3300
  }
3254
- function listSessions(fs10, sessionsDir) {
3301
+ function listSessions(fs12, sessionsDir) {
3255
3302
  const sessions = [];
3256
- for (const name of fs10.readdir(sessionsDir)) {
3303
+ for (const name of fs12.readdir(sessionsDir)) {
3257
3304
  if (!name.endsWith(".json")) {
3258
3305
  continue;
3259
3306
  }
3260
3307
  try {
3261
- const parsed = parseJson(fs10.readFileUtf8(path8.join(sessionsDir, name)), HeadroomSessionSchema);
3308
+ const parsed = parseJson(fs12.readFileUtf8(path8.join(sessionsDir, name)), HeadroomSessionSchema);
3262
3309
  if (parsed !== void 0) {
3263
3310
  sessions.push(parsed);
3264
3311
  }
@@ -3268,22 +3315,22 @@ function listSessions(fs10, sessionsDir) {
3268
3315
  }
3269
3316
  return sessions.sort((a, b) => a.pid - b.pid);
3270
3317
  }
3271
- function sessionsForSupervisor(fs10, sessionsDir, supervisorPid) {
3272
- return listSessions(fs10, sessionsDir).filter((session) => session.supervisorPid === supervisorPid);
3318
+ function sessionsForSupervisor(fs12, sessionsDir, supervisorPid) {
3319
+ return listSessions(fs12, sessionsDir).filter((session) => session.supervisorPid === supervisorPid);
3273
3320
  }
3274
- function pruneDeadSessions(fs10, sessionsDir, isRunning) {
3321
+ function pruneDeadSessions(fs12, sessionsDir, isRunning) {
3275
3322
  const removed = [];
3276
- for (const session of listSessions(fs10, sessionsDir)) {
3323
+ for (const session of listSessions(fs12, sessionsDir)) {
3277
3324
  if (!isRunning(session.pid)) {
3278
- removeSession(fs10, sessionsDir, session.pid);
3325
+ removeSession(fs12, sessionsDir, session.pid);
3279
3326
  removed.push(session.pid);
3280
3327
  }
3281
3328
  }
3282
3329
  return removed;
3283
3330
  }
3284
- function readStartLock(fs10, lockFile) {
3331
+ function readStartLock(fs12, lockFile) {
3285
3332
  try {
3286
- return parseJson(fs10.readFileUtf8(lockFile), HeadroomLockSchema);
3333
+ return parseJson(fs12.readFileUtf8(lockFile), HeadroomLockSchema);
3287
3334
  } catch {
3288
3335
  return void 0;
3289
3336
  }
@@ -3534,12 +3581,12 @@ function isIdentityName(name) {
3534
3581
  function claudeJsonPath(identitiesDir, identity) {
3535
3582
  return path9.join(identitiesDir, identity, CLAUDE_JSON);
3536
3583
  }
3537
- function readAccountMetadata(fs10, identitiesDir, identity) {
3584
+ function readAccountMetadata(fs12, identitiesDir, identity) {
3538
3585
  if (!isIdentityName(identity)) {
3539
3586
  throw new Error(`"${identity}" is not a valid identity name.`);
3540
3587
  }
3541
3588
  const file = claudeJsonPath(identitiesDir, identity);
3542
- const raw = fs10.readFileUtf8(file);
3589
+ const raw = fs12.readFileUtf8(file);
3543
3590
  if (raw === void 0) {
3544
3591
  return void 0;
3545
3592
  }
@@ -3573,8 +3620,8 @@ function readAccountMetadata(fs10, identitiesDir, identity) {
3573
3620
  // src/usage/read.ts
3574
3621
  var SEGMENT_RE = /^(\d{4}-\d{2}-\d{2})\.(\d+)\.jsonl$/;
3575
3622
  var DAY_MS = 864e5;
3576
- function listLogSegments(fs10, logDir) {
3577
- return fs10.readdir(logDir).flatMap((name) => {
3623
+ function listLogSegments(fs12, logDir) {
3624
+ return fs12.readdir(logDir).flatMap((name) => {
3578
3625
  const match = SEGMENT_RE.exec(name);
3579
3626
  const day = match?.[1];
3580
3627
  if (day === void 0) {
@@ -3583,15 +3630,15 @@ function listLogSegments(fs10, logDir) {
3583
3630
  return [{ name, day, endsAt: Date.parse(`${day}T00:00:00.000Z`) + DAY_MS }];
3584
3631
  }).sort((left, right) => left.day.localeCompare(right.day) || left.name.localeCompare(right.name));
3585
3632
  }
3586
- function readUsageLog(fs10, logDir, options = {}) {
3633
+ function readUsageLog(fs12, logDir, options = {}) {
3587
3634
  const { sinceMs } = options;
3588
3635
  const records = [];
3589
3636
  let invalidLines = 0;
3590
- for (const segment of listLogSegments(fs10, logDir)) {
3637
+ for (const segment of listLogSegments(fs12, logDir)) {
3591
3638
  if (sinceMs !== void 0 && segment.endsAt <= sinceMs) {
3592
3639
  continue;
3593
3640
  }
3594
- const contents = fs10.readFileUtf8(path10.join(logDir, segment.name));
3641
+ const contents = fs12.readFileUtf8(path10.join(logDir, segment.name));
3595
3642
  if (contents === void 0) {
3596
3643
  continue;
3597
3644
  }
@@ -3635,9 +3682,9 @@ function snapshotPath(snapshotsDir, identity) {
3635
3682
  }
3636
3683
  return path10.join(snapshotsDir, `${identity}.json`);
3637
3684
  }
3638
- function readUsageSnapshot(fs10, snapshotsDir, identity) {
3685
+ function readUsageSnapshot(fs12, snapshotsDir, identity) {
3639
3686
  const file = snapshotPath(snapshotsDir, identity);
3640
- const raw = fs10.readFileUtf8(file);
3687
+ const raw = fs12.readFileUtf8(file);
3641
3688
  if (raw === void 0) {
3642
3689
  return void 0;
3643
3690
  }
@@ -3653,8 +3700,8 @@ function readUsageSnapshot(fs10, snapshotsDir, identity) {
3653
3700
  }
3654
3701
  return snapshot.data;
3655
3702
  }
3656
- function listUsageSnapshots(fs10, snapshotsDir) {
3657
- return fs10.readdir(snapshotsDir).flatMap((name) => {
3703
+ function listUsageSnapshots(fs12, snapshotsDir) {
3704
+ return fs12.readdir(snapshotsDir).flatMap((name) => {
3658
3705
  if (!name.endsWith(".json")) {
3659
3706
  return [];
3660
3707
  }
@@ -3662,7 +3709,7 @@ function listUsageSnapshots(fs10, snapshotsDir) {
3662
3709
  if (!isIdentityName(identity)) {
3663
3710
  return [];
3664
3711
  }
3665
- const snapshot = readUsageSnapshot(fs10, snapshotsDir, identity);
3712
+ const snapshot = readUsageSnapshot(fs12, snapshotsDir, identity);
3666
3713
  return snapshot === void 0 ? [] : [snapshot];
3667
3714
  }).sort((left, right) => left.identity.localeCompare(right.identity));
3668
3715
  }
@@ -3837,9 +3884,9 @@ function compareVersions(a, b) {
3837
3884
  }
3838
3885
  var HEADROOM_SUPERVISOR_STILL_RUNNING = -1;
3839
3886
  async function runSupervisor(initialConfig, ports, options = {}) {
3840
- const { fs: fs10, paths } = ports;
3887
+ const { fs: fs12, paths } = ports;
3841
3888
  let config = initialConfig;
3842
- const previousState = readHeadroomState(fs10, paths.headroomStateFile);
3889
+ const previousState = readHeadroomState(fs12, paths.headroomStateFile);
3843
3890
  if (previousState?.supervisorPid !== void 0 && previousState.supervisorPid !== ports.ownPid && ports.isRunning(previousState.supervisorPid)) {
3844
3891
  ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: supervisor ${String(previousState.supervisorPid)} already owns the daemon; exiting`);
3845
3892
  return 0;
@@ -3848,19 +3895,19 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3848
3895
  let lastPort = previousState?.lastPort;
3849
3896
  const sticky = () => lastPort === void 0 ? {} : { lastPort };
3850
3897
  const ownsState = () => {
3851
- const owner = readHeadroomState(fs10, paths.headroomStateFile)?.supervisorPid;
3898
+ const owner = readHeadroomState(fs12, paths.headroomStateFile)?.supervisorPid;
3852
3899
  return owner === void 0 || owner === ports.ownPid || !ports.isRunning(owner);
3853
3900
  };
3854
3901
  const writeOwnState = (state) => {
3855
3902
  if (!ownsState()) {
3856
3903
  return false;
3857
3904
  }
3858
- writeHeadroomState(fs10, paths.headroomStateFile, state);
3905
+ writeHeadroomState(fs12, paths.headroomStateFile, state);
3859
3906
  return true;
3860
3907
  };
3861
3908
  const fail = (message) => {
3862
3909
  if (writeOwnState({ lastError: message, ...sticky() })) {
3863
- fs10.removeRecursive(paths.headroomLockFile);
3910
+ fs12.removeRecursive(paths.headroomLockFile);
3864
3911
  }
3865
3912
  ports.log(`agent-shim headroom supervisor: ${message}`);
3866
3913
  return 1;
@@ -3909,7 +3956,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3909
3956
  const settingsHash = hashSettings(config.settings);
3910
3957
  const allowlist = allowlistOf(ports);
3911
3958
  const allowlistHash = hashAllowlist(allowlist);
3912
- pruneDeadSessions(fs10, paths.headroomSessionsDir, ports.isRunning);
3959
+ pruneDeadSessions(fs12, paths.headroomSessionsDir, ports.isRunning);
3913
3960
  const ownsNow = ownsState();
3914
3961
  if (!ownsNow && !superseded) {
3915
3962
  ports.log("agent-shim headroom supervisor: another supervisor now owns state.json; serving this daemon's own sessions until they end");
@@ -3961,7 +4008,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3961
4008
  ...sticky()
3962
4009
  });
3963
4010
  if (recorded) {
3964
- fs10.removeRecursive(paths.headroomLockFile);
4011
+ fs12.removeRecursive(paths.headroomLockFile);
3965
4012
  }
3966
4013
  idleSince = void 0;
3967
4014
  ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on 127.0.0.1:${String(port)}`);
@@ -3976,7 +4023,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3976
4023
  }
3977
4024
  } else {
3978
4025
  if (runningHash !== allowlistHash || runningSettingsHash !== settingsHash || installedSource !== config.source) {
3979
- if (sessionsForSupervisor(fs10, paths.headroomSessionsDir, ports.ownPid).length === 0) {
4026
+ if (sessionsForSupervisor(fs12, paths.headroomSessionsDir, ports.ownPid).length === 0) {
3980
4027
  ports.log("agent-shim headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
3981
4028
  ports.stopProcess(headroomPid);
3982
4029
  headroomPid = void 0;
@@ -3985,7 +4032,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3985
4032
  continue;
3986
4033
  }
3987
4034
  }
3988
- const sessions = sessionsForSupervisor(fs10, paths.headroomSessionsDir, ports.ownPid);
4035
+ const sessions = sessionsForSupervisor(fs12, paths.headroomSessionsDir, ports.ownPid);
3989
4036
  if (sessions.length === 0) {
3990
4037
  idleSince ??= ports.now();
3991
4038
  const idleMs = ports.now() - idleSince;
@@ -4007,9 +4054,9 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4007
4054
  await ports.sleep(HEADROOM_POLL_MS);
4008
4055
  }
4009
4056
  }
4010
- function currentHeadroomAllowlist(fs10, paths) {
4011
- const providers = readAllProviders(fs10, paths.providersDir).map((entry) => entry.provider);
4012
- return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(fs10, paths.frontdoorStateFile))));
4057
+ function currentHeadroomAllowlist(fs12, paths) {
4058
+ const providers = readAllProviders(fs12, paths.providersDir).map((entry) => entry.provider);
4059
+ return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile))));
4013
4060
  }
4014
4061
  function allowlistOf(ports) {
4015
4062
  return currentHeadroomAllowlist(ports.fs, ports.paths);
@@ -4186,8 +4233,8 @@ function decideConfigProfile(params) {
4186
4233
  }
4187
4234
  return { source: "none" };
4188
4235
  }
4189
- function loadIdentity(identitiesDir, name, fs10) {
4190
- return loadConfigFile(path12.join(identitiesDir, name, "identity.json"), IdentitySchema, fs10.readConfigFile);
4236
+ function loadIdentity(identitiesDir, name, fs12) {
4237
+ return loadConfigFile(path12.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
4191
4238
  }
4192
4239
 
4193
4240
  // src/configProfilesStore.ts
@@ -4529,13 +4576,59 @@ import path15 from "node:path";
4529
4576
 
4530
4577
  // src/credentialCache.ts
4531
4578
  import { z as z7 } from "zod";
4579
+ var MS_PER_UNIT = { s: 1e3, m: 6e4, h: 36e5, d: 864e5 };
4532
4580
  var CachedCredentialSchema = z7.strictObject({
4533
4581
  token: z7.string().min(1),
4534
4582
  fetchedAt: z7.number().int().nonnegative(),
4535
4583
  source: CredentialSourceSchema
4536
4584
  });
4585
+ function effectiveStore(cache, platform) {
4586
+ return cache.store ?? (platform === "darwin" ? "keychain" : "file");
4587
+ }
4588
+ function ttlMs(cache) {
4589
+ if (cache.ttl === void 0) {
4590
+ return void 0;
4591
+ }
4592
+ const multiplier = MS_PER_UNIT[cache.ttl.slice(-1)];
4593
+ if (multiplier === void 0) {
4594
+ throw new Error(`credential cache ttl "${cache.ttl}" has no recognised unit`);
4595
+ }
4596
+ return Number(cache.ttl.slice(0, -1)) * multiplier;
4597
+ }
4598
+ function isFresh(entry, cache, now) {
4599
+ const limit = ttlMs(cache);
4600
+ if (entry.fetchedAt > now) {
4601
+ return false;
4602
+ }
4603
+ return limit === void 0 || now - entry.fetchedAt < limit;
4604
+ }
4537
4605
 
4538
4606
  // src/credential.ts
4607
+ var CREDENTIAL_UNAVAILABLE_EXIT = 64;
4608
+ var CREDENTIAL_COMMAND_TIMEOUT_MS = 1e4;
4609
+ var CREDENTIAL_INTERACTIVE_TIMEOUT_MS = 12e4;
4610
+ var GROUP_OTHER_PERMISSION_BITS = 63;
4611
+ var PERMISSION_BITS = 511;
4612
+ var OCTAL_RADIX = 8;
4613
+ function commandArgv(source) {
4614
+ if ("command" in source) {
4615
+ return source.command;
4616
+ }
4617
+ if ("op" in source) {
4618
+ return ["op", "read", source.op];
4619
+ }
4620
+ const account = source.keychain.account;
4621
+ return ["security", "find-generic-password", "-s", source.keychain.service, ...account === void 0 ? [] : ["-a", account], "-w"];
4622
+ }
4623
+ function isInteractiveSource(source, env) {
4624
+ if ("command" in source || "keychain" in source) {
4625
+ return source.interactive ?? false;
4626
+ }
4627
+ if ("op" in source) {
4628
+ return source.interactive ?? (env.OP_SERVICE_ACCOUNT_TOKEN ?? "") === "";
4629
+ }
4630
+ return false;
4631
+ }
4539
4632
  function summariseSource(source) {
4540
4633
  if ("env" in source) {
4541
4634
  return { kind: "env", variable: source.env };
@@ -4583,6 +4676,9 @@ function formatSourceSummary(summary) {
4583
4676
  return summary;
4584
4677
  }
4585
4678
  }
4679
+ function describeSource(source) {
4680
+ return formatSourceSummary(summariseSource(source));
4681
+ }
4586
4682
  function formatCredentialSummary(summary) {
4587
4683
  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`}`;
4588
4684
  return `${summary.target} from ${summary.sources.map(formatSourceSummary).join(", then ")}${cache}`;
@@ -4590,6 +4686,88 @@ function formatCredentialSummary(summary) {
4590
4686
  function describeCredential(credential) {
4591
4687
  return formatCredentialSummary(summariseCredential(credential));
4592
4688
  }
4689
+ function trySource(source, params) {
4690
+ const none = (reason, warn = false) => ({ ok: false, reason, warn });
4691
+ if ("env" in source) {
4692
+ const value = params.env[source.env];
4693
+ return value === void 0 || value === "" ? none("is unset or empty") : { ok: true, token: value };
4694
+ }
4695
+ if ("literal" in source) {
4696
+ return { ok: true, token: source.literal };
4697
+ }
4698
+ if ("file" in source) {
4699
+ const read = params.port.readSecretFile(source.file);
4700
+ if (!read.found) {
4701
+ return none("does not exist");
4702
+ }
4703
+ if (read.mode !== void 0 && (read.mode & GROUP_OTHER_PERMISSION_BITS) !== 0) {
4704
+ return none(
4705
+ `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS).toString(OCTAL_RADIX)}); run \`chmod 600 ${source.file}\``,
4706
+ true
4707
+ );
4708
+ }
4709
+ const token2 = read.content.trim();
4710
+ return token2 === "" ? none("is empty") : { ok: true, token: token2 };
4711
+ }
4712
+ const argv = commandArgv(source);
4713
+ const interactive = isInteractiveSource(source, params.env);
4714
+ if (interactive && !params.port.personPresent()) {
4715
+ return none("needs a person to approve it, but there is no terminal or desktop session");
4716
+ }
4717
+ const timeoutMs = source.timeoutMs ?? (interactive ? CREDENTIAL_INTERACTIVE_TIMEOUT_MS : CREDENTIAL_COMMAND_TIMEOUT_MS);
4718
+ const result = params.port.runCommand(argv, { timeoutMs, interactive });
4719
+ if (result.timedOut) {
4720
+ return none(`timed out after ${String(timeoutMs)}ms`);
4721
+ }
4722
+ if (result.status !== 0) {
4723
+ const stderr = result.stderr.trim();
4724
+ const outcome = result.status === null ? "could not be run or was killed by a signal" : `exited with status ${String(result.status)}`;
4725
+ return none(`${outcome}${stderr === "" ? "" : `: ${stderr}`}`);
4726
+ }
4727
+ const token = result.stdout.trim();
4728
+ return token === "" ? none("printed no token") : { ok: true, token };
4729
+ }
4730
+ function warmCommandFor(subject) {
4731
+ const [kind, name] = subject.split(" ");
4732
+ return kind === "provider" ? `agent-shim credential warm --provider ${name ?? ""}` : `agent-shim credential warm ${name ?? ""}`;
4733
+ }
4734
+ function resolveCredential(params) {
4735
+ const target = params.credential.target ?? "bearer";
4736
+ const cacheBlock = params.credential.cache;
4737
+ const cache = cacheBlock === void 0 ? void 0 : params.port.cache;
4738
+ const store = cacheBlock === void 0 || cache === void 0 ? void 0 : effectiveStore(cacheBlock, cache.platform);
4739
+ if (cacheBlock !== void 0 && cache !== void 0 && store !== void 0 && params.refresh !== true) {
4740
+ const entry = cache.port.read(store, params.subject);
4741
+ if (entry !== void 0 && isFresh(entry, cacheBlock, cache.now())) {
4742
+ return { ok: true, credential: { target, token: entry.token, source: entry.source, warnings: [], cachedAt: entry.fetchedAt } };
4743
+ }
4744
+ }
4745
+ const attempts = [];
4746
+ const warnings = [];
4747
+ for (const source of params.credential.sources) {
4748
+ const outcome = trySource(source, params);
4749
+ if (outcome.ok) {
4750
+ if (cache !== void 0 && store !== void 0) {
4751
+ cache.port.write(store, params.subject, { token: outcome.token, fetchedAt: cache.now(), source });
4752
+ }
4753
+ return { ok: true, credential: { target, token: outcome.token, source, warnings } };
4754
+ }
4755
+ const line = `${describeSource(source)} ${outcome.reason}`;
4756
+ attempts.push(line);
4757
+ if (outcome.warn) {
4758
+ warnings.push(`agent-shim: ${params.subject}: skipped ${line}`);
4759
+ }
4760
+ }
4761
+ const hint = cacheBlock === void 0 ? "" : `; fill the cache from a terminal with \`${warmCommandFor(params.subject)}\``;
4762
+ return { ok: false, message: `agent-shim: ${params.subject} has no usable credential: ${attempts.join("; ")}${hint}` };
4763
+ }
4764
+ function credentialVariables(target, token) {
4765
+ return {
4766
+ ANTHROPIC_AUTH_TOKEN: target === "bearer" ? token : void 0,
4767
+ ANTHROPIC_API_KEY: target === "apiKey" ? token : void 0,
4768
+ CLAUDE_CODE_OAUTH_TOKEN: target === "oauthToken" ? token : void 0
4769
+ };
4770
+ }
4593
4771
 
4594
4772
  // src/providersStore.ts
4595
4773
  var ProviderNotFoundError = class extends CliError {
@@ -4695,6 +4873,11 @@ function readProvider(paths, name) {
4695
4873
  const raw = JSON.parse(fs6.readFileSync(filePath, "utf8"));
4696
4874
  return parseProviderFile(filePath, raw);
4697
4875
  }
4876
+ function loadProvider(providersDir, name, port) {
4877
+ const filePath = path15.join(providersDir, `${name}.json`);
4878
+ const raw = port.readConfigFile(filePath);
4879
+ return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
4880
+ }
4698
4881
  function listProviders(paths) {
4699
4882
  const names = listProviderNames(
4700
4883
  (dir) => fs6.readdirSync(dir),
@@ -4827,6 +5010,30 @@ function cascadeProviderName(cascade) {
4827
5010
  }
4828
5011
  return name;
4829
5012
  }
5013
+ function resolveProvider(params) {
5014
+ const cliName = params.cliProvider !== void 0 && params.cliProvider !== "" ? params.cliProvider : void 0;
5015
+ const name = cliName ?? (params.cascade === void 0 ? void 0 : cascadeProviderName(params.cascade));
5016
+ if (name === void 0) {
5017
+ return void 0;
5018
+ }
5019
+ const definition = loadProvider(params.paths.providersDir, name, params.port);
5020
+ if (definition === void 0) {
5021
+ const known = listProviderNames(params.port.readdir, params.paths.providersDir);
5022
+ return {
5023
+ ok: false,
5024
+ status: 1,
5025
+ message: `agent-shim: no provider named "${name}". ` + (known.length > 0 ? `Known providers: ${known.join(", ")}.` : "No providers are defined yet; run `agent-shim provider add`.")
5026
+ };
5027
+ }
5028
+ if (params.credentials === void 0) {
5029
+ return { ok: false, status: 1, message: `agent-shim: provider ${name} needs its credential resolved, but this launcher has no credential port wired` };
5030
+ }
5031
+ const resolution = resolveCredential({ credential: definition.credential, env: params.env, port: params.credentials, subject: `provider ${name}` });
5032
+ if (!resolution.ok) {
5033
+ return { ok: false, status: CREDENTIAL_UNAVAILABLE_EXIT, message: resolution.message };
5034
+ }
5035
+ return { ok: true, provider: { name, definition, credential: resolution.credential }, warnings: resolution.credential.warnings };
5036
+ }
4830
5037
 
4831
5038
  // src/directoryRulesStore.ts
4832
5039
  var DirectoryRuleNotFoundError = class extends CliError {
@@ -4919,7 +5126,7 @@ function removeDirectoryRule(paths, rulePath) {
4919
5126
  }
4920
5127
 
4921
5128
  // src/checkReport.ts
4922
- import os3 from "node:os";
5129
+ import os4 from "node:os";
4923
5130
 
4924
5131
  // src/launcher/cascade.ts
4925
5132
  import path17 from "node:path";
@@ -5015,6 +5222,7 @@ var MS_PER_SECOND2 = 1e3;
5015
5222
  var SECONDS_PER_MINUTE = 60;
5016
5223
  var MINUTES_PER_HOUR = 60;
5017
5224
  var HOURS_PER_DAY = 24;
5225
+ var WARNING_STATUSES = /* @__PURE__ */ new Set(["allowed_warning", "rejected"]);
5018
5226
  function formatAge(ms) {
5019
5227
  const minutes = Math.floor(ms / (MS_PER_SECOND2 * SECONDS_PER_MINUTE));
5020
5228
  if (minutes < MINUTES_PER_HOUR) {
@@ -5035,8 +5243,30 @@ function effectiveWindow(window, nowMs) {
5035
5243
  ...window.status === void 0 ? {} : { status: window.status }
5036
5244
  };
5037
5245
  }
5246
+ function quotaWarnings(snapshot, provider, nowMs) {
5247
+ const rateLimit = snapshot?.providers[provider]?.rateLimit;
5248
+ const unified = rateLimit?.unified;
5249
+ if (snapshot === void 0 || rateLimit === void 0 || unified === void 0) {
5250
+ return [];
5251
+ }
5252
+ const age = formatAge(nowMs - Date.parse(rateLimit.observedAt));
5253
+ const windows = [
5254
+ { name: "five-hour", window: unified.fiveHour },
5255
+ { name: "seven-day", window: unified.sevenDay }
5256
+ ];
5257
+ return windows.flatMap(({ name, window }) => {
5258
+ const effective = window === void 0 ? void 0 : effectiveWindow(window, nowMs);
5259
+ if (window === void 0 || effective?.status === void 0 || !WARNING_STATUSES.has(effective.status)) {
5260
+ return [];
5261
+ }
5262
+ const reset = window.resetsAt === void 0 ? "" : `, resets ${window.resetsAt}`;
5263
+ const verdict = effective.status === "rejected" ? "exhausted" : "nearly used";
5264
+ return [`agent-shim: identity ${snapshot.identity}: the ${name} quota is ${verdict}${reset} (last seen ${age} ago)`];
5265
+ });
5266
+ }
5038
5267
 
5039
5268
  // src/usage/poolPick.ts
5269
+ import path18 from "node:path";
5040
5270
  import { z as z9 } from "zod";
5041
5271
 
5042
5272
  // src/usage/plan.ts
@@ -5289,14 +5519,14 @@ var PicksFileSchema = z9.strictObject({
5289
5519
  function errorMessage(error) {
5290
5520
  return error instanceof Error ? error.message : String(error);
5291
5521
  }
5292
- function loadPoolMembers(fs10, paths, identities, nowMs) {
5522
+ function loadPoolMembers(fs12, paths, identities, nowMs) {
5293
5523
  const windowStartMs = nowMs - FIVE_HOUR_WINDOW_MS;
5294
- const log = readUsageLog(fs10, paths.usageLogDir, { sinceMs: windowStartMs });
5524
+ const log = readUsageLog(fs12, paths.usageLogDir, { sinceMs: windowStartMs });
5295
5525
  return identities.map((identity) => {
5296
5526
  const records = log.records.filter((record) => record.identity === identity && record.provider === ANTHROPIC_PROVIDER && Date.parse(record.at) >= windowStartMs);
5297
5527
  try {
5298
- const snapshot = readUsageSnapshot(fs10, paths.usageSnapshotsDir, identity);
5299
- const account = readAccountMetadata(fs10, paths.identitiesDir, identity) ?? snapshot?.account;
5528
+ const snapshot = readUsageSnapshot(fs12, paths.usageSnapshotsDir, identity);
5529
+ const account = readAccountMetadata(fs12, paths.identitiesDir, identity) ?? snapshot?.account;
5300
5530
  return { identity, records, ...snapshot === void 0 ? {} : { snapshot }, ...account === void 0 ? {} : { account } };
5301
5531
  } catch (error) {
5302
5532
  if (error instanceof UsageSnapshotError || error instanceof AccountMetadataError) {
@@ -5314,9 +5544,9 @@ function rankPoolFromStore(params) {
5314
5544
  ...params.sticky === void 0 ? {} : { sticky: params.sticky }
5315
5545
  });
5316
5546
  }
5317
- function readPicksFile(fs10, file) {
5547
+ function readPicksFile(fs12, file) {
5318
5548
  const empty = { schemaVersion: SCHEMA_VERSION, picks: {} };
5319
- const raw = fs10.readFileUtf8(file);
5549
+ const raw = fs12.readFileUtf8(file);
5320
5550
  if (raw === void 0) {
5321
5551
  return { file: empty };
5322
5552
  }
@@ -5329,17 +5559,72 @@ function readPicksFile(fs10, file) {
5329
5559
  const result = PicksFileSchema.safeParse(parsed);
5330
5560
  return result.success ? { file: result.data } : { file: empty, problem: `${file} is not a picks file this agent-shim can read` };
5331
5561
  }
5332
- function readStickyPick(fs10, picksFile, directory) {
5333
- const read = readPicksFile(fs10, picksFile);
5562
+ function readStickyPick(fs12, picksFile, directory) {
5563
+ const read = readPicksFile(fs12, picksFile);
5334
5564
  const entry = read.file.picks[directory];
5335
5565
  return { ...entry === void 0 ? {} : { sticky: entry }, ...read.problem === void 0 ? {} : { problem: read.problem } };
5336
5566
  }
5567
+ function recordStickyPick(fs12, picksFile, directory, identity, nowMs) {
5568
+ const current = readPicksFile(fs12, picksFile).file.picks;
5569
+ const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
5570
+ const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
5571
+ fs12.mkdirPrivate(path18.dirname(picksFile));
5572
+ fs12.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
5573
+ `);
5574
+ }
5337
5575
 
5338
5576
  // src/launcher/pool.ts
5339
- function splitMembers(pool, paths, fs10) {
5340
- const exists = (name) => loadIdentity(paths.identitiesDir, name, fs10) !== void 0;
5577
+ var RESUME_FLAGS = /* @__PURE__ */ new Set(["--continue", "-c", "--resume", "-r"]);
5578
+ var TERMINATOR = "--";
5579
+ var REASONS_LOGGED = 3;
5580
+ function splitMembers(pool, paths, fs12) {
5581
+ const exists = (name) => loadIdentity(paths.identitiesDir, name, fs12) !== void 0;
5341
5582
  return { present: pool.identities.filter(exists), missing: pool.identities.filter((name) => !exists(name)) };
5342
5583
  }
5584
+ function isResuming(passthrough) {
5585
+ const end = passthrough.indexOf(TERMINATOR);
5586
+ return (end === -1 ? passthrough : passthrough.slice(0, end)).some((token) => RESUME_FLAGS.has(token));
5587
+ }
5588
+ function resolvePoolLaunch(params) {
5589
+ const { poolName, log } = params;
5590
+ const pool = params.pools?.[poolName];
5591
+ if (pool === void 0) {
5592
+ return { ok: false, message: `agent-shim: no pool named "${poolName}" (selected via ${params.selectedVia}). Run \`agent-shim pool add ${poolName} --identity <name>...\` first.` };
5593
+ }
5594
+ const { present: identities, missing } = splitMembers(pool, params.paths, params.fs);
5595
+ for (const name of missing) {
5596
+ log.warn(`agent-shim: pool "${poolName}" names identity "${name}", which does not exist; skipping it`);
5597
+ }
5598
+ if (identities.length === 0) {
5599
+ return { ok: false, message: `agent-shim: no member of pool "${poolName}" is an existing identity.` };
5600
+ }
5601
+ const resuming = isResuming(params.passthrough);
5602
+ const stickyRead = readStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd);
5603
+ if (stickyRead.problem !== void 0) {
5604
+ log.warn(`agent-shim: ${stickyRead.problem}; ignoring the last-pick record`);
5605
+ }
5606
+ for (; ; ) {
5607
+ const nowMs = params.now();
5608
+ const ranking = rankPoolFromStore({ fs: params.usageFs, paths: params.paths, identities, nowMs, resuming, ...stickyRead.sticky === void 0 ? {} : { sticky: stickyRead.sticky } });
5609
+ const { pick, earliestReturn } = ranking;
5610
+ if (pick !== void 0) {
5611
+ recordStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd, pick.identity, nowMs);
5612
+ return { ok: true, identity: pick.identity, explanation: `pool ${poolName}: ${pick.reasons.slice(0, REASONS_LOGGED).join("; ")}` };
5613
+ }
5614
+ if (earliestReturn === void 0) {
5615
+ return { ok: false, message: `agent-shim: no member of pool "${poolName}" can be picked.` };
5616
+ }
5617
+ const until = new Date(earliestReturn.atMs).toISOString();
5618
+ if (!params.wait) {
5619
+ return {
5620
+ ok: false,
5621
+ 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.`
5622
+ };
5623
+ }
5624
+ log.info(`agent-shim: every member of pool "${poolName}" is refused; waiting until ${until} for ${earliestReturn.identity}`);
5625
+ params.sleep(Math.max(earliestReturn.atMs - nowMs, 0));
5626
+ }
5627
+ }
5343
5628
 
5344
5629
  // src/poolPickReport.ts
5345
5630
  function candidateView(candidate) {
@@ -5379,14 +5664,15 @@ function collectPoolPick(params) {
5379
5664
  import { spawn, spawnSync } from "node:child_process";
5380
5665
  import { createHash as createHash4 } from "node:crypto";
5381
5666
  import fs7 from "node:fs";
5382
- import path19 from "node:path";
5667
+ import os3 from "node:os";
5668
+ import path20 from "node:path";
5383
5669
  import { isSea } from "node:sea";
5384
5670
 
5385
5671
  // src/versionDiscovery.ts
5386
5672
  import os2 from "node:os";
5387
- import path18 from "node:path";
5673
+ import path19 from "node:path";
5388
5674
  function defaultVersionsDir() {
5389
- return path18.join(os2.homedir(), ".local", "share", "claude", "versions");
5675
+ return path19.join(os2.homedir(), ".local", "share", "claude", "versions");
5390
5676
  }
5391
5677
  var NUMERIC_DOTTED_VERSION_RE = /^\d+(?:\.\d+)*$/;
5392
5678
  function isNumericDottedVersion(name) {
@@ -5428,14 +5714,14 @@ function discoverClaudeBinary(options) {
5428
5714
  const highestVersion = pickHighestVersion(entries);
5429
5715
  if (highestVersion !== void 0) {
5430
5716
  return {
5431
- path: path18.join(versionsDir, highestVersion),
5717
+ path: path19.join(versionsDir, highestVersion),
5432
5718
  source: "versions-dir",
5433
5719
  version: highestVersion
5434
5720
  };
5435
5721
  }
5436
- const ownInstallDirs = new Set(options.ownInstallDirs.map((dir) => path18.resolve(dir)));
5722
+ const ownInstallDirs = new Set(options.ownInstallDirs.map((dir) => path19.resolve(dir)));
5437
5723
  for (const dir of options.pathDirs) {
5438
- if (ownInstallDirs.has(path18.resolve(dir))) {
5724
+ if (ownInstallDirs.has(path19.resolve(dir))) {
5439
5725
  continue;
5440
5726
  }
5441
5727
  const found = options.findExecutableInDir(dir, "claude");
@@ -5480,7 +5766,7 @@ function isErrorWithCode(error, code) {
5480
5766
  }
5481
5767
  var OWNER_ONLY_DIR_MODE = 448;
5482
5768
  var OWNER_ONLY_FILE_MODE = 384;
5483
- var PERMISSION_BITS = 511;
5769
+ var PERMISSION_BITS2 = 511;
5484
5770
  var realFarmFs = {
5485
5771
  lstat(filePath) {
5486
5772
  let stat;
@@ -5546,7 +5832,7 @@ var realFarmFs = {
5546
5832
  appendFilePrivate(filePath, contents) {
5547
5833
  const descriptor = fs7.openSync(filePath, "a", OWNER_ONLY_FILE_MODE);
5548
5834
  try {
5549
- if ((fs7.fstatSync(descriptor).mode & PERMISSION_BITS) !== OWNER_ONLY_FILE_MODE) {
5835
+ if ((fs7.fstatSync(descriptor).mode & PERMISSION_BITS2) !== OWNER_ONLY_FILE_MODE) {
5550
5836
  fs7.fchmodSync(descriptor, OWNER_ONLY_FILE_MODE);
5551
5837
  }
5552
5838
  const bytes = Buffer.from(contents, "utf8");
@@ -5580,6 +5866,10 @@ var realFarmFs = {
5580
5866
  }
5581
5867
  }
5582
5868
  };
5869
+ var INT32_BYTE_LENGTH = 4;
5870
+ function realSleepSync(ms) {
5871
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(INT32_BYTE_LENGTH)), 0, 0, ms);
5872
+ }
5583
5873
  function realIsProcessAlive(pid) {
5584
5874
  try {
5585
5875
  process.kill(pid, 0);
@@ -5601,6 +5891,51 @@ var realRunPort = {
5601
5891
  return { status: result.status, stdout: result.stdout, stderr: result.stderr };
5602
5892
  }
5603
5893
  };
5894
+ function expandHome2(filePath) {
5895
+ return filePath.startsWith("~/") ? path20.join(os3.homedir(), filePath.slice(1)) : filePath;
5896
+ }
5897
+ var MACOS_GUI_SESSION_MANAGER = "Aqua";
5898
+ function hasDesktopSession() {
5899
+ if (process.platform === "darwin") {
5900
+ const result = spawnSync("launchctl", ["managername"], { encoding: "utf8" });
5901
+ return result.status === 0 && result.stdout.trim() === MACOS_GUI_SESSION_MANAGER;
5902
+ }
5903
+ if (process.platform === "win32") {
5904
+ return false;
5905
+ }
5906
+ return (process.env.DISPLAY ?? "") !== "" || (process.env.WAYLAND_DISPLAY ?? "") !== "";
5907
+ }
5908
+ var realCredentialPort = {
5909
+ readSecretFile(filePath) {
5910
+ const resolved = expandHome2(filePath);
5911
+ let content;
5912
+ let stat;
5913
+ try {
5914
+ stat = fs7.statSync(resolved);
5915
+ content = fs7.readFileSync(resolved, "utf8");
5916
+ } catch (error) {
5917
+ if (isEnoent3(error)) {
5918
+ return { found: false };
5919
+ }
5920
+ throw error;
5921
+ }
5922
+ return { found: true, content, mode: process.platform === "win32" ? void 0 : stat.mode };
5923
+ },
5924
+ runCommand(argv, options) {
5925
+ const [command, ...args] = argv;
5926
+ const result = spawnSync(command, args, {
5927
+ encoding: "utf8",
5928
+ timeout: options.timeoutMs,
5929
+ stdio: options.interactive ? ["inherit", "pipe", "inherit"] : ["ignore", "pipe", "pipe"]
5930
+ });
5931
+ if (result.error !== void 0) {
5932
+ const timedOut = isErrorWithCode(result.error, "ETIMEDOUT");
5933
+ return { status: result.status, stdout: "", stderr: timedOut ? "" : result.error.message, timedOut };
5934
+ }
5935
+ return { status: result.status, stdout: result.stdout, stderr: options.interactive ? "" : result.stderr, timedOut: false };
5936
+ },
5937
+ personPresent: () => process.stdin.isTTY || hasDesktopSession()
5938
+ };
5604
5939
  function resolveGitBranch(run, cwd) {
5605
5940
  const result = run.run("git", ["-C", cwd, "rev-parse", "--abbrev-ref", "HEAD"]);
5606
5941
  if (result.status !== 0) {
@@ -5615,6 +5950,62 @@ function resolveGitBranch(run, cwd) {
5615
5950
  }
5616
5951
  return { branch: name, branchDetached: false };
5617
5952
  }
5953
+ function resolveGitRoot(run, cwd) {
5954
+ const result = run.run("git", ["-C", cwd, "rev-parse", "--show-toplevel"]);
5955
+ if (result.status !== 0) {
5956
+ return void 0;
5957
+ }
5958
+ const root = result.stdout.trim();
5959
+ return root === "" ? void 0 : root;
5960
+ }
5961
+ function detachedDaemonSpawnOptions(logFd, env) {
5962
+ return { detached: true, stdio: ["ignore", logFd, logFd], env };
5963
+ }
5964
+ function spawnDaemonThrough(executable) {
5965
+ return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: executable, args: [subcommand] }, paths, subcommand, logPath);
5966
+ }
5967
+ function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
5968
+ fs7.mkdirSync(path20.dirname(logPath), { recursive: true });
5969
+ const logFd = fs7.openSync(logPath, "a");
5970
+ try {
5971
+ const child = spawn(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
5972
+ child.unref();
5973
+ if (child.pid === void 0) {
5974
+ throw new Error(`spawning ${subcommand} returned no pid`);
5975
+ }
5976
+ return child.pid;
5977
+ } finally {
5978
+ fs7.closeSync(logFd);
5979
+ }
5980
+ }
5981
+ function spawnHeadroomSupervisor(paths, spawnDaemon) {
5982
+ return spawnDaemon(paths, "__headroom-supervisor", paths.headroomLogPath);
5983
+ }
5984
+ function realHeadroomPort(paths, options) {
5985
+ return {
5986
+ ensure: () => {
5987
+ const up = ensureHeadroom({
5988
+ paths,
5989
+ launcherPid: process.pid,
5990
+ ports: {
5991
+ fs: realFarmFs,
5992
+ // 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.
5993
+ isRunning: realIsProcessRunning,
5994
+ now: () => Date.now(),
5995
+ sleep: realSleepSync,
5996
+ spawnSupervisor: (layout) => spawnHeadroomSupervisor(layout, options.spawnDaemon)
5997
+ }
5998
+ });
5999
+ return {
6000
+ port: up.port,
6001
+ projectId: resolveGitRoot(realRunPort, options.cwd) ?? options.cwd
6002
+ };
6003
+ },
6004
+ release: () => {
6005
+ removeSession(realFarmFs, paths.headroomSessionsDir, process.pid);
6006
+ }
6007
+ };
6008
+ }
5618
6009
  var realProcPort = {
5619
6010
  env: process.env,
5620
6011
  argv: process.argv.slice(2),
@@ -5632,7 +6023,7 @@ function listVersionsDir(dir) {
5632
6023
  throw error;
5633
6024
  }
5634
6025
  return entries.filter((entry) => entry.isFile()).map((entry) => {
5635
- const fullPath = path19.join(dir, entry.name);
6026
+ const fullPath = path20.join(dir, entry.name);
5636
6027
  const stat = fs7.statSync(fullPath);
5637
6028
  return {
5638
6029
  name: entry.name,
@@ -5647,7 +6038,7 @@ function windowsPathExtensions(pathext) {
5647
6038
  return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
5648
6039
  }
5649
6040
  function resolveExecutableCandidate(dir, name, env) {
5650
- const candidate = path19.join(dir, name);
6041
+ const candidate = path20.join(dir, name);
5651
6042
  if (env.platform === "win32") {
5652
6043
  const extensions = windowsPathExtensions(env.pathext);
5653
6044
  const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
@@ -5696,13 +6087,13 @@ function resolveOwnExecutablePath(env) {
5696
6087
  if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
5697
6088
  return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
5698
6089
  }
5699
- const candidate = env.argv1 === void 0 ? env.execPath : path19.resolve(env.cwd, env.argv1);
5700
- const candidateDir = path19.dirname(candidate);
5701
- const candidateDirOnPath = env.pathDirs.some((dir) => path19.resolve(dir) === candidateDir);
6090
+ const candidate = env.argv1 === void 0 ? env.execPath : path20.resolve(env.cwd, env.argv1);
6091
+ const candidateDir = path20.dirname(candidate);
6092
+ const candidateDirOnPath = env.pathDirs.some((dir) => path20.resolve(dir) === candidateDir);
5702
6093
  if (candidateDirOnPath) {
5703
6094
  return candidate;
5704
6095
  }
5705
- const viaPath = searchPathForExecutable(env.pathDirs, path19.basename(candidate), env.findExecutableInDir);
6096
+ const viaPath = searchPathForExecutable(env.pathDirs, path20.basename(candidate), env.findExecutableInDir);
5706
6097
  return viaPath ?? candidate;
5707
6098
  }
5708
6099
  function realOwnExecutablePath() {
@@ -5710,21 +6101,21 @@ function realOwnExecutablePath() {
5710
6101
  argv1: process.argv[1],
5711
6102
  execPath: process.execPath,
5712
6103
  cwd: process.cwd(),
5713
- pathDirs: (process.env.PATH ?? "").split(path19.delimiter).filter((dir) => dir !== ""),
6104
+ pathDirs: (process.env.PATH ?? "").split(path20.delimiter).filter((dir) => dir !== ""),
5714
6105
  findExecutableInDir
5715
6106
  });
5716
6107
  }
5717
6108
  function realResolveClaudeBinary(ownInstallDirs) {
5718
6109
  return () => discoverClaudeBinary({
5719
6110
  listVersionsDir,
5720
- pathDirs: (process.env.PATH ?? "").split(path19.delimiter).filter((dir) => dir !== ""),
6111
+ pathDirs: (process.env.PATH ?? "").split(path20.delimiter).filter((dir) => dir !== ""),
5721
6112
  findExecutableInDir,
5722
6113
  ownInstallDirs: [...ownInstallDirs]
5723
6114
  });
5724
6115
  }
5725
6116
 
5726
6117
  // src/checkReport.ts
5727
- import path20 from "node:path";
6118
+ import path21 from "node:path";
5728
6119
  import { z as z10 } from "zod";
5729
6120
 
5730
6121
  // src/cli/bool.ts
@@ -5913,7 +6304,8 @@ function runCheck(params) {
5913
6304
  nowMs: params.nowMs,
5914
6305
  env: params.env,
5915
6306
  ...params.branch === void 0 ? {} : { branch: params.branch },
5916
- ...params.branchDetached === void 0 ? {} : { branchDetached: params.branchDetached }
6307
+ ...params.branchDetached === void 0 ? {} : { branchDetached: params.branchDetached },
6308
+ descend: descendPolicyFor(params.cascade, params.home)
5917
6309
  });
5918
6310
  const resolved = resolveDecisions({ facts, cascade: params.cascade, classification: params.classification });
5919
6311
  const decisionLines = [...resolved.decisions.values()].slice().sort((a, b) => a.relPath < b.relPath ? -1 : a.relPath > b.relPath ? 1 : 0).map(formatDecision);
@@ -6046,7 +6438,7 @@ function loadCheckProvider(paths, name) {
6046
6438
  }
6047
6439
  function collectCheckReport(params) {
6048
6440
  const { paths, cwd } = params;
6049
- const home = os3.homedir();
6441
+ const home = os4.homedir();
6050
6442
  const claudeHome = resolveClaudeHome();
6051
6443
  const read = cosmiconfigReader();
6052
6444
  const classification = loadClassification(paths);
@@ -6091,10 +6483,10 @@ function collectCheckReport(params) {
6091
6483
  }).input;
6092
6484
  const providerName = cascadeProviderName(cascade);
6093
6485
  const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
6094
- const farmRoot = identityDecision.name === void 0 ? void 0 : path20.join(paths.identitiesDir, identityDecision.name);
6486
+ const farmRoot = identityDecision.name === void 0 ? void 0 : path21.join(paths.identitiesDir, identityDecision.name);
6095
6487
  const settingsFiles = {
6096
- "settings.json": realFsPort.readFileUtf8(path20.join(claudeHome, "settings.json")),
6097
- "settings.local.json": realFsPort.readFileUtf8(path20.join(claudeHome, "settings.local.json"))
6488
+ "settings.json": realFsPort.readFileUtf8(path21.join(claudeHome, "settings.json")),
6489
+ "settings.local.json": realFsPort.readFileUtf8(path21.join(claudeHome, "settings.local.json"))
6098
6490
  };
6099
6491
  const report = runCheck({
6100
6492
  cwd,
@@ -6124,7 +6516,7 @@ function collectCheckReport(params) {
6124
6516
 
6125
6517
  // src/claudeShim.ts
6126
6518
  import fs8 from "node:fs";
6127
- import path21 from "node:path";
6519
+ import path22 from "node:path";
6128
6520
  import { z as z11 } from "zod";
6129
6521
  var ClaudeShimStateSchema = z11.strictObject({
6130
6522
  targetPath: z11.string().min(1),
@@ -6135,29 +6527,29 @@ function commandFilename(ownExecutablePath, commandName) {
6135
6527
  return ownExecutablePath.toLowerCase().endsWith(".exe") ? `${commandName}.exe` : commandName;
6136
6528
  }
6137
6529
  function resolveOwnInstallDirs(paths, ownExecutablePath) {
6138
- const dirs = [path21.dirname(ownExecutablePath)];
6530
+ const dirs = [path22.dirname(ownExecutablePath)];
6139
6531
  const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
6140
6532
  if (state !== void 0) {
6141
- dirs.push(path21.dirname(state.targetPath));
6533
+ dirs.push(path22.dirname(state.targetPath));
6142
6534
  }
6143
6535
  return dirs;
6144
6536
  }
6145
6537
  var nodeLinkFs = { link: fs8.linkSync, copyFile: fs8.copyFileSync, chmod: fs8.chmodSync };
6146
6538
  function findPathShadow(params) {
6147
- const resolvedTargetDir = path21.resolve(params.targetDir);
6539
+ const resolvedTargetDir = path22.resolve(params.targetDir);
6148
6540
  for (const dir of params.pathDirs) {
6149
6541
  const found = params.findExecutableInDir(dir, params.targetFilename);
6150
6542
  if (found === void 0) {
6151
6543
  continue;
6152
6544
  }
6153
- return path21.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
6545
+ return path22.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
6154
6546
  }
6155
- return params.pathDirs.some((dir) => path21.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
6547
+ return params.pathDirs.some((dir) => path22.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
6156
6548
  }
6157
6549
 
6158
6550
  // src/doctorReport.ts
6159
6551
  import fs9 from "node:fs";
6160
- import path22 from "node:path";
6552
+ import path23 from "node:path";
6161
6553
  function refinePathShadow(status, ownExecutablePath, realpath) {
6162
6554
  if (status.status !== "shadowed") {
6163
6555
  return status;
@@ -6181,7 +6573,7 @@ function validateJson(schema, input) {
6181
6573
  return { ok: true, data: result.data };
6182
6574
  }
6183
6575
  function pushPathResolution(push, resolution) {
6184
- const ownDir = path22.dirname(resolution.ownExecutablePath);
6576
+ const ownDir = path23.dirname(resolution.ownExecutablePath);
6185
6577
  switch (resolution.agentShim.status) {
6186
6578
  case "ok":
6187
6579
  push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
@@ -6249,14 +6641,14 @@ function pushProvider(push, entry) {
6249
6641
  }
6250
6642
  function pushLegacyName(push, params) {
6251
6643
  const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
6252
- if (legacyVariables.length === 0 && path22.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
6644
+ if (legacyVariables.length === 0 && path23.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
6253
6645
  push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
6254
6646
  return;
6255
6647
  }
6256
6648
  for (const name of legacyVariables) {
6257
6649
  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);
6258
6650
  }
6259
- if (path22.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
6651
+ if (path23.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
6260
6652
  push(
6261
6653
  "legacy-name",
6262
6654
  "warn",
@@ -6564,18 +6956,18 @@ function collectDoctorReport(params) {
6564
6956
  const { paths } = params;
6565
6957
  const identityNames = fs9.existsSync(paths.identitiesDir) ? fs9.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
6566
6958
  const identities = identityNames.map((name) => {
6567
- const farmRoot = path22.join(paths.identitiesDir, name);
6568
- const identityPath = path22.join(farmRoot, "identity.json");
6959
+ const farmRoot = path23.join(paths.identitiesDir, name);
6960
+ const identityPath = path23.join(farmRoot, "identity.json");
6569
6961
  return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
6570
6962
  });
6571
6963
  const profileNames = fs9.existsSync(paths.configProfilesDir) ? fs9.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
6572
6964
  const configProfiles = profileNames.map((name) => {
6573
- const profilePath = path22.join(paths.configProfilesDir, `${name}.json`);
6965
+ const profilePath = path23.join(paths.configProfilesDir, `${name}.json`);
6574
6966
  return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
6575
6967
  });
6576
6968
  const providerNames = fs9.existsSync(paths.providersDir) ? fs9.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
6577
6969
  const providers = providerNames.map((name) => {
6578
- const providerPath = path22.join(paths.providersDir, `${name}.json`);
6970
+ const providerPath = path23.join(paths.providersDir, `${name}.json`);
6579
6971
  return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
6580
6972
  });
6581
6973
  const ownExecutablePath = realOwnExecutablePath();
@@ -6587,12 +6979,12 @@ function collectDoctorReport(params) {
6587
6979
  binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
6588
6980
  }
6589
6981
  const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
6590
- const pathDirs = (params.env.PATH ?? "").split(path22.delimiter).filter((dir) => dir !== "");
6982
+ const pathDirs = (params.env.PATH ?? "").split(path23.delimiter).filter((dir) => dir !== "");
6591
6983
  const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
6592
6984
  findPathShadow({
6593
6985
  pathDirs,
6594
- targetDir: path22.dirname(shimState.targetPath),
6595
- targetFilename: path22.basename(shimState.targetPath),
6986
+ targetDir: path23.dirname(shimState.targetPath),
6987
+ targetFilename: path23.basename(shimState.targetPath),
6596
6988
  findExecutableInDir
6597
6989
  }),
6598
6990
  shimState.targetPath,
@@ -6615,7 +7007,7 @@ function collectDoctorReport(params) {
6615
7007
  agentShim: refinePathShadow(
6616
7008
  findPathShadow({
6617
7009
  pathDirs,
6618
- targetDir: path22.dirname(ownExecutablePath),
7010
+ targetDir: path23.dirname(ownExecutablePath),
6619
7011
  targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
6620
7012
  findExecutableInDir
6621
7013
  }),
@@ -6633,6 +7025,975 @@ function collectDoctorReport(params) {
6633
7025
  });
6634
7026
  return report;
6635
7027
  }
7028
+
7029
+ // src/launcher.ts
7030
+ import { randomUUID as randomUUID4 } from "node:crypto";
7031
+ import path25 from "node:path";
7032
+
7033
+ // src/launcher/argv.ts
7034
+ var ConflictingIdentityError = class extends UsageError {
7035
+ constructor(positional, flag) {
7036
+ super(`The launch names two identities: "@${positional}" and "--identity ${flag}". Pass only one.`);
7037
+ this.positional = positional;
7038
+ this.flag = flag;
7039
+ this.name = "ConflictingIdentityError";
7040
+ }
7041
+ positional;
7042
+ flag;
7043
+ };
7044
+ var VALUED_FLAGS = ["--identity", "--config-profile", "--provider", "--category", "--share", "--hide"];
7045
+ var BOOLEAN_FLAGS = [
7046
+ { flag: "--headroom", key: "headroom" },
7047
+ { flag: "--track-usage", key: "trackUsage" },
7048
+ { flag: "--skip-permissions", key: "skipPermissions" },
7049
+ { flag: "--remote-control", key: "remoteControl" },
7050
+ { flag: "--wait", key: "wait" }
7051
+ ];
7052
+ var LAUNCHER_FLAG_NAMES = [
7053
+ ...VALUED_FLAGS,
7054
+ "--no-provider",
7055
+ ...BOOLEAN_FLAGS.flatMap(({ flag }) => [flag, `--no-${flag.slice(2)}`])
7056
+ ];
7057
+ var TERMINATOR2 = "--";
7058
+ function matchValuedFlag(token) {
7059
+ for (const flag of VALUED_FLAGS) {
7060
+ if (token === flag) {
7061
+ return { flag };
7062
+ }
7063
+ if (token.startsWith(`${flag}=`)) {
7064
+ return { flag, inlineValue: token.slice(flag.length + 1) };
7065
+ }
7066
+ }
7067
+ return void 0;
7068
+ }
7069
+ function matchBooleanFlag(token) {
7070
+ for (const { flag, key } of BOOLEAN_FLAGS) {
7071
+ if (token === flag) {
7072
+ return { key, value: true };
7073
+ }
7074
+ if (token === `--no-${flag.slice(2)}`) {
7075
+ return { key, value: false };
7076
+ }
7077
+ }
7078
+ return void 0;
7079
+ }
7080
+ function parseLauncherArgv(argv) {
7081
+ const first = argv[0];
7082
+ const positionalIdentity = first !== void 0 && first.startsWith("@") && first.length > 1 ? first.slice(1) : void 0;
7083
+ const remaining = positionalIdentity === void 0 ? argv : argv.slice(1);
7084
+ let flagIdentity;
7085
+ let configProfile;
7086
+ let provider;
7087
+ const booleans = {};
7088
+ const categoryFlags = [];
7089
+ const shareFlags = [];
7090
+ const hideFlags = [];
7091
+ const rest = [];
7092
+ for (let index = 0; index < remaining.length; index += 1) {
7093
+ const token = remaining[index];
7094
+ if (token === void 0) {
7095
+ continue;
7096
+ }
7097
+ if (token === TERMINATOR2) {
7098
+ rest.push(...remaining.slice(index));
7099
+ break;
7100
+ }
7101
+ if (token === "--no-provider") {
7102
+ provider = false;
7103
+ continue;
7104
+ }
7105
+ const booleanFlag = matchBooleanFlag(token);
7106
+ if (booleanFlag !== void 0) {
7107
+ booleans[booleanFlag.key] = booleanFlag.value;
7108
+ continue;
7109
+ }
7110
+ const matched = matchValuedFlag(token);
7111
+ if (matched === void 0) {
7112
+ rest.push(token);
7113
+ continue;
7114
+ }
7115
+ let value;
7116
+ if (matched.inlineValue !== void 0) {
7117
+ value = matched.inlineValue;
7118
+ } else {
7119
+ const next = remaining[index + 1];
7120
+ if (next === void 0 || next === TERMINATOR2) {
7121
+ rest.push(token);
7122
+ continue;
7123
+ }
7124
+ value = next;
7125
+ index += 1;
7126
+ }
7127
+ switch (matched.flag) {
7128
+ case "--identity":
7129
+ flagIdentity = value;
7130
+ break;
7131
+ case "--config-profile":
7132
+ configProfile = value;
7133
+ break;
7134
+ case "--provider":
7135
+ provider = value;
7136
+ break;
7137
+ case "--category":
7138
+ categoryFlags.push(value);
7139
+ break;
7140
+ case "--share":
7141
+ shareFlags.push(value);
7142
+ break;
7143
+ case "--hide":
7144
+ hideFlags.push(value);
7145
+ break;
7146
+ default:
7147
+ matched.flag;
7148
+ }
7149
+ }
7150
+ if (positionalIdentity !== void 0 && flagIdentity !== void 0 && positionalIdentity !== flagIdentity) {
7151
+ throw new ConflictingIdentityError(positionalIdentity, flagIdentity);
7152
+ }
7153
+ const identity = flagIdentity ?? positionalIdentity;
7154
+ return {
7155
+ ...identity === void 0 ? {} : { identity },
7156
+ ...configProfile === void 0 ? {} : { configProfile },
7157
+ ...provider === void 0 ? {} : { provider },
7158
+ ...booleans,
7159
+ categoryFlags,
7160
+ shareFlags,
7161
+ hideFlags,
7162
+ rest
7163
+ };
7164
+ }
7165
+
7166
+ // src/cli/pairs.ts
7167
+ function splitCommas(input) {
7168
+ if (input === "") {
7169
+ return [];
7170
+ }
7171
+ return input.split(",");
7172
+ }
7173
+ function parsePair(input) {
7174
+ const eqIndex = input.indexOf("=");
7175
+ if (eqIndex === -1) {
7176
+ throw new Error(`Expected "<key>=<value>", got "${input}" (no "=" found)`);
7177
+ }
7178
+ const key = input.slice(0, eqIndex);
7179
+ const value = input.slice(eqIndex + 1);
7180
+ if (key === "") {
7181
+ throw new Error(`Expected a non-empty key before "=" in "${input}"`);
7182
+ }
7183
+ return { key, value };
7184
+ }
7185
+ function parseBool(input) {
7186
+ const parsed = parseBoolWord(input);
7187
+ if (parsed === void 0) {
7188
+ throw new Error(`Expected "true", "false", "1" or "0", got "${input}"`);
7189
+ }
7190
+ return parsed;
7191
+ }
7192
+ function parseBoolPairList(input) {
7193
+ const result = {};
7194
+ for (const piece of splitCommas(input)) {
7195
+ const { key, value } = parsePair(piece);
7196
+ result[key] = parseBool(value);
7197
+ }
7198
+ return result;
7199
+ }
7200
+
7201
+ // src/launcher/cliOverride.ts
7202
+ var InvalidCliCategoryError = class extends CliError {
7203
+ constructor(categoryName) {
7204
+ super(`"${categoryName}" is not a category this launch may toggle (runtime, history, knowledge, settings).`);
7205
+ this.categoryName = categoryName;
7206
+ this.name = "InvalidCliCategoryError";
7207
+ }
7208
+ categoryName;
7209
+ };
7210
+ var InvalidCliEntryKeyError = class extends CliError {
7211
+ constructor(key) {
7212
+ super(`"${key}" is not a valid entries key \u2014 it must start with "<category>/", e.g. "knowledge/skills/commit".`);
7213
+ this.key = key;
7214
+ this.name = "InvalidCliEntryKeyError";
7215
+ }
7216
+ key;
7217
+ };
7218
+ function toCategoryMap(pairs) {
7219
+ const expanded = expandAllCategoryKey(pairs);
7220
+ const result = {};
7221
+ for (const [key, value] of Object.entries(expanded)) {
7222
+ if (!isOverridableCategory(key)) {
7223
+ throw new InvalidCliCategoryError(key);
7224
+ }
7225
+ result[key] = value;
7226
+ }
7227
+ return result;
7228
+ }
7229
+ function toEntries(pairs) {
7230
+ for (const key of Object.keys(pairs)) {
7231
+ if (!ENTRY_KEY_RE.test(key)) {
7232
+ throw new InvalidCliEntryKeyError(key);
7233
+ }
7234
+ }
7235
+ return pairs;
7236
+ }
7237
+ function parseOverride(source, raw, parse) {
7238
+ try {
7239
+ return parse(raw);
7240
+ } catch (error) {
7241
+ if (error instanceof Error && !(error instanceof CliError)) {
7242
+ throw new UsageError(`Invalid ${source} value "${raw}": ${error.message}.`);
7243
+ }
7244
+ throw error;
7245
+ }
7246
+ }
7247
+ function buildCliOverride(params) {
7248
+ let categoryPairs = {};
7249
+ if (params.env.AGENT_SHIM_CATEGORY_OVERRIDE !== void 0 && params.env.AGENT_SHIM_CATEGORY_OVERRIDE !== "") {
7250
+ categoryPairs = parseOverride("AGENT_SHIM_CATEGORY_OVERRIDE", params.env.AGENT_SHIM_CATEGORY_OVERRIDE, parseBoolPairList);
7251
+ }
7252
+ for (const flagValue of params.categoryFlags) {
7253
+ const pair = parseOverride("--category", flagValue, (raw) => {
7254
+ const { key, value } = parsePair(raw);
7255
+ return { key, value: parseBool(value) };
7256
+ });
7257
+ categoryPairs[pair.key] = pair.value;
7258
+ }
7259
+ let entryPairs = {};
7260
+ if (params.env.AGENT_SHIM_ENTRY_OVERRIDE !== void 0 && params.env.AGENT_SHIM_ENTRY_OVERRIDE !== "") {
7261
+ entryPairs = parseOverride("AGENT_SHIM_ENTRY_OVERRIDE", params.env.AGENT_SHIM_ENTRY_OVERRIDE, parseBoolPairList);
7262
+ }
7263
+ for (const entryPath of params.shareFlags) {
7264
+ entryPairs[entryPath] = true;
7265
+ }
7266
+ for (const entryPath of params.hideFlags) {
7267
+ entryPairs[entryPath] = false;
7268
+ }
7269
+ const hasCategories = Object.keys(categoryPairs).length > 0;
7270
+ const hasEntries = Object.keys(entryPairs).length > 0;
7271
+ const hasProvider = params.providerFlag !== void 0 && params.providerFlag !== "";
7272
+ if (!hasCategories && !hasEntries && !hasProvider) {
7273
+ return void 0;
7274
+ }
7275
+ return {
7276
+ ...hasCategories ? { categories: toCategoryMap(categoryPairs) } : {},
7277
+ ...hasEntries ? { entries: toEntries(entryPairs) } : {},
7278
+ ...hasProvider ? { launch: { provider: params.providerFlag } } : {}
7279
+ };
7280
+ }
7281
+
7282
+ // src/launcher/flags.ts
7283
+ import path24 from "node:path";
7284
+
7285
+ // src/headroom/headers.ts
7286
+ function mergeAnthropicCustomHeaders(existing, additions) {
7287
+ const merged = /* @__PURE__ */ new Map();
7288
+ for (const block of existing) {
7289
+ if (block === void 0) {
7290
+ continue;
7291
+ }
7292
+ for (const line of block.split("\n")) {
7293
+ const entry = parseCustomHeaderLine(line);
7294
+ if (entry === void 0) {
7295
+ continue;
7296
+ }
7297
+ merged.set(entry.name, entry.value);
7298
+ }
7299
+ }
7300
+ for (const entry of additions) {
7301
+ merged.set(entry.name, entry.value);
7302
+ }
7303
+ return [...merged].map(([name, value]) => `${name}: ${value}`).join("\n");
7304
+ }
7305
+ function parseCustomHeaderLine(line) {
7306
+ const trimmed = line.trim();
7307
+ if (trimmed === "") {
7308
+ return void 0;
7309
+ }
7310
+ const colon = trimmed.indexOf(":");
7311
+ if (colon <= 0) {
7312
+ return void 0;
7313
+ }
7314
+ return { name: trimmed.slice(0, colon).trim(), value: trimmed.slice(colon + 1).trim() };
7315
+ }
7316
+
7317
+ // src/launcher/flags.ts
7318
+ function resolveLaunchFlags(params) {
7319
+ return {
7320
+ skipPermissions: params.flags?.skipPermissions ?? parseEnvBool("AGENT_SHIM_SKIP_PERMISSIONS", params.env.AGENT_SHIM_SKIP_PERMISSIONS) ?? params.cascade?.skipPermissions ?? false,
7321
+ remoteControl: params.flags?.remoteControl ?? parseEnvBool("AGENT_SHIM_REMOTE_CONTROL", params.env.AGENT_SHIM_REMOTE_CONTROL) ?? params.cascade?.remoteControl ?? false,
7322
+ headroom: params.flags?.headroom ?? parseEnvBool("AGENT_SHIM_HEADROOM", params.env.AGENT_SHIM_HEADROOM) ?? params.cascade?.headroom ?? false,
7323
+ trackUsage: params.flags?.trackUsage ?? parseEnvBool("AGENT_SHIM_TRACK_USAGE", params.env.AGENT_SHIM_TRACK_USAGE) ?? params.cascade?.trackUsage ?? params.trackUsageDefault ?? false
7324
+ };
7325
+ }
7326
+ function buildFlagArgs(flags) {
7327
+ const args = [];
7328
+ if (flags.skipPermissions) {
7329
+ args.push("--dangerously-skip-permissions");
7330
+ }
7331
+ if (flags.remoteControl) {
7332
+ args.push("--remote-control=");
7333
+ }
7334
+ return args;
7335
+ }
7336
+ function buildArgv(params) {
7337
+ return [...params.toolFlags, ...params.extraFlags, ...params.passthrough];
7338
+ }
7339
+ var LOOPBACK_HOSTS = ["127.0.0.1", "localhost", "::1"];
7340
+ function isLoopbackUrl(baseUrl) {
7341
+ const host = new URL(baseUrl).hostname.replace(/^\[|\]$/g, "");
7342
+ return LOOPBACK_HOSTS.some((loopback) => loopback === host);
7343
+ }
7344
+ function withLoopbackHosts(existing) {
7345
+ const listed = (existing ?? "").split(",").map((entry) => entry.trim()).filter((entry) => entry !== "");
7346
+ return [...listed, ...LOOPBACK_HOSTS.filter((host) => !listed.includes(host))].join(",");
7347
+ }
7348
+ function buildEnv(params) {
7349
+ const env = { ...params.baseEnv };
7350
+ const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
7351
+ let providerCustomHeaders;
7352
+ if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
7353
+ env.CLAUDE_CONFIG_DIR = path24.join(params.identitiesDir, params.resolvedIdentityName);
7354
+ }
7355
+ if (params.provider !== void 0) {
7356
+ const providerEnv = params.provider.definition.env ?? {};
7357
+ providerCustomHeaders = providerEnv.ANTHROPIC_CUSTOM_HEADERS;
7358
+ env.ANTHROPIC_BASE_URL = params.provider.baseUrl;
7359
+ if (isLoopbackUrl(params.provider.baseUrl)) {
7360
+ env.NO_PROXY = withLoopbackHosts(params.baseEnv.NO_PROXY);
7361
+ env.no_proxy = withLoopbackHosts(params.baseEnv.no_proxy);
7362
+ }
7363
+ env.AGENT_SHIM_PROVIDER = params.provider.definition.displayName;
7364
+ for (const [key, value] of Object.entries(providerEnv)) {
7365
+ env[key] = value;
7366
+ }
7367
+ }
7368
+ const credential = params.provider?.credential ?? params.identityCredential;
7369
+ if (credential !== void 0) {
7370
+ for (const [variable, value] of Object.entries(credentialVariables(credential.target, credential.token))) {
7371
+ env[variable] = value;
7372
+ }
7373
+ }
7374
+ if (params.headroom !== void 0) {
7375
+ env.HEADROOM_PROXY_URL = `http://127.0.0.1:${String(params.headroom.port)}`;
7376
+ }
7377
+ if (params.frontdoor !== void 0) {
7378
+ env.ANTHROPIC_CUSTOM_HEADERS = mergeAnthropicCustomHeaders(
7379
+ [
7380
+ ...parentCustomHeaders === void 0 ? [] : [parentCustomHeaders],
7381
+ ...providerCustomHeaders === void 0 ? [] : [providerCustomHeaders]
7382
+ ],
7383
+ [
7384
+ ...params.resolvedIdentityName === void 0 ? [] : [{ name: IDENTITY_HEADER, value: params.resolvedIdentityName }],
7385
+ { name: SESSION_HEADER, value: params.sessionId },
7386
+ { name: AUTH_HEADER, value: params.frontdoor.sessionToken },
7387
+ ...params.headroom === void 0 ? [] : [
7388
+ { name: HEADROOM_FLAG_HEADER, value: "1" },
7389
+ { name: PROJECT_ID_HEADER, value: params.headroom.projectId }
7390
+ ]
7391
+ ]
7392
+ );
7393
+ env.NODE_EXTRA_CA_CERTS = params.frontdoor.trustBundlePath;
7394
+ if (params.provider === void 0) {
7395
+ env.HTTPS_PROXY = connectProxyUrl(params.frontdoor.connectPort, params.frontdoor.sessionToken);
7396
+ }
7397
+ }
7398
+ return env;
7399
+ }
7400
+
7401
+ // src/launcher/extraFlags.ts
7402
+ function splitExtraFlags(value) {
7403
+ if (value === void 0) {
7404
+ return [];
7405
+ }
7406
+ const trimmed = value.trim();
7407
+ if (trimmed === "") {
7408
+ return [];
7409
+ }
7410
+ return trimmed.split(/\s+/);
7411
+ }
7412
+
7413
+ // src/launcher.ts
7414
+ function resolveIdentityCredential(identity, credential, env, port) {
7415
+ if (port === void 0) {
7416
+ return { ok: false, status: 1, message: `agent-shim: identity ${identity} needs its credential resolved, but this launcher has no credential port wired` };
7417
+ }
7418
+ const resolution = resolveCredential({ credential, env, port, subject: `identity ${identity}` });
7419
+ return resolution.ok ? resolution : { ok: false, status: CREDENTIAL_UNAVAILABLE_EXIT, message: resolution.message };
7420
+ }
7421
+ function pickFromPool(decided, params, parsedArgv) {
7422
+ const { paths, fs: fs12, proc, log } = params;
7423
+ if (decided.pool === void 0) {
7424
+ return { identityDecision: decided };
7425
+ }
7426
+ const farmRuntime = params.farm;
7427
+ if (farmRuntime === void 0) {
7428
+ log.error(`agent-shim: pool "${decided.pool}" was selected, but this launcher has no farm wired to read usage and pick a member with.`);
7429
+ return proc.exit(1);
7430
+ }
7431
+ const resolution = resolvePoolLaunch({
7432
+ poolName: decided.pool,
7433
+ selectedVia: decided.source,
7434
+ pools: params.pools,
7435
+ paths,
7436
+ fs: fs12,
7437
+ usageFs: farmRuntime.fs,
7438
+ cwd: farmRuntime.cwd,
7439
+ now: farmRuntime.now,
7440
+ sleep: farmRuntime.lock.sleep,
7441
+ passthrough: parsedArgv.rest,
7442
+ wait: parsedArgv.wait === true,
7443
+ log
7444
+ });
7445
+ if (!resolution.ok) {
7446
+ log.error(resolution.message);
7447
+ return proc.exit(1);
7448
+ }
7449
+ return { identityDecision: { ...decided, name: resolution.identity }, poolExplanation: resolution.explanation };
7450
+ }
7451
+ function prepareLaunch(params) {
7452
+ const { paths, fs: fs12, proc, log } = params;
7453
+ const { env, argv } = proc;
7454
+ const parsedArgv = parseLauncherArgv(argv);
7455
+ const cliOverride = buildCliOverride({
7456
+ env,
7457
+ categoryFlags: parsedArgv.categoryFlags,
7458
+ shareFlags: parsedArgv.shareFlags,
7459
+ hideFlags: parsedArgv.hideFlags
7460
+ });
7461
+ const configDirEscapeHatchApplies = env.CLAUDE_CONFIG_DIR !== void 0 && env.CLAUDE_CONFIG_DIR !== "";
7462
+ const decidedIdentity = decideIdentity({
7463
+ env,
7464
+ argv0Identity: parsedArgv.identity,
7465
+ directoryPinnedIdentity: params.directoryPinnedIdentity,
7466
+ readActiveIdentityFile: () => {
7467
+ const raw = fs12.readFileUtf8(paths.activeIdentityFile);
7468
+ if (raw === void 0) {
7469
+ return void 0;
7470
+ }
7471
+ const trimmed = raw.trim();
7472
+ return trimmed === "" ? void 0 : trimmed;
7473
+ }
7474
+ });
7475
+ const { identityDecision, poolExplanation } = pickFromPool(decidedIdentity, params, parsedArgv);
7476
+ const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
7477
+ const farm = farmIdentity === void 0 ? void 0 : params.farm;
7478
+ if (farm !== void 0 && farmIdentity !== void 0) {
7479
+ let recovery;
7480
+ try {
7481
+ recovery = recoverFarm({
7482
+ fs: farm.fs,
7483
+ identitiesDir: paths.identitiesDir,
7484
+ identity: farmIdentity,
7485
+ now: farm.now,
7486
+ lock: farm.lock,
7487
+ classification: farm.classification
7488
+ });
7489
+ } catch (error) {
7490
+ if (error instanceof IdentityLockBusyError) {
7491
+ log.error(error.message);
7492
+ proc.exit(1);
7493
+ }
7494
+ throw error;
7495
+ }
7496
+ for (const diagnostic of recoveryDiagnostics(recovery, farmIdentity)) {
7497
+ log.warn(`agent-shim: ${diagnostic.code}: ${diagnostic.message}`);
7498
+ }
7499
+ }
7500
+ let loadedIdentity;
7501
+ if (identityDecision.name !== void 0) {
7502
+ loadedIdentity = loadIdentity(paths.identitiesDir, identityDecision.name, fs12);
7503
+ if (loadedIdentity === void 0) {
7504
+ log.error(
7505
+ `agent-shim: no identity named "${identityDecision.name}" (selected via ${identityDecision.source}). Run \`agent-shim identity add ${identityDecision.name}\` first.`
7506
+ );
7507
+ proc.exit(1);
7508
+ }
7509
+ }
7510
+ const configProfileDecision = decideConfigProfile({
7511
+ env,
7512
+ cliFlagConfigProfile: params.cliFlagConfigProfile ?? parsedArgv.configProfile,
7513
+ directoryRuleConfigProfile: params.directoryRuleConfigProfile,
7514
+ identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
7515
+ globalDefaultConfigProfile: params.globalDefaultConfigProfile
7516
+ });
7517
+ if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path25.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
7518
+ log.error(
7519
+ `agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
7520
+ );
7521
+ proc.exit(1);
7522
+ }
7523
+ const farmContext = farm !== void 0 && farmIdentity !== void 0 ? { farm, identity: farmIdentity, cascade: farm.loadCascade(configProfileDecision.name, cliOverride) } : void 0;
7524
+ const provider = parsedArgv.provider === false ? void 0 : resolveProvider({
7525
+ paths,
7526
+ port: fs12,
7527
+ env,
7528
+ ...params.credentials === void 0 ? {} : { credentials: params.credentials },
7529
+ ...parsedArgv.provider === void 0 ? {} : { cliProvider: parsedArgv.provider },
7530
+ ...farmContext === void 0 ? {} : { cascade: farmContext.cascade }
7531
+ });
7532
+ if (provider !== void 0 && !provider.ok) {
7533
+ log.error(provider.message);
7534
+ proc.exit(provider.status);
7535
+ }
7536
+ const resolvedProvider = provider?.ok === true ? provider.provider : void 0;
7537
+ for (const warning of provider?.ok === true ? provider.warnings : []) {
7538
+ log.warn(warning);
7539
+ }
7540
+ if (farm !== void 0 && farmIdentity !== void 0) {
7541
+ try {
7542
+ const snapshot = readUsageSnapshot(farm.fs, paths.usageSnapshotsDir, farmIdentity);
7543
+ for (const warning of quotaWarnings(snapshot, resolvedProvider?.name ?? ANTHROPIC_PROVIDER, farm.now())) {
7544
+ log.warn(warning);
7545
+ }
7546
+ } catch (error) {
7547
+ if (!(error instanceof UsageSnapshotError)) {
7548
+ throw error;
7549
+ }
7550
+ log.warn(`agent-shim: ${error.message}`);
7551
+ }
7552
+ }
7553
+ const identityCredentialBlock = loadedIdentity?.config.credential;
7554
+ const identityResolution = resolvedProvider === void 0 && farmIdentity !== void 0 && identityCredentialBlock !== void 0 ? resolveIdentityCredential(farmIdentity, identityCredentialBlock, env, params.credentials) : void 0;
7555
+ if (identityResolution !== void 0 && !identityResolution.ok) {
7556
+ log.error(identityResolution.message);
7557
+ proc.exit(identityResolution.status);
7558
+ }
7559
+ const identityCredential = identityResolution?.ok === true ? identityResolution.credential : void 0;
7560
+ for (const warning of identityCredential?.warnings ?? []) {
7561
+ log.warn(warning);
7562
+ }
7563
+ const guardResult = evaluateAmbientCredentialGuard({
7564
+ env,
7565
+ allowAmbientCredential: loadedIdentity?.config.allowAmbientCredential ?? false,
7566
+ allowAmbientCredentialOverride: parseEnvBool("AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL", env.AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL) === true,
7567
+ identityName: identityDecision.name,
7568
+ providerSelected: resolvedProvider !== void 0,
7569
+ ...identityCredential === void 0 ? {} : { injectedCredential: { variable: CREDENTIAL_TARGET_VARS[identityCredential.target], token: identityCredential.token } }
7570
+ });
7571
+ if (!guardResult.ok) {
7572
+ log.error(guardResult.message);
7573
+ proc.exit(1);
7574
+ }
7575
+ log.info(
7576
+ `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)}`)
7577
+ );
7578
+ let cascadeLaunch;
7579
+ if (farmContext !== void 0) {
7580
+ const { farm: resyncFarmRuntime, identity: resyncIdentity, cascade } = farmContext;
7581
+ let result;
7582
+ try {
7583
+ result = resyncFarm({
7584
+ fs: resyncFarmRuntime.fs,
7585
+ identitiesDir: paths.identitiesDir,
7586
+ identity: resyncIdentity,
7587
+ ...configProfileDecision.name === void 0 ? {} : { configProfile: configProfileDecision.name },
7588
+ claudeHome: resyncFarmRuntime.claudeHome,
7589
+ home: resyncFarmRuntime.home,
7590
+ cwd: resyncFarmRuntime.cwd,
7591
+ env,
7592
+ ...resyncFarmRuntime.branch === void 0 ? {} : { branch: resyncFarmRuntime.branch },
7593
+ ...resyncFarmRuntime.branchDetached === void 0 ? {} : { branchDetached: resyncFarmRuntime.branchDetached },
7594
+ cascade,
7595
+ classification: resyncFarmRuntime.classification,
7596
+ now: resyncFarmRuntime.now,
7597
+ uniqueSuffix: resyncFarmRuntime.uniqueSuffix,
7598
+ lock: resyncFarmRuntime.lock
7599
+ });
7600
+ } catch (error) {
7601
+ if (error instanceof IdentityLockBusyError) {
7602
+ log.error(error.message);
7603
+ proc.exit(1);
7604
+ }
7605
+ throw error;
7606
+ }
7607
+ for (const diagnostic of result.diagnostics) {
7608
+ if (diagnostic.severity === "error") {
7609
+ log.error(`agent-shim: ${diagnostic.code}: ${diagnostic.message}`);
7610
+ } else if (diagnostic.severity === "warning") {
7611
+ log.warn(`agent-shim: ${diagnostic.code}: ${diagnostic.message}`);
7612
+ }
7613
+ }
7614
+ log.info(
7615
+ 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}`})`
7616
+ );
7617
+ cascadeLaunch = result.resolved.flattened.launch;
7618
+ } else if (params.farm !== void 0) {
7619
+ cascadeLaunch = flattenLayers(assembleCascade(params.farm.loadCascade(configProfileDecision.name, cliOverride)).layers, { home: params.farm.home }).launch;
7620
+ }
7621
+ const discovered = params.resolveClaudeBinary();
7622
+ const resolvedFlags = resolveLaunchFlags({
7623
+ env,
7624
+ // A pool pick reads the usage the front door records, so a pool launch records its own unless something says otherwise.
7625
+ ...poolExplanation === void 0 ? {} : { trackUsageDefault: true },
7626
+ ...cascadeLaunch === void 0 ? {} : { cascade: cascadeLaunch },
7627
+ flags: {
7628
+ ...parsedArgv.skipPermissions === void 0 ? {} : { skipPermissions: parsedArgv.skipPermissions },
7629
+ ...parsedArgv.remoteControl === void 0 ? {} : { remoteControl: parsedArgv.remoteControl },
7630
+ ...parsedArgv.headroom === void 0 ? {} : { headroom: parsedArgv.headroom },
7631
+ ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage }
7632
+ }
7633
+ });
7634
+ const frontDoorPort = params.frontdoor;
7635
+ const frontDoorEngaged = resolvedProvider !== void 0 || resolvedFlags.headroom || resolvedFlags.trackUsage;
7636
+ if (frontDoorEngaged && frontDoorPort === void 0) {
7637
+ 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.");
7638
+ proc.exit(1);
7639
+ }
7640
+ const frontDoor = frontDoorEngaged && frontDoorPort !== void 0 ? frontDoorPort.ensure(env.NODE_EXTRA_CA_CERTS) : void 0;
7641
+ if (frontDoor?.trustWarning !== void 0) {
7642
+ log.warn(frontDoor.trustWarning);
7643
+ }
7644
+ let routedProvider;
7645
+ if (resolvedProvider !== void 0 && frontDoor !== void 0) {
7646
+ routedProvider = { ...resolvedProvider, baseUrl: providerBaseUrl(frontDoor.port, resolvedProvider.name) };
7647
+ }
7648
+ let headroom;
7649
+ const headroomPort = params.headroom;
7650
+ if (resolvedFlags.headroom && headroomPort !== void 0) {
7651
+ headroom = headroomPort.ensure();
7652
+ const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
7653
+ log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor?.port ?? 0)} with headroom on 127.0.0.1:${String(headroom.port)} (${via}, project ${headroom.projectId})`);
7654
+ } else if (resolvedFlags.headroom) {
7655
+ log.error("agent-shim: headroom routing was requested but this launcher has no headroom port wired; refusing to launch without it.");
7656
+ proc.exit(1);
7657
+ } else if (frontDoor !== void 0) {
7658
+ 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})`}`);
7659
+ }
7660
+ const frontDoorRelease = frontDoor === void 0 ? void 0 : frontDoorPort?.release;
7661
+ const finalArgv = buildArgv({
7662
+ toolFlags: buildFlagArgs(resolvedFlags),
7663
+ extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
7664
+ passthrough: parsedArgv.rest
7665
+ });
7666
+ const finalEnv = buildEnv({
7667
+ baseEnv: env,
7668
+ configDirEscapeHatch: configDirEscapeHatchApplies,
7669
+ resolvedIdentityName: identityDecision.name,
7670
+ identitiesDir: paths.identitiesDir,
7671
+ ...routedProvider === void 0 ? {} : { provider: routedProvider },
7672
+ ...identityCredential === void 0 ? {} : { identityCredential },
7673
+ ...frontDoor === void 0 ? {} : { frontdoor: frontDoor },
7674
+ ...headroom === void 0 ? {} : { headroom },
7675
+ sessionId: randomUUID4()
7676
+ });
7677
+ const releases = [...headroom === void 0 || headroomPort === void 0 ? [] : [headroomPort.release], ...frontDoorRelease === void 0 ? [] : [frontDoorRelease]];
7678
+ const release = () => {
7679
+ for (const registered of releases) {
7680
+ registered();
7681
+ }
7682
+ };
7683
+ return { bin: discovered.path, args: finalArgv, env: finalEnv, release };
7684
+ }
7685
+
7686
+ // src/launchWiring.ts
7687
+ import os5 from "node:os";
7688
+ import { randomUUID as randomUUID5 } from "node:crypto";
7689
+
7690
+ // src/realCredentialCache.ts
7691
+ import { spawnSync as spawnSync2 } from "node:child_process";
7692
+ import fs10 from "node:fs";
7693
+ import path26 from "node:path";
7694
+ var KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
7695
+ var CACHE_DIR_MODE = 448;
7696
+ var CACHE_FILE_MODE = 384;
7697
+ function cacheFileNameFor(owner) {
7698
+ return `${owner.replace(/[^A-Za-z0-9._-]/g, "_")}.json`;
7699
+ }
7700
+ function parseEntry(raw) {
7701
+ let json;
7702
+ try {
7703
+ json = JSON.parse(raw);
7704
+ } catch {
7705
+ return void 0;
7706
+ }
7707
+ const parsed = CachedCredentialSchema.safeParse(json);
7708
+ return parsed.success ? parsed.data : void 0;
7709
+ }
7710
+ function requireKeychain() {
7711
+ if (process.platform !== "darwin") {
7712
+ throw new Error("the keychain credential store needs macOS; use --credential-cache-store file");
7713
+ }
7714
+ }
7715
+ function security(args, stdin) {
7716
+ const result = spawnSync2("security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
7717
+ return { status: result.status, stdout: result.stdout };
7718
+ }
7719
+ function createRealCredentialCache(root) {
7720
+ const dir = path26.join(root, "credential-cache");
7721
+ const filePath = (owner) => path26.join(dir, cacheFileNameFor(owner));
7722
+ return {
7723
+ read(store, owner) {
7724
+ if (store === "file") {
7725
+ try {
7726
+ return parseEntry(fs10.readFileSync(filePath(owner), "utf8"));
7727
+ } catch {
7728
+ return void 0;
7729
+ }
7730
+ }
7731
+ requireKeychain();
7732
+ const result = security(["find-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner, "-w"]);
7733
+ return result.status === 0 ? parseEntry(Buffer.from(result.stdout.trim(), "base64").toString("utf8")) : void 0;
7734
+ },
7735
+ write(store, owner, entry) {
7736
+ const serialised = JSON.stringify(entry);
7737
+ if (store === "file") {
7738
+ fs10.mkdirSync(dir, { recursive: true, mode: CACHE_DIR_MODE });
7739
+ fs10.chmodSync(dir, CACHE_DIR_MODE);
7740
+ const target = filePath(owner);
7741
+ const temp = `${target}.${String(process.pid)}.tmp`;
7742
+ fs10.writeFileSync(temp, serialised, { mode: CACHE_FILE_MODE });
7743
+ fs10.renameSync(temp, target);
7744
+ return;
7745
+ }
7746
+ requireKeychain();
7747
+ const encoded = Buffer.from(serialised, "utf8").toString("base64");
7748
+ const result = security(["-i"], `add-generic-password -U -s ${KEYCHAIN_CACHE_SERVICE} -a ${JSON.stringify(owner)} -w ${encoded}
7749
+ `);
7750
+ if (result.status !== 0) {
7751
+ throw new Error(`could not write the keychain credential cache for ${owner}`);
7752
+ }
7753
+ },
7754
+ remove(store, owner) {
7755
+ if (store === "file") {
7756
+ fs10.rmSync(filePath(owner), { force: true });
7757
+ return;
7758
+ }
7759
+ requireKeychain();
7760
+ security(["delete-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner]);
7761
+ }
7762
+ };
7763
+ }
7764
+ function realCredentialCacheEnv(paths) {
7765
+ return { port: createRealCredentialCache(paths.root), platform: process.platform, now: () => Date.now() };
7766
+ }
7767
+
7768
+ // src/frontdoor/realFrontDoorPort.ts
7769
+ import fs11 from "node:fs";
7770
+
7771
+ // src/frontdoor/probe.ts
7772
+ import { Worker } from "node:worker_threads";
7773
+ var PROBE_TIMEOUT_MS = 2e3;
7774
+ var PROBE_WAIT_MARGIN_MS = 1e3;
7775
+ var REASON_BYTES = 1024;
7776
+ var HEADER_SLOTS = 2;
7777
+ var INT32_BYTES = 4;
7778
+ var VERDICT_PENDING = 0;
7779
+ var VERDICT_OK = 1;
7780
+ var VERDICT_FAILED = 2;
7781
+ var PROBE_SOURCE = `
7782
+ const { workerData } = require("node:worker_threads");
7783
+ const https = require("node:https");
7784
+ const { port, ca, timeoutMs, shared, ok, failed, headerSlots } = workerData;
7785
+ const header = new Int32Array(shared, 0, headerSlots);
7786
+ const reason = new Uint8Array(shared, headerSlots * 4);
7787
+ let done = false;
7788
+ const finish = (verdict, message) => {
7789
+ if (done) return;
7790
+ done = true;
7791
+ const bytes = Buffer.from(String(message), "utf8").subarray(0, reason.length);
7792
+ reason.set(bytes);
7793
+ Atomics.store(header, 1, bytes.length);
7794
+ Atomics.store(header, 0, verdict);
7795
+ Atomics.notify(header, 0);
7796
+ };
7797
+ const request = https.get({ host: "127.0.0.1", port, path: "/healthz", ca: [ca], agent: false }, (response) => {
7798
+ let body = "";
7799
+ response.setEncoding("utf8");
7800
+ response.on("data", (chunk) => { body += chunk; });
7801
+ response.on("end", () => {
7802
+ if (response.statusCode === 200 && body === "ok") finish(ok, "");
7803
+ else finish(failed, "the listener answered its health probe with HTTP " + String(response.statusCode));
7804
+ });
7805
+ response.on("error", (error) => finish(failed, error.message));
7806
+ });
7807
+ // A hard deadline over the whole exchange, handshake included: a listener that accepts the connection and then says nothing must still fail the probe.
7808
+ setTimeout(() => { request.destroy(new Error("no answer within " + String(timeoutMs) + "ms")); }, timeoutMs);
7809
+ request.on("error", (error) => finish(failed, (error.code ? error.code + ": " : "") + error.message));
7810
+ `;
7811
+ function probeFrontDoorSync(port, caPem) {
7812
+ const shared = new SharedArrayBuffer(HEADER_SLOTS * INT32_BYTES + REASON_BYTES);
7813
+ const header = new Int32Array(shared, 0, HEADER_SLOTS);
7814
+ const worker = new Worker(PROBE_SOURCE, {
7815
+ eval: true,
7816
+ workerData: { port, ca: caPem, timeoutMs: PROBE_TIMEOUT_MS, shared, ok: VERDICT_OK, failed: VERDICT_FAILED, headerSlots: HEADER_SLOTS }
7817
+ });
7818
+ worker.unref();
7819
+ try {
7820
+ const waited = Atomics.wait(header, 0, VERDICT_PENDING, PROBE_TIMEOUT_MS + PROBE_WAIT_MARGIN_MS);
7821
+ const verdict = Atomics.load(header, 0);
7822
+ if (waited === "timed-out" || verdict === VERDICT_PENDING) {
7823
+ return { ok: false, reason: `the probe did not finish within ${String(PROBE_TIMEOUT_MS + PROBE_WAIT_MARGIN_MS)}ms` };
7824
+ }
7825
+ if (verdict === VERDICT_OK) {
7826
+ return { ok: true };
7827
+ }
7828
+ const length = Atomics.load(header, 1);
7829
+ return { ok: false, reason: Buffer.from(new Uint8Array(shared, HEADER_SLOTS * INT32_BYTES, length)).toString("utf8") };
7830
+ } finally {
7831
+ void worker.terminate();
7832
+ }
7833
+ }
7834
+
7835
+ // src/frontdoor/trust.ts
7836
+ import { createHash as createHash5 } from "node:crypto";
7837
+ import path27 from "node:path";
7838
+ var BUNDLE_NAME_HEX_DIGITS = 16;
7839
+ function resolveTrustBundle(params) {
7840
+ const { caCertFile, bundlesDir, inherited, fs: fs12 } = params;
7841
+ if (inherited === void 0 || inherited === "" || path27.resolve(inherited) === path27.resolve(caCertFile)) {
7842
+ return { path: caCertFile };
7843
+ }
7844
+ const caPem = fs12.readFileUtf8(caCertFile);
7845
+ let inheritedPem;
7846
+ try {
7847
+ inheritedPem = fs12.readFileUtf8(inherited);
7848
+ } catch (error) {
7849
+ return {
7850
+ path: caCertFile,
7851
+ 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`
7852
+ };
7853
+ }
7854
+ if (inheritedPem.includes(caPem.trim())) {
7855
+ return { path: inherited };
7856
+ }
7857
+ const combined = `${inheritedPem.trimEnd()}
7858
+ ${caPem}`;
7859
+ const bundle = path27.join(bundlesDir, `${createHash5("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7860
+ if (!fs12.exists(bundle)) {
7861
+ fs12.mkdirp(bundlesDir);
7862
+ fs12.writeFileAtomic(bundle, combined);
7863
+ }
7864
+ return { path: bundle };
7865
+ }
7866
+
7867
+ // src/frontdoor/realFrontDoorPort.ts
7868
+ var realTrustBundleFs = {
7869
+ readFileUtf8: (file) => fs11.readFileSync(file, "utf8"),
7870
+ exists: (file) => fs11.existsSync(file),
7871
+ mkdirp: (dir) => {
7872
+ fs11.mkdirSync(dir, { recursive: true });
7873
+ },
7874
+ writeFileAtomic: (file, contents) => {
7875
+ realFarmFs.writeFilePrivate(file, contents);
7876
+ }
7877
+ };
7878
+ function realFrontDoorPort(paths, spawnDaemon) {
7879
+ return {
7880
+ ensure: (inheritedExtraCaCerts) => {
7881
+ const up = ensureFrontDoor({
7882
+ paths,
7883
+ launcherPid: process.pid,
7884
+ ports: {
7885
+ fs: realFarmFs,
7886
+ isRunning: realIsProcessRunning,
7887
+ now: () => Date.now(),
7888
+ sleep: realSleepSync,
7889
+ spawnSupervisor: (layout) => spawnDaemon(layout, "__frontdoor-supervisor", layout.frontdoorLogPath),
7890
+ stopSupervisor: (pid) => {
7891
+ process.kill(pid, "SIGTERM");
7892
+ },
7893
+ // 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.
7894
+ verifyListener: (port) => probeFrontDoorSync(port, fs11.readFileSync(paths.frontdoorCaCertFile, "utf8"))
7895
+ }
7896
+ });
7897
+ const trust = resolveTrustBundle({ caCertFile: paths.frontdoorCaCertFile, bundlesDir: paths.frontdoorCaBundlesDir, inherited: inheritedExtraCaCerts, fs: realTrustBundleFs });
7898
+ return {
7899
+ port: up.port,
7900
+ connectPort: up.connectPort,
7901
+ trustBundlePath: trust.path,
7902
+ ...trust.warning === void 0 ? {} : { trustWarning: trust.warning },
7903
+ sessionToken: up.token
7904
+ };
7905
+ },
7906
+ release: () => {
7907
+ removeFrontDoorSession(realFarmFs, paths.frontdoorSessionsDir, process.pid);
7908
+ }
7909
+ };
7910
+ }
7911
+
7912
+ // src/launchWiring.ts
7913
+ function buildFarmRuntime(paths, cwd) {
7914
+ const home = os5.homedir();
7915
+ const read = cosmiconfigReader();
7916
+ const classification = loadClassification(paths);
7917
+ const loaded = loadCascadeInput({ paths, home, cwd, read });
7918
+ const selections = readDirectorySelections(loaded);
7919
+ const git = resolveGitBranch(realRunPort, cwd);
7920
+ return {
7921
+ runtime: {
7922
+ fs: realFarmFs,
7923
+ claudeHome: resolveClaudeHome(),
7924
+ home,
7925
+ cwd,
7926
+ ...git.branch === void 0 ? {} : { branch: git.branch },
7927
+ ...git.branchDetached === void 0 ? {} : { branchDetached: git.branchDetached },
7928
+ classification,
7929
+ loadCascade: (baseConfigProfile, cliOverride) => loadCascadeInput({
7930
+ paths,
7931
+ home,
7932
+ cwd,
7933
+ read,
7934
+ ...baseConfigProfile === void 0 ? {} : { baseConfigProfile },
7935
+ ...cliOverride === void 0 ? {} : { cliOverride }
7936
+ }).input,
7937
+ now: () => Date.now(),
7938
+ uniqueSuffix: `${String(process.pid)}.${randomUUID5()}`,
7939
+ // 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.
7940
+ lock: { pid: process.pid, isRunning: realIsProcessRunning, sleep: realSleepSync }
7941
+ },
7942
+ ...selections.identity === void 0 ? {} : { directoryIdentity: selections.identity },
7943
+ ...selections.configProfile === void 0 ? {} : { directoryConfigProfile: selections.configProfile },
7944
+ ...loaded.globalConfig?.defaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: loaded.globalConfig.defaultConfigProfile },
7945
+ ...loaded.globalConfig?.pools === void 0 ? {} : { pools: loaded.globalConfig.pools }
7946
+ };
7947
+ }
7948
+ function realPrepareLaunchParams(paths, options) {
7949
+ const { farm } = options;
7950
+ return {
7951
+ paths,
7952
+ fs: realFsPort,
7953
+ proc: options.proc,
7954
+ log: options.log,
7955
+ resolveClaudeBinary: realResolveClaudeBinary(resolveOwnInstallDirs(paths, realOwnExecutablePath())),
7956
+ farm: farm.runtime,
7957
+ headroom: realHeadroomPort(paths, { spawnDaemon: options.spawnDaemon, cwd: farm.runtime.cwd }),
7958
+ frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
7959
+ credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
7960
+ ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
7961
+ ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
7962
+ ...farm.globalDefaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: farm.globalDefaultConfigProfile },
7963
+ ...farm.pools === void 0 ? {} : { pools: farm.pools },
7964
+ ...options.allowMissingConfigProfile === void 0 ? {} : { allowMissingConfigProfile: options.allowMissingConfigProfile }
7965
+ };
7966
+ }
7967
+ var LaunchRefusedError = class extends CliError {
7968
+ exitCode;
7969
+ constructor(message, exitCode) {
7970
+ super(message);
7971
+ this.name = "LaunchRefusedError";
7972
+ this.exitCode = exitCode;
7973
+ }
7974
+ };
7975
+ function prepareClaudeLaunch(options) {
7976
+ const paths = options.paths ?? resolveLayoutPaths();
7977
+ const refusals = [];
7978
+ const log = {
7979
+ info: () => void 0,
7980
+ warn: () => void 0,
7981
+ error: (message) => {
7982
+ refusals.push(message);
7983
+ }
7984
+ };
7985
+ const proc = {
7986
+ env: options.env,
7987
+ argv: options.argv,
7988
+ exit: (code) => {
7989
+ throw new LaunchRefusedError(refusals.join("\n") || `the launch was refused (exit ${String(code)})`, code);
7990
+ }
7991
+ };
7992
+ const spawnDaemon = options.agentShim === void 0 ? () => {
7993
+ 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);
7994
+ } : spawnDaemonThrough(options.agentShim);
7995
+ return prepareLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) }));
7996
+ }
6636
7997
  export {
6637
7998
  AMBIENT_CREDENTIAL_VARS,
6638
7999
  CONNECT_INTERCEPT_HOST,
@@ -6664,6 +8025,7 @@ export {
6664
8025
  InvalidCategoryNameError,
6665
8026
  InvalidIdentityNameError,
6666
8027
  InvalidProviderNameError,
8028
+ LaunchRefusedError,
6667
8029
  LegacyProviderFileError,
6668
8030
  PoolNameSchema,
6669
8031
  PoolNotFoundError,
@@ -6714,6 +8076,8 @@ export {
6714
8076
  listUsageSnapshots,
6715
8077
  mintLeaf,
6716
8078
  parseConnectTarget,
8079
+ prepareClaudeLaunch,
8080
+ prepareLaunch,
6717
8081
  profileExists,
6718
8082
  providerExists,
6719
8083
  readActiveIdentity,