agent-shim 11.81.0 → 11.83.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
@@ -1106,7 +1106,7 @@ var init_schema = __esm({
1106
1106
  resumeOnLimit: z3.boolean().optional(),
1107
1107
  /** Whether a supervised session's context is compacted before its identity's quota is spent, so the resume on the next member writes a small context instead of a large one. Needs `resumeOnLimit`. Absent means false. */
1108
1108
  compactBeforeLimit: z3.boolean().optional(),
1109
- /** The share of a quota window, in whole percent, at which sessions are compacted. Absent means the launcher decides from what compacting every session on the member would cost against what its five-hour window has left. Needs `compactBeforeLimit`. */
1109
+ /** The share of a quota window, in whole percent, at which sessions are compacted. Absent means the launcher decides from what compacting every session on the member would cost against what its tightest quota window has left. Needs `compactBeforeLimit`. */
1110
1110
  compactAtUtilisation: CompactAtUtilisationSchema.optional()
1111
1111
  }).refine((pool) => pool.compactBeforeLimit !== true || pool.resumeOnLimit === true, { message: "compactBeforeLimit needs resumeOnLimit, since a session that is not moved has no cold cache to avoid", path: ["compactBeforeLimit"] }).refine((pool) => pool.compactAtUtilisation === void 0 || pool.compactBeforeLimit === true, { message: "compactAtUtilisation needs compactBeforeLimit", path: ["compactAtUtilisation"] });
1112
1112
  WEEKDAYS = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"];
@@ -1278,7 +1278,7 @@ function parseIgnoringUnrecognisedKeys(schema, raw) {
1278
1278
  return second.success ? { success: true, data: second.data, ignored } : { success: false, issues: second.error.issues };
1279
1279
  }
1280
1280
  function describeIgnoredKeys(filePath, ignored) {
1281
- const places = ignored.map(({ path: path42, keys }) => `${path42.length === 0 ? "" : `${path42.map(String).join(".")}.`}${keys.join(", ")}`);
1281
+ const places = ignored.map(({ path: path45, keys }) => `${path45.length === 0 ? "" : `${path45.map(String).join(".")}.`}${keys.join(", ")}`);
1282
1282
  return `${filePath} has settings this version of agent-shim does not know and ignores: ${places.join("; ")}. A newer release may read them.`;
1283
1283
  }
