claude-use 7.4.0 → 7.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -248,10 +248,18 @@ import { cosmiconfigSync } from "cosmiconfig";
248
248
 
249
249
  // src/cliError.ts
250
250
  var EXIT_FAILURE = 1;
251
+ var EXIT_USAGE = 2;
251
252
  var CliError = class extends Error {
252
253
  /** The process exit status this failure maps to. `EXIT_FAILURE` unless a subclass says otherwise. */
253
254
  exitCode = EXIT_FAILURE;
254
255
  };
256
+ var UsageError = class extends CliError {
257
+ exitCode = EXIT_USAGE;
258
+ constructor(message) {
259
+ super(message);
260
+ this.name = "UsageError";
261
+ }
262
+ };
255
263
 
256
264
  // src/config/classify.ts
257
265
  var GLOB_METACHARACTERS = /[*?[\]{}!()]/;
@@ -1212,6 +1220,8 @@ function planReconciliation(params) {
1212
1220
  }
1213
1221
 
1214
1222
  // src/legacy.ts
1223
+ var HOME_DIRNAME = ".agent-shim";
1224
+ var LEGACY_HOME_DIRNAME = ".claude-use";
1215
1225
  var LEGACY_FARM_MANIFEST_FILENAME = ".claude-use-farm.json";
1216
1226
 
1217
1227
  // src/launcher/lock.ts
@@ -1313,8 +1323,8 @@ var FarmManifestSchema = z2.strictObject({
1313
1323
  materialised: z2.array(z2.string()),
1314
1324
  links: z2.array(z2.strictObject({ rel: z2.string(), target: z2.string() }))
1315
1325
  });