1284
1284
  function noteIgnoredKeys(filePath, ignored) {
@@ -1300,9 +1300,9 @@ function restoreIgnoredKeys(filePath, value) {
1300
1300
  return value;
1301
1301
  }
1302
1302
  const restored = structuredClone(value);
1303
- for (const { path: path42, values } of ignored) {
1303
+ for (const { path: path45, values } of ignored) {
1304
1304
  let holder = restored;
1305
- for (const step of path42) {
1305
+ for (const step of path45) {
1306
1306
  holder = isRecord(holder) ? holder[step] : void 0;
1307
1307
  }
1308
1308
  if (isRecord(holder)) {
@@ -1350,6 +1350,12 @@ function captureRuleEntryOrders(value) {
1350
1350
  }
1351
1351
  return rules.map((rule) => captureEntryOrder(rule));
1352
1352
  }
1353
+ function unparseableFile(error, filepath) {
1354
+ if (error instanceof SyntaxError) {
1355
+ return new ConfigFileNotJsonError(filepath);
1356
+ }
1357
+ return error instanceof Error && error.name === "YAMLException" ? new ConfigFileNotJsonError(filepath, "YAML") : void 0;
1358
+ }
1353
1359
  function cosmiconfigReader(explorer = createExplorer()) {
1354
1360
  return (filepath) => {
1355
1361
  let result;
@@ -1360,7 +1366,7 @@ function cosmiconfigReader(explorer = createExplorer()) {
1360
1366
  if (code === "ENOENT") {
1361
1367
  return void 0;
1362
1368
  }
1363
- throw error;
1369
+ throw unparseableFile(error, filepath) ?? error;
1364
1370
  }
1365
1371
  if (result === null || result.isEmpty === true) {
1366
1372
  return void 0;
@@ -1385,7 +1391,7 @@ function loadConfigFile(filepath, schema, read = cosmiconfigReader()) {
1385
1391
  ruleEntryOrders: captureRuleEntryOrders(raw)
1386
1392
  };
1387
1393
  }
1388
- var ConfigValidationError;
1394
+ var ConfigValidationError, ConfigFileNotJsonError;
1389
1395
  var init_load = __esm({
1390
1396
  "src/config/load.ts"() {
1391
1397
  "use strict";
@@ -1403,6 +1409,16 @@ ${detail}`);
1403
1409
  filepath;
1404
1410
  issues;
1405
1411
  };
1412
+ ConfigFileNotJsonError = class extends CliError {
1413
+ constructor(filepath, format = "JSON") {
1414
+ super(`${filepath} is not valid ${format}.`);
1415
+ this.filepath = filepath;
1416
+ this.format = format;
1417
+ this.name = "ConfigFileNotJsonError";
1418
+ }
1419
+ filepath;
1420
+ format;
1421
+ };
1406
1422
  }
1407
1423
  });
1408
1424
 
@@ -1418,7 +1434,12 @@ function readJson(filePath, schema, storeFs = nodeStoreFs) {
1418
1434
  if (raw === void 0) {
1419
1435
  return void 0;
1420
1436
  }
1421
- const parsed = JSON.parse(raw);
1437
+ let parsed;
1438
+ try {
1439
+ parsed = JSON.parse(raw);
1440
+ } catch (error) {
1441
+ throw error instanceof SyntaxError ? new ConfigFileNotJsonError(filePath) : error;
1442
+ }
1422
1443
  const result = parseIgnoringUnrecognisedKeys(schema, parsed);
1423
1444
  if (!result.success) {
1424
1445
  throw new ConfigValidationError(filePath, result.issues);
@@ -1709,6 +1730,24 @@ function evaluateWhen(when, context) {
1709
1730
  }
1710
1731
  return { status: "definite", passed: failed.length === 0, checked, failed };
1711
1732
  }
1733
+ function referencesFact(when, key) {
1734
+ if (when === void 0 || !("kind" in when)) {
1735
+ return false;
1736
+ }
1737
+ const walk2 = (node) => {
1738
+ if (Array.isArray(node)) {
1739
+ return node.some(walk2);
1740
+ }
1741
+ if (typeof node !== "object" || node === null) {
1742
+ return false;
1743
+ }
1744
+ if ("kind" in node && node.kind === "reference" && "key" in node && node.key === key) {
1745
+ return true;
1746
+ }
1747
+ return Object.values(node).some(walk2);
1748
+ };
1749
+ return walk2(when);
1750
+ }
1712
1751
  function isVacuousWhen(when) {
1713
1752
  return when !== void 0 && !("kind" in when) && Object.keys(when).length === 0;
1714
1753
  }
@@ -2903,6 +2942,14 @@ function acquireIdentityLock(params) {
2903
2942
  return {
2904
2943
  path: lockPath,
2905
2944
  token,
2945
+ refresh: () => {
2946
+ const current = parseLockRecord(params.fs.readFileUtf8(lockPath));
2947
+ if (current?.token !== token) {
2948
+ throw new IdentityLockLostError(params.identity);
2949
+ }
2950
+ params.fs.writeFilePrivate(lockPath, `${JSON.stringify({ ...current, acquiredAtMs: params.nowMs() })}
2951
+ `);
2952
+ },
2906
2953
  release: () => {
2907
2954
  const current = parseLockRecord(params.fs.readFileUtf8(lockPath));
2908
2955
  if (current !== void 0 && current.token !== token) {
@@ -2912,7 +2959,19 @@ function acquireIdentityLock(params) {
2912
2959
  }
2913
2960
  };
2914
2961
  }
2915
- const existing = parseLockRecord(params.fs.readFileUtf8(lockPath));
2962
+ const raw = params.fs.readFileUtf8(lockPath);
2963
+ if (raw === void 0) {
2964
+ continue;
2965
+ }
2966
+ let existing = parseLockRecord(raw);
2967
+ if (existing === void 0) {
2968
+ params.sleep(retryDelayMs);
2969
+ const again = params.fs.readFileUtf8(lockPath);
2970
+ if (again === void 0) {
2971
+ continue;
2972
+ }
2973
+ existing = parseLockRecord(again);
2974
+ }
2916
2975
  if (existing === void 0) {
2917
2976
  params.fs.removeRecursive(lockPath);
2918
2977
  continue;
@@ -2927,7 +2986,7 @@ function acquireIdentityLock(params) {
2927
2986
  }
2928
2987
  throw new IdentityLockBusyError(params.identity, lockPath, lastHolderPid);
2929
2988
  }
2930
- var DEFAULT_STALE_AFTER_MS, DEFAULT_RETRY_DELAY_MS, DEFAULT_MAX_ATTEMPTS, IdentityLockBusyError;
2989
+ var DEFAULT_STALE_AFTER_MS, DEFAULT_RETRY_DELAY_MS, DEFAULT_MAX_ATTEMPTS, IdentityLockLostError, IdentityLockBusyError;
2931
2990
  var init_lock = __esm({
2932
2991
  "src/launcher/lock.ts"() {
2933
2992
  "use strict";
@@ -2935,6 +2994,14 @@ var init_lock = __esm({
2935
2994
  DEFAULT_STALE_AFTER_MS = 12e4;
2936
2995
  DEFAULT_RETRY_DELAY_MS = 50;
2937
2996
  DEFAULT_MAX_ATTEMPTS = 200;
2997
+ IdentityLockLostError = class extends CliError {
2998
+ constructor(identity) {
2999
+ super(`The lock on identity "${identity}" was taken over by another process while it was held, so nothing it guards can be assumed unchanged.`);
3000
+ this.identity = identity;
3001
+ this.name = "IdentityLockLostError";
3002
+ }
3003
+ identity;
3004
+ };
2938
3005
  IdentityLockBusyError = class extends CliError {
2939
3006
  constructor(identity, lockPath, holderPid) {
2940
3007
  super(
@@ -2955,8 +3022,8 @@ var init_lock = __esm({
2955
3022
  // src/launcher/farm.ts
2956
3023
  import path8 from "node:path";
2957
3024
  import { z as z4 } from "zod";
2958
- function readFarmManifest(fs14, farmRoot) {
2959
- const raw = fs14.readFileUtf8(path8.join(farmRoot, FARM_MANIFEST_FILENAME)) ?? fs14.readFileUtf8(path8.join(farmRoot, LEGACY_FARM_MANIFEST_FILENAME));
3025
+ function readFarmManifest(fs15, farmRoot) {
3026
+ const raw = fs15.readFileUtf8(path8.join(farmRoot, FARM_MANIFEST_FILENAME)) ?? fs15.readFileUtf8(path8.join(farmRoot, LEGACY_FARM_MANIFEST_FILENAME));
2960
3027
  if (raw === void 0) {
2961
3028
  return void 0;
2962
3029
  }
@@ -3014,9 +3081,9 @@ function buildEntryFacts(params) {
3014
3081
  entries
3015
3082
  };
3016
3083
  }
3017
- function listSubtree(fs14, root, rel) {
3084
+ function listSubtree(fs15, root, rel) {
3018
3085
  const absolute = path8.join(root, rel);
3019
- const stat = fs14.lstat(absolute);
3086
+ const stat = fs15.lstat(absolute);
3020
3087
  if (stat === void 0) {
3021
3088
  return [];
3022
3089
  }
@@ -3024,10 +3091,10 @@ function listSubtree(fs14, root, rel) {
3024
3091
  return [{ rel, kind: "symlink" }];
3025
3092
  }
3026
3093
  if (stat.kind === "dir") {
3027
- const children = [...fs14.readdir(absolute)].sort().flatMap((name) => listSubtree(fs14, root, `${rel}/${name}`));
3094
+ const children = [...fs15.readdir(absolute)].sort().flatMap((name) => listSubtree(fs15, root, `${rel}/${name}`));
3028
3095
  return [{ rel, kind: "dir" }, ...children];
3029
3096
  }
3030
- const contentHash = fs14.hashFile(absolute);
3097
+ const contentHash = fs15.hashFile(absolute);
3031
3098
  return [{ rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } }];
3032
3099
  }
3033
3100
  function topLevelScopeRoots(roots) {
@@ -3041,25 +3108,25 @@ function topLevelScopeRoots(roots) {
3041
3108
  }
3042
3109
  return kept;
3043
3110
  }
3044
- function reconciliationScope(fs14, farmRoot, manifest) {
3111
+ function reconciliationScope(fs15, farmRoot, manifest) {
3045
3112
  if (manifest !== void 0) {
3046
3113
  return topLevelScopeRoots(manifest.materialised);
3047
3114
  }
3048
- return [...fs14.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && name !== LEGACY_FARM_MANIFEST_FILENAME && fs14.lstat(path8.join(farmRoot, name))?.kind === "dir").sort();
3115
+ return [...fs15.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && name !== LEGACY_FARM_MANIFEST_FILENAME && fs15.lstat(path8.join(farmRoot, name))?.kind === "dir").sort();
3049
3116
  }
3050
- function collectFarmListing(fs14, farmRoot, scopeRoots) {
3051
- return scopeRoots.flatMap((root) => listSubtree(fs14, farmRoot, root));
3117
+ function collectFarmListing(fs15, farmRoot, scopeRoots) {
3118
+ return scopeRoots.flatMap((root) => listSubtree(fs15, farmRoot, root));
3052
3119
  }
3053
- function collectCanonicalCounterparts(fs14, claudeHome, farmListing) {
3120
+ function collectCanonicalCounterparts(fs15, claudeHome, farmListing) {
3054
3121
  const out = [];
3055
3122
  for (const entry of farmListing) {
3056
3123
  const absolute = path8.join(claudeHome, entry.rel);
3057
- const stat = fs14.lstat(absolute);
3124
+ const stat = fs15.lstat(absolute);
3058
3125
  if (stat === void 0) {
3059
3126
  continue;
3060
3127
  }
3061
3128
  if (stat.kind === "file") {
3062
- const contentHash = fs14.hashFile(absolute);
3129
+ const contentHash = fs15.hashFile(absolute);
3063
3130
  out.push({ rel: entry.rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } });
3064
3131
  continue;
3065
3132
  }
@@ -3301,6 +3368,9 @@ function resyncFarm(params) {
3301
3368
  farmRoot,
3302
3369
  classification: params.classification
3303
3370
  });
3371
+ if (params.identityExists?.() === false) {
3372
+ throw new IdentityGoneError(params.identity);
3373
+ }
3304
3374
  const previousManifest = readFarmManifest(params.fs, farmRoot);
3305
3375
  const scope = reconciliationScope(params.fs, farmRoot, previousManifest);
3306
3376
  const farmListing = collectFarmListing(params.fs, farmRoot, scope);
@@ -3416,13 +3486,14 @@ function recoveryDiagnostics(recovery, identity) {
3416
3486
  }
3417
3487
  ];
3418
3488
  }
3419
- var FARM_MANIFEST_FILENAME, FarmManifestSchema;
3489
+ var FARM_MANIFEST_FILENAME, FarmManifestSchema, IdentityGoneError;
3420
3490
  var init_farm = __esm({
3421
3491
  "src/launcher/farm.ts"() {
3422
3492
  "use strict";
3423
3493
  init_classify();
3424
3494
  init_reconcile();
3425
3495
  init_pipeline();
3496
+ init_cliError();
3426
3497
  init_legacy();
3427
3498
  init_lock();
3428
3499
  FARM_MANIFEST_FILENAME = ".agent-shim-farm.json";
@@ -3436,6 +3507,14 @@ var init_farm = __esm({
3436
3507
  materialised: z4.array(z4.string()),
3437
3508
  links: z4.array(z4.strictObject({ rel: z4.string(), target: z4.string() }))
3438
3509
  });
3510
+ IdentityGoneError = class extends CliError {
3511
+ constructor(identity) {
3512
+ super(`Identity "${identity}" no longer exists: it was renamed or removed while this launch waited for it. Launch it under its current name.`);
3513
+ this.identity = identity;
3514
+ this.name = "IdentityGoneError";
3515
+ }
3516
+ identity;
3517
+ };
3439
3518
  }
3440
3519
  });
3441
3520
 
@@ -3830,10 +3909,10 @@ var init_route = __esm({
3830
3909
  // src/frontdoor/state.ts
3831
3910
  import path9 from "node:path";
3832
3911
  import { z as z5 } from "zod";
3833
- function readFrontDoorState(fs14, stateFile) {
3912
+ function readFrontDoorState(fs15, stateFile) {
3834
3913
  let raw;
3835
3914
  try {
3836
- raw = fs14.readFileUtf8(stateFile);
3915
+ raw = fs15.readFileUtf8(stateFile);
3837
3916
  } catch {
3838
3917
  return void 0;
3839
3918
  }
@@ -3847,9 +3926,9 @@ function readFrontDoorState(fs14, stateFile) {
3847
3926
  return void 0;
3848
3927
  }
3849
3928
  }
3850
- function writeFrontDoorState(fs14, stateFile, state) {
3851
- fs14.mkdirp(path9.dirname(stateFile));
3852
- fs14.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
3929
+ function writeFrontDoorState(fs15, stateFile, state) {
3930
+ fs15.mkdirp(path9.dirname(stateFile));
3931
+ fs15.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
3853
3932
  `);
3854
3933
  }
3855
3934
  function directOrigin(port) {
@@ -3859,37 +3938,37 @@ function frontDoorOrigin(state) {
3859
3938
  const port = state?.directPort ?? state?.lastDirectPort;
3860
3939
  return port === void 0 ? void 0 : directOrigin(port);
3861
3940
  }
3862
- function writeFrontDoorDirectRecord(fs14, recordsDir, record) {
3863
- fs14.mkdirp(recordsDir);
3864
- fs14.writeFilePrivate(path9.join(recordsDir, `${String(record.pid)}.json`), `${JSON.stringify({ directPort: record.directPort })}
3941
+ function writeFrontDoorDirectRecord(fs15, recordsDir, record) {
3942
+ fs15.mkdirp(recordsDir);
3943
+ fs15.writeFilePrivate(path9.join(recordsDir, `${String(record.pid)}.json`), `${JSON.stringify({ directPort: record.directPort })}
3865
3944
  `);
3866
3945
  }
3867
- function removeFrontDoorDirectRecord(fs14, recordsDir, pid) {
3868
- fs14.removeRecursive(path9.join(recordsDir, `${String(pid)}.json`));
3946
+ function removeFrontDoorDirectRecord(fs15, recordsDir, pid) {
3947
+ fs15.removeRecursive(path9.join(recordsDir, `${String(pid)}.json`));
3869
3948
  }
3870
- function markFrontDoorDraining(fs14, markersDir, pid) {
3871
- fs14.mkdirp(markersDir);
3872
- fs14.writeFilePrivate(path9.join(markersDir, String(pid)), "\n");
3949
+ function markFrontDoorDraining(fs15, markersDir, pid) {
3950
+ fs15.mkdirp(markersDir);
3951
+ fs15.writeFilePrivate(path9.join(markersDir, String(pid)), "\n");
3873
3952
  }
3874
- function unmarkFrontDoorDraining(fs14, markersDir, pid) {
3875
- fs14.removeRecursive(path9.join(markersDir, String(pid)));
3953
+ function unmarkFrontDoorDraining(fs15, markersDir, pid) {
3954
+ fs15.removeRecursive(path9.join(markersDir, String(pid)));
3876
3955
  }
3877
- function listDrainingFrontDoors(fs14, markersDir, isRunning) {
3878
- return fs14.readdir(markersDir).flatMap((file) => /^[1-9]\d*$/.test(file) && Number.isSafeInteger(Number(file)) ? [Number(file)] : []).filter(isRunning).sort((a, b) => a - b);
3956
+ function listDrainingFrontDoors(fs15, markersDir, isRunning) {
3957
+ return fs15.readdir(markersDir).flatMap((file) => /^[1-9]\d*$/.test(file) && Number.isSafeInteger(Number(file)) ? [Number(file)] : []).filter(isRunning).sort((a, b) => a - b);
3879
3958
  }
3880
3959
  function recordPid(file) {
3881
3960
  const pidText = /^([1-9]\d*)\.json$/.exec(file)?.[1];
3882
3961
  const pid = pidText === void 0 ? void 0 : Number(pidText);
3883
3962
  return pid !== void 0 && Number.isSafeInteger(pid) ? pid : void 0;
3884
3963
  }
3885
- function readDirectRecordEntry(fs14, recordsDir, file) {
3964
+ function readDirectRecordEntry(fs15, recordsDir, file) {
3886
3965
  const pid = recordPid(file);
3887
3966
  if (pid === void 0) {
3888
3967
  return void 0;
3889
3968
  }
3890
3969
  let raw;
3891
3970
  try {
3892
- raw = fs14.readFileUtf8(path9.join(recordsDir, file));
3971
+ raw = fs15.readFileUtf8(path9.join(recordsDir, file));
3893
3972
  } catch {
3894
3973
  return void 0;
3895
3974
  }
@@ -3903,37 +3982,37 @@ function readDirectRecordEntry(fs14, recordsDir, file) {
3903
3982
  return { malformed: true };
3904
3983
  }
3905
3984
  }
3906
- function listFrontDoorDirectRecords(fs14, recordsDir) {
3907
- return fs14.readdir(recordsDir).flatMap((file) => {
3908
- const entry = readDirectRecordEntry(fs14, recordsDir, file);
3985
+ function listFrontDoorDirectRecords(fs15, recordsDir) {
3986
+ return fs15.readdir(recordsDir).flatMap((file) => {
3987
+ const entry = readDirectRecordEntry(fs15, recordsDir, file);
3909
3988
  return entry?.record === void 0 ? [] : [entry.record];
3910
3989
  }).sort((a, b) => a.pid - b.pid);
3911
3990
  }
3912
- function pruneMalformedFrontDoorDirectFiles(fs14, recordsDir, isRunning) {
3913
- for (const file of fs14.readdir(recordsDir)) {
3991
+ function pruneMalformedFrontDoorDirectFiles(fs15, recordsDir, isRunning) {
3992
+ for (const file of fs15.readdir(recordsDir)) {
3914
3993
  const writer = RECORD_TEMPORARY_FILE.exec(file)?.[1];
3915
3994
  const stale = writer !== void 0 && !isRunning(Number(writer));
3916
- if (stale || readDirectRecordEntry(fs14, recordsDir, file)?.malformed === true) {
3917
- fs14.removeRecursive(path9.join(recordsDir, file));
3995
+ if (stale || readDirectRecordEntry(fs15, recordsDir, file)?.malformed === true) {
3996
+ fs15.removeRecursive(path9.join(recordsDir, file));
3918
3997
  }
3919
3998
  }
3920
3999
  }
3921
4000
  function liveFrontDoorDirectRecords(records, liveness) {
3922
4001
  return records.filter((record) => liveness.doors.has(record.pid) || liveness.unknown.has(record.pid));
3923
4002
  }
3924
- function pruneDeadFrontDoorDirectRecords(fs14, recordsDir, records, liveness) {
4003
+ function pruneDeadFrontDoorDirectRecords(fs15, recordsDir, records, liveness) {
3925
4004
  for (const record of records) {
3926
4005
  if (!liveness.doors.has(record.pid) && !liveness.unknown.has(record.pid)) {
3927
- removeFrontDoorDirectRecord(fs14, recordsDir, record.pid);
4006
+ removeFrontDoorDirectRecord(fs15, recordsDir, record.pid);
3928
4007
  }
3929
4008
  }
3930
4009
  }
3931
4010
  function recordOf(details) {
3932
4011
  return details === void 0 ? {} : { sessionId: details.sessionId, ...details.models === void 0 ? {} : { models: details.models } };
3933
4012
  }
3934
- function writeFrontDoorSession(fs14, sessionsDir, session) {
3935
- fs14.mkdirPrivate(sessionsDir);
3936
- fs14.writeFilePrivate(path9.join(sessionsDir, sessionRecordName(session.pid)), `${JSON.stringify(session, null, 2)}
4013
+ function writeFrontDoorSession(fs15, sessionsDir, session) {
4014
+ fs15.mkdirPrivate(sessionsDir);
4015
+ fs15.writeFilePrivate(path9.join(sessionsDir, sessionRecordName(session.pid)), `${JSON.stringify(session, null, 2)}
3937
4016
  `);
3938
4017
  }
3939
4018
  function sessionRecordName(pid) {
@@ -3945,32 +4024,32 @@ function isSessionRecordName(name) {
3945
4024
  function summaryOf(session) {
3946
4025
  return { pid: session.pid, startedAt: session.startedAt, ...session.supervisorPid === void 0 ? {} : { supervisorPid: session.supervisorPid } };
3947
4026
  }
3948
- function readFrontDoorSessionRecord(fs14, sessionsDir, name) {
4027
+ function readFrontDoorSessionRecord(fs15, sessionsDir, name) {
3949
4028
  try {
3950
- const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs14.readFileUtf8(path9.join(sessionsDir, name)) ?? ""));
4029
+ const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs15.readFileUtf8(path9.join(sessionsDir, name)) ?? ""));
3951
4030
  return parsed.success ? parsed.data : void 0;
3952
4031
  } catch {
3953
4032
  return void 0;
3954
4033
  }
3955
4034
  }
3956
- function listFrontDoorSessions(fs14, sessionsDir) {
4035
+ function listFrontDoorSessions(fs15, sessionsDir) {
3957
4036
  const sessions = [];
3958
- for (const name of fs14.readdir(sessionsDir)) {
3959
- const record = isSessionRecordName(name) ? readFrontDoorSessionRecord(fs14, sessionsDir, name) : void 0;
4037
+ for (const name of fs15.readdir(sessionsDir)) {
4038
+ const record = isSessionRecordName(name) ? readFrontDoorSessionRecord(fs15, sessionsDir, name) : void 0;
3960
4039
  if (record !== void 0) {
3961
4040
  sessions.push(summaryOf(record));
3962
4041
  }
3963
4042
  }
3964
4043
  return sessions.sort((a, b) => a.pid - b.pid);
3965
4044
  }
3966
- function removeFrontDoorSession(fs14, sessionsDir, pid) {
3967
- fs14.removeRecursive(path9.join(sessionsDir, sessionRecordName(pid)));
4045
+ function removeFrontDoorSession(fs15, sessionsDir, pid) {
4046
+ fs15.removeRecursive(path9.join(sessionsDir, sessionRecordName(pid)));
3968
4047
  }
3969
- function pruneDeadFrontDoorSessions(fs14, sessionsDir, listed, isRunning) {
4048
+ function pruneDeadFrontDoorSessions(fs15, sessionsDir, listed, isRunning) {
3970
4049
  const removed = [];
3971
4050
  for (const session of listed) {
3972
4051
  if (!isRunning(session.pid)) {
3973
- removeFrontDoorSession(fs14, sessionsDir, session.pid);
4052
+ removeFrontDoorSession(fs15, sessionsDir, session.pid);
3974
4053
  removed.push(session.pid);
3975
4054
  }
3976
4055
  }
@@ -4068,9 +4147,9 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
4068
4147
  }
4069
4148
  }
4070
4149
  async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4071
- const { fs: fs14, paths } = ports;
4150
+ const { fs: fs15, paths } = ports;
4072
4151
  const servingBinary = ports.statOwnExecutable();
4073
- const previous = readFrontDoorState(fs14, paths.frontdoorStateFile);
4152
+ const previous = readFrontDoorState(fs15, paths.frontdoorStateFile);
4074
4153
  let lastPort = previous?.lastPort;
4075
4154
  let lastConnectPort = previous?.lastConnectPort;
4076
4155
  let lastDirectPort = previous?.lastDirectPort;
@@ -4084,14 +4163,14 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4084
4163
  const fail = (message) => {
4085
4164
  ports.closeRcStreamHub();
4086
4165
  if (predecessor === void 0) {
4087
- writeFrontDoorState(fs14, paths.frontdoorStateFile, { lastError: message, ...sticky() });
4088
- fs14.removeRecursive(paths.frontdoorLockFile);
4166
+ writeFrontDoorState(fs15, paths.frontdoorStateFile, { lastError: message, ...sticky() });
4167
+ fs15.removeRecursive(paths.frontdoorLockFile);
4089
4168
  }
4090
4169
  ports.log(`agent-shim frontdoor supervisor: ${message}`);
4091
4170
  return 1;
4092
4171
  };
4093
4172
  if (predecessor === void 0) {
4094
- writeFrontDoorState(fs14, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
4173
+ writeFrontDoorState(fs15, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
4095
4174
  }
4096
4175
  const previousSticky = lastPort;
4097
4176
  let http3;
@@ -4132,11 +4211,11 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4132
4211
  ports.log(`agent-shim frontdoor supervisor: sticky direct port ${String(previousStickyDirect)} was occupied; moving to ${String(direct.port)} (headroom admits the new address once its supervisor rewrites the allowlist file)`);
4133
4212
  }
4134
4213
  lastDirectPort = direct.port;
4135
- writeFrontDoorDirectRecord(fs14, paths.frontdoorDirectRecordsDir, { pid: ports.ownPid, directPort: direct.port });
4136
- writeFrontDoorState(fs14, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http3.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
4214
+ writeFrontDoorDirectRecord(fs15, paths.frontdoorDirectRecordsDir, { pid: ports.ownPid, directPort: direct.port });
4215
+ writeFrontDoorState(fs15, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http3.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
4137
4216
  ports.doorHealth.generation({ providerPort: http3.port, connectPort: connect3.port, directPort: direct.port });
4138
4217
  if (predecessor === void 0) {
4139
- fs14.removeRecursive(paths.frontdoorLockFile);
4218
+ fs15.removeRecursive(paths.frontdoorLockFile);
4140
4219
  } else {
4141
4220
  predecessor.serving();
4142
4221
  }
@@ -4145,7 +4224,7 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4145
4224
  let idleSince;
4146
4225
  let ticks = 0;
4147
4226
  const supersedingOwner = async () => {
4148
- const owner = readFrontDoorState(fs14, paths.frontdoorStateFile)?.supervisorPid;
4227
+ const owner = readFrontDoorState(fs15, paths.frontdoorStateFile)?.supervisorPid;
4149
4228
  return owner !== void 0 && owner !== ports.ownPid && (await ports.runningAmong([owner])).has(owner) ? owner : void 0;
4150
4229
  };
4151
4230
  let supersededBy;
@@ -4174,13 +4253,13 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4174
4253
  ports.stopBackgroundWork?.();
4175
4254
  const drained = [direct.drain(), connect3.drain(), http3.drain()];
4176
4255
  if (await supersedingOwner() === void 0) {
4177
- writeFrontDoorState(fs14, paths.frontdoorStateFile, sticky());
4256
+ writeFrontDoorState(fs15, paths.frontdoorStateFile, sticky());
4178
4257
  }
4179
- markFrontDoorDraining(fs14, paths.frontdoorDrainingDir, ports.ownPid);
4258
+ markFrontDoorDraining(fs15, paths.frontdoorDrainingDir, ports.ownPid);
4180
4259
  ports.closeRcStreamHub();
4181
4260
  await Promise.all(drained);
4182
- unmarkFrontDoorDraining(fs14, paths.frontdoorDrainingDir, ports.ownPid);
4183
- removeFrontDoorDirectRecord(fs14, paths.frontdoorDirectRecordsDir, ports.ownPid);
4261
+ unmarkFrontDoorDraining(fs15, paths.frontdoorDrainingDir, ports.ownPid);
4262
+ removeFrontDoorDirectRecord(fs15, paths.frontdoorDirectRecordsDir, ports.ownPid);
4184
4263
  ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: the connections this door carried have ended; exiting`);
4185
4264
  return 0;
4186
4265
  };
@@ -4201,12 +4280,12 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4201
4280
  await connect3.close();
4202
4281
  await http3.close();
4203
4282
  ports.closeRcStreamHub();
4204
- removeFrontDoorDirectRecord(fs14, paths.frontdoorDirectRecordsDir, ports.ownPid);
4283
+ removeFrontDoorDirectRecord(fs15, paths.frontdoorDirectRecordsDir, ports.ownPid);
4205
4284
  };
4206
4285
  const shutdown = async () => {
4207
4286
  await closeServing();
4208
4287
  if (await supersedingOwner() === void 0) {
4209
- writeFrontDoorState(fs14, paths.frontdoorStateFile, sticky());
4288
+ writeFrontDoorState(fs15, paths.frontdoorStateFile, sticky());
4210
4289
  }
4211
4290
  return 0;
4212
4291
  };
@@ -4225,7 +4304,7 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4225
4304
  ticks += 1;
4226
4305
  const listed = ports.registry.rescan();
4227
4306
  const running = await ports.runningAmong(listed.map((session) => session.pid));
4228
- const pruned = pruneDeadFrontDoorSessions(fs14, paths.frontdoorSessionsDir, listed, (pid) => running.has(pid));
4307
+ const pruned = pruneDeadFrontDoorSessions(fs15, paths.frontdoorSessionsDir, listed, (pid) => running.has(pid));
4229
4308
  ports.registry.forget(pruned);
4230
4309
  ports.observeLaunchRegistry(listed, pruned);
4231
4310
  ports.checkQuotaExpiry();
@@ -4300,8 +4379,8 @@ function parseConnectTarget(authority) {
4300
4379
  function isInterceptedHost(host, interceptHosts) {
4301
4380
  return interceptHosts.includes(host);
4302
4381
  }
4303
- function servedByPipeline(path42) {
4304
- return path42?.startsWith(ROUTED_PATH_PREFIX) === true;
4382
+ function servedByPipeline(path45) {
4383
+ return path45?.startsWith(ROUTED_PATH_PREFIX) === true;
4305
4384
  }
4306
4385
  function forwardableHeaders(headers) {
4307
4386
  const connectionTokens = new Set(
@@ -4745,7 +4824,7 @@ var init_package = __esm({
4745
4824
  "package.json"() {
4746
4825
  package_default = {
4747
4826
  name: "agent-shim",
4748
- version: "11.81.0",
4827
+ version: "11.83.0",
4749
4828
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
4750
4829
  license: "MIT",
4751
4830
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -4971,43 +5050,43 @@ function parseJson(raw, schema) {
4971
5050
  const parsed = schema.safeParse(JSON.parse(raw));
4972
5051
  return parsed.success ? parsed.data : void 0;
4973
5052
  }
4974
- function readHeadroomState(fs14, stateFile) {
5053
+ function readHeadroomState(fs15, stateFile) {
4975
5054
  try {
4976
- return parseJson(fs14.readFileUtf8(stateFile), HeadroomStateSchema);
5055
+ return parseJson(fs15.readFileUtf8(stateFile), HeadroomStateSchema);
4977
5056
  } catch {
4978
5057
  return void 0;
4979
5058
  }
4980
5059
  }
4981
- function writeHeadroomState(fs14, stateFile, state) {
4982
- fs14.mkdirp(path12.dirname(stateFile));
4983
- fs14.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
5060
+ function writeHeadroomState(fs15, stateFile, state) {
5061
+ fs15.mkdirp(path12.dirname(stateFile));
5062
+ fs15.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
4984
5063
  `);
4985
5064
  }
4986
- function resolveServingHeadroomState(fs14, files, isRunning) {
4987
- const current = readHeadroomState(fs14, files.stateFile);
5065
+ function resolveServingHeadroomState(fs15, files, isRunning) {
5066
+ const current = readHeadroomState(fs15, files.stateFile);
4988
5067
  if (current !== void 0) {
4989
5068
  return { path: files.stateFile, state: current };
4990
5069
  }
4991
- const legacy = readHeadroomState(fs14, files.legacyStateFile);
5070
+ const legacy = readHeadroomState(fs15, files.legacyStateFile);
4992
5071
  if (legacy?.supervisorPid !== void 0 && isRunning(legacy.supervisorPid)) {
4993
5072
  return { path: files.legacyStateFile, state: legacy };
4994
5073
  }
4995
5074
  return void 0;
4996
5075
  }
4997
- function migrateHeadroomState(fs14, files, isRunning) {
4998
- const legacy = readHeadroomState(fs14, files.legacyStateFile);
5076
+ function migrateHeadroomState(fs15, files, isRunning) {
5077
+ const legacy = readHeadroomState(fs15, files.legacyStateFile);
4999
5078
  const legacyLive = legacy?.supervisorPid !== void 0 && isRunning(legacy.supervisorPid);
5000
- const current = readHeadroomState(fs14, files.stateFile);
5079
+ const current = readHeadroomState(fs15, files.stateFile);
5001
5080
  if (current !== void 0 || legacyLive) {
5002
- if (!legacyLive && fs14.readFileUtf8(files.legacyStateFile) !== void 0) {
5003
- fs14.removeRecursive(files.legacyStateFile);
5081
+ if (!legacyLive && fs15.readFileUtf8(files.legacyStateFile) !== void 0) {
5082
+ fs15.removeRecursive(files.legacyStateFile);
5004
5083
  }
5005
5084
  return;
5006
5085
  }
5007
5086
  if (legacy !== void 0) {
5008
- writeHeadroomState(fs14, files.stateFile, legacy);
5087
+ writeHeadroomState(fs15, files.stateFile, legacy);
5009
5088
  }
5010
- fs14.removeRecursive(files.legacyStateFile);
5089
+ fs15.removeRecursive(files.legacyStateFile);
5011
5090
  }
5012
5091
  function hashAllowlist(allowlist) {
5013
5092
  return createHash3("sha256").update(allowlist.join("\n")).digest("hex");
@@ -5040,27 +5119,27 @@ function isAdmissibleUrl(entry) {
5040
5119
  function parseAllowlistFile(content) {
5041
5120
  return content.replace(/^\uFEFF/, "").replace(ALLOWLIST_FILE_COMMENT, "").split(ALLOWLIST_FILE_SEPARATORS).map((entry) => entry.replace(ALLOWLIST_SURROUNDING_WHITESPACE, "")).filter((entry) => entry !== "" && !ALLOWLIST_ENTRY_WHITESPACE.test(entry) && (entry.includes("://") ? isAdmissibleUrl(entry) : isBareHost(entry)));
5042
5121
  }
5043
- function writeAllowlistFile(fs14, allowlistFile, allowlist) {
5044
- fs14.mkdirPrivate(path12.dirname(allowlistFile));
5045
- fs14.writeFilePrivate(allowlistFile, formatAllowlistFile(allowlist));
5122
+ function writeAllowlistFile(fs15, allowlistFile, allowlist) {
5123
+ fs15.mkdirPrivate(path12.dirname(allowlistFile));
5124
+ fs15.writeFilePrivate(allowlistFile, formatAllowlistFile(allowlist));
5046
5125
  }
5047
- function pruneStaleAllowlistTemporaries(fs14, allowlistFile, isRunning) {
5126
+ function pruneStaleAllowlistTemporaries(fs15, allowlistFile, isRunning) {
5048
5127
  const prefix = `${path12.basename(allowlistFile)}.`;
5049
- for (const name of fs14.readdir(path12.dirname(allowlistFile))) {
5128
+ for (const name of fs15.readdir(path12.dirname(allowlistFile))) {
5050
5129
  const writer = name.startsWith(prefix) ? /^([1-9]\d*)\.tmp$/.exec(name.slice(prefix.length))?.[1] : void 0;
5051
5130
  if (writer !== void 0 && !isRunning(Number(writer))) {
5052
- fs14.removeRecursive(path12.join(path12.dirname(allowlistFile), name));
5131
+ fs15.removeRecursive(path12.join(path12.dirname(allowlistFile), name));
5053
5132
  }
5054
5133
  }
5055
5134
  }
5056
- function readAllProviders(fs14, providersDir) {
5135
+ function readAllProviders(fs15, providersDir) {
5057
5136
  const result = [];
5058
- for (const name of fs14.readdir(providersDir)) {
5137
+ for (const name of fs15.readdir(providersDir)) {
5059
5138
  if (!name.endsWith(".json")) {
5060
5139
  continue;
5061
5140
  }
5062
5141
  try {
5063
- const parsed = parseJson(fs14.readFileUtf8(path12.join(providersDir, name)), ProviderSchema);
5142
+ const parsed = parseJson(fs15.readFileUtf8(path12.join(providersDir, name)), ProviderSchema);
5064
5143
  if (parsed !== void 0) {
5065
5144
  result.push({ name: name.slice(0, -".json".length), provider: parsed });
5066
5145
  }
@@ -5070,22 +5149,22 @@ function readAllProviders(fs14, providersDir) {
5070
5149
  }
5071
5150
  return result;
5072
5151
  }
5073
- function writeSession(fs14, sessionsDir, session) {
5074
- fs14.mkdirp(sessionsDir);
5075
- fs14.writeFileUtf8(path12.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
5152
+ function writeSession(fs15, sessionsDir, session) {
5153
+ fs15.mkdirp(sessionsDir);
5154
+ fs15.writeFileUtf8(path12.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
5076
5155
  `);
5077
5156
  }
5078
- function removeSession(fs14, sessionsDir, pid) {
5079
- fs14.removeRecursive(path12.join(sessionsDir, `${String(pid)}.json`));
5157
+ function removeSession(fs15, sessionsDir, pid) {
5158
+ fs15.removeRecursive(path12.join(sessionsDir, `${String(pid)}.json`));
5080
5159
  }
5081
- function listSessions(fs14, sessionsDir) {
5160
+ function listSessions(fs15, sessionsDir) {
5082
5161
  const sessions = [];
5083
- for (const name of fs14.readdir(sessionsDir)) {
5162
+ for (const name of fs15.readdir(sessionsDir)) {
5084
5163
  if (!name.endsWith(".json")) {
5085
5164
  continue;
5086
5165
  }
5087
5166
  try {
5088
- const parsed = parseJson(fs14.readFileUtf8(path12.join(sessionsDir, name)), HeadroomSessionSchema);
5167
+ const parsed = parseJson(fs15.readFileUtf8(path12.join(sessionsDir, name)), HeadroomSessionSchema);
5089
5168
  if (parsed !== void 0) {
5090
5169
  sessions.push(parsed);
5091
5170
  }
@@ -5095,22 +5174,22 @@ function listSessions(fs14, sessionsDir) {
5095
5174
  }
5096
5175
  return sessions.sort((a, b) => a.pid - b.pid);
5097
5176
  }
5098
- function sessionsForSupervisor(fs14, sessionsDir, supervisorPid) {
5099
- return listSessions(fs14, sessionsDir).filter((session) => session.supervisorPid === supervisorPid);
5177
+ function sessionsForSupervisor(fs15, sessionsDir, supervisorPid) {
5178
+ return listSessions(fs15, sessionsDir).filter((session) => session.supervisorPid === supervisorPid);
5100
5179
  }
5101
- function pruneDeadSessions(fs14, sessionsDir, isRunning) {
5180
+ function pruneDeadSessions(fs15, sessionsDir, isRunning) {
5102
5181
  const removed = [];
5103
- for (const session of listSessions(fs14, sessionsDir)) {
5182
+ for (const session of listSessions(fs15, sessionsDir)) {
5104
5183
  if (!isRunning(session.pid)) {
5105
- removeSession(fs14, sessionsDir, session.pid);
5184
+ removeSession(fs15, sessionsDir, session.pid);
5106
5185
  removed.push(session.pid);
5107
5186
  }
5108
5187
  }
5109
5188
  return removed;
5110
5189
  }
5111
- function readStartLock(fs14, lockFile) {
5190
+ function readStartLock(fs15, lockFile) {
5112
5191
  try {
5113
- return parseJson(fs14.readFileUtf8(lockFile), HeadroomLockSchema);
5192
+ return parseJson(fs15.readFileUtf8(lockFile), HeadroomLockSchema);
5114
5193
  } catch {
5115
5194
  return void 0;
5116
5195
  }
@@ -5200,12 +5279,12 @@ function earlierReleaseAllowlistHash(providers, doorOrigin) {
5200
5279
  }
5201
5280
  return hashAllowlist([...entries].sort());
5202
5281
  }
5203
- function earlierReleaseDaemon(fs14, paths, daemon) {
5282
+ function earlierReleaseDaemon(fs15, paths, daemon) {
5204
5283
  if (daemonIdentity(daemon.commandLine, daemon.socketPath) !== "earlier-release") {
5205
5284
  return void 0;
5206
5285
  }
5207
- const providers = readAllProviders(fs14, paths.providersDir).map((entry) => entry.provider);
5208
- const expected = earlierReleaseAllowlistHash(providers, frontDoorOrigin(readFrontDoorState(fs14, paths.frontdoorStateFile)));
5286
+ const providers = readAllProviders(fs15, paths.providersDir).map((entry) => entry.provider);
5287
+ const expected = earlierReleaseAllowlistHash(providers, frontDoorOrigin(readFrontDoorState(fs15, paths.frontdoorStateFile)));
5209
5288
  return { admitsServingDoor: daemon.recordedHash === expected };
5210
5289
  }
5211
5290
  var EARLIER_RELEASE_ALLOWLIST, EARLIER_RELEASE_ANTHROPIC_UPSTREAM;
@@ -5230,8 +5309,8 @@ function awaitingCause(daemonPid, identity, allowlistFile) {
5230
5309
  }
5231
5310
  return `the headroom supervisor has not written an allowlist admitting this launch's upstreams to ${allowlistFile} within ${String(HEADROOM_START_TIMEOUT_MS)}ms`;
5232
5311
  }
5233
- function daemonAdmits(fs14, allowlistFile, recordedHash, required) {
5234
- const content = fs14.readFileUtf8(allowlistFile);
5312
+ function daemonAdmits(fs15, allowlistFile, recordedHash, required) {
5313
+ const content = fs15.readFileUtf8(allowlistFile);
5235
5314
  if (content === void 0 || recordedHash === void 0) {
5236
5315
  return false;
5237
5316
  }
@@ -5500,7 +5579,7 @@ function verifyAllowlistFile(allowlistFile, ports) {
5500
5579
  const replaceable = fileStat === void 0 || fileStat.kind === "file" || fileStat.kind === "symlink";
5501
5580
  return { message: refusal2, repairable: replaceable };
5502
5581
  }
5503
- function prepareHeadroomSocket(fs14, ports, paths, supervisorPid) {
5582
+ function prepareHeadroomSocket(fs15, ports, paths, supervisorPid) {
5504
5583
  const unsupported = platformRefusal(ports.platform);
5505
5584
  if (unsupported !== void 0) {
5506
5585
  return { refused: unsupported };
@@ -5515,18 +5594,18 @@ function prepareHeadroomSocket(fs14, ports, paths, supervisorPid) {
5515
5594
  if (ports.lstat(paths.headroomSocketDir)?.kind === "symlink") {
5516
5595
  return { refused: `the headroom socket directory ${paths.headroomSocketDir} is a symlink; it must be the real directory` };
5517
5596
  }
5518
- fs14.mkdirPrivate(paths.headroomSocketDir);
5597
+ fs15.mkdirPrivate(paths.headroomSocketDir);
5519
5598
  const refusal2 = ownerOnlyRefusal("socket directory", paths.headroomSocketDir, ports.lstat(paths.headroomSocketDir), "dir", ports.currentUid());
5520
5599
  return refusal2 === void 0 ? { socketPath } : { refused: refusal2 };
5521
5600
  }
5522
- function pruneStaleHeadroomSockets(fs14, paths, isRunning) {
5601
+ function pruneStaleHeadroomSockets(fs15, paths, isRunning) {
5523
5602
  const removed = [];
5524
- for (const name of fs14.readdir(paths.headroomSocketDir)) {
5603
+ for (const name of fs15.readdir(paths.headroomSocketDir)) {
5525
5604
  const pid = HEADROOM_SOCKET_NAME.exec(name)?.[1];
5526
5605
  if (pid === void 0 || isRunning(Number.parseInt(pid, 10))) {
5527
5606
  continue;
5528
5607
  }
5529
- fs14.removeRecursive(path13.join(paths.headroomSocketDir, name));
5608
+ fs15.removeRecursive(path13.join(paths.headroomSocketDir, name));
5530
5609
  removed.push(name);
5531
5610
  }
5532
5611
  return removed;
@@ -5638,37 +5717,37 @@ function compareVersions2(a, b) {
5638
5717
  return 0;
5639
5718
  }
5640
5719
  async function runSupervisor(initialConfig, ports, options = {}) {
5641
- const { fs: fs14, paths } = ports;
5720
+ const { fs: fs15, paths } = ports;
5642
5721
  let config = initialConfig;
5643
- migrateHeadroomState(fs14, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning);
5644
- const previousState = resolveServingHeadroomState(fs14, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning)?.state;
5722
+ migrateHeadroomState(fs15, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning);
5723
+ const previousState = resolveServingHeadroomState(fs15, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning)?.state;
5645
5724
  if (previousState?.supervisorPid !== void 0 && previousState.supervisorPid !== ports.ownPid && ports.isRunning(previousState.supervisorPid)) {
5646
5725
  ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: supervisor ${String(previousState.supervisorPid)} already owns the daemon; exiting`);
5647
5726
  return 0;
5648
5727
  }
5649
5728
  let installedSource = previousState?.installedSource;
5650
5729
  const ownsState = () => {
5651
- const owner = readHeadroomState(fs14, paths.headroomStateFile)?.supervisorPid;
5730
+ const owner = readHeadroomState(fs15, paths.headroomStateFile)?.supervisorPid;
5652
5731
  return owner === void 0 || owner === ports.ownPid || !ports.isRunning(owner);
5653
5732
  };
5654
5733
  const writeOwnState = (state) => {
5655
5734
  if (!ownsState()) {
5656
5735
  return false;
5657
5736
  }
5658
- writeHeadroomState(fs14, paths.headroomStateFile, state);
5737
+ writeHeadroomState(fs15, paths.headroomStateFile, state);
5659
5738
  return true;
5660
5739
  };
5661
5740
  const fail = (message) => {
5662
5741
  if (writeOwnState({ lastError: message })) {
5663
- fs14.removeRecursive(paths.headroomLockFile);
5742
+ fs15.removeRecursive(paths.headroomLockFile);
5664
5743
  }
5665
5744
  ports.log(`agent-shim headroom supervisor: ${message}`);
5666
5745
  return 1;
5667
5746
  };
5668
5747
  const syncAllowlistFile = (allowlist) => {
5669
5748
  try {
5670
- if (fs14.readFileUtf8(paths.headroomAllowlistFile) !== formatAllowlistFile(allowlist)) {
5671
- writeAllowlistFile(fs14, paths.headroomAllowlistFile, allowlist);
5749
+ if (fs15.readFileUtf8(paths.headroomAllowlistFile) !== formatAllowlistFile(allowlist)) {
5750
+ writeAllowlistFile(fs15, paths.headroomAllowlistFile, allowlist);
5672
5751
  ports.log(`agent-shim headroom supervisor: wrote allowlist [${allowlist.join(", ")}] to ${paths.headroomAllowlistFile}`);
5673
5752
  }
5674
5753
  return void 0;
@@ -5686,9 +5765,9 @@ async function runSupervisor(initialConfig, ports, options = {}) {
5686
5765
  }
5687
5766
  ports.log(`agent-shim headroom supervisor: repairing the allowlist file: ${problem.message}`);
5688
5767
  try {
5689
- fs14.mkdirPrivate(paths.headroomDir);
5690
- fs14.mkdirPrivate(path14.dirname(paths.headroomAllowlistFile));
5691
- writeAllowlistFile(fs14, paths.headroomAllowlistFile, allowlist);
5768
+ fs15.mkdirPrivate(paths.headroomDir);
5769
+ fs15.mkdirPrivate(path14.dirname(paths.headroomAllowlistFile));
5770
+ writeAllowlistFile(fs15, paths.headroomAllowlistFile, allowlist);
5692
5771
  } catch (error) {
5693
5772
  return `could not write the headroom allowlist file ${paths.headroomAllowlistFile}: ${error instanceof Error ? error.message : String(error)}`;
5694
5773
  }
@@ -5713,20 +5792,20 @@ async function runSupervisor(initialConfig, ports, options = {}) {
5713
5792
  installedSource = config.source;
5714
5793
  return void 0;
5715
5794
  };
5716
- const socket = prepareHeadroomSocket(fs14, ports.socketTrust, paths, ports.ownPid);
5795
+ const socket = prepareHeadroomSocket(fs15, ports.socketTrust, paths, ports.ownPid);
5717
5796
  if (socket.refused !== void 0) {
5718
5797
  return fail(socket.refused);
5719
5798
  }
5720
5799
  const { socketPath } = socket;
5721
- pruneStaleHeadroomSockets(fs14, paths, ports.isRunning);
5722
- pruneStaleAllowlistTemporaries(fs14, paths.headroomAllowlistFile, ports.isRunning);
5800
+ pruneStaleHeadroomSockets(fs15, paths, ports.isRunning);
5801
+ pruneStaleAllowlistTemporaries(fs15, paths.headroomAllowlistFile, ports.isRunning);
5723
5802
  const installFailure = ensureInstalled();
5724
5803
  if (installFailure !== void 0) {
5725
5804
  return fail(installFailure);
5726
5805
  }
5727
5806
  const version = ports.headroomVersion() ?? "unknown";
5728
5807
  writeOwnState({ supervisorPid: ports.ownPid, version, installedSource });
5729
- ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${currentHeadroomAllowlistInputs(fs14, paths, ports.frontDoorLiveness).frontDoorOrigins.join(", ")}]`);
5808
+ ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${currentHeadroomAllowlistInputs(fs15, paths, ports.frontDoorLiveness).frontDoorOrigins.join(", ")}]`);
5730
5809
  const orphanPid = previousState?.headroomPid;
5731
5810
  const orphanSocket = previousState?.socketPath ?? (previousState?.supervisorPid === void 0 ? void 0 : headroomSocketPath(paths, previousState.supervisorPid));
5732
5811
  const orphanIdentity = orphanPid === void 0 || orphanSocket === void 0 || !ports.isRunning(orphanPid) ? void 0 : daemonIdentity(ports.daemonCommandLine(orphanPid), orphanSocket);
@@ -5764,12 +5843,12 @@ async function runSupervisor(initialConfig, ports, options = {}) {
5764
5843
  }
5765
5844
  config = ports.readConfig();
5766
5845
  const settingsHash = hashSettings(config.settings);
5767
- const inputs = currentHeadroomAllowlistInputs(fs14, paths, ports.frontDoorLiveness);
5768
- pruneDeadFrontDoorDirectRecords(fs14, paths.frontdoorDirectRecordsDir, inputs.frontDoorRecords, inputs.frontDoorLiveness);
5769
- pruneMalformedFrontDoorDirectFiles(fs14, paths.frontdoorDirectRecordsDir, ports.isRunning);
5846
+ const inputs = currentHeadroomAllowlistInputs(fs15, paths, ports.frontDoorLiveness);
5847
+ pruneDeadFrontDoorDirectRecords(fs15, paths.frontdoorDirectRecordsDir, inputs.frontDoorRecords, inputs.frontDoorLiveness);
5848
+ pruneMalformedFrontDoorDirectFiles(fs15, paths.frontdoorDirectRecordsDir, ports.isRunning);
5770
5849
  const allowlist = inputs.frontDoorOrigins;
5771
5850
  const allowlistHash = hashAllowlist(allowlist);
5772
- pruneDeadSessions(fs14, paths.headroomSessionsDir, ports.isRunning);
5851
+ pruneDeadSessions(fs15, paths.headroomSessionsDir, ports.isRunning);
5773
5852
  const ownsNow = ownsState();
5774
5853
  if (!ownsNow && !superseded) {
5775
5854
  ports.log("agent-shim headroom supervisor: another supervisor now owns the state file; serving this daemon's own sessions until they end");
@@ -5816,7 +5895,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
5816
5895
  runningSettingsHash = settingsHash;
5817
5896
  const recorded = writeOwnState(servingState(pid));
5818
5897
  if (recorded) {
5819
- fs14.removeRecursive(paths.headroomLockFile);
5898
+ fs15.removeRecursive(paths.headroomLockFile);
5820
5899
  }
5821
5900
  idleSince = void 0;
5822
5901
  ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on unix socket ${socketPath}`);
@@ -5844,7 +5923,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
5844
5923
  ports.log(`agent-shim headroom supervisor: headroom pid ${String(headroomPid)} now serves allowlist [${allowlist.join(", ")}]`);
5845
5924
  }
5846
5925
  if (runningSettingsHash !== settingsHash || installedSource !== config.source) {
5847
- if (sessionsForSupervisor(fs14, paths.headroomSessionsDir, ports.ownPid).length === 0) {
5926
+ if (sessionsForSupervisor(fs15, paths.headroomSessionsDir, ports.ownPid).length === 0) {
5848
5927
  ports.log("agent-shim headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
5849
5928
  ports.stopProcess(headroomPid);
5850
5929
  headroomPid = void 0;
@@ -5853,7 +5932,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
5853
5932
  continue;
5854
5933
  }
5855
5934
  }
5856
- const sessions = sessionsForSupervisor(fs14, paths.headroomSessionsDir, ports.ownPid);
5935
+ const sessions = sessionsForSupervisor(fs15, paths.headroomSessionsDir, ports.ownPid);
5857
5936
  if (sessions.length === 0) {
5858
5937
  idleSince ??= ports.now();
5859
5938
  const idleMs = ports.now() - idleSince;
@@ -5878,9 +5957,9 @@ function undeterminedFrontDoors(inputs) {
5878
5957
  return reason === void 0 ? [] : [{ pid: record.pid, origin: directOrigin(record.directPort), reason }];
5879
5958
  });
5880
5959
  }
5881
- function currentHeadroomAllowlistInputs(fs14, paths, frontDoorLiveness) {
5882
- const named = frontDoorOrigin(readFrontDoorState(fs14, paths.frontdoorStateFile));
5883
- const records = listFrontDoorDirectRecords(fs14, paths.frontdoorDirectRecordsDir);
5960
+ function currentHeadroomAllowlistInputs(fs15, paths, frontDoorLiveness) {
5961
+ const named = frontDoorOrigin(readFrontDoorState(fs15, paths.frontdoorStateFile));
5962
+ const records = listFrontDoorDirectRecords(fs15, paths.frontdoorDirectRecordsDir);
5884
5963
  const liveness = frontDoorLiveness(records.map((record) => record.pid));
5885
5964
  const live = liveFrontDoorDirectRecords(records, liveness).map((record) => directOrigin(record.directPort));
5886
5965
  return {
@@ -5889,8 +5968,8 @@ function currentHeadroomAllowlistInputs(fs14, paths, frontDoorLiveness) {
5889
5968
  frontDoorOrigins: [.../* @__PURE__ */ new Set([...named === void 0 ? [] : [named], ...live])].sort()
5890
5969
  };
5891
5970
  }
5892
- function launchRequiredUpstreams(fs14, paths) {
5893
- const door = frontDoorOrigin(readFrontDoorState(fs14, paths.frontdoorStateFile));
5971
+ function launchRequiredUpstreams(fs15, paths) {
5972
+ const door = frontDoorOrigin(readFrontDoorState(fs15, paths.frontdoorStateFile));
5894
5973
  return door === void 0 ? [] : [door];
5895
5974
  }
5896
5975
  async function waitUntilReady(ports, socketPath, pid) {
@@ -6027,6 +6106,29 @@ function isEnoent3(error) {
6027
6106
  function isErrorWithCode(error, code) {
6028
6107
  return typeof error === "object" && error !== null && "code" in error && error.code === code;
6029
6108
  }
6109
+ function writeFileFlushed(file, contents) {
6110
+ const descriptor = fs3.openSync(file, "w", OWNER_ONLY_FILE_MODE);
6111
+ try {
6112
+ fs3.writeFileSync(descriptor, contents, "utf8");
6113
+ fs3.fchmodSync(descriptor, OWNER_ONLY_FILE_MODE);
6114
+ fs3.fsyncSync(descriptor);
6115
+ } finally {
6116
+ fs3.closeSync(descriptor);
6117
+ }
6118
+ }
6119
+ function flushDirectory(directory) {
6120
+ const descriptor = fs3.openSync(directory, "r");
6121
+ try {
6122
+ fs3.fsyncSync(descriptor);
6123
+ } catch (error) {
6124
+ const code = typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" ? error.code : void 0;
6125
+ if (code === void 0 || !DIRECTORY_FLUSH_UNSUPPORTED_CODES.has(code)) {
6126
+ throw error;
6127
+ }
6128
+ } finally {
6129
+ fs3.closeSync(descriptor);
6130
+ }
6131
+ }
6030
6132
  function realSleepSync(ms) {
6031
6133
  refuseToBlockInRole("a synchronous sleep");
6032
6134
  Atomics.wait(new Int32Array(new SharedArrayBuffer(INT32_BYTE_LENGTH)), 0, 0, ms);
@@ -6060,9 +6162,9 @@ function realFrontDoorLiveness(pids) {
6060
6162
  return { status: result.status, stdout: result.stdout, stderr: result.stderr, ...result.error === void 0 ? {} : { error: result.error } };
6061
6163
  });
6062
6164
  }
6063
- async function realRunAsync(command, args) {
6064
- return await new Promise((resolve) => {
6065
- execFile(command, [...args], { encoding: "utf8", timeout: PS_TIMEOUT_MS }, (error, stdout, stderr) => {
6165
+ function realRunAsyncWithin(timeoutMs) {
6166
+ return async (command, args) => await new Promise((resolve) => {
6167
+ execFile(command, [...args], { encoding: "utf8", timeout: timeoutMs }, (error, stdout, stderr) => {
6066
6168
  resolve({ status: error === null ? 0 : typeof error.code === "number" ? error.code : null, stdout, stderr });
6067
6169
  });
6068
6170
  });
@@ -6268,7 +6370,7 @@ function realResolveClaudeBinary(isOwnBinary) {
6268
6370
  function realInstalledClaudeVersions() {
6269
6371
  return installedVersions(listVersionsDir(defaultVersionsDir()));
6270
6372
  }
6271
- var realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, realFarmFs, INT32_BYTE_LENGTH, KEY_POLL_MS, CTRL_C_BYTE, realHoldPort, PS_TIMEOUT_MS, realRunPort, MACOS_GUI_SESSION_MANAGER, realCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, realLogPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
6373
+ var realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, DIRECTORY_FLUSH_UNSUPPORTED_CODES, realFarmFs, INT32_BYTE_LENGTH, KEY_POLL_MS, CTRL_C_BYTE, realHoldPort, PS_TIMEOUT_MS, RUN_OUTPUT_LIMIT_MIB, BYTES_PER_MIB2, RUN_OUTPUT_LIMIT_BYTES, realRunPort, ASYNC_RUN_TIMEOUT_MS, realRunAsync, MACOS_GUI_SESSION_MANAGER, realCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, realLogPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
6272
6374
  var init_realPorts = __esm({
6273
6375
  "src/realPorts.ts"() {
6274
6376
  "use strict";
@@ -6307,6 +6409,7 @@ var init_realPorts = __esm({
6307
6409
  OWNER_ONLY_DIR_MODE = 448;
6308
6410
  OWNER_ONLY_FILE_MODE = 384;
6309
6411
  PERMISSION_BITS = 511;
6412
+ DIRECTORY_FLUSH_UNSUPPORTED_CODES = /* @__PURE__ */ new Set(["EINVAL", "ENOTSUP", "EOPNOTSUPP"]);
6310
6413
  realFarmFs = {
6311
6414
  lstat(filePath) {
6312
6415
  let stat;
@@ -6363,12 +6466,18 @@ var init_realPorts = __esm({
6363
6466
  fs3.mkdirSync(dirPath, { recursive: true, mode: OWNER_ONLY_DIR_MODE });
6364
6467
  fs3.chmodSync(dirPath, OWNER_ONLY_DIR_MODE);
6365
6468
  },
6366
- writeFilePrivate(filePath, contents) {
6469
+ writeFilePrivate(filePath, contents, options) {
6367
6470
  const temp = `${filePath}.${String(process.pid)}.tmp`;
6368
6471
  try {
6369
- fs3.writeFileSync(temp, contents, { encoding: "utf8", mode: OWNER_ONLY_FILE_MODE });
6370
- fs3.chmodSync(temp, OWNER_ONLY_FILE_MODE);
6371
- fs3.renameSync(temp, filePath);
6472
+ if (options?.durable === true) {
6473
+ writeFileFlushed(temp, contents);
6474
+ fs3.renameSync(temp, filePath);
6475
+ flushDirectory(path15.dirname(filePath));
6476
+ } else {
6477
+ fs3.writeFileSync(temp, contents, { encoding: "utf8", mode: OWNER_ONLY_FILE_MODE });
6478
+ fs3.chmodSync(temp, OWNER_ONLY_FILE_MODE);
6479
+ fs3.renameSync(temp, filePath);
6480
+ }
6372
6481
  } catch (error) {
6373
6482
  fs3.rmSync(temp, { force: true });
6374
6483
  throw error;
@@ -6438,12 +6547,17 @@ var init_realPorts = __esm({
6438
6547
  }
6439
6548
  };
6440
6549
  PS_TIMEOUT_MS = 2e3;
6550
+ RUN_OUTPUT_LIMIT_MIB = 256;
6551
+ BYTES_PER_MIB2 = 1048576;
6552
+ RUN_OUTPUT_LIMIT_BYTES = RUN_OUTPUT_LIMIT_MIB * BYTES_PER_MIB2;
6441
6553
  realRunPort = {
6442
- run(command, args) {
6443
- const result = spawnSyncBlocking("an external command", command, args, { encoding: "utf8" });
6554
+ run(command, args, input) {
6555
+ const result = spawnSyncBlocking("an external command", command, args, { encoding: "utf8", maxBuffer: RUN_OUTPUT_LIMIT_BYTES, ...input === void 0 ? {} : { input } });
6444
6556
  return { status: result.status, stdout: result.stdout, stderr: result.stderr };
6445
6557
  }
6446
6558
  };
6559
+ ASYNC_RUN_TIMEOUT_MS = 2e3;
6560
+ realRunAsync = realRunAsyncWithin(ASYNC_RUN_TIMEOUT_MS);
6447
6561
  MACOS_GUI_SESSION_MANAGER = "Aqua";
6448
6562
  realCredentialPort = {
6449
6563
  readSecretFile(filePath) {
@@ -6635,8 +6749,8 @@ import path18 from "node:path";
6635
6749
  function poolNameOf(selector) {
6636
6750
  return selector.startsWith(POOL_SELECTOR_PREFIX) ? selector.slice(POOL_SELECTOR_PREFIX.length) : void 0;
6637
6751
  }
6638
- function readActiveIdentity(fs14, activeIdentityFile) {
6639
- const trimmed = fs14.readFileUtf8(activeIdentityFile)?.trim();
6752
+ function readActiveIdentity(fs15, activeIdentityFile) {
6753
+ const trimmed = fs15.readFileUtf8(activeIdentityFile)?.trim();
6640
6754
  return trimmed === void 0 || trimmed === "" ? void 0 : trimmed;
6641
6755
  }
6642
6756
  function isNonEmpty(value) {
@@ -6686,11 +6800,11 @@ function decideConfigProfile(params) {
6686
6800
  }
6687
6801
  return { source: "none" };
6688
6802
  }
6689
- function loadIdentity(identitiesDir, name, fs14) {
6803
+ function loadIdentity(identitiesDir, name, fs15) {
6690
6804
  if (!isFileName(name)) {
6691
6805
  throw new UnsafeNameError(name, "identity", FILE_NAME_RULE);
6692
6806
  }
6693
- return loadConfigFile(path18.join(identitiesDir, name, "identity.json"), IdentitySchema, fs14.readConfigFile);
6807
+ return loadConfigFile(path18.join(identitiesDir, name, "identity.json"), IdentitySchema, fs15.readConfigFile);
6694
6808
  }
6695
6809
  var IDENTITY_DECISION_SOURCES, IDENTITY_SOURCE_LABELS, CONFIG_PROFILE_DECISION_SOURCES;
6696
6810
  var init_identity = __esm({
@@ -6944,14 +7058,14 @@ function isIdentityName(name) {
6944
7058
  function claudeJsonPath(identitiesDir, identity) {
6945
7059
  return path19.join(identitiesDir, identity, CLAUDE_JSON);
6946
7060
  }
6947
- function readAccountMetadata(fs14, identitiesDir, identity) {
7061
+ function readAccountMetadata(fs15, identitiesDir, identity) {
6948
7062
  if (!isIdentityName(identity)) {
6949
7063
  throw new Error(`"${identity}" is not a valid identity name.`);
6950
7064
  }
6951
- return readAccountMetadataFile(fs14, claudeJsonPath(identitiesDir, identity));
7065
+ return readAccountMetadataFile(fs15, claudeJsonPath(identitiesDir, identity));
6952
7066
  }
6953
- function readAccountMetadataFile(fs14, file) {
6954
- const raw = fs14.readFileUtf8(file);
7067
+ function readAccountMetadataFile(fs15, file) {
7068
+ const raw = fs15.readFileUtf8(file);
6955
7069
  if (raw === void 0) {
6956
7070
  return void 0;
6957
7071
  }
@@ -6981,19 +7095,19 @@ function readAccountMetadataFile(fs14, file) {
6981
7095
  }
6982
7096
  return account.data;
6983
7097
  }
6984
- function createAccountReader(fs14, identitiesDir) {
7098
+ function createAccountReader(fs15, identitiesDir) {
6985
7099
  const cache = /* @__PURE__ */ new Map();
6986
7100
  return (identity) => {
6987
7101
  if (!isIdentityName(identity)) {
6988
7102
  throw new Error(`"${identity}" is not a valid identity name.`);
6989
7103
  }
6990
- const stat = fs14.lstat(claudeJsonPath(identitiesDir, identity));
7104
+ const stat = fs15.lstat(claudeJsonPath(identitiesDir, identity));
6991
7105
  const stamp = stat === void 0 ? "absent" : `${String(stat.mtimeMs)}:${String(stat.sizeBytes)}`;
6992
7106
  const cached = cache.get(identity);
6993
7107
  if (cached?.stamp === stamp) {
6994
7108
  return cached.account;
6995
7109
  }
6996
- const account = readAccountMetadata(fs14, identitiesDir, identity);
7110
+ const account = readAccountMetadata(fs15, identitiesDir, identity);
6997
7111
  cache.set(identity, { stamp, account });
6998
7112
  return account;
6999
7113
  };
@@ -7029,9 +7143,9 @@ var init_accountDescription = __esm({
7029
7143
  });
7030
7144
 
7031
7145
  // src/identityAccounts.ts
7032
- function readIdentityAccount(fs14, identitiesDir, identity) {
7146
+ function readIdentityAccount(fs15, identitiesDir, identity) {
7033
7147
  try {
7034
- const account = readAccountMetadata(fs14, identitiesDir, identity);
7148
+ const account = readAccountMetadata(fs15, identitiesDir, identity);
7035
7149
  return account === void 0 ? void 0 : { account };
7036
7150
  } catch (error) {
7037
7151
  if (error instanceof AccountMetadataError) {
@@ -7403,10 +7517,10 @@ function billedTokensOf(record) {
7403
7517
  const usage = record.usage;
7404
7518
  return (usage?.inputTokens ?? 0) + (usage?.cacheCreationInputTokens ?? 0) + (usage?.outputTokens ?? 0);
7405
7519
  }
7406
- function utilisationPerBilledToken(records) {
7520
+ function utilisationPerBilledToken(records, which) {
7407
7521
  const points = [];
7408
7522
  for (const record of records) {
7409
- const window = record.rateLimitHeaders === void 0 ? void 0 : parseUnifiedRateLimit(record.rateLimitHeaders)?.fiveHour;
7523
+ const window = record.rateLimitHeaders === void 0 ? void 0 : parseUnifiedRateLimit(record.rateLimitHeaders)?.[which];
7410
7524
  if (window?.utilization !== void 0 && window.resetsAt !== void 0) {
7411
7525
  points.push({ resetsAt: window.resetsAt, utilization: window.utilization, billed: billedTokensOf(record) });
7412
7526
  }
@@ -7591,14 +7705,17 @@ function rankPool(input) {
7591
7705
  }
7592
7706
  const { sticky: sticky2 } = input;
7593
7707
  const warmHere = sticky2?.identity === candidate.identity && nowMs - Date.parse(sticky2.at) <= PROMPT_CACHE_TTL_MS;
7594
- if (input.resuming && input.resumeContextTokens !== void 0 && fiveHour !== void 0 && !warmHere) {
7595
- const perToken = utilisationPerBilledToken(assessment.member.records);
7708
+ const resumeTokens = input.resumeContextTokens;
7709
+ if (input.resuming && resumeTokens !== void 0 && !warmHere) {
7596
7710
  const committed = input.committedContextTokens?.[candidate.identity] ?? 0;
7597
- const cost = perToken === void 0 ? void 0 : (input.resumeContextTokens + committed) * perToken;
7598
- if (cost !== void 0 && cost > fiveHour.remaining) {
7599
- dryAfterMs.push(0);
7600
- const alongside = committed === 0 ? "" : ` (with ${String(committed)} tokens of other conversations already moving here)`;
7601
- drySpots.push(`resuming a ${String(input.resumeContextTokens)}-token conversation here${alongside} would cost about ${percent(cost)} of the 5h window, which has ${percent(fiveHour.remaining)} left`);
7711
+ const alongside = committed === 0 ? "" : ` (with ${String(committed)} tokens of other conversations already moving here)`;
7712
+ for (const [name, label, window] of [["fiveHour", "5h", fiveHour], ["sevenDay", "7d", sevenDay]]) {
7713
+ const perToken = window === void 0 ? void 0 : utilisationPerBilledToken(assessment.member.records, name);
7714
+ const cost = perToken === void 0 ? void 0 : (resumeTokens + committed) * perToken;
7715
+ if (window !== void 0 && cost !== void 0 && cost > window.remaining) {
7716
+ dryAfterMs.push(0);
7717
+ drySpots.push(`resuming a ${String(resumeTokens)}-token conversation here${alongside} would cost about ${percent(cost)} of the ${label} window, which has ${percent(window.remaining)} left`);
7718
+ }
7602
7719
  }
7603
7720
  }
7604
7721
  if (drySpots.length === 0) {
@@ -7667,8 +7784,8 @@ function segmentDay(epochMs) {
7667
7784
  function segmentName(day, pid) {
7668
7785
  return `${day}.${String(pid)}.jsonl`;
7669
7786
  }
7670
- function listLogSegments(fs14, logDir) {
7671
- return fs14.readdir(logDir).flatMap((name) => {
7787
+ function listLogSegments(fs15, logDir) {
7788
+ return fs15.readdir(logDir).flatMap((name) => {
7672
7789
  const match = SEGMENT_RE.exec(name);
7673
7790
  const day = match?.[1];
7674
7791
  if (day === void 0) {
@@ -7677,15 +7794,15 @@ function listLogSegments(fs14, logDir) {
7677
7794
  return [{ name, day, endsAt: Date.parse(`${day}T00:00:00.000Z`) + DAY_MS }];
7678
7795
  }).sort((left, right) => left.day.localeCompare(right.day) || left.name.localeCompare(right.name));
7679
7796
  }
7680
- function readUsageLog(fs14, logDir, options = {}) {
7797
+ function readUsageLog(fs15, logDir, options = {}) {
7681
7798
  const { sinceMs } = options;
7682
7799
  const records = [];
7683
7800
  let invalidLines = 0;
7684
- for (const segment of listLogSegments(fs14, logDir)) {
7801
+ for (const segment of listLogSegments(fs15, logDir)) {
7685
7802
  if (sinceMs !== void 0 && segment.endsAt <= sinceMs) {
7686
7803
  continue;
7687
7804
  }
7688
- const read = readSegment(fs14, logDir, segment);
7805
+ const read = readSegment(fs15, logDir, segment);
7689
7806
  if (read === void 0) {
7690
7807
  continue;
7691
7808
  }
@@ -7699,8 +7816,8 @@ function readUsageLog(fs14, logDir, options = {}) {
7699
7816
  records.sort((left, right) => left.at.localeCompare(right.at));
7700
7817
  return { records, invalidLines };
7701
7818
  }
7702
- function readSegment(fs14, logDir, segment) {
7703
- const contents = fs14.readFileUtf8(path20.join(logDir, segment.name));
7819
+ function readSegment(fs15, logDir, segment) {
7820
+ const contents = fs15.readFileUtf8(path20.join(logDir, segment.name));
7704
7821
  if (contents === void 0) {
7705
7822
  return void 0;
7706
7823
  }
@@ -7734,9 +7851,9 @@ function snapshotPath(snapshotsDir, identity) {
7734
7851
  }
7735
7852
  return path20.join(snapshotsDir, `${identity}.json`);
7736
7853
  }
7737
- function readUsageSnapshot(fs14, snapshotsDir, identity) {
7854
+ function readUsageSnapshot(fs15, snapshotsDir, identity) {
7738
7855
  const file = snapshotPath(snapshotsDir, identity);
7739
- const raw = fs14.readFileUtf8(file);
7856
+ const raw = fs15.readFileUtf8(file);
7740
7857
  if (raw === void 0) {
7741
7858
  return void 0;
7742
7859
  }
@@ -7752,8 +7869,8 @@ function readUsageSnapshot(fs14, snapshotsDir, identity) {
7752
7869
  }
7753
7870
  return snapshot.data;
7754
7871
  }
7755
- function listUsageSnapshots(fs14, snapshotsDir) {
7756
- return fs14.readdir(snapshotsDir).flatMap((name) => {
7872
+ function listUsageSnapshots(fs15, snapshotsDir) {
7873
+ return fs15.readdir(snapshotsDir).flatMap((name) => {
7757
7874
  if (!name.endsWith(".json")) {
7758
7875
  return [];
7759
7876
  }
@@ -7761,7 +7878,7 @@ function listUsageSnapshots(fs14, snapshotsDir) {
7761
7878
  if (!isIdentityName(identity)) {
7762
7879
  return [];
7763
7880
  }
7764
- const snapshot = readUsageSnapshot(fs14, snapshotsDir, identity);
7881
+ const snapshot = readUsageSnapshot(fs15, snapshotsDir, identity);
7765
7882
  return snapshot === void 0 ? [] : [snapshot];
7766
7883
  }).sort((left, right) => left.identity.localeCompare(right.identity));
7767
7884
  }
@@ -7786,11 +7903,11 @@ var init_read = __esm({
7786
7903
 
7787
7904
  // src/usage/store.ts
7788
7905
  import path21 from "node:path";
7789
- function pruneUsageLog(fs14, logDir, nowMs) {
7906
+ function pruneUsageLog(fs15, logDir, nowMs) {
7790
7907
  const cutoff = nowMs - USAGE_RETENTION_MS;
7791
- for (const segment of listLogSegments(fs14, logDir)) {
7908
+ for (const segment of listLogSegments(fs15, logDir)) {
7792
7909
  if (segment.endsAt <= cutoff) {
7793
- fs14.removeRecursive(path21.join(logDir, segment.name));
7910
+ fs15.removeRecursive(path21.join(logDir, segment.name));
7794
7911
  }
7795
7912
  }
7796
7913
  }
@@ -7819,7 +7936,7 @@ function foldProviderState(current, record) {
7819
7936
  };
7820
7937
  }
7821
7938
  function createUsageStore(deps) {
7822
- const { fs: fs14, paths } = deps;
7939
+ const { fs: fs15, paths } = deps;
7823
7940
  let prunedDay;
7824
7941
  const rewriteSnapshot = (identity, fold) => {
7825
7942
  if (!isIdentityName(identity)) {
@@ -7828,7 +7945,7 @@ function createUsageStore(deps) {
7828
7945
  }
7829
7946
  let current;
7830
7947
  try {
7831
- current = readUsageSnapshot(fs14, paths.usageSnapshotsDir, identity);
7948
+ current = readUsageSnapshot(fs15, paths.usageSnapshotsDir, identity);
7832
7949
  } catch (error) {
7833
7950
  if (!(error instanceof UsageSnapshotError)) {
7834
7951
  throw error;
@@ -7855,8 +7972,8 @@ function createUsageStore(deps) {
7855
7972
  ...account === void 0 ? {} : { account },
7856
7973
  providers
7857
7974
  });
7858
- fs14.mkdirPrivate(paths.usageSnapshotsDir);
7859
- fs14.writeFilePrivate(snapshotPath(paths.usageSnapshotsDir, identity), `${JSON.stringify(snapshot, null, 2)}
7975
+ fs15.mkdirPrivate(paths.usageSnapshotsDir);
7976
+ fs15.writeFilePrivate(snapshotPath(paths.usageSnapshotsDir, identity), `${JSON.stringify(snapshot, null, 2)}
7860
7977
  `);
7861
7978
  deps.publish?.(snapshot);
7862
7979
  return true;
@@ -7865,14 +7982,14 @@ function createUsageStore(deps) {
7865
7982
  record: (input) => {
7866
7983
  const record = UsageRecordSchema.parse(input);
7867
7984
  const nowMs = deps.now();
7868
- fs14.mkdirPrivate(paths.usageDir);
7869
- fs14.mkdirPrivate(paths.usageLogDir);
7985
+ fs15.mkdirPrivate(paths.usageDir);
7986
+ fs15.mkdirPrivate(paths.usageLogDir);
7870
7987
  const day = segmentDay(nowMs);
7871
7988
  if (prunedDay !== day) {
7872
- pruneUsageLog(fs14, paths.usageLogDir, nowMs);
7989
+ pruneUsageLog(fs15, paths.usageLogDir, nowMs);
7873
7990
  prunedDay = day;
7874
7991
  }
7875
- fs14.appendFilePrivate(path21.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record)}
7992
+ fs15.appendFilePrivate(path21.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record)}
7876
7993
  `);
7877
7994
  deps.onRecord?.(record);
7878
7995
  if (record.identity !== void 0) {
@@ -7916,14 +8033,14 @@ import { z as z15 } from "zod";
7916
8033
  function errorMessage(error) {
7917
8034
  return error instanceof Error ? error.message : String(error);
7918
8035
  }
7919
- function loadPoolMembers(fs14, paths, identities, nowMs) {
8036
+ function loadPoolMembers(fs15, paths, identities, nowMs) {
7920
8037
  const windowStartMs = nowMs - FIVE_HOUR_WINDOW_MS;
7921
- const log = readUsageLog(fs14, paths.usageLogDir, { sinceMs: windowStartMs });
8038
+ const log = readUsageLog(fs15, paths.usageLogDir, { sinceMs: windowStartMs });
7922
8039
  return identities.map((identity) => {
7923
8040
  const records = log.records.filter((record) => record.identity === identity && record.provider === ANTHROPIC_PROVIDER && Date.parse(record.at) >= windowStartMs);
7924
8041
  try {
7925
- const snapshot = readUsageSnapshot(fs14, paths.usageSnapshotsDir, identity);
7926
- const account = readAccountMetadata(fs14, paths.identitiesDir, identity) ?? snapshot?.account;
8042
+ const snapshot = readUsageSnapshot(fs15, paths.usageSnapshotsDir, identity);
8043
+ const account = readAccountMetadata(fs15, paths.identitiesDir, identity) ?? snapshot?.account;
7927
8044
  return { identity, records, ...snapshot === void 0 ? {} : { snapshot }, ...account === void 0 ? {} : { account } };
7928
8045
  } catch (error) {
7929
8046
  if (error instanceof UsageSnapshotError || error instanceof AccountMetadataError) {
@@ -8042,9 +8159,9 @@ function collectPoolIdentities(pools, poolName, stack, found) {
8042
8159
  collectPoolIdentities(pools, nestedName, childStack, found);
8043
8160
  }
8044
8161
  }
8045
- function readPicksFile(fs14, file) {
8162
+ function readPicksFile(fs15, file) {
8046
8163
  const empty = { schemaVersion: SCHEMA_VERSION, picks: {} };
8047
- const raw = fs14.readFileUtf8(file);
8164
+ const raw = fs15.readFileUtf8(file);
8048
8165
  if (raw === void 0) {
8049
8166
  return { file: empty };
8050
8167
  }
@@ -8057,17 +8174,17 @@ function readPicksFile(fs14, file) {
8057
8174
  const result = PicksFileSchema.safeParse(parsed);
8058
8175
  return result.success ? { file: result.data } : { file: empty, problem: `${file} is not a picks file this agent-shim can read` };
8059
8176
  }
8060
- function readStickyPick(fs14, picksFile, directory) {
8061
- const read = readPicksFile(fs14, picksFile);
8177
+ function readStickyPick(fs15, picksFile, directory) {
8178
+ const read = readPicksFile(fs15, picksFile);
8062
8179
  const entry = read.file.picks[directory];
8063
8180
  return { ...entry === void 0 ? {} : { sticky: entry }, ...read.problem === void 0 ? {} : { problem: read.problem } };
8064
8181
  }
8065
- function recordStickyPick(fs14, picksFile, directory, identity, nowMs) {
8066
- const current = readPicksFile(fs14, picksFile).file.picks;
8182
+ function recordStickyPick(fs15, picksFile, directory, identity, nowMs) {
8183
+ const current = readPicksFile(fs15, picksFile).file.picks;
8067
8184
  const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
8068
8185
  const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
8069
- fs14.mkdirPrivate(path22.dirname(picksFile));
8070
- fs14.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
8186
+ fs15.mkdirPrivate(path22.dirname(picksFile));
8187
+ fs15.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
8071
8188
  `);
8072
8189
  }
8073
8190
  var PoolGraphError, SCHEMA_VERSION, PickEntrySchema, PicksFileSchema;
@@ -8100,9 +8217,9 @@ var init_poolPick = __esm({
8100
8217
 
8101
8218
  // src/statusline/keys.ts
8102
8219
  import { z as z16 } from "zod";
8103
- function valueAt(source, path42) {
8220
+ function valueAt(source, path45) {
8104
8221
  let current = source;
8105
- for (const part of path42) {
8222
+ for (const part of path45) {
8106
8223
  if (!isPlainObject(current)) {
8107
8224
  return void 0;
8108
8225
  }
@@ -8110,14 +8227,14 @@ function valueAt(source, path42) {
8110
8227
  }
8111
8228
  return current;
8112
8229
  }
8113
- function acceptsNull(path42) {
8114
- const layer = path42.reduceRight((inner, part) => ({ [part]: inner }), null);
8230
+ function acceptsNull(path45) {
8231
+ const layer = path45.reduceRight((inner, part) => ({ [part]: inner }), null);
8115
8232
  return StatuslineSchema.safeParse(layer).success;
8116
8233
  }
8117
- function keyOf(path42, declared) {
8234
+ function keyOf(path45, declared) {
8118
8235
  const optional = declared instanceof z16.ZodOptional;
8119
8236
  const leaf = optional ? declared.unwrap() : declared;
8120
- const common = { path: path42.join("."), description: declared.description ?? "", defaultValue: valueAt(STATUSLINE_DEFAULTS, path42), optional, unsettable: acceptsNull(path42) };
8237
+ const common = { path: path45.join("."), description: declared.description ?? "", defaultValue: valueAt(STATUSLINE_DEFAULTS, path45), optional, unsettable: acceptsNull(path45) };
8121
8238
  if (leaf instanceof z16.ZodNumber) {
8122
8239
  return { ...common, kind: "integer", choices: [] };
8123
8240
  }
@@ -8142,7 +8259,7 @@ function keyOf(path42, declared) {
8142
8259
  if (leaf instanceof z16.ZodArray && leaf.element instanceof z16.ZodString) {
8143
8260
  return { ...common, kind: "textList", choices: [] };
8144
8261
  }
8145
- throw new TypeError(`statusline setting ${path42.join(".")} has a kind the key listing does not describe`);
8262
+ throw new TypeError(`statusline setting ${path45.join(".")} has a kind the key listing does not describe`);
8146
8263
  }
8147
8264
  function walk(shape, prefix) {
8148
8265
  return Object.entries(shape).flatMap(([name, schema]) => schema instanceof z16.ZodObject ? walk(schema.shape, [...prefix, name]) : [keyOf([...prefix, name], schema)]);
@@ -8158,15 +8275,15 @@ var init_keys = __esm({
8158
8275
  });
8159
8276
 
8160
8277
  // src/statusline/change.ts
8161
- function keyNamed(path42) {
8162
- const found = statuslineKeys().find((key) => key.path === path42);
8278
+ function keyNamed(path45) {
8279
+ const found = statuslineKeys().find((key) => key.path === path45);
8163
8280
  if (found === void 0) {
8164
- throw new UsageError(`"${path42}" is not a statusline setting; \`agent-shim statusline keys\` lists them.`);
8281
+ throw new UsageError(`"${path45}" is not a statusline setting; \`agent-shim statusline keys\` lists them.`);
8165
8282
  }
8166
8283
  return found;
8167
8284
  }
8168
- function setAt(target, path42, value) {
8169
- const [head, ...rest] = path42;
8285
+ function setAt(target, path45, value) {
8286
+ const [head, ...rest] = path45;
8170
8287
  if (head === void 0) {
8171
8288
  return;
8172
8289
  }
@@ -8179,8 +8296,8 @@ function setAt(target, path42, value) {
8179
8296
  target[head] = next;
8180
8297
  setAt(next, rest, value);
8181
8298
  }
8182
- function removeAt(target, path42) {
8183
- const [head, ...rest] = path42;
8299
+ function removeAt(target, path45) {
8300
+ const [head, ...rest] = path45;
8184
8301
  if (head === void 0) {
8185
8302
  return;
8186
8303
  }
@@ -8198,13 +8315,13 @@ function removeAt(target, path42) {
8198
8315
  }
8199
8316
  function applyStatuslineChange(existing, change) {
8200
8317
  const draft = structuredClone(existing ?? {});
8201
- for (const [path42, value] of Object.entries(change.set ?? {})) {
8202
- keyNamed(path42);
8203
- setAt(draft, path42.split("."), value);
8318
+ for (const [path45, value] of Object.entries(change.set ?? {})) {
8319
+ keyNamed(path45);
8320
+ setAt(draft, path45.split("."), value);
8204
8321
  }
8205
- for (const path42 of change.unset ?? []) {
8206
- keyNamed(path42);
8207
- removeAt(draft, path42.split("."));
8322
+ for (const path45 of change.unset ?? []) {
8323
+ keyNamed(path45);
8324
+ removeAt(draft, path45.split("."));
8208
8325
  }
8209
8326
  const result = StatuslineSchema.safeParse(draft);
8210
8327
  if (!result.success) {
@@ -8493,6 +8610,8 @@ function buildLayoutPaths(root) {
8493
8610
  usageAnchorsFile: path23.join(root, "usage", "anchors.json"),
8494
8611
  usageJobsFile: path23.join(root, "usage", "jobs.json"),
8495
8612
  jobLogsDir: path23.join(root, "logs", "jobs"),
8613
+ identityRenamesDir: path23.join(root, "identity-renames"),
8614
+ launchesDir: path23.join(root, "launches"),
8496
8615
  superviseDir: path23.join(root, "supervise"),
8497
8616
  modelMovesDir: path23.join(root, "model-moves"),
8498
8617
  mcpPermissionsFile: path23.join(root, "mcp", "permissions.json")
@@ -9208,7 +9327,12 @@ function readProvider(paths, name) {
9208
9327
  if (!fs7.existsSync(filePath)) {
9209
9328
  return void 0;
9210
9329
  }
9211
- const raw = JSON.parse(fs7.readFileSync(filePath, "utf8"));
9330
+ let raw;
9331
+ try {
9332
+ raw = JSON.parse(fs7.readFileSync(filePath, "utf8"));
9333
+ } catch (error) {
9334
+ throw error instanceof SyntaxError ? new ConfigFileNotJsonError(filePath) : error;
9335
+ }
9212
9336
  return parseProviderFile(filePath, raw);
9213
9337
  }
9214
9338
  function loadProvider(providersDir, name, port) {
@@ -9230,7 +9354,7 @@ function listProviders(paths, onInvalid = reportInvalidProvider) {
9230
9354
  try {
9231
9355
  provider = readProvider(paths, name);
9232
9356
  } catch (error) {
9233
- if (!(error instanceof ConfigValidationError || error instanceof LegacyProviderFileError || error instanceof UnsafeNameError)) {
9357
+ if (!(error instanceof ConfigValidationError || error instanceof LegacyProviderFileError || error instanceof ConfigFileNotJsonError || error instanceof UnsafeNameError)) {
9234
9358
  throw error;
9235
9359
  }
9236
9360
  onInvalid(name, error.message);
@@ -9576,13 +9700,13 @@ function decideSignIn(facts) {
9576
9700
  function credentialsFilePath(farmRoot) {
9577
9701
  return path25.join(farmRoot, CREDENTIALS_FILE);
9578
9702
  }
9579
- function identitySignIn(fs14, probe, identity) {
9703
+ function identitySignIn(fs15, probe, identity) {
9580
9704
  const probing = !identity.hasCredentialBlock && identity.provider === void 0;
9581
9705
  return decideSignIn({
9582
9706
  hasCredentialBlock: identity.hasCredentialBlock,
9583
9707
  provider: identity.provider,
9584
9708
  keychainItem: probing && probe.platform === "darwin" && probe.run !== void 0 ? keychainHasItem(probe.run, identity.farmRoot) : void 0,
9585
- credentialsFile: probing && fs14.lstat(credentialsFilePath(identity.farmRoot)) !== void 0,
9709
+ credentialsFile: probing && fs15.lstat(credentialsFilePath(identity.farmRoot)) !== void 0,
9586
9710
  platform: probe.platform
9587
9711
  });
9588
9712
  }
@@ -9961,62 +10085,62 @@ var init_signatures = __esm({
9961
10085
  });
9962
10086
 
9963
10087
  // src/codex/anthropic.ts
9964
- import { z as z27 } from "zod";
10088
+ import { z as z28 } from "zod";
9965
10089
  var TextBlockSchema, Base64ImageSourceSchema, UrlImageSourceSchema, ImageBlockSchema, ToolUseBlockSchema, ToolResultContentBlockSchema, ToolResultBlockSchema, OtherBlockSchema, ContentBlockSchema, MessageSchema, ToolSchema, ToolChoiceSchema, SystemSchema, MessagesRequestSchema, CountTokensRequestSchema;
9966
10090
  var init_anthropic = __esm({
9967
10091
  "src/codex/anthropic.ts"() {
9968
10092
  "use strict";
9969
- TextBlockSchema = z27.looseObject({ type: z27.literal("text"), text: z27.string() });
9970
- Base64ImageSourceSchema = z27.looseObject({ type: z27.literal("base64"), media_type: z27.string().min(1), data: z27.string() });
9971
- UrlImageSourceSchema = z27.looseObject({ type: z27.literal("url"), url: z27.string().min(1) });
9972
- ImageBlockSchema = z27.looseObject({
9973
- type: z27.literal("image"),
9974
- source: z27.union([Base64ImageSourceSchema, UrlImageSourceSchema])
10093
+ TextBlockSchema = z28.looseObject({ type: z28.literal("text"), text: z28.string() });
10094
+ Base64ImageSourceSchema = z28.looseObject({ type: z28.literal("base64"), media_type: z28.string().min(1), data: z28.string() });
10095
+ UrlImageSourceSchema = z28.looseObject({ type: z28.literal("url"), url: z28.string().min(1) });
10096
+ ImageBlockSchema = z28.looseObject({
10097
+ type: z28.literal("image"),
10098
+ source: z28.union([Base64ImageSourceSchema, UrlImageSourceSchema])
9975
10099
  });
9976
- ToolUseBlockSchema = z27.looseObject({
9977
- type: z27.literal("tool_use"),
9978
- id: z27.string().min(1),
9979
- name: z27.string().min(1),
9980
- input: z27.unknown()
10100
+ ToolUseBlockSchema = z28.looseObject({
10101
+ type: z28.literal("tool_use"),
10102
+ id: z28.string().min(1),
10103
+ name: z28.string().min(1),
10104
+ input: z28.unknown()
9981
10105
  });
9982
- ToolResultContentBlockSchema = z27.union([TextBlockSchema, z27.looseObject({ type: z27.string() })]);
9983
- ToolResultBlockSchema = z27.looseObject({
9984
- type: z27.literal("tool_result"),
9985
- tool_use_id: z27.string().min(1),
9986
- content: z27.union([z27.string(), z27.array(ToolResultContentBlockSchema)]).optional()
10106
+ ToolResultContentBlockSchema = z28.union([TextBlockSchema, z28.looseObject({ type: z28.string() })]);
10107
+ ToolResultBlockSchema = z28.looseObject({
10108
+ type: z28.literal("tool_result"),
10109
+ tool_use_id: z28.string().min(1),
10110
+ content: z28.union([z28.string(), z28.array(ToolResultContentBlockSchema)]).optional()
9987
10111
  });
9988
- OtherBlockSchema = z27.looseObject({ type: z27.string() });
9989
- ContentBlockSchema = z27.union([TextBlockSchema, ImageBlockSchema, ToolUseBlockSchema, ToolResultBlockSchema, OtherBlockSchema]);
9990
- MessageSchema = z27.looseObject({
9991
- role: z27.enum(["user", "assistant", "system"]),
9992
- content: z27.union([z27.string(), z27.array(ContentBlockSchema)])
10112
+ OtherBlockSchema = z28.looseObject({ type: z28.string() });
10113
+ ContentBlockSchema = z28.union([TextBlockSchema, ImageBlockSchema, ToolUseBlockSchema, ToolResultBlockSchema, OtherBlockSchema]);
10114
+ MessageSchema = z28.looseObject({
10115
+ role: z28.enum(["user", "assistant", "system"]),
10116
+ content: z28.union([z28.string(), z28.array(ContentBlockSchema)])
9993
10117
  });
9994
- ToolSchema = z27.looseObject({
9995
- name: z27.string().min(1),
9996
- description: z27.string().optional(),
9997
- input_schema: z27.record(z27.string(), z27.unknown()).optional()
10118
+ ToolSchema = z28.looseObject({
10119
+ name: z28.string().min(1),
10120
+ description: z28.string().optional(),
10121
+ input_schema: z28.record(z28.string(), z28.unknown()).optional()
9998
10122
  });
9999
- ToolChoiceSchema = z27.union([
10000
- z27.looseObject({ type: z27.enum(["auto", "none", "any"]) }),
10001
- z27.looseObject({ type: z27.literal("tool"), name: z27.string().min(1) })
10123
+ ToolChoiceSchema = z28.union([
10124
+ z28.looseObject({ type: z28.enum(["auto", "none", "any"]) }),
10125
+ z28.looseObject({ type: z28.literal("tool"), name: z28.string().min(1) })
10002
10126
  ]);
10003
- SystemSchema = z27.union([z27.string(), z27.array(z27.union([TextBlockSchema, OtherBlockSchema]))]);
10004
- MessagesRequestSchema = z27.looseObject({
10005
- model: z27.string().optional(),
10127
+ SystemSchema = z28.union([z28.string(), z28.array(z28.union([TextBlockSchema, OtherBlockSchema]))]);
10128
+ MessagesRequestSchema = z28.looseObject({
10129
+ model: z28.string().optional(),
10006
10130
  system: SystemSchema.optional(),
10007
- messages: z27.array(MessageSchema),
10008
- tools: z27.array(ToolSchema).optional(),
10131
+ messages: z28.array(MessageSchema),
10132
+ tools: z28.array(ToolSchema).optional(),
10009
10133
  tool_choice: ToolChoiceSchema.optional(),
10010
- stream: z27.boolean().optional(),
10134
+ stream: z28.boolean().optional(),
10011
10135
  /** `user_id` is stable for one Claude Code session and differs between sessions, which is what makes it the right key for both the backend's prompt cache and its session header. */
10012
- metadata: z27.looseObject({ user_id: z27.string().optional() }).optional(),
10136
+ metadata: z28.looseObject({ user_id: z28.string().optional() }).optional(),
10013
10137
  /** Claude Code's effort setting. Any string is accepted; the translator honours only the levels the backend understands. */
10014
- output_config: z27.looseObject({ effort: z27.string().optional() }).optional()
10138
+ output_config: z28.looseObject({ effort: z28.string().optional() }).optional()
10015
10139
  });
10016
- CountTokensRequestSchema = z27.looseObject({
10017
- system: z27.unknown().optional(),
10018
- messages: z27.unknown().optional(),
10019
- tools: z27.unknown().optional()
10140
+ CountTokensRequestSchema = z28.looseObject({
10141
+ system: z28.unknown().optional(),
10142
+ messages: z28.unknown().optional(),
10143
+ tools: z28.unknown().optional()
10020
10144
  });
10021
10145
  }
10022
10146
  });
@@ -10100,7 +10224,7 @@ var init_translate2 = __esm({
10100
10224
 
10101
10225
  // src/providerCatalogue.ts
10102
10226
  import picomatch4 from "picomatch";
10103
- import { z as z28 } from "zod";
10227
+ import { z as z29 } from "zod";
10104
10228
  function catalogueCachePath(paths, name) {
10105
10229
  return providerFilePath(paths.catalogueDir, name);
10106
10230
  }
@@ -10136,8 +10260,8 @@ var init_providerCatalogue = __esm({
10136
10260
  CATALOGUE_REQUEST_SECONDS = 10;
10137
10261
  CATALOGUE_REQUEST_TIMEOUT_MS = CATALOGUE_REQUEST_SECONDS * MS_PER_SECOND5;
10138
10262
  CATALOGUE_REFRESH_TIMEOUT_MS = DEFAULT_CANDIDATE_URLS * CATALOGUE_REQUEST_TIMEOUT_MS;
10139
- CatalogueModelSchema = z28.strictObject({ id: z28.string().min(1), name: z28.string().min(1).optional() });
10140
- CatalogueCacheSchema = z28.strictObject({ fetchedAt: z28.number(), url: z28.string().min(1), models: z28.array(CatalogueModelSchema) });
10263
+ CatalogueModelSchema = z29.strictObject({ id: z29.string().min(1), name: z29.string().min(1).optional() });
10264
+ CatalogueCacheSchema = z29.strictObject({ fetchedAt: z29.number(), url: z29.string().min(1), models: z29.array(CatalogueModelSchema) });
10141
10265
  }
10142
10266
  });
10143
10267
 
@@ -10444,6 +10568,60 @@ var init_proxyBypass2 = __esm({
10444
10568
  }
10445
10569
  });
10446
10570
 
10571
+ // src/replayRun.ts
10572
+ function keyOf2(command, args) {
10573
+ return JSON.stringify([command, args]);
10574
+ }
10575
+ async function recordRuns(decide, runAsync) {
10576
+ const answers = /* @__PURE__ */ new Map();
10577
+ const replay = {
10578
+ run: (command, args) => {
10579
+ const answer = answers.get(keyOf2(command, args));
10580
+ if (answer === void 0) {
10581
+ throw new RunNeededError(command, args);
10582
+ }
10583
+ return answer;
10584
+ }
10585
+ };
10586
+ for (; ; ) {
10587
+ try {
10588
+ decide(replay);
10589
+ return replay;
10590
+ } catch (error) {
10591
+ if (!(error instanceof RunNeededError)) {
10592
+ throw error;
10593
+ }
10594
+ answers.set(keyOf2(error.command, error.args), await runAsync(error.command, error.args));
10595
+ }
10596
+ }
10597
+ }
10598
+ async function resolveWithAsyncRuns(decide, runAsync) {
10599
+ let result;
10600
+ await recordRuns((run) => {
10601
+ result = { value: decide(run) };
10602
+ }, runAsync);
10603
+ if (result === void 0) {
10604
+ throw new Error("the decision finished without a result");
10605
+ }
10606
+ return result.value;
10607
+ }
10608
+ var RunNeededError;
10609
+ var init_replayRun = __esm({
10610
+ "src/replayRun.ts"() {
10611
+ "use strict";
10612
+ RunNeededError = class extends Error {
10613
+ constructor(command, args) {
10614
+ super(`no recorded answer for ${command} ${args.join(" ")}`);
10615
+ this.command = command;
10616
+ this.args = args;
10617
+ this.name = "RunNeededError";
10618
+ }
10619
+ command;
10620
+ args;
10621
+ };
10622
+ }
10623
+ });
10624
+
10447
10625
  // src/update/update.ts
10448
10626
  function compareVersions3(left, right) {
10449
10627
  const parse = (version) => {
@@ -10950,6 +11128,59 @@ var init_cliOverride = __esm({
10950
11128
  }
10951
11129
  });
10952
11130
 
11131
+ // src/launcher/launchRecords.ts
11132
+ import path38 from "node:path";
11133
+ import { z as z36 } from "zod";
11134
+ function recordFile(directory, pid, identity) {
11135
+ return path38.join(directory, `${String(pid)}.${identity}${RECORD_SUFFIX}`);
11136
+ }
11137
+ function readRecord(fs15, directory, name) {
11138
+ if (!name.endsWith(RECORD_SUFFIX)) {
11139
+ return void 0;
11140
+ }
11141
+ const raw = fs15.readFileUtf8(path38.join(directory, name));
11142
+ if (raw === void 0) {
11143
+ return void 0;
11144
+ }
11145
+ let parsed;
11146
+ try {
11147
+ parsed = JSON.parse(raw);
11148
+ } catch {
11149
+ return void 0;
11150
+ }
11151
+ const result = LaunchRecordSchema.safeParse(parsed);
11152
+ return result.success ? result.data : void 0;
11153
+ }
11154
+ function registerLaunch(fs15, directory, owner, isRunning) {
11155
+ fs15.mkdirPrivate(directory);
11156
+ for (const name of fs15.readdir(directory)) {
11157
+ const record2 = readRecord(fs15, directory, name);
11158
+ if (record2 !== void 0 && !isRunning(record2.pid)) {
11159
+ fs15.removeRecursive(path38.join(directory, name));
11160
+ }
11161
+ }
11162
+ const file = recordFile(directory, owner.pid, owner.identity);
11163
+ const record = { pid: owner.pid, identity: owner.identity, startedAt: new Date(owner.startedAtMs).toISOString() };
11164
+ fs15.writeFilePrivate(file, `${JSON.stringify(record)}
11165
+ `);
11166
+ return () => {
11167
+ fs15.removeRecursive(file);
11168
+ };
11169
+ }
11170
+ var LaunchRecordSchema, RECORD_SUFFIX;
11171
+ var init_launchRecords = __esm({
11172
+ "src/launcher/launchRecords.ts"() {
11173
+ "use strict";
11174
+ LaunchRecordSchema = z36.strictObject({
11175
+ /** The launcher's process id, which is what tells a launch in progress from a record a crashed launcher left behind. */
11176
+ pid: z36.number().int().positive(),
11177
+ identity: z36.string().min(1),
11178
+ startedAt: z36.iso.datetime()
11179
+ });
11180
+ RECORD_SUFFIX = ".json";
11181
+ }
11182
+ });
11183
+
10953
11184
  // src/headroom/headers.ts
10954
11185
  function mergeAnthropicCustomHeaders(existing, additions) {
10955
11186
  const merged = /* @__PURE__ */ new Map();
@@ -11018,7 +11249,7 @@ var init_settings2 = __esm({
11018
11249
  });
11019
11250
 
11020
11251
  // src/launcher/flags.ts
11021
- import path36 from "node:path";
11252
+ import path39 from "node:path";
11022
11253
  function resolveLaunchFlags(params) {
11023
11254
  const statusline = resolveStatuslineSettings(params);
11024
11255
  return {
@@ -11074,7 +11305,7 @@ function buildEnv(params) {
11074
11305
  const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
11075
11306
  let providerCustomHeaders;
11076
11307
  if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
11077
- env.CLAUDE_CONFIG_DIR = path36.join(params.identitiesDir, params.resolvedIdentityName);
11308
+ env.CLAUDE_CONFIG_DIR = path39.join(params.identitiesDir, params.resolvedIdentityName);
11078
11309
  }
11079
11310
  if (params.provider !== void 0) {
11080
11311
  const providerEnv = params.provider.definition.kind !== void 0 && params.provider.definition.kind !== "http" ? {} : params.provider.definition.env ?? {};
@@ -11166,7 +11397,7 @@ var init_extraFlags = __esm({
11166
11397
  });
11167
11398
 
11168
11399
  // src/usage/resumeContext.ts
11169
- import path37 from "node:path";
11400
+ import path40 from "node:path";
11170
11401
  function projectDirNameOf(cwd) {
11171
11402
  return cwd.replace(/[^A-Za-z0-9]/g, "-");
11172
11403
  }
@@ -11217,15 +11448,15 @@ function contextTokensOfTranscript(text) {
11217
11448
  }
11218
11449
  return void 0;
11219
11450
  }
11220
- function newestTranscript(fs14, projectDir) {
11451
+ function newestTranscript(fs15, projectDir) {
11221
11452
  let newest;
11222
11453
  let newestMs = -Infinity;
11223
- for (const name of fs14.readdir(projectDir)) {
11454
+ for (const name of fs15.readdir(projectDir)) {
11224
11455
  if (!name.endsWith(".jsonl")) {
11225
11456
  continue;
11226
11457
  }
11227
- const candidate = path37.join(projectDir, name);
11228
- const stat = fs14.lstat(candidate);
11458
+ const candidate = path40.join(projectDir, name);
11459
+ const stat = fs15.lstat(candidate);
11229
11460
  if (stat?.kind === "file" && stat.mtimeMs > newestMs) {
11230
11461
  newestMs = stat.mtimeMs;
11231
11462
  newest = candidate;
@@ -11233,14 +11464,14 @@ function newestTranscript(fs14, projectDir) {
11233
11464
  }
11234
11465
  return newest;
11235
11466
  }
11236
- function resumedContextTokens(fs14, params) {
11467
+ function resumedContextTokens(fs15, params) {
11237
11468
  const target = resumeTargetOf(params.passthrough);
11238
11469
  if (target === void 0) {
11239
11470
  return void 0;
11240
11471
  }
11241
- const projectDir = path37.join(params.claudeHome, "projects", projectDirNameOf(params.cwd));
11242
- const file = target.kind === "id" ? path37.join(projectDir, `${target.id}.jsonl`) : newestTranscript(fs14, projectDir);
11243
- const text = file === void 0 ? void 0 : fs14.readFileUtf8(file);
11472
+ const projectDir = path40.join(params.claudeHome, "projects", projectDirNameOf(params.cwd));
11473
+ const file = target.kind === "id" ? path40.join(projectDir, `${target.id}.jsonl`) : newestTranscript(fs15, projectDir);
11474
+ const text = file === void 0 ? void 0 : fs15.readFileUtf8(file);
11244
11475
  return text === void 0 ? void 0 : contextTokensOfTranscript(text);
11245
11476
  }
11246
11477
  var init_resumeContext = __esm({
@@ -11836,7 +12067,7 @@ var init_launchHook = __esm({
11836
12067
  // src/launcher.ts
11837
12068
  import { randomUUID as randomUUID4 } from "node:crypto";
11838
12069
  import { isDeepStrictEqual } from "node:util";
11839
- import path38 from "node:path";
12070
+ import path41 from "node:path";
11840
12071
  function resolveIdentityCredential(identity, credential, env, port) {
11841
12072
  if (port === void 0) {
11842
12073
  return { ok: false, status: 1, message: `agent-shim: identity ${identity} needs its credential resolved, but this launcher has no credential port wired` };
@@ -11845,7 +12076,7 @@ function resolveIdentityCredential(identity, credential, env, port) {
11845
12076
  return resolution.ok ? resolution : { ok: false, status: CREDENTIAL_UNAVAILABLE_EXIT, message: resolution.message };
11846
12077
  }
11847
12078
  function pickFromPool(decided, params, parsedArgv, readOnly) {
11848
- const { paths, fs: fs14, proc, log } = params;
12079
+ const { paths, fs: fs15, proc, log } = params;
11849
12080
  if (decided.pool === void 0) {
11850
12081
  return { identityDecision: decided };
11851
12082
  }
@@ -11864,7 +12095,7 @@ function pickFromPool(decided, params, parsedArgv, readOnly) {
11864
12095
  selectedVia: decided.source,
11865
12096
  pools: params.pools,
11866
12097
  paths,
11867
- fs: fs14,
12098
+ fs: fs15,
11868
12099
  usageFs: farmRuntime.fs,
11869
12100
  cwd: farmRuntime.cwd,
11870
12101
  now: farmRuntime.now,
@@ -11888,7 +12119,7 @@ function pickFromPool(decided, params, parsedArgv, readOnly) {
11888
12119
  };
11889
12120
  }
11890
12121
  function decideLaunch(params, readOnly) {
11891
- const { paths, fs: fs14, proc, log } = params;
12122
+ const { paths, fs: fs15, proc, log } = params;
11892
12123
  const { env, argv } = proc;
11893
12124
  const parsedArgv = parseLauncherArgv(argv);
11894
12125
  const cliOverride = buildCliOverride({
@@ -11903,7 +12134,7 @@ function decideLaunch(params, readOnly) {
11903
12134
  argv0Identity: params.pickedIdentity ?? parsedArgv.identity,
11904
12135
  directoryPinnedIdentity: params.directoryPinnedIdentity,
11905
12136
  readActiveIdentityFile: () => {
11906
- const raw = fs14.readFileUtf8(paths.activeIdentityFile);
12137
+ const raw = fs15.readFileUtf8(paths.activeIdentityFile);
11907
12138
  if (raw === void 0) {
11908
12139
  return void 0;
11909
12140
  }
@@ -11938,7 +12169,7 @@ function decideLaunch(params, readOnly) {
11938
12169
  }
11939
12170
  let loadedIdentity;
11940
12171
  if (identityDecision.name !== void 0) {
11941
- loadedIdentity = loadIdentity(paths.identitiesDir, identityDecision.name, fs14);
12172
+ loadedIdentity = loadIdentity(paths.identitiesDir, identityDecision.name, fs15);
11942
12173
  if (loadedIdentity === void 0) {
11943
12174
  log.error(
11944
12175
  `agent-shim: no identity named "${identityDecision.name}" (selected via ${identityDecision.source}). Run \`agent-shim identity add ${identityDecision.name}\` first.`
@@ -11953,7 +12184,7 @@ function decideLaunch(params, readOnly) {
11953
12184
  identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
11954
12185
  globalDefaultConfigProfile: params.globalDefaultConfigProfile
11955
12186
  });
11956
- if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs14.readConfigFile(profileFilePath(paths.configProfilesDir, configProfileDecision.name, `the configuration profile selected via ${configProfileDecision.source}`)) === void 0) {
12187
+ if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs15.readConfigFile(profileFilePath(paths.configProfilesDir, configProfileDecision.name, `the configuration profile selected via ${configProfileDecision.source}`)) === void 0) {
11957
12188
  log.error(
11958
12189
  `agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
11959
12190
  );
@@ -11962,7 +12193,7 @@ function decideLaunch(params, readOnly) {
11962
12193
  const farmContext = farm !== void 0 && farmIdentity !== void 0 ? { farm, identity: farmIdentity, cascade: farm.loadCascade(configProfileDecision.name, cliOverride) } : void 0;
11963
12194
  const providerParams = {
11964
12195
  paths,
11965
- port: fs14,
12196
+ port: fs15,
11966
12197
  ...parsedArgv.provider === void 0 || parsedArgv.provider === false ? {} : { cliProvider: parsedArgv.provider },
11967
12198
  ...farmContext === void 0 ? {} : { cascade: farmContext.cascade },
11968
12199
  ...loadedIdentity?.config.provider === void 0 ? {} : { identityProvider: loadedIdentity.config.provider }
@@ -12074,9 +12305,9 @@ function decideLaunch(params, readOnly) {
12074
12305
  const flags = loginlessProvider === void 0 ? requestedFlags : { ...requestedFlags, remoteControl: false };
12075
12306
  const globalModels = loadConfigFile(paths.globalConfigFile, GlobalConfigSchema, params.fs.readConfigFile)?.config.models;
12076
12307
  const models = launchCascade !== void 0 && params.farm !== void 0 ? cascadeModels : globalModels;
12077
- const listedProviders = listProviderNames(fs14.readdir, paths.providersDir).flatMap((name) => {
12308
+ const listedProviders = listProviderNames(fs15.readdir, paths.providersDir).flatMap((name) => {
12078
12309
  try {
12079
- const definition = loadProvider(paths.providersDir, name, fs14);
12310
+ const definition = loadProvider(paths.providersDir, name, fs15);
12080
12311
  return definition === void 0 ? [] : [[name, definition, parseCatalogueCache(params.fs.readFileUtf8(catalogueCachePath(paths, name)))?.models ?? []]];
12081
12312
  } catch {
12082
12313
  return [];
@@ -12094,7 +12325,7 @@ function decideLaunch(params, readOnly) {
12094
12325
  extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
12095
12326
  passthrough: withLauncherSettings(params.supervised === void 0 ? parsedArgv.rest : withSupervision(parsedArgv.rest, params.supervised), launcherSettings)
12096
12327
  }) : [...parsedArgv.rest];
12097
- const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR : path38.join(paths.identitiesDir, identityDecision.name);
12328
+ const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR : path41.join(paths.identitiesDir, identityDecision.name);
12098
12329
  const decision = {
12099
12330
  identitySource: identityDecision.source,
12100
12331
  configDirEscapeHatch: identityDecision.configDirEscapeHatch,
@@ -12132,6 +12363,19 @@ function decideLaunch(params, readOnly) {
12132
12363
  };
12133
12364
  }
12134
12365
  function prepareLaunch(params) {
12366
+ const removers = [];
12367
+ try {
12368
+ return prepareRegisteredLaunch(params, (remove) => {
12369
+ removers.push(remove);
12370
+ });
12371
+ } catch (error) {
12372
+ for (const remove of removers) {
12373
+ remove();
12374
+ }
12375
+ throw error;
12376
+ }
12377
+ }
12378
+ function prepareRegisteredLaunch(params, onRecorded) {
12135
12379
  const { paths, proc, log } = params;
12136
12380
  const { env } = proc;
12137
12381
  const decided = decideLaunch(params, false);
@@ -12152,14 +12396,17 @@ function prepareLaunch(params) {
12152
12396
  })
12153
12397
  ];
12154
12398
  let warnings = [];
12399
+ let unregisterLaunch;
12155
12400
  const updateCheck = runLaunchUpdateCheck({
12156
12401
  mode: params.updateMode ?? "off",
12157
- checkPath: path38.join(paths.root, "update.check"),
12402
+ checkPath: path41.join(paths.root, "update.check"),
12158
12403
  currentVersion: package_default.version,
12159
12404
  port: params.update
12160
12405
  });
12161
12406
  if (decided.farmContext !== void 0) {
12162
12407
  const { farm: resyncFarmRuntime, identity: resyncIdentity, cascade } = decided.farmContext;
12408
+ unregisterLaunch = registerLaunch(resyncFarmRuntime.fs, paths.launchesDir, { pid: resyncFarmRuntime.lock.pid, identity: resyncIdentity, startedAtMs: resyncFarmRuntime.now() }, resyncFarmRuntime.lock.isRunning);
12409
+ onRecorded(unregisterLaunch);
12163
12410
  let result;
12164
12411
  try {
12165
12412
  result = resyncFarm({
@@ -12177,10 +12424,11 @@ function prepareLaunch(params) {
12177
12424
  classification: resyncFarmRuntime.classification,
12178
12425
  now: resyncFarmRuntime.now,
12179
12426
  uniqueSuffix: resyncFarmRuntime.uniqueSuffix,
12427
+ identityExists: () => loadIdentity(paths.identitiesDir, resyncIdentity, params.fs) !== void 0,
12180
12428
  lock: resyncFarmRuntime.lock
12181
12429
  });
12182
12430
  } catch (error) {
12183
- if (error instanceof IdentityLockBusyError) {
12431
+ if (error instanceof IdentityLockBusyError || error instanceof IdentityGoneError) {
12184
12432
  log.error(error.message);
12185
12433
  proc.exit(1);
12186
12434
  }
@@ -12240,7 +12488,7 @@ function prepareLaunch(params) {
12240
12488
  proxyBypass: resolvedFlags.proxyBypass,
12241
12489
  ...resolvedFlags.statusline === void 0 ? {} : { statusline: resolvedFlags.statusline }
12242
12490
  });
12243
- const releases = [...headroom === void 0 || headroomPort === void 0 ? [] : [headroomPort.release], ...frontDoorRelease === void 0 ? [] : [frontDoorRelease]];
12491
+ const releases = [...unregisterLaunch === void 0 ? [] : [unregisterLaunch], ...headroom === void 0 || headroomPort === void 0 ? [] : [headroomPort.release], ...frontDoorRelease === void 0 ? [] : [frontDoorRelease]];
12244
12492
  const release = () => {
12245
12493
  for (const registered of releases) {
12246
12494
  registered();
@@ -12309,6 +12557,7 @@ var init_launcher = __esm({
12309
12557
  init_argv();
12310
12558
  init_cliOverride();
12311
12559
  init_farm();
12560
+ init_launchRecords();
12312
12561
  init_guard();
12313
12562
  init_identity();
12314
12563
  init_flags();
@@ -12344,12 +12593,12 @@ var init_launcher = __esm({
12344
12593
  });
12345
12594
 
12346
12595
  // src/ownCli.ts
12347
- import path39 from "node:path";
12596
+ import path42 from "node:path";
12348
12597
  function agentShimCliPath(distDir = typeof __AGENT_SHIM_DIST_DIR__ === "string" ? __AGENT_SHIM_DIST_DIR__ : void 0) {
12349
12598
  if (distDir === void 0) {
12350
12599
  throw new OwnCliPathUnknownError();
12351
12600
  }
12352
- return path39.join(distDir, OWN_CLI_FILE_NAME);
12601
+ return path42.join(distDir, OWN_CLI_FILE_NAME);
12353
12602
  }
12354
12603
  var OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
12355
12604
  var init_ownCli = __esm({
@@ -12367,10 +12616,10 @@ var init_ownCli = __esm({
12367
12616
  });
12368
12617
 
12369
12618
  // src/frontdoor/doorLog.ts
12370
- import fs12 from "node:fs";
12619
+ import fs13 from "node:fs";
12371
12620
  function appendDoorLog(paths, line) {
12372
- fs12.mkdirSync(paths.logsDir, { recursive: true });
12373
- fs12.appendFileSync(paths.frontdoorLogPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
12621
+ fs13.mkdirSync(paths.logsDir, { recursive: true });
12622
+ fs13.appendFileSync(paths.frontdoorLogPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
12374
12623
  `);
12375
12624
  }
12376
12625
  var init_doorLog = __esm({
@@ -12395,16 +12644,16 @@ var init_selfIdentity = __esm({
12395
12644
 
12396
12645
  // src/frontdoor/trust.ts
12397
12646
  import { createHash as createHash7 } from "node:crypto";
12398
- import path40 from "node:path";
12647
+ import path43 from "node:path";
12399
12648
  function resolveTrustBundle(params) {
12400
- const { caCertFile, bundlesDir, variable, inherited, fs: fs14 } = params;
12401
- if (inherited === void 0 || inherited === "" || path40.resolve(inherited) === path40.resolve(caCertFile)) {
12649
+ const { caCertFile, bundlesDir, variable, inherited, fs: fs15 } = params;
12650
+ if (inherited === void 0 || inherited === "" || path43.resolve(inherited) === path43.resolve(caCertFile)) {
12402
12651
  return { path: caCertFile };
12403
12652
  }
12404
- const caPem = fs14.readFileUtf8(caCertFile);
12653
+ const caPem = fs15.readFileUtf8(caCertFile);
12405
12654
  let inheritedPem;
12406
12655
  try {
12407
- inheritedPem = fs14.readFileUtf8(inherited);
12656
+ inheritedPem = fs15.readFileUtf8(inherited);
12408
12657
  } catch (error) {
12409
12658
  return {
12410
12659
  path: caCertFile,
@@ -12416,10 +12665,10 @@ function resolveTrustBundle(params) {
12416
12665
  }
12417
12666
  const combined = `${inheritedPem.trimEnd()}
12418
12667
  ${caPem}`;
12419
- const bundle = path40.join(bundlesDir, `${createHash7("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
12420
- if (!fs14.exists(bundle)) {
12421
- fs14.mkdirp(bundlesDir);
12422
- fs14.writeFileAtomic(bundle, combined);
12668
+ const bundle = path43.join(bundlesDir, `${createHash7("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
12669
+ if (!fs15.exists(bundle)) {
12670
+ fs15.mkdirp(bundlesDir);
12671
+ fs15.writeFileAtomic(bundle, combined);
12423
12672
  }
12424
12673
  return { path: bundle };
12425
12674
  }
@@ -12432,7 +12681,7 @@ var init_trust = __esm({
12432
12681
  });
12433
12682
 
12434
12683
  // src/frontdoor/realFrontDoorPort.ts
12435
- import fs13 from "node:fs";
12684
+ import fs14 from "node:fs";
12436
12685
  function realEnsurePorts(paths, spawnDaemon) {
12437
12686
  return {
12438
12687
  fs: realFarmFs,
@@ -12458,7 +12707,7 @@ function realEnsurePorts(paths, spawnDaemon) {
12458
12707
  }
12459
12708
  },
12460
12709
  // 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.
12461
- verifyListener: (port) => probeFrontDoorSync(port, fs13.readFileSync(paths.frontdoorCaCertFile, "utf8"))
12710
+ verifyListener: (port) => probeFrontDoorSync(port, fs14.readFileSync(paths.frontdoorCaCertFile, "utf8"))
12462
12711
  };
12463
12712
  }
12464
12713
  function realFrontDoorPort(paths, spawnDaemon) {
@@ -12491,10 +12740,10 @@ var init_realFrontDoorPort = __esm({
12491
12740
  init_selfIdentity();
12492
12741
  init_trust();
12493
12742
  realTrustBundleFs = {
12494
- readFileUtf8: (file) => fs13.readFileSync(file, "utf8"),
12495
- exists: (file) => fs13.existsSync(file),
12743
+ readFileUtf8: (file) => fs14.readFileSync(file, "utf8"),
12744
+ exists: (file) => fs14.existsSync(file),
12496
12745
  mkdirp: (dir) => {
12497
- fs13.mkdirSync(dir, { recursive: true });
12746
+ fs14.mkdirSync(dir, { recursive: true });
12498
12747
  },
12499
12748
  writeFileAtomic: (file, contents) => {
12500
12749
  realFarmFs.writeFilePrivate(file, contents);
@@ -12503,53 +12752,9 @@ var init_realFrontDoorPort = __esm({
12503
12752
  }
12504
12753
  });
12505
12754
 
12506
- // src/replayRun.ts
12507
- function keyOf2(command, args) {
12508
- return JSON.stringify([command, args]);
12509
- }
12510
- async function recordRuns(decide, runAsync) {
12511
- const answers = /* @__PURE__ */ new Map();
12512
- const replay = {
12513
- run: (command, args) => {
12514
- const answer = answers.get(keyOf2(command, args));
12515
- if (answer === void 0) {
12516
- throw new RunNeededError(command, args);
12517
- }
12518
- return answer;
12519
- }
12520
- };
12521
- for (; ; ) {
12522
- try {
12523
- decide(replay);
12524
- return replay;
12525
- } catch (error) {
12526
- if (!(error instanceof RunNeededError)) {
12527
- throw error;
12528
- }
12529
- answers.set(keyOf2(error.command, error.args), await runAsync(error.command, error.args));
12530
- }
12531
- }
12532
- }
12533
- var RunNeededError;
12534
- var init_replayRun = __esm({
12535
- "src/replayRun.ts"() {
12536
- "use strict";
12537
- RunNeededError = class extends Error {
12538
- constructor(command, args) {
12539
- super(`no recorded answer for ${command} ${args.join(" ")}`);
12540
- this.command = command;
12541
- this.args = args;
12542
- this.name = "RunNeededError";
12543
- }
12544
- command;
12545
- args;
12546
- };
12547
- }
12548
- });
12549
-
12550
12755
  // src/launchWiring.ts
12551
12756
  import os8 from "node:os";
12552
- import path41 from "node:path";
12757
+ import path44 from "node:path";
12553
12758
  import { randomUUID as randomUUID5 } from "node:crypto";
12554
12759
  function buildFarmRuntime(paths, cwd, run = realRunPort) {
12555
12760
  const home = os8.homedir();
@@ -12604,7 +12809,7 @@ function realPrepareLaunchParams(paths, options) {
12604
12809
  frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
12605
12810
  credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
12606
12811
  hold: realHoldPort,
12607
- hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: options.run ?? realRunPort }, { farmRoot: path41.join(paths.identitiesDir, identity), hasCredentialBlock: false, provider: void 0 }).state !== "signed-out",
12812
+ hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: options.run ?? realRunPort }, { farmRoot: path44.join(paths.identitiesDir, identity), hasCredentialBlock: false, provider: void 0 }).state !== "signed-out",
12608
12813
  ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
12609
12814
  ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
12610
12815
  ...farm.globalDefaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: farm.globalDefaultConfigProfile },
@@ -12889,7 +13094,7 @@ var init_identityClaude = __esm({
12889
13094
  });
12890
13095
 
12891
13096
  // src/usage/providerQuota.ts
12892
- import { z as z35 } from "zod";
13097
+ import { z as z37 } from "zod";
12893
13098
  var MS_PER_SECOND9, SECONDS_PER_HOUR3, HOURS_PER_DAY6, DAYS_PER_MONTH, ZAI_HOST, ZAI_QUOTA_URL, ZAI_UNIT_HOURS, ZAI_UNIT_MONTHS, ZAI_UNIT_MS, ZaiLimitSchema, ZaiResponseSchema, OPENROUTER_HOST, OPENROUTER_KEY_URL, OPENROUTER_CREDITS_URL, MS_PER_DAY2, OpenRouterKeySchema, OpenRouterCreditsSchema, ANTIGRAVITY_HOST, ANTIGRAVITY_QUOTA_URL, ANTIGRAVITY_USER_URL, FIVE_HOURS2, DAYS_PER_WEEK2, FIVE_HOURS_MS, WEEK_MS, AntigravityBucketSchema, AntigravitySummarySchema, GoogleTokenInfoSchema, AntigravityUserSchema;
12894
13099
  var init_providerQuota = __esm({
12895
13100
  "src/usage/providerQuota.ts"() {
@@ -12908,35 +13113,35 @@ var init_providerQuota = __esm({
12908
13113
  [ZAI_UNIT_HOURS, SECONDS_PER_HOUR3 * MS_PER_SECOND9],
12909
13114
  [ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND9]
12910
13115
  ]);
12911
- ZaiLimitSchema = z35.object({
12912
- type: z35.string(),
12913
- unit: z35.number().int(),
12914
- number: z35.number().int().positive(),
12915
- percentage: z35.number().nonnegative(),
12916
- nextResetTime: z35.number().positive().optional(),
12917
- usage: z35.number().nonnegative().optional(),
12918
- currentValue: z35.number().nonnegative().optional(),
12919
- remaining: z35.number().nonnegative().optional()
13116
+ ZaiLimitSchema = z37.object({
13117
+ type: z37.string(),
13118
+ unit: z37.number().int(),
13119
+ number: z37.number().int().positive(),
13120
+ percentage: z37.number().nonnegative(),
13121
+ nextResetTime: z37.number().positive().optional(),
13122
+ usage: z37.number().nonnegative().optional(),
13123
+ currentValue: z37.number().nonnegative().optional(),
13124
+ remaining: z37.number().nonnegative().optional()
12920
13125
  });
12921
- ZaiResponseSchema = z35.object({
12922
- success: z35.boolean(),
12923
- msg: z35.string().optional(),
12924
- data: z35.object({ level: z35.string().optional(), limits: z35.array(ZaiLimitSchema) })
13126
+ ZaiResponseSchema = z37.object({
13127
+ success: z37.boolean(),
13128
+ msg: z37.string().optional(),
13129
+ data: z37.object({ level: z37.string().optional(), limits: z37.array(ZaiLimitSchema) })
12925
13130
  });
12926
13131
  OPENROUTER_HOST = "openrouter.ai";
12927
13132
  OPENROUTER_KEY_URL = `https://${OPENROUTER_HOST}/api/v1/key`;
12928
13133
  OPENROUTER_CREDITS_URL = `https://${OPENROUTER_HOST}/api/v1/credits`;
12929
13134
  MS_PER_DAY2 = HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
12930
- OpenRouterKeySchema = z35.object({
12931
- data: z35.object({
12932
- limit: z35.number().nonnegative().nullable(),
12933
- limit_remaining: z35.number().nullable(),
12934
- limit_reset: z35.string().nullable(),
12935
- is_free_tier: z35.boolean().optional(),
12936
- free_model_daily_requests: z35.object({ used: z35.number().nonnegative(), limit: z35.number().nonnegative(), remaining: z35.number() }).optional()
13135
+ OpenRouterKeySchema = z37.object({
13136
+ data: z37.object({
13137
+ limit: z37.number().nonnegative().nullable(),
13138
+ limit_remaining: z37.number().nullable(),
13139
+ limit_reset: z37.string().nullable(),
13140
+ is_free_tier: z37.boolean().optional(),
13141
+ free_model_daily_requests: z37.object({ used: z37.number().nonnegative(), limit: z37.number().nonnegative(), remaining: z37.number() }).optional()
12937
13142
  })
12938
13143
  });
12939
- OpenRouterCreditsSchema = z35.object({ data: z35.object({ total_credits: z35.number().nonnegative(), total_usage: z35.number().nonnegative() }) });
13144
+ OpenRouterCreditsSchema = z37.object({ data: z37.object({ total_credits: z37.number().nonnegative(), total_usage: z37.number().nonnegative() }) });
12940
13145
  ANTIGRAVITY_HOST = "daily-cloudcode-pa.googleapis.com";
12941
13146
  ANTIGRAVITY_QUOTA_URL = `https://${ANTIGRAVITY_HOST}/v1internal:retrieveUserQuotaSummary`;
12942
13147
  ANTIGRAVITY_USER_URL = `https://${ANTIGRAVITY_HOST}/v1internal:loadCodeAssist`;
@@ -12944,21 +13149,21 @@ var init_providerQuota = __esm({
12944
13149
  DAYS_PER_WEEK2 = 7;
12945
13150
  FIVE_HOURS_MS = FIVE_HOURS2 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
12946
13151
  WEEK_MS = DAYS_PER_WEEK2 * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
12947
- AntigravityBucketSchema = z35.object({
12948
- bucketId: z35.string(),
12949
- remainingFraction: z35.number().optional(),
12950
- resetTime: z35.string().optional()
13152
+ AntigravityBucketSchema = z37.object({
13153
+ bucketId: z37.string(),
13154
+ remainingFraction: z37.number().optional(),
13155
+ resetTime: z37.string().optional()
12951
13156
  });
12952
- AntigravitySummarySchema = z35.object({ groups: z35.array(z35.object({ buckets: z35.array(AntigravityBucketSchema) })) });
12953
- GoogleTokenInfoSchema = z35.object({
12954
- email: z35.string().optional(),
12955
- sub: z35.string().optional()
13157
+ AntigravitySummarySchema = z37.object({ groups: z37.array(z37.object({ buckets: z37.array(AntigravityBucketSchema) })) });
13158
+ GoogleTokenInfoSchema = z37.object({
13159
+ email: z37.string().optional(),
13160
+ sub: z37.string().optional()
12956
13161
  });
12957
- AntigravityUserSchema = z35.object({
13162
+ AntigravityUserSchema = z37.object({
12958
13163
  /** The code-assist tier context, which defaults to the free tier for every account. */
12959
- currentTier: z35.object({ name: z35.string().optional(), id: z35.string().optional() }).optional(),
13164
+ currentTier: z37.object({ name: z37.string().optional(), id: z37.string().optional() }).optional(),
12960
13165
  /** The account's paid subscription; absent when the account has none. */
12961
- paidTier: z35.object({ name: z35.string().optional(), id: z35.string().optional() }).optional()
13166
+ paidTier: z37.object({ name: z37.string().optional(), id: z37.string().optional() }).optional()
12962
13167
  });
12963
13168
  }
12964
13169
  });
@@ -13337,8 +13542,8 @@ function pathnameOf(url) {
13337
13542
  return new URL(url ?? "/", "http://127.0.0.1").pathname;
13338
13543
  }
13339
13544
  function isRcSessionExchange(url) {
13340
- const path42 = pathnameOf(url);
13341
- return path42 === RC_SESSIONS_PATH_PREFIX || path42.startsWith(`${RC_SESSIONS_PATH_PREFIX}/`);
13545
+ const path45 = pathnameOf(url);
13546
+ return path45 === RC_SESSIONS_PATH_PREFIX || path45.startsWith(`${RC_SESSIONS_PATH_PREFIX}/`);
13342
13547
  }
13343
13548
  var RC_SESSION_ID_PREFIX = "cse_";
13344
13549
  var RC_IDLE_EXPIRY_MS = 45e3;
@@ -13897,8 +14102,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
13897
14102
  function isRcReadFileEncoding(value) {
13898
14103
  return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
13899
14104
  }
13900
- function buildRcReadFilePayload(requestId, path42, options) {
13901
- return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path42, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
14105
+ function buildRcReadFilePayload(requestId, path45, options) {
14106
+ return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path45, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
13902
14107
  }
13903
14108
  function buildRcFileSuggestionsPayload(requestId, query) {
13904
14109
  return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
@@ -14000,15 +14205,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
14000
14205
  const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
14001
14206
  return result.ok ? { ...result, requestId } : result;
14002
14207
  }
14003
- async function readRcSessionFile(deps, sessionId, path42, options) {
14004
- if (path42 === "") {
14208
+ async function readRcSessionFile(deps, sessionId, path45, options) {
14209
+ if (path45 === "") {
14005
14210
  return { ok: false, message: "a read-file write needs a non-empty path: the SDK's own field names the file the worker resolves against the session's cwd, and an empty string names none" };
14006
14211
  }
14007
14212
  if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
14008
14213
  return { ok: false, message: "a read-file write's max-bytes is a positive whole number of bytes: the SDK's own field caps the read, and a zero or negative cap reads nothing" };
14009
14214
  }
14010
14215
  const requestId = deps.newUuid();
14011
- const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path42, options), `read ${path42} from session ${sessionId}`);
14216
+ const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path45, options), `read ${path45} from session ${sessionId}`);
14012
14217
  return result.ok ? { ...result, requestId } : result;
14013
14218
  }
14014
14219
  async function suggestRcSessionFiles(deps, sessionId, query) {
@@ -14177,11 +14382,11 @@ function createRcControlHandler(deps) {
14177
14382
  path: "read-file",
14178
14383
  read: (body) => {
14179
14384
  const session = bodyString(body, "session");
14180
- const path42 = bodyString(body, "path");
14385
+ const path45 = bodyString(body, "path");
14181
14386
  const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
14182
14387
  const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
14183
- const refused2 = session === void 0 || path42 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
14184
- return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path42, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
14388
+ const refused2 = session === void 0 || path45 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
14389
+ return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path45, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
14185
14390
  }
14186
14391
  },
14187
14392
  {
@@ -14491,9 +14696,9 @@ function requestIdOfBody(body) {
14491
14696
  }
14492
14697
  function frontDoorRcControl(transport, token) {
14493
14698
  const headers = { authorization: `Bearer ${token}` };
14494
- const listAnswerOf = async (path42, what) => {
14699
+ const listAnswerOf = async (path45, what) => {
14495
14700
  try {
14496
- return await transport.request({ method: "GET", path: path42, headers });
14701
+ return await transport.request({ method: "GET", path: path45, headers });
14497
14702
  } catch (error) {
14498
14703
  throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
14499
14704
  }
@@ -14565,10 +14770,10 @@ function frontDoorRcControl(transport, token) {
14565
14770
  }
14566
14771
  return pending;
14567
14772
  };
14568
- const writeOf = async (path42, body, describeFailure2) => {
14773
+ const writeOf = async (path45, body, describeFailure2) => {
14569
14774
  let answer;
14570
14775
  try {
14571
- answer = await transport.request({ method: "POST", path: path42, headers: { ...headers, "content-type": "application/json" }, body });
14776
+ answer = await transport.request({ method: "POST", path: path45, headers: { ...headers, "content-type": "application/json" }, body });
14572
14777
  } catch (error) {
14573
14778
  return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
14574
14779
  }
@@ -14599,10 +14804,10 @@ function frontDoorRcControl(transport, token) {
14599
14804
  endSession: async (sessionId, reason) => await writeOf(`${CONTROL_PATH_PREFIX}/end-session`, JSON.stringify({ session: sessionId, ...reason === void 0 ? {} : { reason } }), (status, message) => `ending ${sessionId} failed (HTTP ${String(status)}): ${message}`),
14600
14805
  getUsage: async (sessionId, skipBehaviors) => await writeOf(`${CONTROL_PATH_PREFIX}/get-usage`, JSON.stringify({ session: sessionId, ...skipBehaviors === void 0 ? {} : { skipBehaviors } }), (status, message) => `requesting the usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
14601
14806
  getContextUsage: async (sessionId, detail) => await writeOf(`${CONTROL_PATH_PREFIX}/get-context-usage`, JSON.stringify({ session: sessionId, ...detail === void 0 ? {} : { detail } }), (status, message) => `requesting the context usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
14602
- readFile: async (sessionId, path42, options) => await writeOf(
14807
+ readFile: async (sessionId, path45, options) => await writeOf(
14603
14808
  `${CONTROL_PATH_PREFIX}/read-file`,
14604
- JSON.stringify({ session: sessionId, path: path42, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
14605
- (status, message) => `reading ${path42} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
14809
+ JSON.stringify({ session: sessionId, path: path45, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
14810
+ (status, message) => `reading ${path45} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
14606
14811
  ),
14607
14812
  fileSuggestions: async (sessionId, query) => await writeOf(`${CONTROL_PATH_PREFIX}/file-suggestions`, JSON.stringify({ session: sessionId, query }), (status, message) => `requesting file suggestions from ${sessionId} failed (HTTP ${String(status)}): ${message}`),
14608
14813
  keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
@@ -14761,12 +14966,12 @@ function tlsFacts(options) {
14761
14966
  }
14762
14967
  function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
14763
14968
  const agent = new ExemptTlsAgent();
14764
- const post = async (path42, headers, body) => await new Promise((resolve, reject) => {
14969
+ const post = async (path45, headers, body) => await new Promise((resolve, reject) => {
14765
14970
  const options = {
14766
14971
  host: target.host,
14767
14972
  port: target.port,
14768
14973
  method: "POST",
14769
- path: path42,
14974
+ path: path45,
14770
14975
  // The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
14771
14976
  headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
14772
14977
  agent
@@ -14831,12 +15036,12 @@ function lateRcStreamDial(resolve) {
14831
15036
  }
14832
15037
  function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
14833
15038
  const agent = new ExemptTlsAgent();
14834
- const request4 = async (method, path42, headers, body, signal) => await new Promise((resolve, reject) => {
15039
+ const request4 = async (method, path45, headers, body, signal) => await new Promise((resolve, reject) => {
14835
15040
  const options = {
14836
15041
  host: target.host,
14837
15042
  port: target.port,
14838
15043
  method,
14839
- path: path42,
15044
+ path: path45,
14840
15045
  // The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
14841
15046
  headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
14842
15047
  agent,
@@ -14878,9 +15083,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
14878
15083
  return { status, body: await readAll(response) };
14879
15084
  },
14880
15085
  openStream: async (sessionId, headers, resume, signal) => {
14881
- const path42 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
15086
+ const path45 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
14882
15087
  const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
14883
- const { status, response } = await request4("GET", path42, streamHeaders, void 0, signal);
15088
+ const { status, response } = await request4("GET", path45, streamHeaders, void 0, signal);
14884
15089
  if (!isSuccessful2(status)) {
14885
15090
  await readAll(response);
14886
15091
  return { status, chunks: NO_CHUNKS };
@@ -15130,11 +15335,11 @@ function credentialOfJson(parsed) {
15130
15335
  function sequenceNumOfJson(value) {
15131
15336
  return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : void 0;
15132
15337
  }
15133
- function createRcCredentialStore(fs14, dir) {
15134
- fs14.mkdirPrivate(dir);
15338
+ function createRcCredentialStore(fs15, dir) {
15339
+ fs15.mkdirPrivate(dir);
15135
15340
  const fileFor = (sessionId) => path11.join(dir, `${sessionId}.json`);
15136
15341
  const readParsed = (sessionId) => {
15137
- const raw = fs14.readFileUtf8(fileFor(sessionId));
15342
+ const raw = fs15.readFileUtf8(fileFor(sessionId));
15138
15343
  if (raw === void 0) {
15139
15344
  return void 0;
15140
15345
  }
@@ -15159,7 +15364,7 @@ function createRcCredentialStore(fs14, dir) {
15159
15364
  }
15160
15365
  const cursor = sequenceNumOfJson(readParsed(sessionId)?.highestSequenceNum);
15161
15366
  const record = { ...credential, ...cursor === void 0 ? {} : { highestSequenceNum: cursor } };
15162
- fs14.writeFilePrivate(fileFor(sessionId), `${JSON.stringify(record, null, 2)}
15367
+ fs15.writeFilePrivate(fileFor(sessionId), `${JSON.stringify(record, null, 2)}
15163
15368
  `);
15164
15369
  },
15165
15370
  readCursor: (sessionId) => {
@@ -15174,14 +15379,14 @@ function createRcCredentialStore(fs14, dir) {
15174
15379
  }
15175
15380
  const credential = credentialOfJson(readParsed(sessionId));
15176
15381
  const record = credential === void 0 ? { highestSequenceNum } : { ...credential, highestSequenceNum };
15177
- fs14.writeFilePrivate(fileFor(sessionId), `${JSON.stringify(record, null, 2)}
15382
+ fs15.writeFilePrivate(fileFor(sessionId), `${JSON.stringify(record, null, 2)}
15178
15383
  `);
15179
15384
  },
15180
15385
  remove: (sessionId) => {
15181
15386
  if (!isSafeSessionId(sessionId)) {
15182
15387
  return;
15183
15388
  }
15184
- fs14.removeRecursive(fileFor(sessionId));
15389
+ fs15.removeRecursive(fileFor(sessionId));
15185
15390
  }
15186
15391
  };
15187
15392
  }
@@ -15873,19 +16078,19 @@ function writePools(paths, pools) {
15873
16078
  applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
15874
16079
  }
15875
16080
  function poolCycleOf(pools, name) {
15876
- const walk2 = (current, path42) => {
16081
+ const walk2 = (current, path45) => {
15877
16082
  for (const entry of pools[current]?.identities ?? []) {
15878
16083
  const nested = poolNameOf(poolMemberIdentity(entry));
15879
16084
  if (nested === void 0) {
15880
16085
  continue;
15881
16086
  }
15882
16087
  if (nested === name) {
15883
- return [...path42, nested];
16088
+ return [...path45, nested];
15884
16089
  }
15885
- if (path42.includes(nested)) {
16090
+ if (path45.includes(nested)) {
15886
16091
  continue;
15887
16092
  }
15888
- const found = walk2(nested, [...path42, nested]);
16093
+ const found = walk2(nested, [...path45, nested]);
15889
16094
  if (found !== void 0) {
15890
16095
  return found;
15891
16096
  }
@@ -16325,7 +16530,7 @@ function loadCheckProvider(paths, name) {
16325
16530
  try {
16326
16531
  definition = readProvider(paths, name);
16327
16532
  } catch (error) {
16328
- if (error instanceof ConfigValidationError || error instanceof LegacyProviderFileError) {
16533
+ if (error instanceof ConfigValidationError || error instanceof LegacyProviderFileError || error instanceof ConfigFileNotJsonError) {
16329
16534
  return { name, problem: error.message };
16330
16535
  }
16331
16536
  throw error;
@@ -16597,8 +16802,8 @@ var ResetRowSchema = z22.strictObject({
16597
16802
  var ResetScheduleSchema = z22.strictObject({ resets: z22.readonly(z22.array(ResetRowSchema)) });
16598
16803
 
16599
16804
  // src/frontdoor/controlSchemas.ts
16600
- import path30 from "node:path";
16601
- import { z as z29 } from "zod";
16805
+ import path32 from "node:path";
16806
+ import { z as z30 } from "zod";
16602
16807
 
16603
16808
  // src/doctorReport.ts
16604
16809
  init_claudeShim();
@@ -16607,13 +16812,211 @@ init_store();
16607
16812
 
16608
16813
  // src/identityStore.ts
16609
16814
  init_load();
16815
+ init_names();
16610
16816
  init_store();
16611
16817
  init_schema();
16612
16818
  init_cliError();
16613
16819
  init_identity();
16614
- import fs9 from "node:fs";
16615
- import path28 from "node:path";
16820
+ import fs10 from "node:fs";
16821
+ import path30 from "node:path";
16616
16822
  init_lock();
16823
+
16824
+ // src/identityRenameJournal.ts
16825
+ init_cliError();
16826
+ import path28 from "node:path";
16827
+ import { z as z24 } from "zod";
16828
+ var RenameJournalSchema = z24.strictObject({
16829
+ version: z24.literal(1),
16830
+ from: z24.string().min(1),
16831
+ to: z24.string().min(1),
16832
+ startedAt: z24.iso.datetime(),
16833
+ /** The process that began the rename, for a person reading the file. Whether it is still running is told by the locks, not by this. */
16834
+ pid: z24.number().int().positive(),
16835
+ steps: z24.array(
16836
+ z24.strictObject({
16837
+ description: z24.string().min(1),
16838
+ /** Whether the step has been applied and marked so. */
16839
+ done: z24.boolean(),
16840
+ /** Whether the step was begun: written ahead of the step, before it runs, so a process that dies after the step took effect and before `done` was written still leaves a record that it may have. */
16841
+ started: z24.boolean()
16842
+ })
16843
+ )
16844
+ });
16845
+ var JOURNAL_SUFFIX = ".json";
16846
+ var RenameJournalUnreadableError = class extends CliError {
16847
+ constructor(file, detail) {
16848
+ super(`${file} is not a rename journal this agent-shim can read (${detail}). If no rename was left unfinished, remove it; otherwise look at what it names before renaming anything.`);
16849
+ this.detail = detail;
16850
+ this.name = "RenameJournalUnreadableError";
16851
+ }
16852
+ detail;
16853
+ };
16854
+ function readRenameJournal(fs15, file) {
16855
+ const raw = fs15.readFileUtf8(file);
16856
+ if (raw === void 0) {
16857
+ return void 0;
16858
+ }
16859
+ let parsed;
16860
+ try {
16861
+ parsed = JSON.parse(raw);
16862
+ } catch {
16863
+ throw new RenameJournalUnreadableError(file, "not valid JSON");
16864
+ }
16865
+ const result = RenameJournalSchema.safeParse(parsed);
16866
+ if (!result.success) {
16867
+ throw new RenameJournalUnreadableError(file, result.error.issues.map((issue) => `${issue.path.join(".") || "(root)"}: ${issue.message}`).join("; "));
16868
+ }
16869
+ return result.data;
16870
+ }
16871
+ function listRenameJournals(fs15, directory) {
16872
+ const journals = [];
16873
+ const unreadable = [];
16874
+ for (const name of [...fs15.readdir(directory)].sort()) {
16875
+ if (!name.endsWith(JOURNAL_SUFFIX)) {
16876
+ continue;
16877
+ }
16878
+ const file = path28.join(directory, name);
16879
+ try {
16880
+ const journal = readRenameJournal(fs15, file);
16881
+ if (journal !== void 0) {
16882
+ journals.push(journal);
16883
+ }
16884
+ } catch (error) {
16885
+ if (!(error instanceof RenameJournalUnreadableError)) {
16886
+ throw error;
16887
+ }
16888
+ unreadable.push({ file, detail: error.detail });
16889
+ }
16890
+ }
16891
+ return { journals, unreadable };
16892
+ }
16893
+ function stepMayBeApplied(step) {
16894
+ return step.done || step.started;
16895
+ }
16896
+ function recordsNothingApplied(journal) {
16897
+ return !journal.steps.some(stepMayBeApplied);
16898
+ }
16899
+ function describeUnfinishable(bothExist) {
16900
+ return bothExist ? "both names are identities" : "there is no identity under either name";
16901
+ }
16902
+ function finishabilityOf(journal, exists) {
16903
+ const underFrom = exists(journal.from);
16904
+ if (underFrom === exists(journal.to)) {
16905
+ return { finishable: false, reason: describeUnfinishable(underFrom) };
16906
+ }
16907
+ return underFrom && recordsNothingApplied(journal) ? { finishable: true, discardable: true } : { finishable: true };
16908
+ }
16909
+ function discardJournalCommand(journal) {
16910
+ return `agent-shim identity rename ${journal.from} ${journal.to} --discard-journal`;
16911
+ }
16912
+ function describeUnfinishedRename(journal, finishability) {
16913
+ const applied = journal.steps.filter(stepMayBeApplied).length;
16914
+ const progress = `an unfinished rename of identity "${journal.from}" to "${journal.to}" (${String(applied)} of ${String(journal.steps.length)} steps recorded as begun or done)`;
16915
+ return finishability.finishable ? `${progress}. Finish it with \`agent-shim identity rename ${journal.from} ${journal.to}\`; to put the name back afterwards, run \`agent-shim identity rename ${journal.to} ${journal.from}\`.${finishability.discardable === true ? ` No step is recorded as begun or done and the identity is still under "${journal.from}", so its record can be discarded with \`${discardJournalCommand(journal)}\`; that removes only the record.` : ""}` : `${progress} that cannot be finished: ${finishability.reason}. If nothing is left of it to keep, discard its record with \`${discardJournalCommand(journal)}\`; that removes only the record and changes no identity.`;
16916
+ }
16917
+ var NameHeldByUnfinishedRenameError = class extends CliError {
16918
+ constructor(action, name, journal, finishability) {
16919
+ super(`Cannot ${action} identity "${name}": there is ${describeUnfinishedRename(journal, finishability)}`);
16920
+ this.name = "NameHeldByUnfinishedRenameError";
16921
+ }
16922
+ };
16923
+ function requireNameFreeOfUnfinishedRename(fs15, directory, name, action, sameName, exists) {
16924
+ const held = listRenameJournals(fs15, directory).journals.find((journal) => [journal.from, journal.to].some((heldName) => heldName === name || sameName(name, heldName)));
16925
+ if (held !== void 0) {
16926
+ throw new NameHeldByUnfinishedRenameError(action, name, held, finishabilityOf(held, exists));
16927
+ }
16928
+ }
16929
+
16930
+ // src/keychainLogin.ts
16931
+ init_cliError();
16932
+ init_signIn();
16933
+ var ITEM_NOT_FOUND_STATUS = 44;
16934
+ var MAX_DETAIL_CHARS = 200;
16935
+ var CONTROL_CHARACTER = new RegExp("\\p{Cc}", "u");
16936
+ var KeychainLoginError = class extends CliError {
16937
+ constructor(message) {
16938
+ super(message);
16939
+ this.name = "KeychainLoginError";
16940
+ }
16941
+ };
16942
+ var KeychainLookupError = class extends KeychainLoginError {
16943
+ constructor(message) {
16944
+ super(message);
16945
+ this.name = "KeychainLookupError";
16946
+ }
16947
+ };
16948
+ function statusPhrase(status) {
16949
+ return status === null ? "without a status" : String(status);
16950
+ }
16951
+ function describe(stderr) {
16952
+ const [first] = stderr.trim().split("\n");
16953
+ return first === void 0 || first === "" ? "" : ` (${first.slice(0, MAX_DETAIL_CHARS)})`;
16954
+ }
16955
+ function lookup(run, service) {
16956
+ const result = run.run("security", ["find-generic-password", "-s", service]);
16957
+ if (result.status === 0) {
16958
+ return { found: true, attributes: result.stdout };
16959
+ }
16960
+ if (result.status === ITEM_NOT_FOUND_STATUS) {
16961
+ return { found: false };
16962
+ }
16963
+ throw new KeychainLookupError(`Could not look up the Keychain item ${service}: security exited ${statusPhrase(result.status)}${describe(result.stderr)}.`);
16964
+ }
16965
+ function plainAccountOf(attributes) {
16966
+ const line = attributes.split("\n").find((candidate) => candidate.includes('"acct"<blob>='));
16967
+ const value = line?.slice(line.indexOf("=") + 1).trim();
16968
+ const name = value === void 0 ? void 0 : /^"([^"\\]*)"$/u.exec(value)?.[1];
16969
+ return name === void 0 || name === "" || CONTROL_CHARACTER.test(name) ? void 0 : name;
16970
+ }
16971
+ function keychainDeleteCommand(service, account) {
16972
+ return `security delete-generic-password -s ${shellQuoted(service)}${account === void 0 ? "" : ` -a ${shellQuoted(account)}`}`;
16973
+ }
16974
+ function shellQuoted(value) {
16975
+ return `'${value.replace(/'/gu, "'\\''")}'`;
16976
+ }
16977
+ var KEEP_KEYCHAIN_LOGIN_DESCRIPTION = "Create the identity even though the macOS Keychain already holds a Claude Code login filed for its directory (left by an identity of that name that was renamed or removed); the identity starts signed in as that account. If another identity holds that login, the two share it. Without it that login is refused and the command that deletes it is printed.";
16978
+ function requireNoLeftoverKeychainLogin(keychain, configDir, name, keepLogin) {
16979
+ if (keepLogin || keychain.platform !== "darwin") {
16980
+ return;
16981
+ }
16982
+ const service = claudeCodeKeychainService(configDir);
16983
+ const found = lookup(keychain.run, service);
16984
+ if (!found.found) {
16985
+ return;
16986
+ }
16987
+ const account = plainAccountOf(found.attributes);
16988
+ throw new KeychainLoginError(
16989
+ `Cannot create identity "${name}": the Keychain already holds a Claude Code login filed for ${configDir} (service ${service}${account === void 0 ? "" : `, account ${account}`}), left behind by an identity of that name that was renamed or removed. A new identity there would start signed in as that account. If you do not need it, delete it with \`${keychainDeleteCommand(service, account)}\` and run the command again. To create the identity signed in as that account on purpose, run \`agent-shim identity add ${name} --keep-keychain-login\`. If another identity holds a copy of that login, as a renamed identity does when its old item could not be deleted, keeping it makes the two share one login.`
16990
+ );
16991
+ }
16992
+
16993
+ // src/sameDirectory.ts
16994
+ import fs9 from "node:fs";
16995
+ import path29 from "node:path";
16996
+ function sameDirectory(first, second) {
16997
+ const a = fs9.statSync(first, { throwIfNoEntry: false });
16998
+ const b = fs9.statSync(second, { throwIfNoEntry: false });
16999
+ if (a === void 0 || b === void 0) {
17000
+ return false;
17001
+ }
17002
+ return a.dev === b.dev && a.ino === b.ino;
17003
+ }
17004
+ function caseSwapped(name) {
17005
+ return name.replace(/[A-Za-z]/gu, (letter) => letter === letter.toLowerCase() ? letter.toUpperCase() : letter.toLowerCase());
17006
+ }
17007
+ function ignoresCase(directory) {
17008
+ if (!fs9.existsSync(directory)) {
17009
+ return false;
17010
+ }
17011
+ const probe = fs9.mkdtempSync(path29.join(directory, ".case-probe-"));
17012
+ try {
17013
+ return sameDirectory(probe, path29.join(directory, caseSwapped(path29.basename(probe))));
17014
+ } finally {
17015
+ fs9.rmSync(probe, { recursive: true, force: true });
17016
+ }
17017
+ }
17018
+
17019
+ // src/identityStore.ts
16617
17020
  var IdentityNotFoundError = class extends CliError {
16618
17021
  constructor(name) {
16619
17022
  super(`No identity named "${name}". Run \`agent-shim identity add ${name}\` first.`);
@@ -16641,7 +17044,7 @@ var InvalidIdentityNameError = class extends CliError {
16641
17044
  attemptedName;
16642
17045
  };
16643
17046
  function identityJsonPath(paths, name) {
16644
- return path28.join(paths.identitiesDir, name, "identity.json");
17047
+ return path30.join(paths.identitiesDir, name, "identity.json");
16645
17048
  }
16646
17049
  function requireIdentityNames(paths, names) {
16647
17050
  const existing = new Set(listIdentities(paths).map((entry) => entry.name));
@@ -16652,21 +17055,23 @@ function requireIdentityNames(paths, names) {
16652
17055
  }
16653
17056
  }
16654
17057
  function identityExists(paths, name) {
16655
- return fs9.existsSync(identityJsonPath(paths, name));
17058
+ return fs10.existsSync(identityJsonPath(paths, name));
16656
17059
  }
16657
17060
  function readIdentity(paths, name) {
16658
17061
  return readJson(identityJsonPath(paths, name), IdentitySchema);
16659
17062
  }
16660
- function addIdentity(paths, name) {
17063
+ function requireIdentityCreatable(paths, name) {
17064
+ requireNoUnfinishedRenameNaming(paths, name, "add");
16661
17065
  if (identityExists(paths, name)) {
16662
17066
  throw new IdentityAlreadyExistsError(name);
16663
17067
  }
16664
- const parsed = IdentitySchema.safeParse({ name, allowAmbientCredential: false });
16665
- if (!parsed.success) {
16666
- throw new InvalidIdentityNameError(name);
16667
- }
16668
- writeJsonAtomic(identityJsonPath(paths, name), parsed.data);
16669
- return parsed.data;
17068
+ requireNewIdentityName(name);
17069
+ }
17070
+ function addIdentity(paths, name) {
17071
+ requireIdentityCreatable(paths, name);
17072
+ const identity = IdentitySchema.parse({ name, allowAmbientCredential: false });
17073
+ writeJsonAtomic(identityJsonPath(paths, name), identity);
17074
+ return identity;
16670
17075
  }
16671
17076
  function useIdentity(paths, name) {
16672
17077
  const pool = poolNameOf(name);
@@ -16679,33 +17084,89 @@ function useIdentity(paths, name) {
16679
17084
  `);
16680
17085
  }
16681
17086
  function readActiveIdentity2(paths) {
16682
- if (!fs9.existsSync(paths.activeIdentityFile)) {
17087
+ if (!fs10.existsSync(paths.activeIdentityFile)) {
16683
17088
  return void 0;
16684
17089
  }
16685
- const raw = fs9.readFileSync(paths.activeIdentityFile, "utf8").trim();
17090
+ const raw = fs10.readFileSync(paths.activeIdentityFile, "utf8").trim();
16686
17091
  return raw === "" ? void 0 : raw;
16687
17092
  }
16688
17093
  function isIdentityDirectoryName(name) {
16689
17094
  return !name.startsWith(".");
16690
17095
  }
17096
+ var UNREACHABLE_CODES = /* @__PURE__ */ new Set(["ELOOP", "EACCES", "ENOTDIR"]);
17097
+ function systemErrorCode(error) {
17098
+ return typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" ? error.code : void 0;
17099
+ }
17100
+ function unreachableCodeOf(error) {
17101
+ const code = systemErrorCode(error);
17102
+ if (code === "ENOENT") {
17103
+ return void 0;
17104
+ }
17105
+ if (code !== void 0 && UNREACHABLE_CODES.has(code)) {
17106
+ return code;
17107
+ }
17108
+ throw error;
17109
+ }
17110
+ function followedLink(link) {
17111
+ try {
17112
+ return fs10.statSync(link).isDirectory() ? "directory" : "other";
17113
+ } catch (error) {
17114
+ const code = unreachableCodeOf(error);
17115
+ return code === void 0 ? "other" : { code };
17116
+ }
17117
+ }
17118
+ function entryRefusal(directory) {
17119
+ try {
17120
+ fs10.accessSync(directory, fs10.constants.X_OK);
17121
+ return void 0;
17122
+ } catch (error) {
17123
+ return unreachableCodeOf(error);
17124
+ }
17125
+ }
17126
+ function listIdentityDirectories(paths) {
17127
+ const names = [];
17128
+ const unreachable = [];
17129
+ if (fs10.existsSync(paths.identitiesDir)) {
17130
+ for (const entry of fs10.readdirSync(paths.identitiesDir, { withFileTypes: true })) {
17131
+ if (!isIdentityDirectoryName(entry.name)) {
17132
+ continue;
17133
+ }
17134
+ const entryPath = path30.join(paths.identitiesDir, entry.name);
17135
+ const followed = entry.isDirectory() ? "directory" : entry.isSymbolicLink() ? followedLink(entryPath) : "other";
17136
+ if (followed === "other") {
17137
+ continue;
17138
+ }
17139
+ const code = followed === "directory" ? entryRefusal(entryPath) : followed.code;
17140
+ if (code === void 0) {
17141
+ names.push(entry.name);
17142
+ } else {
17143
+ unreachable.push({ name: entry.name, code });
17144
+ }
17145
+ }
17146
+ }
17147
+ return { names: names.sort(), unreachable: unreachable.sort((a, b) => a.name.localeCompare(b.name)) };
17148
+ }
17149
+ var NOT_JSON_PROBLEM = "is not valid JSON";
16691
17150
  function readIdentityForListing(paths, name) {
16692
17151
  try {
16693
17152
  return readIdentity(paths, name);
16694
17153
  } catch (error) {
16695
- if (error instanceof ConfigValidationError || error instanceof SyntaxError) {
17154
+ if (error instanceof ConfigFileNotJsonError) {
17155
+ return { problem: NOT_JSON_PROBLEM };
17156
+ }
17157
+ if (error instanceof ConfigValidationError) {
16696
17158
  return { problem: error.message.replace(/\s*\n\s*/g, " ") };
16697
17159
  }
16698
17160
  throw error;
16699
17161
  }
16700
17162
  }
16701
17163
  function listIdentities(paths) {
16702
- if (!fs9.existsSync(paths.identitiesDir)) {
17164
+ if (!fs10.existsSync(paths.identitiesDir)) {
16703
17165
  return [];
16704
17166
  }
16705
17167
  const active = readActiveIdentity2(paths);
16706
- const names = fs9.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort();
16707
17168
  const result = [];
16708
- for (const name of names) {
17169
+ for (const name of listIdentityDirectories(paths).names) {
16709
17170
  const read = readIdentityForListing(paths, name);
16710
17171
  if (read === void 0) {
16711
17172
  continue;
@@ -16715,6 +17176,10 @@ function listIdentities(paths) {
16715
17176
  }
16716
17177
  return result;
16717
17178
  }
17179
+ function requireIdentityAddable(paths, name, keychain, keepKeychainLogin) {
17180
+ requireIdentityCreatable(paths, name);
17181
+ requireNoLeftoverKeychainLogin(keychain, path30.join(paths.identitiesDir, name), name, keepKeychainLogin);
17182
+ }
16718
17183
  function setIdentityAnchors(paths, identityName, anchors) {
16719
17184
  if (!identityExists(paths, identityName)) {
16720
17185
  throw new IdentityNotFoundError(identityName);
@@ -16767,49 +17232,70 @@ function setIdentityCredential(paths, identityName, change) {
16767
17232
  credential: { sources: [...sources], ...target === void 0 ? {} : { target }, ...cache === void 0 ? {} : { cache } }
16768
17233
  });
16769
17234
  }
17235
+ var UUID_PATTERN = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
17236
+ var FARM_SUFFIX_PATTERN = `\\.(?:scratch|previous)\\.\\d+\\.${UUID_PATTERN}`;
17237
+ function escapedForPattern(text) {
17238
+ return text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
17239
+ }
17240
+ function isFarmEntry(entry, name) {
17241
+ return entry === name || new RegExp(`^\\.${escapedForPattern(name)}${FARM_SUFFIX_PATTERN}$`, "u").test(entry);
17242
+ }
16770
17243
  function belongsToIdentity(entry, name) {
16771
- return entry === name || entry === path28.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
17244
+ return isFarmEntry(entry, name) || entry === path30.basename(identityLockPath("", name));
17245
+ }
17246
+ function requireNewIdentityName(name) {
17247
+ if (!FileNameSchema.safeParse(name).success) {
17248
+ throw new InvalidIdentityNameError(name);
17249
+ }
17250
+ }
17251
+ function sameIdentityName(paths, first, second) {
17252
+ return sameDirectory(path30.join(paths.identitiesDir, first), path30.join(paths.identitiesDir, second)) || first.toLowerCase() === second.toLowerCase() && ignoresCase(paths.identitiesDir);
17253
+ }
17254
+ function requireNoUnfinishedRenameNaming(paths, name, action) {
17255
+ requireNameFreeOfUnfinishedRename({ readFileUtf8: nodeStoreFs.readFileUtf8, readdir: (directory) => fs10.existsSync(directory) ? fs10.readdirSync(directory) : [] }, paths.identityRenamesDir, name, action, (first, second) => sameIdentityName(paths, first, second), (identity) => identityExists(paths, identity));
16772
17256
  }
16773
17257
  function removeIdentity(paths, name) {
17258
+ requireNoUnfinishedRenameNaming(paths, name, "remove");
16774
17259
  if (!identityExists(paths, name)) {
16775
17260
  throw new IdentityNotFoundError(name);
16776
17261
  }
16777
- for (const entry of fs9.readdirSync(paths.identitiesDir)) {
17262
+ for (const entry of fs10.readdirSync(paths.identitiesDir)) {
16778
17263
  if (belongsToIdentity(entry, name)) {
16779
- fs9.rmSync(path28.join(paths.identitiesDir, entry), { recursive: true, force: true });
17264
+ fs10.rmSync(path30.join(paths.identitiesDir, entry), { recursive: true, force: true });
16780
17265
  }
16781
17266
  }
16782
17267
  if (readActiveIdentity2(paths) === name) {
16783
- fs9.rmSync(paths.activeIdentityFile);
17268
+ fs10.rmSync(paths.activeIdentityFile);
16784
17269
  }
16785
17270
  }
16786
17271
 
16787
17272
  // src/doctorReport.ts
16788
17273
  init_realPorts();
16789
- import fs11 from "node:fs";
16790
- import path29 from "node:path";
17274
+ import fs12 from "node:fs";
17275
+ import path31 from "node:path";
16791
17276
  init_signIn();
16792
17277
  init_identityAccounts();
17278
+ init_read();
16793
17279
 
16794
17280
  // src/codex/siwcStore.ts
16795
- import { z as z26 } from "zod";
17281
+ import { z as z27 } from "zod";
16796
17282
 
16797
17283
  // src/codex/auth.ts
16798
- import { z as z24 } from "zod";
16799
- var AuthFileSchema = z24.looseObject({
16800
- tokens: z24.looseObject({
16801
- access_token: z24.string().optional(),
16802
- refresh_token: z24.string().optional(),
16803
- id_token: z24.string().optional(),
16804
- account_id: z24.string().optional()
17284
+ import { z as z25 } from "zod";
17285
+ var AuthFileSchema = z25.looseObject({
17286
+ tokens: z25.looseObject({
17287
+ access_token: z25.string().optional(),
17288
+ refresh_token: z25.string().optional(),
17289
+ id_token: z25.string().optional(),
17290
+ account_id: z25.string().optional()
16805
17291
  }).nullish(),
16806
- last_refresh: z24.string().optional()
17292
+ last_refresh: z25.string().optional()
16807
17293
  });
16808
- var TokenGrantSchema = z24.looseObject({
16809
- access_token: z24.string().min(1).optional(),
16810
- refresh_token: z24.string().min(1).optional(),
16811
- id_token: z24.string().min(1).optional(),
16812
- account_id: z24.string().min(1).optional()
17294
+ var TokenGrantSchema = z25.looseObject({
17295
+ access_token: z25.string().min(1).optional(),
17296
+ refresh_token: z25.string().min(1).optional(),
17297
+ id_token: z25.string().min(1).optional(),
17298
+ account_id: z25.string().min(1).optional()
16813
17299
  });
16814
17300
  var CodexAuthError = class extends Error {
16815
17301
  constructor(message) {
@@ -16819,41 +17305,41 @@ var CodexAuthError = class extends Error {
16819
17305
  };
16820
17306
 
16821
17307
  // src/codex/siwc.ts
16822
- import { z as z25 } from "zod";
17308
+ import { z as z26 } from "zod";
16823
17309
  var SIWC_RESOURCE = "https://api.openai.com/v1";
16824
17310
  var SIWC_RESPONSES_URL = `${SIWC_RESOURCE}/responses`;
16825
17311
  var SIWC_PLAN_SCOPE = "chatgpt.tokens.use.direct";
16826
- var TokenResponseSchema = z25.looseObject({
16827
- access_token: z25.string().min(1),
16828
- refresh_token: z25.string().min(1).optional(),
16829
- id_token: z25.string().min(1).optional(),
16830
- expires_in: z25.number().positive(),
16831
- scope: z25.string().optional()
17312
+ var TokenResponseSchema = z26.looseObject({
17313
+ access_token: z26.string().min(1),
17314
+ refresh_token: z26.string().min(1).optional(),
17315
+ id_token: z26.string().min(1).optional(),
17316
+ expires_in: z26.number().positive(),
17317
+ scope: z26.string().optional()
16832
17318
  });
16833
- var JwtHeaderSchema = z25.looseObject({ alg: z25.string(), kid: z25.string().optional() });
16834
- var IdTokenClaimsSchema = z25.looseObject({
16835
- iss: z25.string(),
16836
- sub: z25.string().min(1),
16837
- aud: z25.union([z25.string(), z25.array(z25.string())]),
16838
- exp: z25.number(),
16839
- nonce: z25.string().optional(),
16840
- email: z25.string().optional()
17319
+ var JwtHeaderSchema = z26.looseObject({ alg: z26.string(), kid: z26.string().optional() });
17320
+ var IdTokenClaimsSchema = z26.looseObject({
17321
+ iss: z26.string(),
17322
+ sub: z26.string().min(1),
17323
+ aud: z26.union([z26.string(), z26.array(z26.string())]),
17324
+ exp: z26.number(),
17325
+ nonce: z26.string().optional(),
17326
+ email: z26.string().optional()
16841
17327
  });
16842
- var JwksSchema = z25.object({ keys: z25.array(z25.looseObject({ kid: z25.string().optional(), kty: z25.string() })) });
17328
+ var JwksSchema = z26.object({ keys: z26.array(z26.looseObject({ kid: z26.string().optional(), kty: z26.string() })) });
16843
17329
 
16844
17330
  // src/codex/siwcStore.ts
16845
- var SiwcGrantSchema = z26.strictObject({
16846
- clientId: z26.string().min(1),
16847
- sub: z26.string().min(1),
16848
- email: z26.string().optional(),
16849
- idToken: z26.string().min(1),
16850
- accessToken: z26.string().min(1),
16851
- refreshToken: z26.string().min(1),
16852
- scopes: z26.array(z26.string()).readonly(),
17331
+ var SiwcGrantSchema = z27.strictObject({
17332
+ clientId: z27.string().min(1),
17333
+ sub: z27.string().min(1),
17334
+ email: z27.string().optional(),
17335
+ idToken: z27.string().min(1),
17336
+ accessToken: z27.string().min(1),
17337
+ refreshToken: z27.string().min(1),
17338
+ scopes: z27.array(z27.string()).readonly(),
16853
17339
  /** When the access token stops working, in milliseconds since the epoch. */
16854
- expiresAt: z26.number()
17340
+ expiresAt: z27.number()
16855
17341
  });
16856
- var SiwcFileSchema = z26.strictObject({ registeredClientId: z26.string().min(1).optional(), grant: SiwcGrantSchema.optional() });
17342
+ var SiwcFileSchema = z27.strictObject({ registeredClientId: z27.string().min(1).optional(), grant: SiwcGrantSchema.optional() });
16857
17343
  function parseSiwcFile(raw, filePath) {
16858
17344
  let json;
16859
17345
  try {
@@ -17110,7 +17596,7 @@ function pushFrontDoorListeners(push, readings) {
17110
17596
 
17111
17597
  // src/frontdoor/listenerReadings.ts
17112
17598
  init_probe();
17113
- import fs10 from "node:fs";
17599
+ import fs11 from "node:fs";
17114
17600
  function readFrontDoorListeners(state, supervisorAlive, probes) {
17115
17601
  if (!supervisorAlive) {
17116
17602
  return [];
@@ -17130,7 +17616,7 @@ function readFrontDoorListeners(state, supervisorAlive, probes) {
17130
17616
  }
17131
17617
  function realFrontDoorListenerProbes(paths) {
17132
17618
  return {
17133
- authenticateProvider: (port) => probeFrontDoorSync(port, fs10.readFileSync(paths.frontdoorCaCertFile, "utf8")),
17619
+ authenticateProvider: (port) => probeFrontDoorSync(port, fs11.readFileSync(paths.frontdoorCaCertFile, "utf8")),
17134
17620
  connect: probeListenerAcceptSync,
17135
17621
  now: () => performance.now()
17136
17622
  };
@@ -17163,6 +17649,82 @@ function describeSharedLoginMembers(poolName, shared) {
17163
17649
  return `Pool "${poolName}" lists ${joinNames(shared.members)}, which hold the same login${holder === void 0 ? "" : ` (${holder})`}, so they share one quota window. A launch ranks them as one candidate and never fails over from one to another; keep one of them in the pool.`;
17164
17650
  }
17165
17651
 
17652
+ // src/poolWindowReads.ts
17653
+ init_schema();
17654
+ init_identity();
17655
+ init_conditions();
17656
+ init_middleware();
17657
+ init_rateLimit();
17658
+ var WINDOW_NAMES = ["fiveHour", "sevenDay", "extraUsage"];
17659
+ var WINDOW_PROSE = { fiveHour: "five-hour", sevenDay: "seven-day", extraUsage: "extra-usage" };
17660
+ var WINDOW_FACTS = ["remaining", "utilization", "hoursUntilReset"];
17661
+ var DERIVED_FACTS = [{ key: "quota.burnPerHour", window: "fiveHour" }];
17662
+ function receivedWindows(snapshot) {
17663
+ const unified = snapshot?.providers[ANTHROPIC_PROVIDER]?.rateLimit?.unified;
17664
+ if (unified === void 0) {
17665
+ return void 0;
17666
+ }
17667
+ return /* @__PURE__ */ new Set([...unified.fiveHour === void 0 ? [] : ["fiveHour"], ...unified.sevenDay === void 0 ? [] : ["sevenDay"], ...soleOverageWindow(unified) === void 0 ? [] : ["extraUsage"]]);
17668
+ }
17669
+ function conditionReads(when) {
17670
+ const direct = WINDOW_NAMES.flatMap((window) => WINDOW_FACTS.some((fact) => referencesFact(when, `quota.${window}.${fact}`)) ? [{ window, reference: `quota.${window}` }] : []);
17671
+ const derived = DERIVED_FACTS.flatMap(({ key, window }) => referencesFact(when, key) ? [{ window, reference: key }] : []);
17672
+ return [...direct, ...derived];
17673
+ }
17674
+ function identitiesOf(selector, pools, visited = /* @__PURE__ */ new Set()) {
17675
+ const nested = poolNameOf(selector);
17676
+ if (nested === void 0) {
17677
+ return [selector];
17678
+ }
17679
+ const pool = pools[nested];
17680
+ if (pool === void 0 || visited.has(nested)) {
17681
+ return [];
17682
+ }
17683
+ visited.add(nested);
17684
+ return [...new Set(pool.identities.flatMap((member) => identitiesOf(poolMemberIdentity(member), pools, visited)))];
17685
+ }
17686
+ function poolWindowReadFindings(pools, windowsOf) {
17687
+ const findings = [];
17688
+ for (const [poolName, pool] of Object.entries(pools)) {
17689
+ for (const member of pool.identities) {
17690
+ if (typeof member === "string") {
17691
+ continue;
17692
+ }
17693
+ const reads = conditionReads(member.when);
17694
+ for (const identity of identitiesOf(member.identity, pools)) {
17695
+ const received = windowsOf(identity);
17696
+ for (const { window, reference } of reads) {
17697
+ if (received !== void 0 && !received.has(window)) {
17698
+ findings.push({ subject: poolName, message: `Pool "${poolName}" guards ${member.identity} with a condition that reads ${reference}, but ${identity} reports no ${WINDOW_PROSE[window]} window, so the condition is undecided for it and it always ranks last within its class.` });
17699
+ }
17700
+ }
17701
+ }
17702
+ }
17703
+ if (pool.compactBeforeLimit === true) {
17704
+ for (const identity of identitiesOf(`pool:${poolName}`, pools)) {
17705
+ const received = windowsOf(identity);
17706
+ if (received !== void 0 && !received.has("fiveHour") && !received.has("sevenDay")) {
17707
+ findings.push({ subject: poolName, message: `Pool "${poolName}" compacts before the limit, but ${identity} reports no five-hour or seven-day window, so its sessions are never compacted before the limit.` });
17708
+ }
17709
+ }
17710
+ }
17711
+ }
17712
+ return findings;
17713
+ }
17714
+ function jobWindowReadFindings(jobs, pools, windowsOf) {
17715
+ return Object.entries(jobs).flatMap(([jobName, job]) => {
17716
+ const { trigger, target } = job;
17717
+ if (!("beforeReset" in trigger)) {
17718
+ return [];
17719
+ }
17720
+ const identities = "pool" in target ? identitiesOf(`pool:${target.pool}`, pools) : identitiesOf(target.identity, pools);
17721
+ return identities.flatMap((identity) => {
17722
+ const received = windowsOf(identity);
17723
+ return received === void 0 || received.has(trigger.beforeReset) ? [] : [{ subject: jobName, message: `Job "${jobName}" runs before the ${WINDOW_PROSE[trigger.beforeReset]} window resets, but ${identity} reports no ${WINDOW_PROSE[trigger.beforeReset]} window, so the job is skipped whenever it runs as ${identity}.` }];
17724
+ });
17725
+ });
17726
+ }
17727
+
17166
17728
  // src/doctorReport.ts
17167
17729
  init_extends();
17168
17730
  var DOCTOR_SEVERITIES = ["pass", "warn", "fail"];
@@ -17199,8 +17761,8 @@ function validateJson(schema, input) {
17199
17761
  let parsed;
17200
17762
  try {
17201
17763
  parsed = JSON.parse(input.raw);
17202
- } catch (error) {
17203
- return { ok: false, message: `${input.path} is not valid JSON: ${error instanceof Error ? error.message : String(error)}` };
17764
+ } catch {
17765
+ return { ok: false, message: `${input.path} is not valid JSON.` };
17204
17766
  }
17205
17767
  const result = parseIgnoringUnrecognisedKeys(schema, parsed);
17206
17768
  if (!result.success) {
@@ -17219,7 +17781,7 @@ function tcpPortEraRecord(raw) {
17219
17781
  return (has("port") || has("lastPort")) && !has("socketPath");
17220
17782
  }
17221
17783
  function pushPathResolution(push, resolution) {
17222
- const ownDir = path29.dirname(resolution.ownExecutablePath);
17784
+ const ownDir = path31.dirname(resolution.ownExecutablePath);
17223
17785
  switch (resolution.agentShim.status) {
17224
17786
  case "ok":
17225
17787
  push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
@@ -17306,8 +17868,8 @@ function pushProvider(push, entry, cacheEnv, signIn) {
17306
17868
  let parsed;
17307
17869
  try {
17308
17870
  parsed = JSON.parse(entry.raw);
17309
- } catch (error) {
17310
- push("provider", "fail", `${entry.path} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`, entry.name);
17871
+ } catch {
17872
+ push("provider", "fail", `${entry.path} is not valid JSON.`, entry.name);
17311
17873
  return;
17312
17874
  }
17313
17875
  const conversion = legacyProviderConversion(parsed);
@@ -17339,14 +17901,14 @@ function pushProvider(push, entry, cacheEnv, signIn) {
17339
17901
  }
17340
17902
  function pushLegacyName(push, params) {
17341
17903
  const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
17342
- if (legacyVariables.length === 0 && path29.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
17904
+ if (legacyVariables.length === 0 && path31.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
17343
17905
  push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
17344
17906
  return;
17345
17907
  }
17346
17908
  for (const name of legacyVariables) {
17347
17909
  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);
17348
17910
  }
17349
- if (path29.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
17911
+ if (path31.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
17350
17912
  push(
17351
17913
  "legacy-name",
17352
17914
  "warn",
@@ -17432,6 +17994,16 @@ function runDoctor(params) {
17432
17994
  }
17433
17995
  const validProfileNames = new Set(profileSources.keys());
17434
17996
  const validProviderNames = /* @__PURE__ */ new Set([...params.providers.map((entry) => entry.name), ...Object.keys(params.providerAliases ?? {})]);
17997
+ const identityNames = new Set(params.identities.filter((entry) => entry.raw !== void 0).map((entry) => entry.name));
17998
+ for (const journal of params.renameJournals?.journals ?? []) {
17999
+ push("identity", "fail", `There is ${describeUnfinishedRename(journal, finishabilityOf(journal, (name) => identityNames.has(name)))}`, journal.from);
18000
+ }
18001
+ for (const { name, code } of params.unreachableIdentities ?? []) {
18002
+ push("identity", "warn", `identities/${name} cannot be reached (${code}), so it is not counted as an identity. Repair the permissions of the directory or of what a symlink points through, or remove the entry.`, name);
18003
+ }
18004
+ for (const { file, detail } of params.renameJournals?.unreadable ?? []) {
18005
+ push("identity", "fail", `${file} is not a rename journal this agent-shim can read (${detail}), so no identity can be renamed until it is fixed or removed, and it may be the trace of a rename that was left unfinished.`, path31.basename(file));
18006
+ }
17435
18007
  const validIdentityNames = /* @__PURE__ */ new Set();
17436
18008
  const signedInAccounts = [];
17437
18009
  for (const entry of params.identities) {
@@ -17531,6 +18103,17 @@ function runDoctor(params) {
17531
18103
  reportedCycles.add(key);
17532
18104
  push("pool", "fail", `Pool cycle: ${chain.join(" -> ")}. A pool cannot nest itself, directly or through another pool.`, chain[0]);
17533
18105
  }
18106
+ const { usageSnapshots } = params;
18107
+ if (usageSnapshots !== void 0) {
18108
+ const windowsOf = (identityName) => receivedWindows(usageSnapshots[identityName]);
18109
+ for (const finding of poolWindowReadFindings(pools, windowsOf)) {
18110
+ push("pool", "warn", finding.message, finding.subject);
18111
+ }
18112
+ const jobs = validatedGlobalConfig?.ok === true ? validatedGlobalConfig.data.jobs ?? {} : {};
18113
+ for (const finding of jobWindowReadFindings(jobs, pools, windowsOf)) {
18114
+ push("global-config", "warn", finding.message, finding.subject);
18115
+ }
18116
+ }
17534
18117
  const selectionExists = (selector) => {
17535
18118
  const poolName = poolNameOf(selector);
17536
18119
  return poolName === void 0 ? validIdentityNames.has(selector) : poolName in pools;
@@ -17771,7 +18354,7 @@ function formatDoctorReport(report) {
17771
18354
  }
17772
18355
  function realpathOrSelf(target) {
17773
18356
  try {
17774
- return fs11.realpathSync(target);
18357
+ return fs12.realpathSync(target);
17775
18358
  } catch {
17776
18359
  return target;
17777
18360
  }
@@ -17783,20 +18366,33 @@ function servingDoorListeners(paths) {
17783
18366
  }
17784
18367
  function collectDoctorReport(params) {
17785
18368
  const { paths } = params;
17786
- const identityNames = fs11.existsSync(paths.identitiesDir) ? fs11.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
18369
+ const { names: identityNames, unreachable: unreachableIdentities } = listIdentityDirectories(paths);
17787
18370
  const identities = identityNames.map((name) => {
17788
- const farmRoot = path29.join(paths.identitiesDir, name);
17789
- const identityPath = path29.join(farmRoot, "identity.json");
17790
- return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot, credentialsFilePresent: fs11.existsSync(credentialsFilePath(farmRoot)), account: readIdentityAccount(realFsPort, paths.identitiesDir, name)?.account };
18371
+ const farmRoot = path31.join(paths.identitiesDir, name);
18372
+ const identityPath = path31.join(farmRoot, "identity.json");
18373
+ return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot, credentialsFilePresent: fs12.existsSync(credentialsFilePath(farmRoot)), account: readIdentityAccount(realFsPort, paths.identitiesDir, name)?.account };
17791
18374
  });
17792
- const profileNames = fs11.existsSync(paths.configProfilesDir) ? fs11.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
18375
+ const usageSnapshots = {};
18376
+ for (const name of identityNames) {
18377
+ try {
18378
+ const snapshot = readUsageSnapshot(realFsPort, paths.usageSnapshotsDir, name);
18379
+ if (snapshot !== void 0) {
18380
+ usageSnapshots[name] = snapshot;
18381
+ }
18382
+ } catch (error) {
18383
+ if (!(error instanceof UsageSnapshotError)) {
18384
+ throw error;
18385
+ }
18386
+ }
18387
+ }
18388
+ const profileNames = fs12.existsSync(paths.configProfilesDir) ? fs12.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
17793
18389
  const configProfiles = profileNames.map((name) => {
17794
- const profilePath = path29.join(paths.configProfilesDir, `${name}.json`);
18390
+ const profilePath = path31.join(paths.configProfilesDir, `${name}.json`);
17795
18391
  return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
17796
18392
  });
17797
- const providerNames = fs11.existsSync(paths.providersDir) ? fs11.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
18393
+ const providerNames = fs12.existsSync(paths.providersDir) ? fs12.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
17798
18394
  const providers = providerNames.map((name) => {
17799
- const providerPath = path29.join(paths.providersDir, `${name}.json`);
18395
+ const providerPath = path31.join(paths.providersDir, `${name}.json`);
17800
18396
  return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
17801
18397
  });
17802
18398
  const ownExecutablePath = realOwnExecutablePath();
@@ -17808,12 +18404,12 @@ function collectDoctorReport(params) {
17808
18404
  binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
17809
18405
  }
17810
18406
  const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
17811
- const pathDirs = (params.env.PATH ?? "").split(path29.delimiter).filter((dir) => dir !== "");
18407
+ const pathDirs = (params.env.PATH ?? "").split(path31.delimiter).filter((dir) => dir !== "");
17812
18408
  const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
17813
18409
  findPathShadow({
17814
18410
  pathDirs,
17815
- targetDir: path29.dirname(shimState.targetPath),
17816
- targetFilename: path29.basename(shimState.targetPath),
18411
+ targetDir: path31.dirname(shimState.targetPath),
18412
+ targetFilename: path31.basename(shimState.targetPath),
17817
18413
  findExecutableInDir
17818
18414
  }),
17819
18415
  shimState.targetPath,
@@ -17832,9 +18428,12 @@ function collectDoctorReport(params) {
17832
18428
  chatgptSignIn: { path: paths.chatgptSignInFile, raw: realFsPort.readFileUtf8(paths.chatgptSignInFile) },
17833
18429
  installedClaudeVersions: realInstalledClaudeVersions(),
17834
18430
  identities,
18431
+ usageSnapshots,
17835
18432
  configProfiles,
17836
18433
  providers,
17837
18434
  providerAliases: readProviderAliases(paths),
18435
+ renameJournals: listRenameJournals(realFarmFs, paths.identityRenamesDir),
18436
+ unreachableIdentities,
17838
18437
  directoryRules: { path: paths.directoryRulesFile, raw: realFsPort.readFileUtf8(paths.directoryRulesFile) },
17839
18438
  globalConfig: { path: paths.globalConfigFile, raw: realFsPort.readFileUtf8(paths.globalConfigFile) },
17840
18439
  models: parsedModelsOf(paths),
@@ -17842,14 +18441,14 @@ function collectDoctorReport(params) {
17842
18441
  categoriesLocal: { path: paths.categoriesLocalFile, raw: realFsPort.readFileUtf8(paths.categoriesLocalFile) },
17843
18442
  activeIdentity: { path: paths.activeIdentityFile, raw: realFsPort.readFileUtf8(paths.activeIdentityFile) },
17844
18443
  binaryDiscovery,
17845
- claudeShim: { state: shimState, targetExists: shimState !== void 0 && fs11.existsSync(shimState.targetPath) },
18444
+ claudeShim: { state: shimState, targetExists: shimState !== void 0 && fs12.existsSync(shimState.targetPath) },
17846
18445
  rootPath: paths.root,
17847
18446
  pathResolution: {
17848
18447
  ownExecutablePath,
17849
18448
  agentShim: refinePathShadow(
17850
18449
  findPathShadow({
17851
18450
  pathDirs,
17852
- targetDir: path29.dirname(ownExecutablePath),
18451
+ targetDir: path31.dirname(ownExecutablePath),
17853
18452
  targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
17854
18453
  findExecutableInDir
17855
18454
  }),
@@ -17890,92 +18489,92 @@ function collectDoctorReport(params) {
17890
18489
  // src/frontdoor/controlSchemas.ts
17891
18490
  init_schema2();
17892
18491
  init_state();
17893
- var UsageListOutputSchema = z29.strictObject({ snapshots: z29.readonly(z29.array(UsageSnapshotSchema)) });
17894
- var UsageWindowsInputSchema = z29.strictObject({
17895
- identity: z29.string().min(1),
17896
- provider: z29.string().min(1).optional()
18492
+ var UsageListOutputSchema = z30.strictObject({ snapshots: z30.readonly(z30.array(UsageSnapshotSchema)) });
18493
+ var UsageWindowsInputSchema = z30.strictObject({
18494
+ identity: z30.string().min(1),
18495
+ provider: z30.string().min(1).optional()
17897
18496
  });
17898
- var EffectiveWindowSchema = z29.strictObject({
18497
+ var EffectiveWindowSchema = z30.strictObject({
17899
18498
  /** True when the window's reset time has passed, so the recorded observation describes a window that no longer exists. */
17900
- reset: z29.boolean(),
18499
+ reset: z30.boolean(),
17901
18500
  /** The fraction used: 0 for a reset window, otherwise what was last observed, absent when none was reported. */
17902
- utilization: z29.number().optional(),
18501
+ utilization: z30.number().optional(),
17903
18502
  /** The reset instant, for a window that has not reset yet and reported one. */
17904
- resetsAtMs: z29.number().optional(),
18503
+ resetsAtMs: z30.number().optional(),
17905
18504
  /** The window's own status, for a window that has not reset yet. */
17906
- status: z29.string().optional()
18505
+ status: z30.string().optional()
17907
18506
  });
17908
- var UsageWindowsOutputSchema = z29.strictObject({
17909
- identity: z29.string(),
17910
- provider: z29.string(),
18507
+ var UsageWindowsOutputSchema = z30.strictObject({
18508
+ identity: z30.string(),
18509
+ provider: z30.string(),
17911
18510
  /** When the rate-limit state the windows come from was observed. */
17912
- observedAt: z29.iso.datetime().optional(),
18511
+ observedAt: z30.iso.datetime().optional(),
17913
18512
  fiveHour: EffectiveWindowSchema.optional(),
17914
18513
  sevenDay: EffectiveWindowSchema.optional()
17915
18514
  });
17916
- var UsageLiveOutputSchema = z29.strictObject({
18515
+ var UsageLiveOutputSchema = z30.strictObject({
17917
18516
  /** The freshest observation the door holds, never narrowed by the read's session filter because it is the door's single latest statement of the account's quota; absent while no rate_limit_event has been filed at all. */
17918
18517
  latest: RcLiveRateLimitSchema.optional(),
17919
18518
  /** One observation per session whose stream has filed a rate_limit_event this door generation. */
17920
- sessions: z29.readonly(z29.array(RcLiveRateLimitSchema))
18519
+ sessions: z30.readonly(z30.array(RcLiveRateLimitSchema))
17921
18520
  });
17922
- var FrontDoorSessionStatusSchema = z29.strictObject({
17923
- pid: z29.int().positive(),
17924
- startedAt: z29.number(),
17925
- alive: z29.boolean()
18521
+ var FrontDoorSessionStatusSchema = z30.strictObject({
18522
+ pid: z30.int().positive(),
18523
+ startedAt: z30.number(),
18524
+ alive: z30.boolean()
17926
18525
  });
17927
- var HeadroomSocketTargetSchema = z29.union([z29.strictObject({ socketPath: z29.string() }), z29.strictObject({ refused: z29.string() })]);
17928
- var FrontDoorStatusOutputSchema = z29.strictObject({
18526
+ var HeadroomSocketTargetSchema = z30.union([z30.strictObject({ socketPath: z30.string() }), z30.strictObject({ refused: z30.string() })]);
18527
+ var FrontDoorStatusOutputSchema = z30.strictObject({
17929
18528
  state: FrontDoorStateSchema,
17930
- supervisorAlive: z29.boolean(),
18529
+ supervisorAlive: z30.boolean(),
17931
18530
  /** The pids of earlier doors that released their addresses and are finishing the connections they carried: running, but not serving anything new. */
17932
- draining: z29.readonly(z29.array(z29.number().int().positive())),
17933
- sessions: z29.readonly(z29.array(FrontDoorSessionStatusSchema)),
18531
+ draining: z30.readonly(z30.array(z30.number().int().positive())),
18532
+ sessions: z30.readonly(z30.array(FrontDoorSessionStatusSchema)),
17934
18533
  headroomSocket: HeadroomSocketTargetSchema.optional(),
17935
- logPath: z29.string(),
17936
- logExists: z29.boolean()
18534
+ logPath: z30.string(),
18535
+ logExists: z30.boolean()
17937
18536
  });
17938
- var FrontDoorSessionsOutputSchema = z29.strictObject({ sessions: z29.readonly(z29.array(FrontDoorSessionStatusSchema)) });
17939
- var CheckRunInputSchema = z29.strictObject({
17940
- path: z29.string().min(1),
17941
- identity: z29.string().min(1).optional()
17942
- }).refine((input) => path30.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
17943
- var PoolPickInputSchema = z29.strictObject({
17944
- pool: z29.string().min(1),
17945
- path: z29.string().min(1)
17946
- }).refine((input) => path30.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
17947
- var DoctorFindingSchema = z29.strictObject({
17948
- section: z29.enum(DOCTOR_SECTIONS),
17949
- subject: z29.string().optional(),
17950
- severity: z29.enum(DOCTOR_SEVERITIES),
17951
- message: z29.string()
18537
+ var FrontDoorSessionsOutputSchema = z30.strictObject({ sessions: z30.readonly(z30.array(FrontDoorSessionStatusSchema)) });
18538
+ var CheckRunInputSchema = z30.strictObject({
18539
+ path: z30.string().min(1),
18540
+ identity: z30.string().min(1).optional()
18541
+ }).refine((input) => path32.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
18542
+ var PoolPickInputSchema = z30.strictObject({
18543
+ pool: z30.string().min(1),
18544
+ path: z30.string().min(1)
18545
+ }).refine((input) => path32.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
18546
+ var DoctorFindingSchema = z30.strictObject({
18547
+ section: z30.enum(DOCTOR_SECTIONS),
18548
+ subject: z30.string().optional(),
18549
+ severity: z30.enum(DOCTOR_SEVERITIES),
18550
+ message: z30.string()
17952
18551
  });
17953
- var DoctorRunOutputSchema = z29.strictObject({
18552
+ var DoctorRunOutputSchema = z30.strictObject({
17954
18553
  /** False exactly when any finding is a `fail`; a `warn` never fails the report on its own. */
17955
- ok: z29.boolean(),
17956
- findings: z29.readonly(z29.array(DoctorFindingSchema))
18554
+ ok: z30.boolean(),
18555
+ findings: z30.readonly(z30.array(DoctorFindingSchema))
17957
18556
  });
17958
- var FrontDoorRestartOutputSchema = z29.strictObject({
17959
- action: z29.literal("restarting"),
17960
- previousPid: z29.int().positive()
18557
+ var FrontDoorRestartOutputSchema = z30.strictObject({
18558
+ action: z30.literal("restarting"),
18559
+ previousPid: z30.int().positive()
17961
18560
  });
17962
- var UpdateCheckOutputSchema = z29.strictObject({
17963
- current: z29.string(),
17964
- latest: z29.string(),
17965
- action: z29.enum(["current", "available", "updated"])
18561
+ var UpdateCheckOutputSchema = z30.strictObject({
18562
+ current: z30.string(),
18563
+ latest: z30.string(),
18564
+ action: z30.enum(["current", "available", "updated"])
17966
18565
  });
17967
- var CodexSignInSchema = z29.discriminatedUnion("state", [
17968
- z29.strictObject({ state: z29.literal("none") }),
17969
- z29.strictObject({ state: z29.literal("signed-in"), email: z29.string().optional(), planScope: z29.boolean(), accessTokenExpiresAt: z29.number() }),
17970
- z29.strictObject({ state: z29.literal("unreadable"), message: z29.string() })
18566
+ var CodexSignInSchema = z30.discriminatedUnion("state", [
18567
+ z30.strictObject({ state: z30.literal("none") }),
18568
+ z30.strictObject({ state: z30.literal("signed-in"), email: z30.string().optional(), planScope: z30.boolean(), accessTokenExpiresAt: z30.number() }),
18569
+ z30.strictObject({ state: z30.literal("unreadable"), message: z30.string() })
17971
18570
  ]);
17972
- var CodexStatusOutputSchema = z29.strictObject({
18571
+ var CodexStatusOutputSchema = z30.strictObject({
17973
18572
  signIn: CodexSignInSchema,
17974
- codexProviders: z29.readonly(z29.array(z29.string()))
18573
+ codexProviders: z30.readonly(z30.array(z30.string()))
17975
18574
  });
17976
- var CodexLogoutOutputSchema = z29.strictObject({
17977
- hadGrant: z29.boolean(),
17978
- revoked: z29.boolean()
18575
+ var CodexLogoutOutputSchema = z30.strictObject({
18576
+ hadGrant: z30.boolean(),
18577
+ revoked: z30.boolean()
17979
18578
  });
17980
18579
 
17981
18580
  // src/frontdoor/codexApi.ts
@@ -18130,72 +18729,74 @@ function requireRuleSelector(paths, selector) {
18130
18729
 
18131
18730
  // src/frontdoor/configApi.ts
18132
18731
  init_identity();
18732
+ init_replayRun();
18133
18733
  init_providersStore();
18134
18734
 
18135
18735
  // src/frontdoor/configSchemas.ts
18136
18736
  init_schema();
18137
18737
  init_names();
18738
+ import { z as z31 } from "zod";
18138
18739
  init_statusline();
18139
- import { z as z30 } from "zod";
18140
- var RemovalConfirmationSchema = z30.boolean();
18141
- var CredentialWriteSchema = (targets) => z30.strictObject({
18142
- sources: z30.array(RemoteCredentialSourceSchema).min(1).optional(),
18143
- target: z30.enum(targets).optional(),
18144
- cache: z30.union([z30.literal(false), CredentialCacheSchema]).optional()
18740
+ var RemovalConfirmationSchema = z31.boolean();
18741
+ var CredentialWriteSchema = (targets) => z31.strictObject({
18742
+ sources: z31.array(RemoteCredentialSourceSchema).min(1).optional(),
18743
+ target: z31.enum(targets).optional(),
18744
+ cache: z31.union([z31.literal(false), CredentialCacheSchema]).optional()
18145
18745
  });
18146
- var CredentialSummarySchema2 = z30.strictObject({
18147
- target: z30.enum(CREDENTIAL_TARGETS),
18148
- sources: z30.readonly(z30.array(
18149
- z30.discriminatedUnion("kind", [
18150
- z30.strictObject({ kind: z30.literal("env"), variable: z30.string() }),
18151
- z30.strictObject({ kind: z30.literal("file"), path: z30.string() }),
18152
- z30.strictObject({ kind: z30.literal("command"), program: z30.string() }),
18153
- z30.strictObject({ kind: z30.literal("op"), reference: z30.string() }),
18154
- z30.strictObject({ kind: z30.literal("keychain"), service: z30.string(), account: z30.string().optional() }),
18155
- z30.strictObject({ kind: z30.literal("literal") })
18746
+ var CredentialSummarySchema2 = z31.strictObject({
18747
+ target: z31.enum(CREDENTIAL_TARGETS),
18748
+ sources: z31.readonly(z31.array(
18749
+ z31.discriminatedUnion("kind", [
18750
+ z31.strictObject({ kind: z31.literal("env"), variable: z31.string() }),
18751
+ z31.strictObject({ kind: z31.literal("file"), path: z31.string() }),
18752
+ z31.strictObject({ kind: z31.literal("command"), program: z31.string() }),
18753
+ z31.strictObject({ kind: z31.literal("op"), reference: z31.string() }),
18754
+ z31.strictObject({ kind: z31.literal("keychain"), service: z31.string(), account: z31.string().optional() }),
18755
+ z31.strictObject({ kind: z31.literal("literal") })
18156
18756
  ])
18157
18757
  )),
18158
18758
  cache: CredentialCacheSchema.optional()
18159
18759
  });
18160
- var mutationOutput = (kind, action) => z30.strictObject({ action: z30.literal(action), kind: z30.literal(kind), name: z30.string() });
18161
- var storedMutationOutput = (kind, action, value) => z30.strictObject({ action: z30.literal(action), kind: z30.literal(kind), name: z30.string(), value });
18162
- var IdentityValueSchema = z30.strictObject({
18163
- name: z30.string(),
18164
- label: z30.string().optional(),
18165
- defaultConfigProfile: z30.string().optional(),
18166
- provider: z30.string().optional(),
18167
- allowAmbientCredential: z30.boolean(),
18760
+ var mutationOutput = (kind, action) => z31.strictObject({ action: z31.literal(action), kind: z31.literal(kind), name: z31.string() });
18761
+ var storedMutationOutput = (kind, action, value) => z31.strictObject({ action: z31.literal(action), kind: z31.literal(kind), name: z31.string(), value });
18762
+ var IdentityValueSchema = z31.strictObject({
18763
+ name: z31.string(),
18764
+ label: z31.string().optional(),
18765
+ defaultConfigProfile: z31.string().optional(),
18766
+ provider: z31.string().optional(),
18767
+ allowAmbientCredential: z31.boolean(),
18168
18768
  credential: CredentialSummarySchema2.optional(),
18169
- anchors: z30.array(AnchorSchema).optional()
18769
+ anchors: z31.array(AnchorSchema).optional()
18170
18770
  });
18171
18771
  var ProfileValueSchema = ConfigProfileSchema.omit({ $schema: true });
18172
- var ProviderValueSchema = z30.strictObject({
18173
- name: z30.string(),
18174
- kind: z30.enum(PROVIDER_KINDS),
18175
- displayName: z30.string(),
18176
- baseUrl: z30.string().optional(),
18772
+ var ProviderValueSchema = z31.strictObject({
18773
+ name: z31.string(),
18774
+ kind: z31.enum(PROVIDER_KINDS),
18775
+ displayName: z31.string(),
18776
+ baseUrl: z31.string().optional(),
18177
18777
  codex: CodexProviderConfigSchema.optional(),
18178
18778
  credential: CredentialSummarySchema2.optional(),
18179
- env: z30.record(z30.string(), z30.string()).optional()
18779
+ env: z31.record(z31.string(), z31.string()).optional()
18180
18780
  });
18181
- var ConfigNameInputSchema = z30.strictObject({ name: z30.string().min(1) });
18781
+ var ConfigNameInputSchema = z31.strictObject({ name: z31.string().min(1) });
18782
+ var ConfigIdentityAddInputSchema = z31.strictObject({ name: z31.string().min(1), keepKeychainLogin: z31.boolean().optional().describe(KEEP_KEYCHAIN_LOGIN_DESCRIPTION) });
18182
18783
  var ConfigIdentityAddOutputSchema = storedMutationOutput("identity", "created", IdentityValueSchema);
18183
- var ConfigIdentitySetInputSchema = z30.strictObject({
18184
- name: z30.string().min(1),
18784
+ var ConfigIdentitySetInputSchema = z31.strictObject({
18785
+ name: z31.string().min(1),
18185
18786
  /** The identity's display label; `false` clears it. */
18186
- label: z30.union([IdentityLabelSchema, z30.literal(false)]).optional(),
18187
- defaultConfigProfile: z30.union([z30.string().min(1), z30.literal(false)]).optional(),
18787
+ label: z31.union([IdentityLabelSchema, z31.literal(false)]).optional(),
18788
+ defaultConfigProfile: z31.union([z31.string().min(1), z31.literal(false)]).optional(),
18188
18789
  /** The provider the identity exists for; `false` clears it. */
18189
- provider: z30.union([z30.string().min(1), z30.literal(false)]).optional(),
18190
- allowAmbientCredential: z30.boolean().optional(),
18191
- credential: z30.union([z30.literal(false), CredentialWriteSchema(CREDENTIAL_TARGETS)]).optional(),
18790
+ provider: z31.union([z31.string().min(1), z31.literal(false)]).optional(),
18791
+ allowAmbientCredential: z31.boolean().optional(),
18792
+ credential: z31.union([z31.literal(false), CredentialWriteSchema(CREDENTIAL_TARGETS)]).optional(),
18192
18793
  /** `false` removes the anchors; a list replaces them. */
18193
- anchors: z30.union([z30.literal(false), z30.array(AnchorSchema).min(1)]).optional()
18794
+ anchors: z31.union([z31.literal(false), z31.array(AnchorSchema).min(1)]).optional()
18194
18795
  });
18195
18796
  var ConfigIdentitySetOutputSchema = storedMutationOutput("identity", "updated", IdentityValueSchema);
18196
- var ConfigIdentityRemoveInputSchema = z30.strictObject({ name: z30.string().min(1), confirm: RemovalConfirmationSchema });
18797
+ var ConfigIdentityRemoveInputSchema = z31.strictObject({ name: z31.string().min(1), confirm: RemovalConfirmationSchema });
18197
18798
  var ConfigIdentityRemoveOutputSchema = mutationOutput("identity", "removed");
18198
- var ConfigStatuslineSetSchema = z30.record(z30.string(), z30.unknown()).superRefine((settings, context) => {
18799
+ var ConfigStatuslineSetSchema = z31.record(z31.string(), z31.unknown()).superRefine((settings, context) => {
18199
18800
  for (const key of Object.keys(settings)) {
18200
18801
  if (key === STATUSLINE_EXTRA_GROUP || key.startsWith(`${STATUSLINE_EXTRA_GROUP}.`)) {
18201
18802
  context.addIssue({ code: "custom", path: [key], message: `a config write through the API cannot set "${key}": the extra segment's command runs a program, so only your own configuration (the global config, a profile you edit yourself, a directory rule or a command-line assignment) may set it` });
@@ -18203,102 +18804,105 @@ var ConfigStatuslineSetSchema = z30.record(z30.string(), z30.unknown()).superRef
18203
18804
  }
18204
18805
  });
18205
18806
  var ConfigIdentityUseOutputSchema = mutationOutput("identity", "selected");
18206
- var ConfigProfileAddInputSchema = z30.strictObject({
18207
- name: z30.string().min(1),
18208
- extends: z30.array(z30.string().min(1)).optional(),
18209
- description: z30.string().optional()
18807
+ var ConfigProfileAddInputSchema = z31.strictObject({
18808
+ name: z31.string().min(1),
18809
+ extends: z31.array(z31.string().min(1)).optional(),
18810
+ description: z31.string().optional()
18210
18811
  });
18211
18812
  var ConfigProfileAddOutputSchema = storedMutationOutput("profile", "created", ProfileValueSchema);
18212
- var ConfigProfileSetInputSchema = z30.strictObject({
18213
- name: z30.string().min(1),
18214
- category: z30.record(z30.string(), z30.boolean()).optional(),
18215
- entry: z30.record(z30.string(), z30.boolean()).optional(),
18216
- extends: z30.union([z30.array(z30.string().min(1)), z30.literal(false)]).optional(),
18217
- description: z30.union([z30.string(), z30.literal(false)]).optional(),
18218
- launch: z30.strictObject({
18219
- skipPermissions: z30.boolean().optional(),
18220
- remoteControl: z30.boolean().optional(),
18221
- headroom: z30.boolean().optional(),
18222
- trackUsage: z30.boolean().optional(),
18223
- provider: z30.union([z30.string().min(1), z30.literal(false)]).optional(),
18224
- claudeVersion: z30.union([z30.string().min(1), z30.literal(false)]).optional(),
18225
- delay: z30.union([z30.string().regex(DURATION_RE), z30.literal(false)]).optional(),
18226
- pause: z30.boolean().optional(),
18227
- explain: z30.boolean().optional(),
18228
- proxyBypass: z30.union([z30.array(z30.string().min(1)), z30.literal(false)]).optional(),
18229
- statusline: z30.strictObject({
18813
+ var ConfigProfileSetInputSchema = z31.strictObject({
18814
+ name: z31.string().min(1),
18815
+ category: z31.record(z31.string(), z31.boolean()).optional(),
18816
+ entry: z31.record(z31.string(), z31.boolean()).optional(),
18817
+ extends: z31.union([z31.array(z31.string().min(1)), z31.literal(false)]).optional(),
18818
+ description: z31.union([z31.string(), z31.literal(false)]).optional(),
18819
+ launch: z31.strictObject({
18820
+ skipPermissions: z31.boolean().optional(),
18821
+ remoteControl: z31.boolean().optional(),
18822
+ headroom: z31.boolean().optional(),
18823
+ trackUsage: z31.boolean().optional(),
18824
+ provider: z31.union([z31.string().min(1), z31.literal(false)]).optional(),
18825
+ claudeVersion: z31.union([z31.string().min(1), z31.literal(false)]).optional(),
18826
+ delay: z31.union([z31.string().regex(DURATION_RE), z31.literal(false)]).optional(),
18827
+ pause: z31.boolean().optional(),
18828
+ explain: z31.boolean().optional(),
18829
+ proxyBypass: z31.union([z31.array(z31.string().min(1)), z31.literal(false)]).optional(),
18830
+ statusline: z31.strictObject({
18230
18831
  set: ConfigStatuslineSetSchema.optional(),
18231
- unset: z30.array(z30.string()).optional()
18832
+ unset: z31.array(z31.string()).optional()
18232
18833
  }).optional()
18233
18834
  }).optional()
18234
18835
  });
18235
18836
  var ConfigProfileSetOutputSchema = storedMutationOutput("profile", "updated", ProfileValueSchema);
18236
- var ConfigProfileRemoveInputSchema = z30.strictObject({ name: z30.string().min(1), confirm: RemovalConfirmationSchema });
18837
+ var ConfigProfileRemoveInputSchema = z31.strictObject({ name: z31.string().min(1), confirm: RemovalConfirmationSchema });
18237
18838
  var ConfigProfileRemoveOutputSchema = mutationOutput("profile", "removed");
18238
18839
  var ConfigProfileUseOutputSchema = mutationOutput("profile", "selected");
18239
- var PoolMembersInputSchema = z30.array(z30.string().min(1)).min(1);
18240
- var ConfigPoolAddInputSchema = z30.strictObject({
18241
- name: z30.string().min(1),
18840
+ var PoolMembersInputSchema = z31.array(z31.string().min(1)).min(1);
18841
+ var ConfigPoolAddInputSchema = z31.strictObject({
18842
+ name: z31.string().min(1),
18242
18843
  identities: PoolMembersInputSchema,
18243
- preference: z30.enum(POOL_PREFERENCES).optional(),
18244
- resumeOnLimit: z30.boolean().optional(),
18245
- compactBeforeLimit: z30.boolean().optional(),
18844
+ preference: z31.enum(POOL_PREFERENCES).optional(),
18845
+ resumeOnLimit: z31.boolean().optional(),
18846
+ compactBeforeLimit: z31.boolean().optional(),
18246
18847
  compactAtUtilisation: CompactAtUtilisationSchema.optional()
18247
18848
  });
18248
18849
  var ConfigPoolAddOutputSchema = storedMutationOutput("pool", "created", PoolSchema);
18249
- var ConfigPoolSetInputSchema = z30.strictObject({
18250
- name: z30.string().min(1),
18850
+ var ConfigPoolSetInputSchema = z31.strictObject({
18851
+ name: z31.string().min(1),
18251
18852
  identities: PoolMembersInputSchema.optional(),
18252
- preference: z30.union([z30.enum(POOL_PREFERENCES), z30.literal(false)]).optional(),
18253
- resumeOnLimit: z30.boolean().optional(),
18254
- compactBeforeLimit: z30.boolean().optional(),
18255
- compactAtUtilisation: z30.union([CompactAtUtilisationSchema, z30.literal(false)]).optional()
18853
+ preference: z31.union([z31.enum(POOL_PREFERENCES), z31.literal(false)]).optional(),
18854
+ resumeOnLimit: z31.boolean().optional(),
18855
+ compactBeforeLimit: z31.boolean().optional(),
18856
+ compactAtUtilisation: z31.union([CompactAtUtilisationSchema, z31.literal(false)]).optional()
18256
18857
  });
18257
18858
  var ConfigPoolSetOutputSchema = storedMutationOutput("pool", "updated", PoolSchema);
18258
- var ConfigPoolRemoveInputSchema = z30.strictObject({ name: z30.string().min(1), confirm: RemovalConfirmationSchema });
18859
+ var ConfigPoolRemoveInputSchema = z31.strictObject({ name: z31.string().min(1), confirm: RemovalConfirmationSchema });
18259
18860
  var ConfigPoolRemoveOutputSchema = mutationOutput("pool", "removed");
18260
18861
  var ConfigPoolUseOutputSchema = mutationOutput("pool", "selected");
18261
- var ConfigProviderAddInputSchema = z30.strictObject({
18262
- name: z30.string().min(1),
18263
- kind: z30.enum(PROVIDER_KINDS).optional(),
18264
- displayName: z30.string().min(1),
18265
- baseUrl: z30.string().min(1).optional(),
18862
+ var ConfigProviderAddInputSchema = z31.strictObject({
18863
+ name: z31.string().min(1),
18864
+ kind: z31.enum(PROVIDER_KINDS).optional(),
18865
+ displayName: z31.string().min(1),
18866
+ baseUrl: z31.string().min(1).optional(),
18266
18867
  credential: CredentialWriteSchema(PROVIDER_CREDENTIAL_TARGETS).required({ sources: true }),
18267
18868
  codex: CodexProviderConfigSchema.optional()
18268
18869
  });
18269
18870
  var ConfigProviderAddOutputSchema = storedMutationOutput("provider", "created", ProviderValueSchema);
18270
- var ConfigProviderSetInputSchema = z30.strictObject({
18271
- name: z30.string().min(1),
18272
- displayName: z30.string().min(1).optional(),
18273
- baseUrl: z30.string().min(1).optional(),
18871
+ var ConfigProviderSetInputSchema = z31.strictObject({
18872
+ name: z31.string().min(1),
18873
+ displayName: z31.string().min(1).optional(),
18874
+ baseUrl: z31.string().min(1).optional(),
18274
18875
  credential: CredentialWriteSchema(PROVIDER_CREDENTIAL_TARGETS).optional(),
18275
18876
  codex: CodexProviderConfigSchema.optional()
18276
18877
  });
18277
18878
  var ConfigProviderSetOutputSchema = storedMutationOutput("provider", "updated", ProviderValueSchema);
18278
- var ConfigProviderRemoveInputSchema = z30.strictObject({ name: z30.string().min(1), confirm: RemovalConfirmationSchema });
18879
+ var ConfigProviderRemoveInputSchema = z31.strictObject({ name: z31.string().min(1), confirm: RemovalConfirmationSchema });
18279
18880
  var ConfigProviderRemoveOutputSchema = mutationOutput("provider", "removed");
18280
- var ConfigRuleAddInputSchema = z30.strictObject({
18281
- path: z30.string().min(1),
18282
- configProfile: z30.string().min(1).optional(),
18283
- identity: z30.string().min(1).optional()
18881
+ var ConfigRuleAddInputSchema = z31.strictObject({
18882
+ path: z31.string().min(1),
18883
+ configProfile: z31.string().min(1).optional(),
18884
+ identity: z31.string().min(1).optional()
18284
18885
  });
18285
18886
  var ConfigRuleAddOutputSchema = storedMutationOutput("rule", "created", DirectoryRuleSchema);
18286
- var ConfigRuleSetInputSchema = z30.strictObject({
18287
- path: z30.string().min(1),
18288
- configProfile: z30.union([z30.string().min(1), z30.literal(false)]).optional(),
18289
- identity: z30.union([z30.string().min(1), z30.literal(false)]).optional()
18887
+ var ConfigRuleSetInputSchema = z31.strictObject({
18888
+ path: z31.string().min(1),
18889
+ configProfile: z31.union([z31.string().min(1), z31.literal(false)]).optional(),
18890
+ identity: z31.union([z31.string().min(1), z31.literal(false)]).optional()
18290
18891
  });
18291
18892
  var ConfigRuleSetOutputSchema = storedMutationOutput("rule", "updated", DirectoryRuleSchema);
18292
- var ConfigRuleRemoveInputSchema = z30.strictObject({ path: z30.string().min(1), confirm: RemovalConfirmationSchema });
18893
+ var ConfigRuleRemoveInputSchema = z31.strictObject({ path: z31.string().min(1), confirm: RemovalConfirmationSchema });
18293
18894
  var ConfigRuleRemoveOutputSchema = mutationOutput("rule", "removed");
18294
18895
 
18295
18896
  // src/frontdoor/configApi.ts
18296
18897
  var CONFIG_API_TAG = "config";
18297
18898
  function refusal(error) {
18899
+ if (error instanceof KeychainLookupError) {
18900
+ throw new ORPCError2("SERVICE_UNAVAILABLE", { message: error.message });
18901
+ }
18298
18902
  if (error instanceof IdentityNotFoundError || error instanceof ProfileNotFoundError || error instanceof PoolNotFoundError || error instanceof ProviderNotFoundError || error instanceof DirectoryRuleNotFoundError) {
18299
18903
  throw new ORPCError2("NOT_FOUND", { message: error.message });
18300
18904
  }
18301
- if (error instanceof IdentityAlreadyExistsError || error instanceof ProfileAlreadyExistsError || error instanceof PoolAlreadyExistsError || error instanceof ProviderAlreadyExistsError || error instanceof DirectoryRuleAlreadyExistsError) {
18905
+ if (error instanceof IdentityAlreadyExistsError || error instanceof ProfileAlreadyExistsError || error instanceof PoolAlreadyExistsError || error instanceof ProviderAlreadyExistsError || error instanceof DirectoryRuleAlreadyExistsError || error instanceof KeychainLoginError) {
18302
18906
  throw new ORPCError2("CONFLICT", { message: error.message });
18303
18907
  }
18304
18908
  if (error instanceof CliError) {
@@ -18306,6 +18910,13 @@ function refusal(error) {
18306
18910
  }
18307
18911
  throw error;
18308
18912
  }
18913
+ async function guardedAsync(write) {
18914
+ try {
18915
+ await write();
18916
+ } catch (error) {
18917
+ refusal(error);
18918
+ }
18919
+ }
18309
18920
  function guarded(write) {
18310
18921
  try {
18311
18922
  return write();
@@ -18355,16 +18966,21 @@ function profileValue(name, paths) {
18355
18966
  function createConfigApiRouter(deps) {
18356
18967
  const authed = doorApiAuth(deps.expectedToken);
18357
18968
  const { paths } = deps;
18358
- const route = (path42, summary) => authed.meta(openapi3({ method: "POST", path: path42, summary, tags: [CONFIG_API_TAG] }));
18969
+ const route = (path45, summary) => authed.meta(openapi3({ method: "POST", path: path45, summary, tags: [CONFIG_API_TAG] }));
18359
18970
  return {
18360
18971
  config: {
18361
18972
  identity: {
18362
- add: route("/rest/config/identity/add", "Create an identity").input(ConfigNameInputSchema).output(ConfigIdentityAddOutputSchema).handler(
18363
- ({ input }) => guarded(() => {
18973
+ add: route("/rest/config/identity/add", "Create an identity").input(ConfigIdentityAddInputSchema).output(ConfigIdentityAddOutputSchema).handler(async ({ input }) => {
18974
+ await guardedAsync(async () => {
18975
+ await resolveWithAsyncRuns((run) => {
18976
+ requireIdentityAddable(paths, input.name, { run, platform: deps.keychain.platform }, input.keepKeychainLogin === true);
18977
+ }, deps.keychain.runAsync);
18978
+ });
18979
+ return guarded(() => {
18364
18980
  addIdentity(paths, input.name);
18365
18981
  return { action: "created", kind: "identity", name: input.name, value: identityValue(input.name, paths) };
18366
- })
18367
- ),
18982
+ });
18983
+ }),
18368
18984
  set: route("/rest/config/identity/set", "Update an identity's label, default profile, provider, ambient-credential setting, credential or anchors").input(ConfigIdentitySetInputSchema).output(ConfigIdentitySetOutputSchema).handler(
18369
18985
  ({ input }) => guarded(() => {
18370
18986
  requireChange(input.label !== void 0 || input.defaultConfigProfile !== void 0 || input.provider !== void 0 || input.allowAmbientCredential !== void 0 || input.credential !== void 0 || input.anchors !== void 0, "label, defaultConfigProfile, provider, allowAmbientCredential, credential or anchors");
@@ -18613,43 +19229,43 @@ import { openapi as openapi4 } from "@orpc/openapi";
18613
19229
  import { eventIterator as eventIterator2, withEventMeta as withEventMeta2 } from "@orpc/server";
18614
19230
 
18615
19231
  // src/frontdoor/eventSchemas.ts
18616
- import { z as z31 } from "zod";
19232
+ import { z as z32 } from "zod";
18617
19233
  var DOOR_EVENT_SOURCE_RC = "rc";
18618
19234
  var LAUNCH_EVENT_SOURCE = "launch";
18619
19235
  var USAGE_EVENT_SOURCE = "usage";
18620
19236
  var DOOR_HEALTH_EVENT_SOURCE = "door";
18621
19237
  var QUOTA_EXPIRING_EVENT_SOURCE = "quota-expiring";
18622
- var DoorEventSchema = z31.strictObject({
18623
- source: z31.string().min(1),
19238
+ var DoorEventSchema = z32.strictObject({
19239
+ source: z32.string().min(1),
18624
19240
  /** A positive integer because the backbone's counters start at one and only ever increase. */
18625
- sequence: z31.number().int().positive(),
18626
- payload: z31.unknown()
19241
+ sequence: z32.number().int().positive(),
19242
+ payload: z32.unknown()
18627
19243
  });
18628
- var DoorEventSourceQuerySchema = z31.strictObject({
18629
- sources: z31.array(z31.string().min(1)).min(1).optional()
19244
+ var DoorEventSourceQuerySchema = z32.strictObject({
19245
+ sources: z32.array(z32.string().min(1)).min(1).optional()
18630
19246
  });
18631
- var LaunchLifecycleEventSchema = z31.strictObject({
18632
- kind: z31.enum(["registered", "pruned", "ended"]),
18633
- pid: z31.number().int().positive(),
18634
- startedAt: z31.number(),
18635
- observedAt: z31.number()
19247
+ var LaunchLifecycleEventSchema = z32.strictObject({
19248
+ kind: z32.enum(["registered", "pruned", "ended"]),
19249
+ pid: z32.number().int().positive(),
19250
+ startedAt: z32.number(),
19251
+ observedAt: z32.number()
18636
19252
  });
18637
- var DoorHealthEventSchema = z31.discriminatedUnion("kind", [
18638
- z31.strictObject({ kind: z31.literal("generation"), pid: z31.number().int().positive(), providerPort: z31.number().int().positive(), connectPort: z31.number().int().positive(), directPort: z31.number().int().positive(), observedAt: z31.number() }),
18639
- z31.strictObject({ kind: z31.literal("listenerFailed"), pid: z31.number().int().positive(), listener: z31.enum(["provider", "connect", "direct"]), message: z31.string(), observedAt: z31.number() }),
18640
- z31.strictObject({ kind: z31.literal("binaryTurnover"), pid: z31.number().int().positive(), observedAt: z31.number() }),
18641
- z31.strictObject({ kind: z31.literal("idleShutdown"), pid: z31.number().int().positive(), observedAt: z31.number() }),
18642
- z31.strictObject({ kind: z31.literal("superseded"), pid: z31.number().int().positive(), ownerPid: z31.number().int().positive(), observedAt: z31.number() }),
18643
- z31.strictObject({ kind: z31.literal("drained"), pid: z31.number().int().positive(), observedAt: z31.number() })
19253
+ var DoorHealthEventSchema = z32.discriminatedUnion("kind", [
19254
+ z32.strictObject({ kind: z32.literal("generation"), pid: z32.number().int().positive(), providerPort: z32.number().int().positive(), connectPort: z32.number().int().positive(), directPort: z32.number().int().positive(), observedAt: z32.number() }),
19255
+ z32.strictObject({ kind: z32.literal("listenerFailed"), pid: z32.number().int().positive(), listener: z32.enum(["provider", "connect", "direct"]), message: z32.string(), observedAt: z32.number() }),
19256
+ z32.strictObject({ kind: z32.literal("binaryTurnover"), pid: z32.number().int().positive(), observedAt: z32.number() }),
19257
+ z32.strictObject({ kind: z32.literal("idleShutdown"), pid: z32.number().int().positive(), observedAt: z32.number() }),
19258
+ z32.strictObject({ kind: z32.literal("superseded"), pid: z32.number().int().positive(), ownerPid: z32.number().int().positive(), observedAt: z32.number() }),
19259
+ z32.strictObject({ kind: z32.literal("drained"), pid: z32.number().int().positive(), observedAt: z32.number() })
18644
19260
  ]);
18645
- var QuotaExpiringEventSchema = z31.strictObject({
18646
- identity: z31.string().min(1),
18647
- provider: z31.string().min(1),
18648
- window: z31.enum(["fiveHour", "sevenDay"]),
19261
+ var QuotaExpiringEventSchema = z32.strictObject({
19262
+ identity: z32.string().min(1),
19263
+ provider: z32.string().min(1),
19264
+ window: z32.enum(["fiveHour", "sevenDay"]),
18649
19265
  /** The fraction of the window already used when it was seen expiring, always below one because a fully used window has nothing left to spend. */
18650
- utilization: z31.number().min(0).max(1),
18651
- resetsAt: z31.iso.datetime(),
18652
- observedAt: z31.number()
19266
+ utilization: z32.number().min(0).max(1),
19267
+ resetsAt: z32.iso.datetime(),
19268
+ observedAt: z32.number()
18653
19269
  });
18654
19270
 
18655
19271
  // src/frontdoor/eventsApi.ts
@@ -18732,61 +19348,61 @@ import { ORPCError as ORPCError5 } from "@orpc/client";
18732
19348
  import { openapi as openapi6 } from "@orpc/openapi";
18733
19349
 
18734
19350
  // src/frontdoor/launchSchemas.ts
18735
- import path31 from "node:path";
18736
- import { z as z32 } from "zod";
19351
+ import path33 from "node:path";
19352
+ import { z as z33 } from "zod";
18737
19353
  init_statusline();
18738
19354
  init_claudeVersion();
18739
19355
  init_identity();
18740
- var LaunchResolveInputSchema = z32.strictObject({
18741
- path: z32.string().min(1),
19356
+ var LaunchResolveInputSchema = z33.strictObject({
19357
+ path: z33.string().min(1),
18742
19358
  /** `@name`, launch flags, then the arguments for `claude`; empty for a bare launch. */
18743
- argv: z32.readonly(z32.array(z32.string())).optional(),
19359
+ argv: z33.readonly(z33.array(z33.string())).optional(),
18744
19360
  /** The launch's inherited environment. Absent means an empty one: the door's own environment is never a substitute for the caller's, so a caller that wants `AGENT_SHIM_*` switches or a `CLAUDE_CONFIG_DIR` considered names them here. Values are read, never reported. */
18745
- env: z32.record(z32.string(), z32.string()).optional()
18746
- }).refine((input) => path31.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
18747
- var LaunchPoolDecisionSchema = z32.strictObject({
18748
- name: z32.string(),
18749
- reasons: z32.readonly(z32.array(z32.string())),
18750
- movedOff: z32.strictObject({ identity: z32.string(), reason: z32.string() }).optional()
19361
+ env: z33.record(z33.string(), z33.string()).optional()
19362
+ }).refine((input) => path33.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
19363
+ var LaunchPoolDecisionSchema = z33.strictObject({
19364
+ name: z33.string(),
19365
+ reasons: z33.readonly(z33.array(z33.string())),
19366
+ movedOff: z33.strictObject({ identity: z33.string(), reason: z33.string() }).optional()
18751
19367
  });
18752
- var LaunchDecisionSchema = z32.strictObject({
18753
- identity: z32.string().optional(),
18754
- identitySource: z32.enum(IDENTITY_DECISION_SOURCES),
19368
+ var LaunchDecisionSchema = z33.strictObject({
19369
+ identity: z33.string().optional(),
19370
+ identitySource: z33.enum(IDENTITY_DECISION_SOURCES),
18755
19371
  pool: LaunchPoolDecisionSchema.optional(),
18756
- configDirEscapeHatch: z32.boolean(),
18757
- configDir: z32.string().optional(),
18758
- configProfile: z32.string().optional(),
18759
- configProfileSource: z32.enum(CONFIG_PROFILE_DECISION_SOURCES),
18760
- provider: z32.string().optional()
19372
+ configDirEscapeHatch: z33.boolean(),
19373
+ configDir: z33.string().optional(),
19374
+ configProfile: z33.string().optional(),
19375
+ configProfileSource: z33.enum(CONFIG_PROFILE_DECISION_SOURCES),
19376
+ provider: z33.string().optional()
18761
19377
  });
18762
- var LaunchFlagsSchema = z32.strictObject({
18763
- skipPermissions: z32.boolean(),
18764
- remoteControl: z32.boolean(),
18765
- headroom: z32.boolean(),
18766
- trackUsage: z32.boolean(),
18767
- pause: z32.boolean(),
18768
- explain: z32.boolean(),
19378
+ var LaunchFlagsSchema = z33.strictObject({
19379
+ skipPermissions: z33.boolean(),
19380
+ remoteControl: z33.boolean(),
19381
+ headroom: z33.boolean(),
19382
+ trackUsage: z33.boolean(),
19383
+ pause: z33.boolean(),
19384
+ explain: z33.boolean(),
18769
19385
  /** How long the launch waits after its own output before it starts claude, in milliseconds. */
18770
- delayMs: z32.number(),
19386
+ delayMs: z33.number(),
18771
19387
  /** The hosts the launch keeps off the front door by adding them to the child's `NO_PROXY`. */
18772
- proxyBypass: z32.array(z32.string()).readonly(),
19388
+ proxyBypass: z33.array(z33.string()).readonly(),
18773
19389
  /** How the session's built-in statusline looks, when the launch configures any of it. */
18774
19390
  statusline: StatuslineSchema.optional()
18775
19391
  });
18776
- var LaunchResolveOutputSchema = z32.strictObject({
19392
+ var LaunchResolveOutputSchema = z33.strictObject({
18777
19393
  decision: LaunchDecisionSchema,
18778
19394
  flags: LaunchFlagsSchema,
18779
- claudeVersion: z32.strictObject({ version: z32.string(), source: z32.enum(CLAUDE_VERSION_SOURCES) }).optional(),
19395
+ claudeVersion: z33.strictObject({ version: z33.string(), source: z33.enum(CLAUDE_VERSION_SOURCES) }).optional(),
18780
19396
  /** The real `claude` binary the launch would spawn, on the door's host. */
18781
- bin: z32.string(),
19397
+ bin: z33.string(),
18782
19398
  /** The arguments the launch would pass it: the tool's own flags, then `CLAUDE_EXTRA_FLAGS`, then the caller's own. */
18783
- args: z32.readonly(z32.array(z32.string())),
19399
+ args: z33.readonly(z33.array(z33.string())),
18784
19400
  /** The credential the launch would authenticate with, by target and source kinds. Absent when none applies. */
18785
- credential: z32.strictObject({ subject: z32.enum(["provider", "identity"]), name: z32.string(), summary: CredentialSummarySchema }).optional(),
18786
- routing: z32.strictObject({ frontDoor: z32.boolean(), headroom: z32.boolean() }),
19401
+ credential: z33.strictObject({ subject: z33.enum(["provider", "identity"]), name: z33.string(), summary: CredentialSummarySchema }).optional(),
19402
+ routing: z33.strictObject({ frontDoor: z33.boolean(), headroom: z33.boolean() }),
18787
19403
  /** The names of the environment variables the launch would set or unset, sorted. Values are not reported. */
18788
- environment: z32.readonly(z32.array(z32.string())),
18789
- warnings: z32.readonly(z32.array(z32.string()))
19404
+ environment: z33.readonly(z33.array(z33.string())),
19405
+ warnings: z33.readonly(z33.array(z33.string()))
18790
19406
  });
18791
19407
 
18792
19408
  // src/frontdoor/launchApi.ts
@@ -18822,22 +19438,22 @@ function createLaunchApiRouter(deps) {
18822
19438
  // src/frontdoor/agentTreesApi.ts
18823
19439
  import { ORPCError as ORPCError6 } from "@orpc/client";
18824
19440
  import { openapi as openapi7 } from "@orpc/openapi";
18825
- import { z as z33 } from "zod";
19441
+ import { z as z34 } from "zod";
18826
19442
  init_cliError();
18827
- var AgentTreesListInputSchema = z33.strictObject({
19443
+ var AgentTreesListInputSchema = z34.strictObject({
18828
19444
  /** Only this identity's sessions. */
18829
- identity: z33.string().optional(),
19445
+ identity: z34.string().optional(),
18830
19446
  /** Include sessions that spawned no agent and ran no workflow. */
18831
- all: z33.boolean().optional()
19447
+ all: z34.boolean().optional()
18832
19448
  });
18833
- var AgentTreesListOutputSchema = z33.array(SessionSummarySchema);
18834
- var AgentTreesShowInputSchema = z33.strictObject({
19449
+ var AgentTreesListOutputSchema = z34.array(SessionSummarySchema);
19450
+ var AgentTreesShowInputSchema = z34.strictObject({
18835
19451
  /** A session id, or an unambiguous prefix of one. */
18836
- session: z33.string().min(1),
19452
+ session: z34.string().min(1),
18837
19453
  /** Look only in this identity. */
18838
- identity: z33.string().optional()
19454
+ identity: z34.string().optional()
18839
19455
  });
18840
- var AgentTreesShowOutputSchema = z33.strictObject({ identities: z33.array(z33.string()), ...MergedAgentTreeSchema.shape });
19456
+ var AgentTreesShowOutputSchema = z34.strictObject({ identities: z34.array(z34.string()), ...MergedAgentTreeSchema.shape });
18841
19457
  function asBadRequest(error) {
18842
19458
  if (error instanceof CliError) {
18843
19459
  throw new ORPCError6("BAD_REQUEST", { message: error.message });
@@ -20924,7 +21540,7 @@ data: ${JSON.stringify(envelope)}
20924
21540
 
20925
21541
  // src/frontdoor/rcSelfHostMint.ts
20926
21542
  init_account();
20927
- import path32 from "node:path";
21543
+ import path34 from "node:path";
20928
21544
  var CREDENTIALS_FILE2 = ".credentials.json";
20929
21545
  var CLAUDE_JSON2 = ".claude.json";
20930
21546
  var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
@@ -20934,8 +21550,8 @@ var SELF_HOST_SUBSCRIPTION_TYPE = "max";
20934
21550
  function isRecord14(value) {
20935
21551
  return typeof value === "object" && value !== null && !Array.isArray(value);
20936
21552
  }
20937
- function readJsonObject(fs14, file) {
20938
- const raw = fs14.readFileUtf8(file);
21553
+ function readJsonObject(fs15, file) {
21554
+ const raw = fs15.readFileUtf8(file);
20939
21555
  if (raw === void 0) {
20940
21556
  return void 0;
20941
21557
  }
@@ -20947,8 +21563,8 @@ function readJsonObject(fs14, file) {
20947
21563
  }
20948
21564
  return isRecord14(parsed) ? parsed : void 0;
20949
21565
  }
20950
- function readRcSelfHostRecord(fs14, frontdoorDir) {
20951
- const parsed = readJsonObject(fs14, path32.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
21566
+ function readRcSelfHostRecord(fs15, frontdoorDir) {
21567
+ const parsed = readJsonObject(fs15, path34.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
20952
21568
  if (parsed === void 0) {
20953
21569
  return void 0;
20954
21570
  }
@@ -20962,11 +21578,11 @@ function mintRcSelfHostCredential(deps) {
20962
21578
  if (!isIdentityName(deps.identity)) {
20963
21579
  throw new Error(`"${deps.identity}" is not a valid identity name.`);
20964
21580
  }
20965
- const identityDir = path32.join(deps.identitiesDir, deps.identity);
20966
- const credentialsFile = path32.join(identityDir, CREDENTIALS_FILE2);
20967
- const claudeJsonFile = path32.join(identityDir, CLAUDE_JSON2);
20968
- const recordDir = path32.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
20969
- const recordFile = path32.join(recordDir, RC_SELF_HOST_RECORD_FILE);
21581
+ const identityDir = path34.join(deps.identitiesDir, deps.identity);
21582
+ const credentialsFile = path34.join(identityDir, CREDENTIALS_FILE2);
21583
+ const claudeJsonFile = path34.join(identityDir, CLAUDE_JSON2);
21584
+ const recordDir = path34.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
21585
+ const recordFile2 = path34.join(recordDir, RC_SELF_HOST_RECORD_FILE);
20970
21586
  const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
20971
21587
  const existingCredentials = readJsonObject(deps.fs, credentialsFile);
20972
21588
  const existingOauth = isRecord14(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
@@ -20982,7 +21598,7 @@ function mintRcSelfHostCredential(deps) {
20982
21598
  const organizationUuid = deps.newUuid();
20983
21599
  const accountUuid = deps.newUuid();
20984
21600
  const mintedAt = new Date(deps.now()).toISOString();
20985
- deps.fs.mkdirPrivate(path32.dirname(credentialsFile));
21601
+ deps.fs.mkdirPrivate(path34.dirname(credentialsFile));
20986
21602
  deps.fs.writeFilePrivate(credentialsFile, `${JSON.stringify({ ...existingCredentials, claudeAiOauth: { accessToken, refreshToken, expiresAt: null, scopes: [...RC_SELF_HOST_SCOPE_LIST], subscriptionType: SELF_HOST_SUBSCRIPTION_TYPE, rateLimitTier: null } }, null, 2)}
20987
21603
  `);
20988
21604
  const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
@@ -21009,9 +21625,9 @@ function mintRcSelfHostCredential(deps) {
21009
21625
  }, null, 2)}
21010
21626
  `);
21011
21627
  deps.fs.mkdirPrivate(recordDir);
21012
- deps.fs.writeFilePrivate(recordFile, `${JSON.stringify({ accessToken, refreshToken, organizationUuid, accountUuid }, null, 2)}
21628
+ deps.fs.writeFilePrivate(recordFile2, `${JSON.stringify({ accessToken, refreshToken, organizationUuid, accountUuid }, null, 2)}
21013
21629
  `);
21014
- return { identity: deps.identity, organizationUuid, credentialsFile, claudeJsonFile, recordFile, replaced: existingIsOwn };
21630
+ return { identity: deps.identity, organizationUuid, credentialsFile, claudeJsonFile, recordFile: recordFile2, replaced: existingIsOwn };
21015
21631
  }
21016
21632
 
21017
21633
  // src/index.ts
@@ -21020,25 +21636,25 @@ init_ensure2();
21020
21636
  // src/frontdoor/liveSessionRegistry.ts
21021
21637
  init_capability();
21022
21638
  init_state();
21023
- import path33 from "node:path";
21639
+ import path35 from "node:path";
21024
21640
  function sameStat(recorded, current) {
21025
21641
  return recorded?.mtimeMs === current.mtimeMs && recorded.sizeBytes === current.sizeBytes;
21026
21642
  }
21027
21643
  function createLiveSessionRegistry(ports) {
21028
- const { fs: fs14, sessionsDir } = ports;
21644
+ const { fs: fs15, sessionsDir } = ports;
21029
21645
  const known = /* @__PURE__ */ new Map();
21030
21646
  let tokens = /* @__PURE__ */ new Set();
21031
21647
  let bySessionId = /* @__PURE__ */ new Map();
21032
- const recordNames = () => fs14.readdir(sessionsDir).filter(isSessionRecordName);
21648
+ const recordNames = () => fs15.readdir(sessionsDir).filter(isSessionRecordName);
21033
21649
  const rebuildIndexes = () => {
21034
21650
  const records = [...known.values()].flatMap(({ record }) => record === void 0 ? [] : [record]);
21035
21651
  tokens = new Set(records.map((record) => record.token));
21036
21652
  bySessionId = new Map(records.flatMap((record) => record.sessionId === void 0 ? [] : [[record.sessionId, record]]));
21037
21653
  };
21038
21654
  const load = (name, stat) => {
21039
- known.set(name, { stat: { mtimeMs: stat.mtimeMs, sizeBytes: stat.sizeBytes }, record: readFrontDoorSessionRecord(fs14, sessionsDir, name) });
21655
+ known.set(name, { stat: { mtimeMs: stat.mtimeMs, sizeBytes: stat.sizeBytes }, record: readFrontDoorSessionRecord(fs15, sessionsDir, name) });
21040
21656
  };
21041
- const statOf = (name) => fs14.lstat(path33.join(sessionsDir, name));
21657
+ const statOf = (name) => fs15.lstat(path35.join(sessionsDir, name));
21042
21658
  const reconcile = () => {
21043
21659
  const names = new Set(recordNames());
21044
21660
  let changed = false;
@@ -21105,8 +21721,8 @@ init_plan2();
21105
21721
  init_poolPick();
21106
21722
 
21107
21723
  // src/agents/read.ts
21108
- import path34 from "node:path";
21109
- import { z as z34 } from "zod";
21724
+ import path36 from "node:path";
21725
+ import { z as z35 } from "zod";
21110
21726
  var PROJECTS_DIR = "projects";
21111
21727
  var TASKS_DIR = "tasks";
21112
21728
  var SUBAGENTS_DIR = "subagents";
@@ -21129,17 +21745,17 @@ function parseEntry2(project, entry) {
21129
21745
  const base = match?.[1];
21130
21746
  return base === void 0 ? { project, sessionId: entry, superseded: false, entry } : { project, sessionId: base, superseded: true, entry };
21131
21747
  }
21132
- function listSessions2(fs14, configDir) {
21748
+ function listSessions2(fs15, configDir) {
21133
21749
  const found = [];
21134
- for (const project of fs14.readdir(path34.join(configDir, PROJECTS_DIR))) {
21135
- const projectDir = path34.join(configDir, PROJECTS_DIR, project);
21750
+ for (const project of fs15.readdir(path36.join(configDir, PROJECTS_DIR))) {
21751
+ const projectDir = path36.join(configDir, PROJECTS_DIR, project);
21136
21752
  const entries = /* @__PURE__ */ new Set();
21137
- for (const name of fs14.readdir(projectDir)) {
21753
+ for (const name of fs15.readdir(projectDir)) {
21138
21754
  if (name.endsWith(TRANSCRIPT_SUFFIX)) {
21139
21755
  entries.add(name.slice(0, -TRANSCRIPT_SUFFIX.length));
21140
21756
  continue;
21141
21757
  }
21142
- const children = fs14.readdir(path34.join(projectDir, name));
21758
+ const children = fs15.readdir(path36.join(projectDir, name));
21143
21759
  if (children.includes(SUBAGENTS_DIR) || children.includes(WORKFLOWS_DIR)) {
21144
21760
  entries.add(name);
21145
21761
  }
@@ -21150,17 +21766,17 @@ function listSessions2(fs14, configDir) {
21150
21766
  }
21151
21767
  return found.sort((left, right) => left.project.localeCompare(right.project) || left.entry.localeCompare(right.entry));
21152
21768
  }
21153
- function locateAgents(fs14, configDir, relativeDir, workflowRunId, report) {
21769
+ function locateAgents(fs15, configDir, relativeDir, workflowRunId, report) {
21154
21770
  const located = [];
21155
- for (const name of listDirOrReport(fs14, configDir, relativeDir, report)) {
21771
+ for (const name of listDirOrReport(fs15, configDir, relativeDir, report)) {
21156
21772
  if (!name.startsWith(AGENT_FILE_PREFIX) || !name.endsWith(META_SUFFIX)) {
21157
21773
  continue;
21158
21774
  }
21159
21775
  const id = name.slice(AGENT_FILE_PREFIX.length, -META_SUFFIX.length);
21160
21776
  located.push({
21161
21777
  id,
21162
- metaPath: path34.join(relativeDir, name),
21163
- transcriptPath: path34.join(relativeDir, `${AGENT_FILE_PREFIX}${id}${TRANSCRIPT_SUFFIX}`),
21778
+ metaPath: path36.join(relativeDir, name),
21779
+ transcriptPath: path36.join(relativeDir, `${AGENT_FILE_PREFIX}${id}${TRANSCRIPT_SUFFIX}`),
21164
21780
  workflowRunId
21165
21781
  });
21166
21782
  }
@@ -21201,17 +21817,17 @@ function toNode(read, children) {
21201
21817
  function describeFailure(error) {
21202
21818
  return error instanceof Error ? error.message : String(error);
21203
21819
  }
21204
- function readFileOrReport(fs14, configDir, relative, report) {
21820
+ function readFileOrReport(fs15, configDir, relative, report) {
21205
21821
  try {
21206
- return fs14.readFileUtf8(path34.join(configDir, relative));
21822
+ return fs15.readFileUtf8(path36.join(configDir, relative));
21207
21823
  } catch (error) {
21208
21824
  report({ path: relative, reason: `could not be read: ${describeFailure(error)}` });
21209
21825
  return void 0;
21210
21826
  }
21211
21827
  }
21212
- function listDirOrReport(fs14, configDir, relative, report) {
21828
+ function listDirOrReport(fs15, configDir, relative, report) {
21213
21829
  try {
21214
- return fs14.readdir(path34.join(configDir, relative));
21830
+ return fs15.readdir(path36.join(configDir, relative));
21215
21831
  } catch (error) {
21216
21832
  report({ path: relative, reason: `could not be listed: ${describeFailure(error)}` });
21217
21833
  return [];
@@ -21225,47 +21841,47 @@ function parseJson2(text) {
21225
21841
  return void 0;
21226
21842
  }
21227
21843
  }
21228
- var TaskFileSchema = z34.object({ ...TaskItemSchema.omit({ taskList: true }).shape, blocks: z34.array(z34.string()).default([]), blockedBy: z34.array(z34.string()).default([]) });
21229
- var WorkflowRunFileSchema = z34.object({
21230
- runId: z34.string(),
21231
- workflowName: z34.string().optional(),
21232
- status: z34.string().optional(),
21233
- startTime: z34.number().optional(),
21234
- phases: z34.array(z34.object({ title: z34.string() })).default([]),
21235
- summary: z34.string().optional()
21844
+ var TaskFileSchema = z35.object({ ...TaskItemSchema.omit({ taskList: true }).shape, blocks: z35.array(z35.string()).default([]), blockedBy: z35.array(z35.string()).default([]) });
21845
+ var WorkflowRunFileSchema = z35.object({
21846
+ runId: z35.string(),
21847
+ workflowName: z35.string().optional(),
21848
+ status: z35.string().optional(),
21849
+ startTime: z35.number().optional(),
21850
+ phases: z35.array(z35.object({ title: z35.string() })).default([]),
21851
+ summary: z35.string().optional()
21236
21852
  });
21237
- function summariseSession(fs14, configDir, ref) {
21238
- const sessionRelative = path34.join(PROJECTS_DIR, ref.project, ref.entry);
21239
- const subagentsRelative = path34.join(sessionRelative, SUBAGENTS_DIR);
21240
- const workflowsUnderSubagents = path34.join(subagentsRelative, WORKFLOWS_DIR);
21853
+ function summariseSession(fs15, configDir, ref) {
21854
+ const sessionRelative = path36.join(PROJECTS_DIR, ref.project, ref.entry);
21855
+ const subagentsRelative = path36.join(sessionRelative, SUBAGENTS_DIR);
21856
+ const workflowsUnderSubagents = path36.join(subagentsRelative, WORKFLOWS_DIR);
21241
21857
  const isMeta = (name) => name.startsWith(AGENT_FILE_PREFIX) && name.endsWith(META_SUFFIX);
21242
- let agentCount = fs14.readdir(path34.join(configDir, subagentsRelative)).filter(isMeta).length;
21243
- for (const runDir of fs14.readdir(path34.join(configDir, workflowsUnderSubagents))) {
21858
+ let agentCount = fs15.readdir(path36.join(configDir, subagentsRelative)).filter(isMeta).length;
21859
+ for (const runDir of fs15.readdir(path36.join(configDir, workflowsUnderSubagents))) {
21244
21860
  if (runDir.startsWith(WORKFLOW_RUN_PREFIX)) {
21245
- agentCount += fs14.readdir(path34.join(configDir, workflowsUnderSubagents, runDir)).filter(isMeta).length;
21861
+ agentCount += fs15.readdir(path36.join(configDir, workflowsUnderSubagents, runDir)).filter(isMeta).length;
21246
21862
  }
21247
21863
  }
21248
- const workflowRunCount = fs14.readdir(path34.join(configDir, sessionRelative, WORKFLOWS_DIR)).filter((name) => name.startsWith(WORKFLOW_RUN_PREFIX) && name.endsWith(JSON_SUFFIX)).length;
21249
- const transcript = fs14.lstat(path34.join(configDir, PROJECTS_DIR, ref.project, `${ref.entry}${TRANSCRIPT_SUFFIX}`));
21864
+ const workflowRunCount = fs15.readdir(path36.join(configDir, sessionRelative, WORKFLOWS_DIR)).filter((name) => name.startsWith(WORKFLOW_RUN_PREFIX) && name.endsWith(JSON_SUFFIX)).length;
21865
+ const transcript = fs15.lstat(path36.join(configDir, PROJECTS_DIR, ref.project, `${ref.entry}${TRANSCRIPT_SUFFIX}`));
21250
21866
  return { ...ref, agentCount, workflowRunCount, ...transcript === void 0 ? {} : { updatedAt: new Date(transcript.mtimeMs).toISOString() } };
21251
21867
  }
21252
- function readSessionAgentTree(fs14, configDir, ref, options = {}) {
21868
+ function readSessionAgentTree(fs15, configDir, ref, options = {}) {
21253
21869
  const problems = [];
21254
21870
  const report = (problem) => {
21255
21871
  problems.push(problem);
21256
21872
  };
21257
- const sessionRelative = path34.join(PROJECTS_DIR, ref.project, ref.entry);
21258
- const subagentsRelative = path34.join(sessionRelative, SUBAGENTS_DIR);
21259
- const workflowsUnderSubagents = path34.join(subagentsRelative, WORKFLOWS_DIR);
21260
- const located = locateAgents(fs14, configDir, subagentsRelative, void 0, report);
21261
- for (const runDir of listDirOrReport(fs14, configDir, workflowsUnderSubagents, report)) {
21873
+ const sessionRelative = path36.join(PROJECTS_DIR, ref.project, ref.entry);
21874
+ const subagentsRelative = path36.join(sessionRelative, SUBAGENTS_DIR);
21875
+ const workflowsUnderSubagents = path36.join(subagentsRelative, WORKFLOWS_DIR);
21876
+ const located = locateAgents(fs15, configDir, subagentsRelative, void 0, report);
21877
+ for (const runDir of listDirOrReport(fs15, configDir, workflowsUnderSubagents, report)) {
21262
21878
  if (runDir.startsWith(WORKFLOW_RUN_PREFIX)) {
21263
- located.push(...locateAgents(fs14, configDir, path34.join(workflowsUnderSubagents, runDir), runDir, report));
21879
+ located.push(...locateAgents(fs15, configDir, path36.join(workflowsUnderSubagents, runDir), runDir, report));
21264
21880
  }
21265
21881
  }
21266
21882
  const agents = /* @__PURE__ */ new Map();
21267
21883
  for (const candidate of located) {
21268
- const text = readFileOrReport(fs14, configDir, candidate.metaPath, report);
21884
+ const text = readFileOrReport(fs15, configDir, candidate.metaPath, report);
21269
21885
  if (text === void 0) {
21270
21886
  continue;
21271
21887
  }
@@ -21277,7 +21893,7 @@ function readSessionAgentTree(fs14, configDir, ref, options = {}) {
21277
21893
  agents.set(candidate.id, { located: candidate, meta: parsed.data });
21278
21894
  }
21279
21895
  const teamNames = [...new Set([...agents.values()].flatMap((agent) => agent.meta.teamName === void 0 ? [] : [agent.meta.teamName]))].sort();
21280
- const parentOf3 = resolveParents(fs14, configDir, agents, report);
21896
+ const parentOf3 = resolveParents(fs15, configDir, agents, report);
21281
21897
  const childrenOf = /* @__PURE__ */ new Map();
21282
21898
  const roots = [];
21283
21899
  for (const id of agents.keys()) {
@@ -21300,12 +21916,12 @@ function readSessionAgentTree(fs14, configDir, ref, options = {}) {
21300
21916
  sessionId: ref.sessionId,
21301
21917
  superseded: ref.superseded,
21302
21918
  agents: roots.sort().map(build),
21303
- tasks: readTasks(fs14, configDir, ownTaskLists(ref.sessionId), [.../* @__PURE__ */ new Set([...teamNames, ...options.taskListIds ?? []])].filter((id) => !ownTaskLists(ref.sessionId).includes(id)), report),
21304
- workflowRuns: readWorkflowRuns(fs14, configDir, path34.join(sessionRelative, WORKFLOWS_DIR), report),
21919
+ tasks: readTasks(fs15, configDir, ownTaskLists(ref.sessionId), [.../* @__PURE__ */ new Set([...teamNames, ...options.taskListIds ?? []])].filter((id) => !ownTaskLists(ref.sessionId).includes(id)), report),
21920
+ workflowRuns: readWorkflowRuns(fs15, configDir, path36.join(sessionRelative, WORKFLOWS_DIR), report),
21305
21921
  problems
21306
21922
  };
21307
21923
  }
21308
- function resolveParents(fs14, configDir, agents, report) {
21924
+ function resolveParents(fs15, configDir, agents, report) {
21309
21925
  const parentOf3 = /* @__PURE__ */ new Map();
21310
21926
  const transcriptCache = /* @__PURE__ */ new Map();
21311
21927
  const transcriptOf = (agent) => {
@@ -21313,7 +21929,7 @@ function resolveParents(fs14, configDir, agents, report) {
21313
21929
  if (cached !== void 0) {
21314
21930
  return cached;
21315
21931
  }
21316
- const text = readFileOrReport(fs14, configDir, agent.located.transcriptPath, report) ?? "";
21932
+ const text = readFileOrReport(fs15, configDir, agent.located.transcriptPath, report) ?? "";
21317
21933
  transcriptCache.set(agent.located.id, text);
21318
21934
  return text;
21319
21935
  };
@@ -21363,16 +21979,16 @@ function resolveParents(fs14, configDir, agents, report) {
21363
21979
  function ownTaskLists(sessionId) {
21364
21980
  return [sessionId, `${SHORT_SESSION_LIST_PREFIX}${sessionId.slice(0, SHORT_SESSION_ID_LENGTH)}`];
21365
21981
  }
21366
- function readTasks(fs14, configDir, ownLists, sharedLists, report) {
21982
+ function readTasks(fs15, configDir, ownLists, sharedLists, report) {
21367
21983
  const tasks = [];
21368
21984
  [...ownLists, ...sharedLists].forEach((scope, index) => {
21369
- const relativeDir = path34.join(TASKS_DIR, scope);
21370
- for (const name of [...listDirOrReport(fs14, configDir, relativeDir, report)].sort()) {
21985
+ const relativeDir = path36.join(TASKS_DIR, scope);
21986
+ for (const name of [...listDirOrReport(fs15, configDir, relativeDir, report)].sort()) {
21371
21987
  if (name.startsWith(".") || !name.endsWith(JSON_SUFFIX)) {
21372
21988
  continue;
21373
21989
  }
21374
- const relative = path34.join(relativeDir, name);
21375
- const text = readFileOrReport(fs14, configDir, relative, report);
21990
+ const relative = path36.join(relativeDir, name);
21991
+ const text = readFileOrReport(fs15, configDir, relative, report);
21376
21992
  const parsed = TaskFileSchema.safeParse(text === void 0 ? void 0 : parseJson2(text));
21377
21993
  if (parsed.success) {
21378
21994
  tasks.push(index < ownLists.length ? parsed.data : { ...parsed.data, taskList: scope });
@@ -21383,14 +21999,14 @@ function readTasks(fs14, configDir, ownLists, sharedLists, report) {
21383
21999
  });
21384
22000
  return tasks;
21385
22001
  }
21386
- function readWorkflowRuns(fs14, configDir, relativeDir, report) {
22002
+ function readWorkflowRuns(fs15, configDir, relativeDir, report) {
21387
22003
  const runs = [];
21388
- for (const name of [...listDirOrReport(fs14, configDir, relativeDir, report)].sort()) {
22004
+ for (const name of [...listDirOrReport(fs15, configDir, relativeDir, report)].sort()) {
21389
22005
  if (!name.startsWith(WORKFLOW_RUN_PREFIX) || !name.endsWith(JSON_SUFFIX)) {
21390
22006
  continue;
21391
22007
  }
21392
- const relative = path34.join(relativeDir, name);
21393
- const text = readFileOrReport(fs14, configDir, relative, report);
22008
+ const relative = path36.join(relativeDir, name);
22009
+ const text = readFileOrReport(fs15, configDir, relative, report);
21394
22010
  const parsed = WorkflowRunFileSchema.safeParse(text === void 0 ? void 0 : parseJson2(text));
21395
22011
  if (!parsed.success) {
21396
22012
  if (text !== void 0) {
@@ -21406,7 +22022,7 @@ function readWorkflowRuns(fs14, configDir, relativeDir, report) {
21406
22022
 
21407
22023
  // src/agents/sessions.ts
21408
22024
  init_cliError();
21409
- import path35 from "node:path";
22025
+ import path37 from "node:path";
21410
22026
  var SessionLookupError = class extends CliError {
21411
22027
  constructor(message) {
21412
22028
  super(message);
@@ -21414,13 +22030,13 @@ var SessionLookupError = class extends CliError {
21414
22030
  }
21415
22031
  };
21416
22032
  function identityConfigDir(identitiesDir, identity) {
21417
- return path35.join(identitiesDir, identity);
22033
+ return path37.join(identitiesDir, identity);
21418
22034
  }
21419
- function historyStores(fs14, identitiesDir, identities) {
22035
+ function historyStores(fs15, identitiesDir, identities) {
21420
22036
  const byRealPath = /* @__PURE__ */ new Map();
21421
22037
  for (const identity of identities) {
21422
22038
  const configDir = identityConfigDir(identitiesDir, identity);
21423
- const real = fs14.realpath(path35.join(configDir, "projects"));
22039
+ const real = fs15.realpath(path37.join(configDir, "projects"));
21424
22040
  if (real === void 0) {
21425
22041
  continue;
21426
22042
  }
@@ -21433,15 +22049,15 @@ function historyStores(fs14, identitiesDir, identities) {
21433
22049
  }
21434
22050
  return [...byRealPath.values()];
21435
22051
  }
21436
- function collectSessionList(fs14, identitiesDir, identities, filters) {
22052
+ function collectSessionList(fs15, identitiesDir, identities, filters) {
21437
22053
  const names = filters.identity === void 0 ? identities : identities.filter((name) => name === filters.identity);
21438
22054
  if (filters.identity !== void 0 && names.length === 0) {
21439
22055
  throw new SessionLookupError(`no identity named "${filters.identity}"`);
21440
22056
  }
21441
22057
  const sessions = [];
21442
- for (const store of historyStores(fs14, identitiesDir, names)) {
21443
- for (const ref of listSessions2(fs14, store.configDir)) {
21444
- const summary = summariseSession(fs14, store.configDir, ref);
22058
+ for (const store of historyStores(fs15, identitiesDir, names)) {
22059
+ for (const ref of listSessions2(fs15, store.configDir)) {
22060
+ const summary = summariseSession(fs15, store.configDir, ref);
21445
22061
  if (filters.all === true || summary.agentCount > 0 || summary.workflowRunCount > 0) {
21446
22062
  sessions.push({ ...summary, identities: store.identities });
21447
22063
  }
@@ -21449,14 +22065,14 @@ function collectSessionList(fs14, identitiesDir, identities, filters) {
21449
22065
  }
21450
22066
  return sessions.sort((left, right) => (right.updatedAt ?? "").localeCompare(left.updatedAt ?? "") || left.sessionId.localeCompare(right.sessionId));
21451
22067
  }
21452
- function locateSession(fs14, identitiesDir, identities, query, onlyIdentity) {
22068
+ function locateSession(fs15, identitiesDir, identities, query, onlyIdentity) {
21453
22069
  const names = onlyIdentity === void 0 ? identities : identities.filter((name) => name === onlyIdentity);
21454
22070
  if (onlyIdentity !== void 0 && names.length === 0) {
21455
22071
  throw new SessionLookupError(`no identity named "${onlyIdentity}"`);
21456
22072
  }
21457
22073
  const matches = [];
21458
- for (const store of historyStores(fs14, identitiesDir, names)) {
21459
- for (const ref of listSessions2(fs14, store.configDir)) {
22074
+ for (const store of historyStores(fs15, identitiesDir, names)) {
22075
+ for (const ref of listSessions2(fs15, store.configDir)) {
21460
22076
  if (ref.sessionId.startsWith(query)) {
21461
22077
  matches.push({ identities: store.identities, configDir: store.configDir, ref });
21462
22078
  }
@@ -21473,9 +22089,9 @@ function locateSession(fs14, identitiesDir, identities, query, onlyIdentity) {
21473
22089
  }
21474
22090
  throw new SessionLookupError(`"${query}" matches ${String(candidates.length)} sessions: ${candidates.map((match) => `${match.ref.sessionId} (${match.identities.join(", ")})`).join("; ")}; give more of the id or pass --identity`);
21475
22091
  }
21476
- function showSession(fs14, identitiesDir, identities, query, onlyIdentity) {
21477
- const located = locateSession(fs14, identitiesDir, identities, query, onlyIdentity);
21478
- return { identities: located.identities, tree: readSessionAgentTree(fs14, located.configDir, located.ref) };
22092
+ function showSession(fs15, identitiesDir, identities, query, onlyIdentity) {
22093
+ const located = locateSession(fs15, identitiesDir, identities, query, onlyIdentity);
22094
+ return { identities: located.identities, tree: readSessionAgentTree(fs15, located.configDir, located.ref) };
21479
22095
  }
21480
22096
 
21481
22097
  // src/agents/realFs.ts
@@ -21630,6 +22246,7 @@ export {
21630
22246
  CodexRateLimitsReadSchema,
21631
22247
  CodexSignInSchema,
21632
22248
  CodexStatusOutputSchema,
22249
+ ConfigIdentityAddInputSchema,
21633
22250
  ConfigIdentityAddOutputSchema,
21634
22251
  ConfigIdentityRemoveInputSchema,
21635
22252
  ConfigIdentityRemoveOutputSchema,