1316
- function readFarmManifest(fs2, farmRoot) {
1317
- const raw = fs2.readFileUtf8(path4.join(farmRoot, FARM_MANIFEST_FILENAME)) ?? fs2.readFileUtf8(path4.join(farmRoot, LEGACY_FARM_MANIFEST_FILENAME));
1326
+ function readFarmManifest(fs3, farmRoot) {
1327
+ const raw = fs3.readFileUtf8(path4.join(farmRoot, FARM_MANIFEST_FILENAME)) ?? fs3.readFileUtf8(path4.join(farmRoot, LEGACY_FARM_MANIFEST_FILENAME));
1318
1328
  if (raw === void 0) {
1319
1329
  return void 0;
1320
1330
  }
@@ -1372,9 +1382,9 @@ function buildEntryFacts(params) {
1372
1382
  entries
1373
1383
  };
1374
1384
  }
1375
- function listSubtree(fs2, root, rel) {
1385
+ function listSubtree(fs3, root, rel) {
1376
1386
  const absolute = path4.join(root, rel);
1377
- const stat = fs2.lstat(absolute);
1387
+ const stat = fs3.lstat(absolute);
1378
1388
  if (stat === void 0) {
1379
1389
  return [];
1380
1390
  }
@@ -1382,10 +1392,10 @@ function listSubtree(fs2, root, rel) {
1382
1392
  return [{ rel, kind: "symlink" }];
1383
1393
  }
1384
1394
  if (stat.kind === "dir") {
1385
- const children = [...fs2.readdir(absolute)].sort().flatMap((name) => listSubtree(fs2, root, `${rel}/${name}`));
1395
+ const children = [...fs3.readdir(absolute)].sort().flatMap((name) => listSubtree(fs3, root, `${rel}/${name}`));
1386
1396
  return [{ rel, kind: "dir" }, ...children];
1387
1397
  }
1388
- const contentHash = fs2.hashFile(absolute);
1398
+ const contentHash = fs3.hashFile(absolute);
1389
1399
  return [{ rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } }];
1390
1400
  }
1391
1401
  function topLevelScopeRoots(roots) {
@@ -1399,25 +1409,25 @@ function topLevelScopeRoots(roots) {
1399
1409
  }
1400
1410
  return kept;
1401
1411
  }
1402
- function reconciliationScope(fs2, farmRoot, manifest) {
1412
+ function reconciliationScope(fs3, farmRoot, manifest) {
1403
1413
  if (manifest !== void 0) {
1404
1414
  return topLevelScopeRoots(manifest.materialised);
1405
1415
  }
1406
- return [...fs2.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && name !== LEGACY_FARM_MANIFEST_FILENAME && fs2.lstat(path4.join(farmRoot, name))?.kind === "dir").sort();
1416
+ return [...fs3.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && name !== LEGACY_FARM_MANIFEST_FILENAME && fs3.lstat(path4.join(farmRoot, name))?.kind === "dir").sort();
1407
1417
  }
1408
- function collectFarmListing(fs2, farmRoot, scopeRoots) {
1409
- return scopeRoots.flatMap((root) => listSubtree(fs2, farmRoot, root));
1418
+ function collectFarmListing(fs3, farmRoot, scopeRoots) {
1419
+ return scopeRoots.flatMap((root) => listSubtree(fs3, farmRoot, root));
1410
1420
  }
1411
- function collectCanonicalCounterparts(fs2, claudeHome, farmListing) {
1421
+ function collectCanonicalCounterparts(fs3, claudeHome, farmListing) {
1412
1422
  const out = [];
1413
1423
  for (const entry of farmListing) {
1414
1424
  const absolute = path4.join(claudeHome, entry.rel);
1415
- const stat = fs2.lstat(absolute);
1425
+ const stat = fs3.lstat(absolute);
1416
1426
  if (stat === void 0) {
1417
1427
  continue;
1418
1428
  }
1419
1429
  if (stat.kind === "file") {
1420
- const contentHash = fs2.hashFile(absolute);
1430
+ const contentHash = fs3.hashFile(absolute);
1421
1431
  out.push({ rel: entry.rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } });
1422
1432
  continue;
1423
1433
  }
@@ -1777,10 +1787,6 @@ function recoveryDiagnostics(recovery, identity) {
1777
1787
  // src/frontdoor/connect.ts
1778
1788
  import { X509Certificate as X509Certificate2, createPrivateKey as createPrivateKey2 } from "node:crypto";
1779
1789
  import * as fs from "node:fs";
1780
- import * as http from "node:http";
1781
- import * as https from "node:https";
1782
- import * as net2 from "node:net";
1783
- import * as tls from "node:tls";
1784
1790
 
1785
1791
  // src/frontdoor/x509.ts
1786
1792
  import { createHash, createPrivateKey, generateKeyPairSync, randomBytes, sign, X509Certificate } from "node:crypto";
@@ -2053,6 +2059,54 @@ function issueLeafCertificate(ca, names, notBefore, notAfter) {
2053
2059
  return { certPem: toPem("CERTIFICATE", der), keyPem: keyPem(privateKey) };
2054
2060
  }
2055
2061
 
2062
+ // src/frontdoor/tap.ts
2063
+ function pumpTapSession(secure, openUpstream, tap) {
2064
+ let upstream;
2065
+ let ended = false;
2066
+ const end = () => {
2067
+ if (!ended) {
2068
+ ended = true;
2069
+ tap?.onEnd();
2070
+ }
2071
+ };
2072
+ const drop = () => {
2073
+ end();
2074
+ secure.destroy();
2075
+ upstream?.destroy();
2076
+ };
2077
+ secure.once("close", () => {
2078
+ end();
2079
+ upstream?.destroy();
2080
+ });
2081
+ secure.once("error", drop);
2082
+ const clientAlpn = "alpnProtocol" in secure && typeof secure.alpnProtocol === "string" ? secure.alpnProtocol : void 0;
2083
+ void (async () => {
2084
+ try {
2085
+ upstream = await openUpstream(clientAlpn);
2086
+ } catch {
2087
+ drop();
2088
+ return;
2089
+ }
2090
+ if (secure.destroyed) {
2091
+ end();
2092
+ upstream.destroy();
2093
+ return;
2094
+ }
2095
+ if (tap !== void 0) {
2096
+ secure.on("data", (chunk) => {
2097
+ tap.onChunk("client-to-server", chunk);
2098
+ });
2099
+ upstream.on("data", (chunk) => {
2100
+ tap.onChunk("server-to-client", chunk);
2101
+ });
2102
+ }
2103
+ secure.pipe(upstream);
2104
+ upstream.pipe(secure);
2105
+ upstream.once("close", drop);
2106
+ upstream.once("error", drop);
2107
+ })();
2108
+ }
2109
+
2056
2110
  // src/frontdoor/capability.ts
2057
2111
  var CONNECT_PROXY_REALM = "agent-shim front door";
2058
2112
  var BASIC_SCHEME = "basic";
@@ -2101,10 +2155,10 @@ var FrontDoorStateSchema = z3.strictObject({
2101
2155
  /** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
2102
2156
  lastError: z3.string().optional()
2103
2157
  });
2104
- function readFrontDoorState(fs2, stateFile) {
2158
+ function readFrontDoorState(fs3, stateFile) {
2105
2159
  let raw;
2106
2160
  try {
2107
- raw = fs2.readFileUtf8(stateFile);
2161
+ raw = fs3.readFileUtf8(stateFile);
2108
2162
  } catch {
2109
2163
  return void 0;
2110
2164
  }
@@ -2118,28 +2172,28 @@ function readFrontDoorState(fs2, stateFile) {
2118
2172
  return void 0;
2119
2173
  }
2120
2174
  }
2121
- function writeFrontDoorState(fs2, stateFile, state) {
2122
- fs2.mkdirp(path5.dirname(stateFile));
2123
- fs2.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
2175
+ function writeFrontDoorState(fs3, stateFile, state) {
2176
+ fs3.mkdirp(path5.dirname(stateFile));
2177
+ fs3.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
2124
2178
  `);
2125
2179
  }
2126
2180
  function frontDoorOrigin(state) {
2127
2181
  const port = state?.directPort ?? state?.lastDirectPort;
2128
2182
  return port === void 0 ? void 0 : `http://127.0.0.1:${String(port)}`;
2129
2183
  }
2130
- function writeFrontDoorSession(fs2, sessionsDir, session) {
2131
- fs2.mkdirPrivate(sessionsDir);
2132
- fs2.writeFilePrivate(path5.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
2184
+ function writeFrontDoorSession(fs3, sessionsDir, session) {
2185
+ fs3.mkdirPrivate(sessionsDir);
2186
+ fs3.writeFilePrivate(path5.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
2133
2187
  `);
2134
2188
  }
2135
- function listFrontDoorSessions(fs2, sessionsDir) {
2189
+ function listFrontDoorSessions(fs3, sessionsDir) {
2136
2190
  const sessions = [];
2137
- for (const name of fs2.readdir(sessionsDir)) {
2191
+ for (const name of fs3.readdir(sessionsDir)) {
2138
2192
  if (!name.endsWith(".json")) {
2139
2193
  continue;
2140
2194
  }
2141
2195
  try {
2142
- const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs2.readFileUtf8(path5.join(sessionsDir, name)) ?? ""));
2196
+ const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs3.readFileUtf8(path5.join(sessionsDir, name)) ?? ""));
2143
2197
  if (parsed.success) {
2144
2198
  sessions.push({ pid: parsed.data.pid, startedAt: parsed.data.startedAt });
2145
2199
  }
@@ -2149,14 +2203,14 @@ function listFrontDoorSessions(fs2, sessionsDir) {
2149
2203
  }
2150
2204
  return sessions.sort((a, b) => a.pid - b.pid);
2151
2205
  }
2152
- function removeFrontDoorSession(fs2, sessionsDir, pid) {
2153
- fs2.removeRecursive(path5.join(sessionsDir, `${String(pid)}.json`));
2206
+ function removeFrontDoorSession(fs3, sessionsDir, pid) {
2207
+ fs3.removeRecursive(path5.join(sessionsDir, `${String(pid)}.json`));
2154
2208
  }
2155
- function pruneDeadFrontDoorSessions(fs2, sessionsDir, isRunning) {
2209
+ function pruneDeadFrontDoorSessions(fs3, sessionsDir, isRunning) {
2156
2210
  const removed = [];
2157
- for (const session of listFrontDoorSessions(fs2, sessionsDir)) {
2211
+ for (const session of listFrontDoorSessions(fs3, sessionsDir)) {
2158
2212
  if (!isRunning(session.pid)) {
2159
- removeFrontDoorSession(fs2, sessionsDir, session.pid);
2213
+ removeFrontDoorSession(fs3, sessionsDir, session.pid);
2160
2214
  removed.push(session.pid);
2161
2215
  }
2162
2216
  }
@@ -2168,8 +2222,8 @@ var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
2168
2222
  var FRONTDOOR_POLL_MS = 1e3;
2169
2223
  var MS_PER_MINUTE = 6e4;
2170
2224
  async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
2171
- const { fs: fs2, paths } = ports;
2172
- const previous = readFrontDoorState(fs2, paths.frontdoorStateFile);
2225
+ const { fs: fs3, paths } = ports;
2226
+ const previous = readFrontDoorState(fs3, paths.frontdoorStateFile);
2173
2227
  let lastPort = previous?.lastPort;
2174
2228
  let lastConnectPort = previous?.lastConnectPort;
2175
2229
  let lastDirectPort = previous?.lastDirectPort;
@@ -2179,12 +2233,12 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2179
2233
  ...lastDirectPort === void 0 ? {} : { lastDirectPort }
2180
2234
  });
2181
2235
  const fail = (message) => {
2182
- writeFrontDoorState(fs2, paths.frontdoorStateFile, { lastError: message, ...sticky() });
2183
- fs2.removeRecursive(paths.frontdoorLockFile);
2236
+ writeFrontDoorState(fs3, paths.frontdoorStateFile, { lastError: message, ...sticky() });
2237
+ fs3.removeRecursive(paths.frontdoorLockFile);
2184
2238
  ports.log(`agent-shim frontdoor supervisor: ${message}`);
2185
2239
  return 1;
2186
2240
  };
2187
- writeFrontDoorState(fs2, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
2241
+ writeFrontDoorState(fs3, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
2188
2242
  const previousSticky = lastPort;
2189
2243
  let http2;
2190
2244
  try {
@@ -2197,23 +2251,23 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2197
2251
  }
2198
2252
  lastPort = http2.port;
2199
2253
  const previousStickyConnect = lastConnectPort;
2200
- let connect2;
2254
+ let connect3;
2201
2255
  try {
2202
- connect2 = await ports.startConnectListener(lastConnectPort);
2256
+ connect3 = await ports.startConnectListener(lastConnectPort);
2203
2257
  } catch (error) {
2204
2258
  await http2.close();
2205
2259
  return fail(`could not start the CONNECT surface: ${error instanceof Error ? error.message : String(error)}`);
2206
2260
  }
2207
- if (previousStickyConnect !== void 0 && connect2.port !== previousStickyConnect) {
2208
- ports.log(`agent-shim frontdoor supervisor: sticky CONNECT port ${String(previousStickyConnect)} was occupied; moving to ${String(connect2.port)} (OAuth sessions launched against the old port are stale until they relaunch)`);
2261
+ if (previousStickyConnect !== void 0 && connect3.port !== previousStickyConnect) {
2262
+ ports.log(`agent-shim frontdoor supervisor: sticky CONNECT port ${String(previousStickyConnect)} was occupied; moving to ${String(connect3.port)} (OAuth sessions launched against the old port are stale until they relaunch)`);
2209
2263
  }
2210
- lastConnectPort = connect2.port;
2264
+ lastConnectPort = connect3.port;
2211
2265
  const previousStickyDirect = lastDirectPort;
2212
2266
  let direct;
2213
2267
  try {
2214
2268
  direct = await ports.startDirectListener(lastDirectPort);
2215
2269
  } catch (error) {
2216
- await connect2.close();
2270
+ await connect3.close();
2217
2271
  await http2.close();
2218
2272
  return fail(`could not start the direct listener: ${error instanceof Error ? error.message : String(error)}`);
2219
2273
  }
@@ -2221,9 +2275,9 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2221
2275
  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)`);
2222
2276
  }
2223
2277
  lastDirectPort = direct.port;
2224
- writeFrontDoorState(fs2, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, port: http2.port, connectPort: connect2.port, directPort: direct.port, ...sticky() });
2225
- fs2.removeRecursive(paths.frontdoorLockFile);
2226
- 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(connect2.port)}`);
2278
+ writeFrontDoorState(fs3, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, port: http2.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
2279
+ fs3.removeRecursive(paths.frontdoorLockFile);
2280
+ 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)}`);
2227
2281
  let idleSince;
2228
2282
  let ticks = 0;
2229
2283
  for (; ; ) {
@@ -2231,15 +2285,15 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
2231
2285
  return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
2232
2286
  }
2233
2287
  ticks += 1;
2234
- pruneDeadFrontDoorSessions(fs2, paths.frontdoorSessionsDir, ports.isRunning);
2235
- if (listFrontDoorSessions(fs2, paths.frontdoorSessionsDir).length === 0) {
2288
+ pruneDeadFrontDoorSessions(fs3, paths.frontdoorSessionsDir, ports.isRunning);
2289
+ if (listFrontDoorSessions(fs3, paths.frontdoorSessionsDir).length === 0) {
2236
2290
  idleSince ??= ports.now();
2237
2291
  if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
2238
2292
  ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
2239
2293
  await direct.close();
2240
- await connect2.close();
2294
+ await connect3.close();
2241
2295
  await http2.close();
2242
- writeFrontDoorState(fs2, paths.frontdoorStateFile, sticky());
2296
+ writeFrontDoorState(fs3, paths.frontdoorStateFile, sticky());
2243
2297
  return 0;
2244
2298
  }
2245
2299
  } else {
@@ -2294,8 +2348,8 @@ function parseConnectTarget(authority) {
2294
2348
  function isInterceptedHost(host, interceptHosts) {
2295
2349
  return interceptHosts.includes(host);
2296
2350
  }
2297
- function servedByPipeline(path8) {
2298
- return path8?.startsWith(ROUTED_PATH_PREFIX) === true;
2351
+ function servedByPipeline(path9) {
2352
+ return path9?.startsWith(ROUTED_PATH_PREFIX) === true;
2299
2353
  }
2300
2354
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
2301
2355
  "connection",
@@ -2361,9 +2415,20 @@ function caParses(ca) {
2361
2415
  return false;
2362
2416
  }
2363
2417
  }
2418
+ var TAP_ALPN_PROTOCOLS = ["h2", "http/1.1"];
2364
2419
  async function startConnectServer(config, effects, preferredPort) {
2365
2420
  const onUpgrade = config.capture === void 0 ? void 0 : (request3) => config.capture?.upgrade(request3);
2366
2421
  const sessions = config.interceptHosts.map((host) => {
2422
+ if (config.tapHosts.includes(host)) {
2423
+ const tlsAcceptor2 = effects.createTlsAcceptor(
2424
+ config.leafFor(host),
2425
+ (secure) => {
2426
+ pumpTapSession(secure, async (clientAlpn) => await effects.connectTlsUpstream(host, HTTPS_PORT, clientAlpn), config.capture?.tapStream?.(host));
2427
+ },
2428
+ TAP_ALPN_PROTOCOLS
2429
+ );
2430
+ return { host, tlsAcceptor: tlsAcceptor2 };
2431
+ }
2367
2432
  const handler = (request3, response) => {
2368
2433
  if (host === config.routedHost && servedByPipeline(request3.url)) {
2369
2434
  config.serveRouted(request3, response);
@@ -2388,7 +2453,7 @@ async function startConnectServer(config, effects, preferredPort) {
2388
2453
  await listener.close();
2389
2454
  for (const { httpSession, tlsAcceptor } of sessions) {
2390
2455
  tlsAcceptor.close();
2391
- httpSession.close();
2456
+ httpSession?.close();
2392
2457
  }
2393
2458
  }
2394
2459
  };
@@ -2564,6 +2629,40 @@ async function blindTunnel(socket, target, effects) {
2564
2629
  socket.destroy();
2565
2630
  });
2566
2631
  }
2632
+ function isEnoent(error) {
2633
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
2634
+ }
2635
+ function realConnectCertStore(paths) {
2636
+ const read = (file) => {
2637
+ try {
2638
+ return fs.readFileSync(file, "utf8");
2639
+ } catch (error) {
2640
+ if (isEnoent(error)) {
2641
+ return void 0;
2642
+ }
2643
+ throw error;
2644
+ }
2645
+ };
2646
+ return {
2647
+ loadCa: () => {
2648
+ const certPem = read(paths.frontdoorCaCertFile);
2649
+ const keyPem2 = read(paths.frontdoorCaKeyFile);
2650
+ return certPem === void 0 || keyPem2 === void 0 ? void 0 : { certPem, keyPem: keyPem2 };
2651
+ },
2652
+ writeCa: (ca) => {
2653
+ fs.mkdirSync(paths.frontdoorCaDir, { recursive: true });
2654
+ fs.writeFileSync(paths.frontdoorCaCertFile, ca.certPem, "utf8");
2655
+ fs.writeFileSync(paths.frontdoorCaKeyFile, ca.keyPem, { encoding: "utf8", mode: CA_KEY_FILE_MODE });
2656
+ fs.chmodSync(paths.frontdoorCaKeyFile, CA_KEY_FILE_MODE);
2657
+ }
2658
+ };
2659
+ }
2660
+
2661
+ // src/frontdoor/connectEffects.ts
2662
+ import * as http from "node:http";
2663
+ import * as https from "node:https";
2664
+ import * as net2 from "node:net";
2665
+ import * as tls from "node:tls";
2567
2666
  function realConnectEffects() {
2568
2667
  const plainAgent = new http.Agent({ keepAlive: true });
2569
2668
  const tlsAgent = new https.Agent({ keepAlive: true });
@@ -2609,10 +2708,13 @@ function realConnectEffects() {
2609
2708
  }
2610
2709
  return await listenOnce(0, onSocket);
2611
2710
  },
2612
- createTlsAcceptor: (leaf, onSecure) => {
2613
- const server = tls.createServer({ key: leaf.keyPem, cert: leaf.certPem }, (secure) => {
2614
- onSecure(secure);
2615
- });
2711
+ createTlsAcceptor: (leaf, onSecure, alpnProtocols) => {
2712
+ const server = tls.createServer(
2713
+ { key: leaf.keyPem, cert: leaf.certPem, ...alpnProtocols === void 0 ? {} : { ALPNProtocols: [...alpnProtocols] } },
2714
+ (secure) => {
2715
+ onSecure(secure);
2716
+ }
2717
+ );
2616
2718
  server.on("clientError", (_error, socket) => {
2617
2719
  socket.destroy();
2618
2720
  });
@@ -2647,6 +2749,13 @@ function realConnectEffects() {
2647
2749
  }
2648
2750
  };
2649
2751
  },
2752
+ connectTlsUpstream: async (host, port, clientAlpn) => await new Promise((resolve, reject) => {
2753
+ const socket = tls.connect({ host, port, servername: host, ...clientAlpn === void 0 ? {} : { ALPNProtocols: [clientAlpn] } });
2754
+ socket.once("secureConnect", () => {
2755
+ resolve(socket);
2756
+ });
2757
+ socket.once("error", reject);
2758
+ }),
2650
2759
  connectTcp: async (host, port) => await new Promise((resolve, reject) => {
2651
2760
  const socket = net2.connect({ host, port });
2652
2761
  socket.once("connect", () => {
@@ -2710,34 +2819,6 @@ function realConnectEffects() {
2710
2819
  }
2711
2820
  };
2712
2821
  }
2713
- function isEnoent(error) {
2714
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
2715
- }
2716
- function realConnectCertStore(paths) {
2717
- const read = (file) => {
2718
- try {
2719
- return fs.readFileSync(file, "utf8");
2720
- } catch (error) {
2721
- if (isEnoent(error)) {
2722
- return void 0;
2723
- }
2724
- throw error;
2725
- }
2726
- };
2727
- return {
2728
- loadCa: () => {
2729
- const certPem = read(paths.frontdoorCaCertFile);
2730
- const keyPem2 = read(paths.frontdoorCaKeyFile);
2731
- return certPem === void 0 || keyPem2 === void 0 ? void 0 : { certPem, keyPem: keyPem2 };
2732
- },
2733
- writeCa: (ca) => {
2734
- fs.mkdirSync(paths.frontdoorCaDir, { recursive: true });
2735
- fs.writeFileSync(paths.frontdoorCaCertFile, ca.certPem, "utf8");
2736
- fs.writeFileSync(paths.frontdoorCaKeyFile, ca.keyPem, { encoding: "utf8", mode: CA_KEY_FILE_MODE });
2737
- fs.chmodSync(paths.frontdoorCaKeyFile, CA_KEY_FILE_MODE);
2738
- }
2739
- };
2740
- }
2741
2822
 
2742
2823
  // src/frontdoor/ensure.ts
2743
2824
  import { randomUUID as randomUUID2 } from "node:crypto";
@@ -2778,16 +2859,16 @@ function parseJson(raw, schema) {
2778
2859
  const parsed = schema.safeParse(JSON.parse(raw));
2779
2860
  return parsed.success ? parsed.data : void 0;
2780
2861
  }
2781
- function readHeadroomState(fs2, stateFile) {
2862
+ function readHeadroomState(fs3, stateFile) {
2782
2863
  try {
2783
- return parseJson(fs2.readFileUtf8(stateFile), HeadroomStateSchema);
2864
+ return parseJson(fs3.readFileUtf8(stateFile), HeadroomStateSchema);
2784
2865
  } catch {
2785
2866
  return void 0;
2786
2867
  }
2787
2868
  }
2788
- function writeHeadroomState(fs2, stateFile, state) {
2789
- fs2.mkdirp(path6.dirname(stateFile));
2790
- fs2.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
2869
+ function writeHeadroomState(fs3, stateFile, state) {
2870
+ fs3.mkdirp(path6.dirname(stateFile));
2871
+ fs3.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
2791
2872
  `);
2792
2873
  }
2793
2874
  function headroomAllowlist(providers) {
@@ -2807,14 +2888,14 @@ function headroomUpstreams(providers, frontDoorOrigin2) {
2807
2888
  function hashAllowlist(allowlist) {
2808
2889
  return createHash2("sha256").update(allowlist.join("\n")).digest("hex");
2809
2890
  }
2810
- function readAllProviders(fs2, providersDir) {
2891
+ function readAllProviders(fs3, providersDir) {
2811
2892
  const result = [];
2812
- for (const name of fs2.readdir(providersDir)) {
2893
+ for (const name of fs3.readdir(providersDir)) {
2813
2894
  if (!name.endsWith(".json")) {
2814
2895
  continue;
2815
2896
  }
2816
2897
  try {
2817
- const parsed = parseJson(fs2.readFileUtf8(path6.join(providersDir, name)), ProviderSchema);
2898
+ const parsed = parseJson(fs3.readFileUtf8(path6.join(providersDir, name)), ProviderSchema);
2818
2899
  if (parsed !== void 0) {
2819
2900
  result.push({ name: name.slice(0, -".json".length), provider: parsed });
2820
2901
  }
@@ -2824,22 +2905,22 @@ function readAllProviders(fs2, providersDir) {
2824
2905
  }
2825
2906
  return result;
2826
2907
  }
2827
- function writeSession(fs2, sessionsDir, session) {
2828
- fs2.mkdirp(sessionsDir);
2829
- fs2.writeFileUtf8(path6.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
2908
+ function writeSession(fs3, sessionsDir, session) {
2909
+ fs3.mkdirp(sessionsDir);
2910
+ fs3.writeFileUtf8(path6.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
2830
2911
  `);
2831
2912
  }
2832
- function removeSession(fs2, sessionsDir, pid) {
2833
- fs2.removeRecursive(path6.join(sessionsDir, `${String(pid)}.json`));
2913
+ function removeSession(fs3, sessionsDir, pid) {
2914
+ fs3.removeRecursive(path6.join(sessionsDir, `${String(pid)}.json`));
2834
2915
  }
2835
- function listSessions(fs2, sessionsDir) {
2916
+ function listSessions(fs3, sessionsDir) {
2836
2917
  const sessions = [];
2837
- for (const name of fs2.readdir(sessionsDir)) {
2918
+ for (const name of fs3.readdir(sessionsDir)) {
2838
2919
  if (!name.endsWith(".json")) {
2839
2920
  continue;
2840
2921
  }
2841
2922
  try {
2842
- const parsed = parseJson(fs2.readFileUtf8(path6.join(sessionsDir, name)), HeadroomSessionSchema);
2923
+ const parsed = parseJson(fs3.readFileUtf8(path6.join(sessionsDir, name)), HeadroomSessionSchema);
2843
2924
  if (parsed !== void 0) {
2844
2925
  sessions.push(parsed);
2845
2926
  }
@@ -2849,22 +2930,22 @@ function listSessions(fs2, sessionsDir) {
2849
2930
  }
2850
2931
  return sessions.sort((a, b) => a.pid - b.pid);
2851
2932
  }
2852
- function sessionsForSupervisor(fs2, sessionsDir, supervisorPid) {
2853
- return listSessions(fs2, sessionsDir).filter((session) => session.supervisorPid === supervisorPid);
2933
+ function sessionsForSupervisor(fs3, sessionsDir, supervisorPid) {
2934
+ return listSessions(fs3, sessionsDir).filter((session) => session.supervisorPid === supervisorPid);
2854
2935
  }
2855
- function pruneDeadSessions(fs2, sessionsDir, isRunning) {
2936
+ function pruneDeadSessions(fs3, sessionsDir, isRunning) {
2856
2937
  const removed = [];
2857
- for (const session of listSessions(fs2, sessionsDir)) {
2938
+ for (const session of listSessions(fs3, sessionsDir)) {
2858
2939
  if (!isRunning(session.pid)) {
2859
- removeSession(fs2, sessionsDir, session.pid);
2940
+ removeSession(fs3, sessionsDir, session.pid);
2860
2941
  removed.push(session.pid);
2861
2942
  }
2862
2943
  }
2863
2944
  return removed;
2864
2945
  }
2865
- function readStartLock(fs2, lockFile) {
2946
+ function readStartLock(fs3, lockFile) {
2866
2947
  try {
2867
- return parseJson(fs2.readFileUtf8(lockFile), HeadroomLockSchema);
2948
+ return parseJson(fs3.readFileUtf8(lockFile), HeadroomLockSchema);
2868
2949
  } catch {
2869
2950
  return void 0;
2870
2951
  }
@@ -3101,9 +3182,9 @@ function snapshotPath(snapshotsDir, identity) {
3101
3182
  }
3102
3183
  return path7.join(snapshotsDir, `${identity}.json`);
3103
3184
  }
3104
- function readUsageSnapshot(fs2, snapshotsDir, identity) {
3185
+ function readUsageSnapshot(fs3, snapshotsDir, identity) {
3105
3186
  const file = snapshotPath(snapshotsDir, identity);
3106
- const raw = fs2.readFileUtf8(file);
3187
+ const raw = fs3.readFileUtf8(file);
3107
3188
  if (raw === void 0) {
3108
3189
  return void 0;
3109
3190
  }
@@ -3119,8 +3200,8 @@ function readUsageSnapshot(fs2, snapshotsDir, identity) {
3119
3200
  }
3120
3201
  return snapshot.data;
3121
3202
  }
3122
- function listUsageSnapshots(fs2, snapshotsDir) {
3123
- return fs2.readdir(snapshotsDir).flatMap((name) => {
3203
+ function listUsageSnapshots(fs3, snapshotsDir) {
3204
+ return fs3.readdir(snapshotsDir).flatMap((name) => {
3124
3205
  if (!name.endsWith(".json")) {
3125
3206
  return [];
3126
3207
  }
@@ -3128,7 +3209,7 @@ function listUsageSnapshots(fs2, snapshotsDir) {
3128
3209
  if (!isIdentityName(identity)) {
3129
3210
  return [];
3130
3211
  }
3131
- const snapshot = readUsageSnapshot(fs2, snapshotsDir, identity);
3212
+ const snapshot = readUsageSnapshot(fs3, snapshotsDir, identity);
3132
3213
  return snapshot === void 0 ? [] : [snapshot];
3133
3214
  }).sort((left, right) => left.identity.localeCompare(right.identity));
3134
3215
  }
@@ -3295,9 +3376,9 @@ function compareVersions(a, b) {
3295
3376
  }
3296
3377
  var HEADROOM_SUPERVISOR_STILL_RUNNING = -1;
3297
3378
  async function runSupervisor(initialConfig, ports, options = {}) {
3298
- const { fs: fs2, paths } = ports;
3379
+ const { fs: fs3, paths } = ports;
3299
3380
  let config = initialConfig;
3300
- const previousState = readHeadroomState(fs2, paths.headroomStateFile);
3381
+ const previousState = readHeadroomState(fs3, paths.headroomStateFile);
3301
3382
  if (previousState?.supervisorPid !== void 0 && previousState.supervisorPid !== ports.ownPid && ports.isRunning(previousState.supervisorPid)) {
3302
3383
  ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: supervisor ${String(previousState.supervisorPid)} already owns the daemon; exiting`);
3303
3384
  return 0;
@@ -3306,19 +3387,19 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3306
3387
  let lastPort = previousState?.lastPort;
3307
3388
  const sticky = () => lastPort === void 0 ? {} : { lastPort };
3308
3389
  const ownsState = () => {
3309
- const owner = readHeadroomState(fs2, paths.headroomStateFile)?.supervisorPid;
3390
+ const owner = readHeadroomState(fs3, paths.headroomStateFile)?.supervisorPid;
3310
3391
  return owner === void 0 || owner === ports.ownPid || !ports.isRunning(owner);
3311
3392
  };
3312
3393
  const writeOwnState = (state) => {
3313
3394
  if (!ownsState()) {
3314
3395
  return false;
3315
3396
  }
3316
- writeHeadroomState(fs2, paths.headroomStateFile, state);
3397
+ writeHeadroomState(fs3, paths.headroomStateFile, state);
3317
3398
  return true;
3318
3399
  };
3319
3400
  const fail = (message) => {
3320
3401
  if (writeOwnState({ lastError: message, ...sticky() })) {
3321
- fs2.removeRecursive(paths.headroomLockFile);
3402
+ fs3.removeRecursive(paths.headroomLockFile);
3322
3403
  }
3323
3404
  ports.log(`agent-shim headroom supervisor: ${message}`);
3324
3405
  return 1;
@@ -3367,7 +3448,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3367
3448
  const settingsHash = hashSettings(config.settings);
3368
3449
  const allowlist = allowlistOf(ports);
3369
3450
  const allowlistHash = hashAllowlist(allowlist);
3370
- pruneDeadSessions(fs2, paths.headroomSessionsDir, ports.isRunning);
3451
+ pruneDeadSessions(fs3, paths.headroomSessionsDir, ports.isRunning);
3371
3452
  const ownsNow = ownsState();
3372
3453
  if (!ownsNow && !superseded) {
3373
3454
  ports.log("agent-shim headroom supervisor: another supervisor now owns state.json; serving this daemon's own sessions until they end");
@@ -3419,7 +3500,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3419
3500
  ...sticky()
3420
3501
  });
3421
3502
  if (recorded) {
3422
- fs2.removeRecursive(paths.headroomLockFile);
3503
+ fs3.removeRecursive(paths.headroomLockFile);
3423
3504
  }
3424
3505
  idleSince = void 0;
3425
3506
  ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on 127.0.0.1:${String(port)}`);
@@ -3434,7 +3515,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3434
3515
  }
3435
3516
  } else {
3436
3517
  if (runningHash !== allowlistHash || runningSettingsHash !== settingsHash || installedSource !== config.source) {
3437
- if (sessionsForSupervisor(fs2, paths.headroomSessionsDir, ports.ownPid).length === 0) {
3518
+ if (sessionsForSupervisor(fs3, paths.headroomSessionsDir, ports.ownPid).length === 0) {
3438
3519
  ports.log("agent-shim headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
3439
3520
  ports.stopProcess(headroomPid);
3440
3521
  headroomPid = void 0;
@@ -3443,7 +3524,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3443
3524
  continue;
3444
3525
  }
3445
3526
  }
3446
- const sessions = sessionsForSupervisor(fs2, paths.headroomSessionsDir, ports.ownPid);
3527
+ const sessions = sessionsForSupervisor(fs3, paths.headroomSessionsDir, ports.ownPid);
3447
3528
  if (sessions.length === 0) {
3448
3529
  idleSince ??= ports.now();
3449
3530
  const idleMs = ports.now() - idleSince;
@@ -3465,9 +3546,9 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3465
3546
  await ports.sleep(HEADROOM_POLL_MS);
3466
3547
  }
3467
3548
  }
3468
- function currentHeadroomAllowlist(fs2, paths) {
3469
- const providers = readAllProviders(fs2, paths.providersDir).map((entry) => entry.provider);
3470
- return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(fs2, paths.frontdoorStateFile))));
3549
+ function currentHeadroomAllowlist(fs3, paths) {
3550
+ const providers = readAllProviders(fs3, paths.providersDir).map((entry) => entry.provider);
3551
+ return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(fs3, paths.frontdoorStateFile))));
3471
3552
  }
3472
3553
  function allowlistOf(ports) {
3473
3554
  return currentHeadroomAllowlist(ports.fs, ports.paths);
@@ -3531,18 +3612,99 @@ function evaluateAmbientCredentialGuard(params) {
3531
3612
  message: formatAmbientCredentialGuardMessage(detected.variable, params.identityName)
3532
3613
  };
3533
3614
  }
3615
+
3616
+ // src/paths.ts
3617
+ import fs2 from "node:fs";
3618
+ import os from "node:os";
3619
+ import path8 from "node:path";
3620
+ function resolveAgentShimHome(env = process.env, home = os.homedir(), isDirectory = isExistingDirectory) {
3621
+ const fromEnv = env.AGENT_SHIM_HOME;
3622
+ if (fromEnv !== void 0 && fromEnv !== "") {
3623
+ return fromEnv;
3624
+ }
3625
+ const current = path8.join(home, HOME_DIRNAME);
3626
+ const legacy = path8.join(home, LEGACY_HOME_DIRNAME);
3627
+ return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
3628
+ }
3629
+ function isExistingDirectory(candidate) {
3630
+ return fs2.statSync(candidate, { throwIfNoEntry: false })?.isDirectory() ?? false;
3631
+ }
3632
+ function resolveClaudeHome() {
3633
+ const fromEnv = process.env.AGENT_SHIM_CLAUDE_HOME;
3634
+ if (fromEnv !== void 0 && fromEnv !== "") {
3635
+ return fromEnv;
3636
+ }
3637
+ return path8.join(os.homedir(), ".claude");
3638
+ }
3639
+ function buildLayoutPaths(root) {
3640
+ return {
3641
+ root,
3642
+ identitiesDir: path8.join(root, "identities"),
3643
+ configProfilesDir: path8.join(root, "config-profiles"),
3644
+ providersDir: path8.join(root, "providers"),
3645
+ directoryRulesFile: path8.join(root, "directory-rules.json"),
3646
+ activeIdentityFile: path8.join(root, "active-identity"),
3647
+ globalConfigFile: path8.join(root, "config.json"),
3648
+ categoriesLocalFile: path8.join(root, "categories.local.json"),
3649
+ claudeShimFile: path8.join(root, "claude-shim.json"),
3650
+ headroomDir: path8.join(root, "headroom"),
3651
+ headroomStateFile: path8.join(root, "headroom", "state.json"),
3652
+ headroomLockFile: path8.join(root, "headroom", "start.lock"),
3653
+ headroomSessionsDir: path8.join(root, "headroom", "sessions"),
3654
+ logsDir: path8.join(root, "logs"),
3655
+ headroomLogPath: path8.join(root, "logs", "headroom.log"),
3656
+ frontdoorDir: path8.join(root, "frontdoor"),
3657
+ frontdoorCaDir: path8.join(root, "frontdoor", "ca"),
3658
+ frontdoorCaCertFile: path8.join(root, "frontdoor", "ca", "ca.pem"),
3659
+ frontdoorCaKeyFile: path8.join(root, "frontdoor", "ca", "ca.key"),
3660
+ frontdoorCaBundlesDir: path8.join(root, "frontdoor", "ca", "bundles"),
3661
+ frontdoorStateFile: path8.join(root, "frontdoor", "state.json"),
3662
+ frontdoorLockFile: path8.join(root, "frontdoor", "start.lock"),
3663
+ frontdoorSessionsDir: path8.join(root, "frontdoor", "sessions"),
3664
+ frontdoorLogPath: path8.join(root, "logs", "frontdoor.log"),
3665
+ usageDir: path8.join(root, "usage"),
3666
+ usageLogDir: path8.join(root, "usage", "log"),
3667
+ usageSnapshotsDir: path8.join(root, "usage", "snapshots"),
3668
+ usagePicksFile: path8.join(root, "usage", "picks.json")
3669
+ };
3670
+ }
3671
+ function resolveLayoutPaths() {
3672
+ return buildLayoutPaths(resolveAgentShimHome());
3673
+ }
3534
3674
  export {
3535
3675
  AMBIENT_CREDENTIAL_VARS,
3536
3676
  CONNECT_INTERCEPT_HOST,
3537
3677
  CONNECT_INTERCEPT_HOSTS,
3538
3678
  CONNECT_LIMITS,
3679
+ CategoryClassificationOverlaySchema,
3680
+ CategoryClassificationSchema,
3681
+ CategoryMapSchema,
3682
+ CliError,
3683
+ ConfigProfileSchema,
3684
+ CredentialCacheSchema,
3685
+ CredentialSchema,
3686
+ CredentialSourceSchema,
3687
+ DirectoryRuleSchema,
3688
+ DirectoryRulesSchema,
3689
+ EXIT_FAILURE,
3690
+ EXIT_USAGE,
3691
+ EntryValueSchema,
3539
3692
  FARM_MANIFEST_FILENAME,
3540
3693
  FrontDoorStartError,
3694
+ GlobalConfigSchema,
3541
3695
  HeadroomStartError,
3696
+ IdentitySchema,
3697
+ PoolNameSchema,
3698
+ PoolSchema,
3699
+ PortableConfigSchema,
3700
+ ProviderSchema,
3542
3701
  ROUTED_PATH_PREFIX,
3702
+ UsageError,
3543
3703
  UsageSnapshotError,
3544
3704
  UsageSnapshotSchema,
3705
+ WhenSchema,
3545
3706
  buildEntryFacts,
3707
+ buildLayoutPaths,
3546
3708
  carryOver,
3547
3709
  createLeafCache,
3548
3710
  detectAmbientCredential,
@@ -3563,7 +3725,10 @@ export {
3563
3725
  realConnectEffects,
3564
3726
  recoverFarm,
3565
3727
  recoveryDiagnostics,
3728
+ resolveAgentShimHome,
3729
+ resolveClaudeHome,
3566
3730
  resolveDecisions,
3731
+ resolveLayoutPaths,
3567
3732
  resolveSupervisorConfig,
3568
3733
  resyncFarm,
3569
3734
  runFrontDoorSupervisor,