claude-use 9.19.0 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +1628 -1029
- package/dist/index.cjs +855 -306
- package/dist/index.mjs +839 -291
- package/dist/types/index.d.ts +201 -133
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -472,7 +472,7 @@ var init_schema = __esm({
|
|
|
472
472
|
context.addIssue({ code: "custom", path: ["readMaturation"], message: "readMaturation needs rolloutChannel beta or dev" });
|
|
473
473
|
}
|
|
474
474
|
});
|
|
475
|
-
HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@
|
|
475
|
+
HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@ca7589c574bfd52919503a74f09f4d1fe5ecf106";
|
|
476
476
|
HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES = 15;
|
|
477
477
|
FrontDoorGlobalConfigSchema = import_zod.z.strictObject({
|
|
478
478
|
/** How long the front door may sit with no registered sessions before it closes and exits. Defaults to FRONTDOOR_DEFAULT_IDLE_SHUTDOWN_MINUTES. */
|
|
@@ -2607,9 +2607,71 @@ function writeFrontDoorState(fs12, stateFile, state) {
|
|
|
2607
2607
|
fs12.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
|
|
2608
2608
|
`);
|
|
2609
2609
|
}
|
|
2610
|
+
function directOrigin(port) {
|
|
2611
|
+
return `http://127.0.0.1:${String(port)}`;
|
|
2612
|
+
}
|
|
2610
2613
|
function frontDoorOrigin(state) {
|
|
2611
2614
|
const port = state?.directPort ?? state?.lastDirectPort;
|
|
2612
|
-
return port === void 0 ? void 0 :
|
|
2615
|
+
return port === void 0 ? void 0 : directOrigin(port);
|
|
2616
|
+
}
|
|
2617
|
+
function writeFrontDoorDirectRecord(fs12, recordsDir, record) {
|
|
2618
|
+
fs12.mkdirp(recordsDir);
|
|
2619
|
+
fs12.writeFilePrivate(import_node_path8.default.join(recordsDir, `${String(record.pid)}.json`), `${JSON.stringify({ directPort: record.directPort })}
|
|
2620
|
+
`);
|
|
2621
|
+
}
|
|
2622
|
+
function removeFrontDoorDirectRecord(fs12, recordsDir, pid) {
|
|
2623
|
+
fs12.removeRecursive(import_node_path8.default.join(recordsDir, `${String(pid)}.json`));
|
|
2624
|
+
}
|
|
2625
|
+
function recordPid(file) {
|
|
2626
|
+
const pidText = /^([1-9]\d*)\.json$/.exec(file)?.[1];
|
|
2627
|
+
const pid = pidText === void 0 ? void 0 : Number(pidText);
|
|
2628
|
+
return pid !== void 0 && Number.isSafeInteger(pid) ? pid : void 0;
|
|
2629
|
+
}
|
|
2630
|
+
function readDirectRecordEntry(fs12, recordsDir, file) {
|
|
2631
|
+
const pid = recordPid(file);
|
|
2632
|
+
if (pid === void 0) {
|
|
2633
|
+
return void 0;
|
|
2634
|
+
}
|
|
2635
|
+
let raw;
|
|
2636
|
+
try {
|
|
2637
|
+
raw = fs12.readFileUtf8(import_node_path8.default.join(recordsDir, file));
|
|
2638
|
+
} catch {
|
|
2639
|
+
return void 0;
|
|
2640
|
+
}
|
|
2641
|
+
if (raw === void 0) {
|
|
2642
|
+
return void 0;
|
|
2643
|
+
}
|
|
2644
|
+
try {
|
|
2645
|
+
const parsed = FrontDoorDirectRecordSchema.safeParse(JSON.parse(raw));
|
|
2646
|
+
return parsed.success ? { record: { pid, directPort: parsed.data.directPort } } : { malformed: true };
|
|
2647
|
+
} catch {
|
|
2648
|
+
return { malformed: true };
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
function listFrontDoorDirectRecords(fs12, recordsDir) {
|
|
2652
|
+
return fs12.readdir(recordsDir).flatMap((file) => {
|
|
2653
|
+
const entry = readDirectRecordEntry(fs12, recordsDir, file);
|
|
2654
|
+
return entry?.record === void 0 ? [] : [entry.record];
|
|
2655
|
+
}).sort((a, b) => a.pid - b.pid);
|
|
2656
|
+
}
|
|
2657
|
+
function pruneMalformedFrontDoorDirectFiles(fs12, recordsDir, isRunning) {
|
|
2658
|
+
for (const file of fs12.readdir(recordsDir)) {
|
|
2659
|
+
const writer = RECORD_TEMPORARY_FILE.exec(file)?.[1];
|
|
2660
|
+
const stale = writer !== void 0 && !isRunning(Number(writer));
|
|
2661
|
+
if (stale || readDirectRecordEntry(fs12, recordsDir, file)?.malformed === true) {
|
|
2662
|
+
fs12.removeRecursive(import_node_path8.default.join(recordsDir, file));
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
function liveFrontDoorDirectRecords(records, liveness) {
|
|
2667
|
+
return records.filter((record) => liveness.doors.has(record.pid) || liveness.unknown.has(record.pid));
|
|
2668
|
+
}
|
|
2669
|
+
function pruneDeadFrontDoorDirectRecords(fs12, recordsDir, records, liveness) {
|
|
2670
|
+
for (const record of records) {
|
|
2671
|
+
if (!liveness.doors.has(record.pid) && !liveness.unknown.has(record.pid)) {
|
|
2672
|
+
removeFrontDoorDirectRecord(fs12, recordsDir, record.pid);
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2613
2675
|
}
|
|
2614
2676
|
function writeFrontDoorSession(fs12, sessionsDir, session) {
|
|
2615
2677
|
fs12.mkdirPrivate(sessionsDir);
|
|
@@ -2646,7 +2708,7 @@ function pruneDeadFrontDoorSessions(fs12, sessionsDir, isRunning) {
|
|
|
2646
2708
|
}
|
|
2647
2709
|
return removed;
|
|
2648
2710
|
}
|
|
2649
|
-
var import_node_path8, import_zod3, FRONT_DOOR_PROTOCOL, FrontDoorSessionSchema, FrontDoorStateSchema;
|
|
2711
|
+
var import_node_path8, import_zod3, FRONT_DOOR_PROTOCOL, FrontDoorSessionSchema, FrontDoorStateSchema, MAX_TCP_PORT, FrontDoorDirectRecordSchema, RECORD_TEMPORARY_FILE;
|
|
2650
2712
|
var init_state = __esm({
|
|
2651
2713
|
"src/frontdoor/state.ts"() {
|
|
2652
2714
|
"use strict";
|
|
@@ -2676,7 +2738,7 @@ var init_state = __esm({
|
|
|
2676
2738
|
*/
|
|
2677
2739
|
lastConnectPort: import_zod3.z.number().int().positive().optional(),
|
|
2678
2740
|
/**
|
|
2679
|
-
* The loopback port the direct listener serves on: the listener a headroom hop tells the daemon to forward routed traffic back to. Sticky like the others, because headroom's allowlist admits its exact origin
|
|
2741
|
+
* The loopback port the direct listener serves on: the listener a headroom hop tells the daemon to forward routed traffic back to. Sticky like the others, because headroom's allowlist admits its exact origin: the headroom supervisor rewrites the daemon's allowlist file when the origin moves, but a provider launch waits at its gate until it has, so an ephemeral port would hold launches up after every restart.
|
|
2680
2742
|
*/
|
|
2681
2743
|
directPort: import_zod3.z.number().int().positive().optional(),
|
|
2682
2744
|
/** The sticky port preference for the direct listener, for the reason `directPort` gives. */
|
|
@@ -2684,6 +2746,9 @@ var init_state = __esm({
|
|
|
2684
2746
|
/** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
|
|
2685
2747
|
lastError: import_zod3.z.string().optional()
|
|
2686
2748
|
});
|
|
2749
|
+
MAX_TCP_PORT = 65535;
|
|
2750
|
+
FrontDoorDirectRecordSchema = import_zod3.z.strictObject({ directPort: import_zod3.z.number().int().positive().max(MAX_TCP_PORT) });
|
|
2751
|
+
RECORD_TEMPORARY_FILE = /^[1-9]\d*\.json\.([1-9]\d*)\.tmp$/;
|
|
2687
2752
|
}
|
|
2688
2753
|
});
|
|
2689
2754
|
|
|
@@ -2693,7 +2758,7 @@ var init_package = __esm({
|
|
|
2693
2758
|
"package.json"() {
|
|
2694
2759
|
package_default = {
|
|
2695
2760
|
name: "claude-use",
|
|
2696
|
-
version: "
|
|
2761
|
+
version: "10.0.0",
|
|
2697
2762
|
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.",
|
|
2698
2763
|
license: "MIT",
|
|
2699
2764
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -2818,11 +2883,75 @@ function listFrontDoorSupervisors(run, uid) {
|
|
|
2818
2883
|
}
|
|
2819
2884
|
return { ok: true, pids: parseFrontDoorSupervisorPids(result.stdout) };
|
|
2820
2885
|
}
|
|
2821
|
-
|
|
2886
|
+
function frontDoorLivenessFromPs(run, asked) {
|
|
2887
|
+
if (refusedEveryPidAsTooLarge(run, asked)) {
|
|
2888
|
+
return { doors: /* @__PURE__ */ new Set(), unknown: /* @__PURE__ */ new Map() };
|
|
2889
|
+
}
|
|
2890
|
+
const failure = psFailure(run);
|
|
2891
|
+
if (failure !== void 0) {
|
|
2892
|
+
return { doors: /* @__PURE__ */ new Set(), unknown: new Map(asked.map((pid) => [pid, failure])) };
|
|
2893
|
+
}
|
|
2894
|
+
const askedSet = new Set(asked);
|
|
2895
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2896
|
+
const doors = /* @__PURE__ */ new Set();
|
|
2897
|
+
for (const line of run.stdout.split("\n")) {
|
|
2898
|
+
const [pidText, stat, ...argumentsList] = line.trim().split(/\s+/);
|
|
2899
|
+
const pid = Number(pidText);
|
|
2900
|
+
if (!askedSet.has(pid) || seen.has(pid)) {
|
|
2901
|
+
continue;
|
|
2902
|
+
}
|
|
2903
|
+
seen.add(pid);
|
|
2904
|
+
if (stat !== void 0 && !stat.startsWith("Z") && argumentsList.includes(FRONT_DOOR_SUPERVISOR_ARGUMENT)) {
|
|
2905
|
+
doors.add(pid);
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
return { doors, unknown: /* @__PURE__ */ new Map() };
|
|
2909
|
+
}
|
|
2910
|
+
function refusedEveryPidAsTooLarge(run, asked) {
|
|
2911
|
+
const lines = run.stderr.split("\n").filter((line) => line.trim() !== "");
|
|
2912
|
+
const tooLarge = new Set(lines.map((line) => Number(PID_TOO_LARGE.exec(line.trim())?.[1])));
|
|
2913
|
+
return run.status === 1 && run.stdout.trim() === "" && lines.length > 0 && lines.every((line) => PID_TOO_LARGE.test(line.trim())) && asked.every((pid) => tooLarge.has(pid));
|
|
2914
|
+
}
|
|
2915
|
+
function psFailure(run) {
|
|
2916
|
+
if (run.error !== void 0) {
|
|
2917
|
+
return run.error.message;
|
|
2918
|
+
}
|
|
2919
|
+
if (run.status === null) {
|
|
2920
|
+
return "ps was terminated before it answered";
|
|
2921
|
+
}
|
|
2922
|
+
const noneExist = run.status === 1 && run.stdout.trim() === "" && run.stderr.trim() === "";
|
|
2923
|
+
if (run.status !== 0 && !noneExist) {
|
|
2924
|
+
return `ps exited ${String(run.status)}${run.stderr.trim() === "" ? "" : `: ${run.stderr.trim()}`}`;
|
|
2925
|
+
}
|
|
2926
|
+
return void 0;
|
|
2927
|
+
}
|
|
2928
|
+
function frontDoorLivenessOf(pids, runPs) {
|
|
2929
|
+
if (pids.length === 0) {
|
|
2930
|
+
return { doors: /* @__PURE__ */ new Set(), unknown: /* @__PURE__ */ new Map() };
|
|
2931
|
+
}
|
|
2932
|
+
const batch = frontDoorLivenessFromPs(runPs(pids), pids);
|
|
2933
|
+
if (batch.unknown.size === 0 || pids.length === 1) {
|
|
2934
|
+
return batch;
|
|
2935
|
+
}
|
|
2936
|
+
const doors = /* @__PURE__ */ new Set();
|
|
2937
|
+
const unknown = /* @__PURE__ */ new Map();
|
|
2938
|
+
for (const pid of pids) {
|
|
2939
|
+
const single = frontDoorLivenessFromPs(runPs([pid]), [pid]);
|
|
2940
|
+
for (const door of single.doors) {
|
|
2941
|
+
doors.add(door);
|
|
2942
|
+
}
|
|
2943
|
+
for (const [unanswered, reason] of single.unknown) {
|
|
2944
|
+
unknown.set(unanswered, reason);
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
return { doors, unknown };
|
|
2948
|
+
}
|
|
2949
|
+
var FRONT_DOOR_SUPERVISOR_ARGUMENT, PID_TOO_LARGE;
|
|
2822
2950
|
var init_supervisorProcesses = __esm({
|
|
2823
2951
|
"src/frontdoor/supervisorProcesses.ts"() {
|
|
2824
2952
|
"use strict";
|
|
2825
2953
|
FRONT_DOOR_SUPERVISOR_ARGUMENT = "__frontdoor-supervisor";
|
|
2954
|
+
PID_TOO_LARGE = /^ps: process id too large: (\d+)$/;
|
|
2826
2955
|
}
|
|
2827
2956
|
});
|
|
2828
2957
|
|
|
@@ -2872,22 +3001,49 @@ function migrateHeadroomState(fs12, files, isRunning) {
|
|
|
2872
3001
|
}
|
|
2873
3002
|
fs12.removeRecursive(files.legacyStateFile);
|
|
2874
3003
|
}
|
|
2875
|
-
function
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
3004
|
+
function hashAllowlist(allowlist) {
|
|
3005
|
+
return (0, import_node_crypto6.createHash)("sha256").update(allowlist.join("\n")).digest("hex");
|
|
3006
|
+
}
|
|
3007
|
+
function formatAllowlistFile(allowlist) {
|
|
3008
|
+
return allowlist.map((entry) => `${entry}
|
|
3009
|
+
`).join("");
|
|
3010
|
+
}
|
|
3011
|
+
function hashAllowlistFile(content) {
|
|
3012
|
+
return hashAllowlist([...new Set(parseAllowlistFile(content))].sort());
|
|
3013
|
+
}
|
|
3014
|
+
function isBareHost(entry) {
|
|
3015
|
+
if (/[/?#@]/.test(entry)) {
|
|
3016
|
+
return false;
|
|
2879
3017
|
}
|
|
2880
|
-
|
|
3018
|
+
if (entry.startsWith("[")) {
|
|
3019
|
+
const close = entry.indexOf("]");
|
|
3020
|
+
return close > 1 && !entry.slice(close + 1).includes(":");
|
|
3021
|
+
}
|
|
3022
|
+
return entry !== "" && !entry.includes(":");
|
|
2881
3023
|
}
|
|
2882
|
-
function
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
3024
|
+
function isAdmissibleUrl(entry) {
|
|
3025
|
+
try {
|
|
3026
|
+
const url = new URL(entry);
|
|
3027
|
+
return ALLOWLIST_SAFE_SCHEMES.has(url.protocol) && url.hostname !== "";
|
|
3028
|
+
} catch {
|
|
3029
|
+
return false;
|
|
2886
3030
|
}
|
|
2887
|
-
return upstreams;
|
|
2888
3031
|
}
|
|
2889
|
-
function
|
|
2890
|
-
return (
|
|
3032
|
+
function parseAllowlistFile(content) {
|
|
3033
|
+
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)));
|
|
3034
|
+
}
|
|
3035
|
+
function writeAllowlistFile(fs12, allowlistFile, allowlist) {
|
|
3036
|
+
fs12.mkdirPrivate(import_node_path11.default.dirname(allowlistFile));
|
|
3037
|
+
fs12.writeFilePrivate(allowlistFile, formatAllowlistFile(allowlist));
|
|
3038
|
+
}
|
|
3039
|
+
function pruneStaleAllowlistTemporaries(fs12, allowlistFile, isRunning) {
|
|
3040
|
+
const prefix = `${import_node_path11.default.basename(allowlistFile)}.`;
|
|
3041
|
+
for (const name of fs12.readdir(import_node_path11.default.dirname(allowlistFile))) {
|
|
3042
|
+
const writer = name.startsWith(prefix) ? /^([1-9]\d*)\.tmp$/.exec(name.slice(prefix.length))?.[1] : void 0;
|
|
3043
|
+
if (writer !== void 0 && !isRunning(Number(writer))) {
|
|
3044
|
+
fs12.removeRecursive(import_node_path11.default.join(import_node_path11.default.dirname(allowlistFile), name));
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
2891
3047
|
}
|
|
2892
3048
|
function readAllProviders(fs12, providersDir) {
|
|
2893
3049
|
const result = [];
|
|
@@ -2951,7 +3107,7 @@ function readStartLock(fs12, lockFile) {
|
|
|
2951
3107
|
return void 0;
|
|
2952
3108
|
}
|
|
2953
3109
|
}
|
|
2954
|
-
var import_node_crypto6, import_node_path11, import_zod8,
|
|
3110
|
+
var import_node_crypto6, import_node_path11, import_zod8, HeadroomStateSchema, HeadroomSessionSchema, HeadroomLockSchema, HEADROOM_ALLOWLIST_FILE_FLAG, ALLOWLIST_LINE_BREAKS, ALLOWLIST_WHITESPACE, ALLOWLIST_FILE_SEPARATORS, ALLOWLIST_FILE_COMMENT, ALLOWLIST_ENTRY_WHITESPACE, ALLOWLIST_SURROUNDING_WHITESPACE, ALLOWLIST_SAFE_SCHEMES;
|
|
2955
3111
|
var init_state2 = __esm({
|
|
2956
3112
|
"src/headroom/state.ts"() {
|
|
2957
3113
|
"use strict";
|
|
@@ -2959,11 +3115,10 @@ var init_state2 = __esm({
|
|
|
2959
3115
|
import_node_path11 = __toESM(require("node:path"), 1);
|
|
2960
3116
|
import_zod8 = require("zod");
|
|
2961
3117
|
init_schema();
|
|
2962
|
-
HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
|
|
2963
3118
|
HeadroomStateSchema = import_zod8.z.strictObject({
|
|
2964
3119
|
/** The supervisor process owning the daemon. Alive means someone is keeping headroom running. */
|
|
2965
3120
|
supervisorPid: import_zod8.z.number().int().positive().optional(),
|
|
2966
|
-
/** The headroom proxy process itself. Absent while the supervisor is between restarts. */
|
|
3121
|
+
/** The headroom proxy process itself, recorded as soon as it is spawned (before it is ready, which `socketPath` signals) so a successor can find a daemon whose supervisor died during its start. Absent while the supervisor is between restarts. */
|
|
2967
3122
|
headroomPid: import_zod8.z.number().int().positive().optional(),
|
|
2968
3123
|
/**
|
|
2969
3124
|
* The unix socket the proxy serves on, inside the owner-only socket directory. Absent until the proxy has passed its readiness check, so "socketPath is set" is itself the ready signal a launcher polls for. The front door reads it on every hop, so a restart (which keeps the generation's path) is followed without anything being relaunched.
|
|
@@ -2971,7 +3126,9 @@ var init_state2 = __esm({
|
|
|
2971
3126
|
socketPath: import_zod8.z.string().min(1).optional(),
|
|
2972
3127
|
/** The `headroom --version` output of the running install. */
|
|
2973
3128
|
version: import_zod8.z.string().optional(),
|
|
2974
|
-
/**
|
|
3129
|
+
/**
|
|
3130
|
+
* Hash of the allowlist the running proxy serves. The supervisor records it in the same tick it writes that allowlist to `LayoutPaths.headroomAllowlistFile`, which the proxy re-reads on its next request, so a provider launch, whose requests come back through its front door's direct origin, waits until this names an allowlist holding that origin. A supervisor from an earlier release records here the hash of the allowlist its daemon was started with instead (see `earlierRelease.ts`).
|
|
3131
|
+
*/
|
|
2975
3132
|
allowlistHash: import_zod8.z.string().optional(),
|
|
2976
3133
|
/** Hash of the token-saving settings the running proxy was started with, so a settings change is detected as drift. */
|
|
2977
3134
|
settingsHash: import_zod8.z.string().optional(),
|
|
@@ -2982,33 +3139,133 @@ var init_state2 = __esm({
|
|
|
2982
3139
|
});
|
|
2983
3140
|
HeadroomSessionSchema = import_zod8.z.strictObject({ pid: import_zod8.z.number().int().positive(), startedAt: import_zod8.z.number(), supervisorPid: import_zod8.z.number().int().positive() });
|
|
2984
3141
|
HeadroomLockSchema = import_zod8.z.strictObject({ pid: import_zod8.z.number().int().positive(), at: import_zod8.z.number() });
|
|
3142
|
+
HEADROOM_ALLOWLIST_FILE_FLAG = "--allowed-base-urls-file";
|
|
3143
|
+
ALLOWLIST_LINE_BREAKS = "\\n\\r\\u000b\\u000c\\u001c\\u001d\\u001e\\u0085\\u2028\\u2029";
|
|
3144
|
+
ALLOWLIST_WHITESPACE = "\\t\\n\\u000b\\u000c\\r\\u001c-\\u001f \\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000";
|
|
3145
|
+
ALLOWLIST_FILE_SEPARATORS = new RegExp(`[,\\t${ALLOWLIST_LINE_BREAKS}]`, "u");
|
|
3146
|
+
ALLOWLIST_FILE_COMMENT = new RegExp(`(?:^|(?<=[${ALLOWLIST_WHITESPACE}]))#[^${ALLOWLIST_LINE_BREAKS}]*`, "gu");
|
|
3147
|
+
ALLOWLIST_ENTRY_WHITESPACE = new RegExp(`[${ALLOWLIST_WHITESPACE}]`, "u");
|
|
3148
|
+
ALLOWLIST_SURROUNDING_WHITESPACE = new RegExp(`^[${ALLOWLIST_WHITESPACE}]+|[${ALLOWLIST_WHITESPACE}]+$`, "gu");
|
|
3149
|
+
ALLOWLIST_SAFE_SCHEMES = /* @__PURE__ */ new Set(["http:", "https:", "ws:", "wss:"]);
|
|
3150
|
+
}
|
|
3151
|
+
});
|
|
3152
|
+
|
|
3153
|
+
// src/headroom/earlierRelease.ts
|
|
3154
|
+
function withoutOurSocket(commandLine, socketPath) {
|
|
3155
|
+
for (const argument of [`--uds ${socketPath}`, `--uds=${socketPath}`]) {
|
|
3156
|
+
let from = 0;
|
|
3157
|
+
for (; ; ) {
|
|
3158
|
+
const index = commandLine.indexOf(argument, from);
|
|
3159
|
+
if (index === -1) {
|
|
3160
|
+
break;
|
|
3161
|
+
}
|
|
3162
|
+
const end = index + argument.length;
|
|
3163
|
+
const startsArgument = index === 0 || /\s/.test(commandLine.charAt(index - 1));
|
|
3164
|
+
const endsArgument = end === commandLine.length || /\s/.test(commandLine.charAt(end));
|
|
3165
|
+
if (startsArgument && endsArgument) {
|
|
3166
|
+
return `${commandLine.slice(0, index)} ${commandLine.slice(end)}`;
|
|
3167
|
+
}
|
|
3168
|
+
from = index + 1;
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
return void 0;
|
|
3172
|
+
}
|
|
3173
|
+
function daemonIdentity(commandLine, socketPath) {
|
|
3174
|
+
if (commandLine === void 0) {
|
|
3175
|
+
return "unreadable";
|
|
3176
|
+
}
|
|
3177
|
+
const rest = withoutOurSocket(commandLine, socketPath);
|
|
3178
|
+
const argumentsList = rest === void 0 ? [] : rest.trim().split(/\s+/);
|
|
3179
|
+
if (rest === void 0 || !argumentsList.includes("proxy")) {
|
|
3180
|
+
return "not-headroom";
|
|
3181
|
+
}
|
|
3182
|
+
return argumentsList.some((argument) => argument === HEADROOM_ALLOWLIST_FILE_FLAG || argument.startsWith(`${HEADROOM_ALLOWLIST_FILE_FLAG}=`)) ? "this-release" : "earlier-release";
|
|
3183
|
+
}
|
|
3184
|
+
function earlierReleaseAllowlistHash(providers, doorOrigin) {
|
|
3185
|
+
const entries = /* @__PURE__ */ new Set([EARLIER_RELEASE_ANTHROPIC_UPSTREAM]);
|
|
3186
|
+
for (const provider of providers) {
|
|
3187
|
+
if (!isCodexProvider(provider)) {
|
|
3188
|
+
entries.add(provider.baseUrl);
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
if (providers.length > 0 && doorOrigin !== void 0) {
|
|
3192
|
+
entries.add(doorOrigin);
|
|
3193
|
+
}
|
|
3194
|
+
return hashAllowlist([...entries].sort());
|
|
3195
|
+
}
|
|
3196
|
+
function earlierReleaseDaemon(fs12, paths, daemon) {
|
|
3197
|
+
if (daemonIdentity(daemon.commandLine, daemon.socketPath) !== "earlier-release") {
|
|
3198
|
+
return void 0;
|
|
3199
|
+
}
|
|
3200
|
+
const providers = readAllProviders(fs12, paths.providersDir).map((entry) => entry.provider);
|
|
3201
|
+
const expected = earlierReleaseAllowlistHash(providers, frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile)));
|
|
3202
|
+
return { admitsServingDoor: daemon.recordedHash === expected };
|
|
3203
|
+
}
|
|
3204
|
+
var EARLIER_RELEASE_ALLOWLIST, EARLIER_RELEASE_ANTHROPIC_UPSTREAM;
|
|
3205
|
+
var init_earlierRelease = __esm({
|
|
3206
|
+
"src/headroom/earlierRelease.ts"() {
|
|
3207
|
+
"use strict";
|
|
3208
|
+
init_schema();
|
|
3209
|
+
init_state();
|
|
3210
|
+
init_state2();
|
|
3211
|
+
EARLIER_RELEASE_ALLOWLIST = "started by an earlier release with an allowlist fixed at start; it restarts once its sessions end";
|
|
3212
|
+
EARLIER_RELEASE_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
|
|
2985
3213
|
}
|
|
2986
3214
|
});
|
|
2987
3215
|
|
|
2988
3216
|
// src/headroom/ensure.ts
|
|
3217
|
+
function awaitingCause(daemonPid, identity, allowlistFile) {
|
|
3218
|
+
if (identity === "unreadable") {
|
|
3219
|
+
return `could not read the command line of the headroom daemon (pid ${String(daemonPid)}), so whether it reads an allowlist file is unknown, and its allowlist was not recorded as admitting this launch's upstreams within ${String(HEADROOM_START_TIMEOUT_MS)}ms`;
|
|
3220
|
+
}
|
|
3221
|
+
if (identity === "not-headroom") {
|
|
3222
|
+
return `the headroom daemon pid ${String(daemonPid)} the state records is no longer a headroom proxy on its socket, and no daemon was recorded as admitting this launch's upstreams within ${String(HEADROOM_START_TIMEOUT_MS)}ms`;
|
|
3223
|
+
}
|
|
3224
|
+
return `the headroom supervisor has not written an allowlist admitting this launch's upstreams to ${allowlistFile} within ${String(HEADROOM_START_TIMEOUT_MS)}ms`;
|
|
3225
|
+
}
|
|
3226
|
+
function daemonAdmits(fs12, allowlistFile, recordedHash, required) {
|
|
3227
|
+
const content = fs12.readFileUtf8(allowlistFile);
|
|
3228
|
+
if (content === void 0 || recordedHash === void 0) {
|
|
3229
|
+
return false;
|
|
3230
|
+
}
|
|
3231
|
+
const served = parseAllowlistFile(content);
|
|
3232
|
+
return recordedHash === hashAllowlistFile(content) && required.every((upstream) => served.includes(upstream));
|
|
3233
|
+
}
|
|
2989
3234
|
function ensureHeadroom(params) {
|
|
2990
3235
|
const { paths, ports } = params;
|
|
2991
3236
|
const deadline = ports.now() + HEADROOM_START_TIMEOUT_MS;
|
|
2992
3237
|
let spawnedSupervisor = false;
|
|
2993
|
-
let awaitingAllowlist = false;
|
|
2994
3238
|
migrateHeadroomState(ports.fs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning);
|
|
3239
|
+
const commandLines = /* @__PURE__ */ new Map();
|
|
3240
|
+
const commandLineOf = (pid) => {
|
|
3241
|
+
if (!commandLines.has(pid)) {
|
|
3242
|
+
commandLines.set(pid, ports.daemonCommandLine(pid));
|
|
3243
|
+
}
|
|
3244
|
+
return commandLines.get(pid);
|
|
3245
|
+
};
|
|
2995
3246
|
for (; ; ) {
|
|
3247
|
+
let awaiting;
|
|
2996
3248
|
const state = resolveServingHeadroomState(ports.fs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning)?.state;
|
|
2997
3249
|
if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
|
|
2998
3250
|
const daemonUp = state.socketPath !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
|
|
2999
|
-
if (daemonUp && state.socketPath !== void 0) {
|
|
3000
|
-
const required = params.
|
|
3001
|
-
if (required === void 0 || state.allowlistHash
|
|
3251
|
+
if (daemonUp && state.socketPath !== void 0 && state.headroomPid !== void 0) {
|
|
3252
|
+
const required = params.requiredUpstreams?.();
|
|
3253
|
+
if (required === void 0 || daemonAdmits(ports.fs, paths.headroomAllowlistFile, state.allowlistHash, required)) {
|
|
3002
3254
|
writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
|
|
3003
3255
|
return { socketPath: state.socketPath };
|
|
3004
3256
|
}
|
|
3005
|
-
const
|
|
3006
|
-
|
|
3257
|
+
const commandLine = commandLineOf(state.headroomPid);
|
|
3258
|
+
const earlierRelease = earlierReleaseDaemon(ports.fs, paths, { commandLine, socketPath: state.socketPath, recordedHash: state.allowlistHash });
|
|
3259
|
+
if (earlierRelease !== void 0) {
|
|
3260
|
+
if (earlierRelease.admitsServingDoor) {
|
|
3261
|
+
writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
|
|
3262
|
+
return { socketPath: state.socketPath };
|
|
3263
|
+
}
|
|
3007
3264
|
throw new HeadroomStartError(
|
|
3008
|
-
`the running headroom daemon was
|
|
3265
|
+
`the running headroom daemon (pid ${String(state.headroomPid)}) was ${EARLIER_RELEASE_ALLOWLIST}, and its allowlist cannot be shown to admit the serving front door; launch with --no-headroom until then. Supervisor and daemon log: ${paths.headroomLogPath}`
|
|
3009
3266
|
);
|
|
3010
3267
|
}
|
|
3011
|
-
|
|
3268
|
+
awaiting = { daemonPid: state.headroomPid, identity: daemonIdentity(commandLine, state.socketPath) };
|
|
3012
3269
|
}
|
|
3013
3270
|
if (state.lastError !== void 0) {
|
|
3014
3271
|
throw new HeadroomStartError(
|
|
@@ -3034,10 +3291,11 @@ function ensureHeadroom(params) {
|
|
|
3034
3291
|
}
|
|
3035
3292
|
}
|
|
3036
3293
|
if (ports.now() >= deadline) {
|
|
3037
|
-
const lastError = state?.lastError
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3294
|
+
const lastError = state?.lastError === void 0 ? "" : ` (last error: ${state.lastError})`;
|
|
3295
|
+
if (awaiting !== void 0) {
|
|
3296
|
+
throw new HeadroomStartError(`${awaitingCause(awaiting.daemonPid, awaiting.identity, paths.headroomAllowlistFile)}${lastError}, so the daemon would refuse every request this launch sends through it; launch with --no-headroom to bypass it. Supervisor and daemon log: ${paths.headroomLogPath}`);
|
|
3297
|
+
}
|
|
3298
|
+
throw new HeadroomStartError(`the headroom daemon did not become ready within ${String(HEADROOM_START_TIMEOUT_MS)}ms${lastError}. Daemon log: ${paths.headroomLogPath}`);
|
|
3041
3299
|
}
|
|
3042
3300
|
ports.sleep(HEADROOM_LAUNCHER_POLL_MS);
|
|
3043
3301
|
}
|
|
@@ -3047,6 +3305,7 @@ var init_ensure = __esm({
|
|
|
3047
3305
|
"src/headroom/ensure.ts"() {
|
|
3048
3306
|
"use strict";
|
|
3049
3307
|
init_cliError();
|
|
3308
|
+
init_earlierRelease();
|
|
3050
3309
|
init_state2();
|
|
3051
3310
|
HEADROOM_START_TIMEOUT_MS = 12e4;
|
|
3052
3311
|
HEADROOM_LAUNCHER_POLL_MS = 250;
|
|
@@ -3094,6 +3353,22 @@ var init_settings = __esm({
|
|
|
3094
3353
|
}
|
|
3095
3354
|
});
|
|
3096
3355
|
|
|
3356
|
+
// src/frontdoor/capture.ts
|
|
3357
|
+
function redactText(text) {
|
|
3358
|
+
return SECRET_BODY_PATTERNS.reduce((accumulated, { pattern, replacement }) => accumulated.replace(pattern, replacement), text);
|
|
3359
|
+
}
|
|
3360
|
+
var SECRET_BODY_PATTERNS;
|
|
3361
|
+
var init_capture = __esm({
|
|
3362
|
+
"src/frontdoor/capture.ts"() {
|
|
3363
|
+
"use strict";
|
|
3364
|
+
SECRET_BODY_PATTERNS = [
|
|
3365
|
+
{ pattern: /sk-ant-[A-Za-z0-9_-]{8,}/g, replacement: "<redacted>" },
|
|
3366
|
+
{ pattern: /Bearer\s+[A-Za-z0-9._~+/=-]{8,}/gi, replacement: "Bearer <redacted>" },
|
|
3367
|
+
{ pattern: /eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{8,}/g, replacement: "<redacted>" }
|
|
3368
|
+
];
|
|
3369
|
+
}
|
|
3370
|
+
});
|
|
3371
|
+
|
|
3097
3372
|
// src/headroom/socket.ts
|
|
3098
3373
|
function headroomSocketPath(paths, supervisorPid) {
|
|
3099
3374
|
return import_node_path12.default.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
|
|
@@ -3106,10 +3381,10 @@ function ownerOnlyRefusal(label, target, stat, expected, uid) {
|
|
|
3106
3381
|
return `the headroom ${label} ${target} does not exist`;
|
|
3107
3382
|
}
|
|
3108
3383
|
if (stat.kind === "symlink") {
|
|
3109
|
-
return `the headroom ${label} ${target} is a symlink; it must be the real ${expected
|
|
3384
|
+
return `the headroom ${label} ${target} is a symlink; it must be the real ${KIND_NAMES[expected]}`;
|
|
3110
3385
|
}
|
|
3111
3386
|
if (stat.kind !== expected) {
|
|
3112
|
-
return `the headroom ${label} ${target} is not a ${expected
|
|
3387
|
+
return `the headroom ${label} ${target} is not a ${KIND_NAMES[expected]}`;
|
|
3113
3388
|
}
|
|
3114
3389
|
if (stat.uid !== uid) {
|
|
3115
3390
|
return `the headroom ${label} ${target} is owned by uid ${String(stat.uid)}, not by this user (uid ${String(uid)})`;
|
|
@@ -3129,6 +3404,86 @@ function verifyHeadroomSocket(socketPath, ports) {
|
|
|
3129
3404
|
const refusal2 = ownerOnlyRefusal("socket directory", directory, ports.lstat(directory), "dir", uid) ?? ownerOnlyRefusal("socket", socketPath, ports.lstat(socketPath), "socket", uid);
|
|
3130
3405
|
return refusal2 === void 0 ? { socketPath } : { refused: refusal2 };
|
|
3131
3406
|
}
|
|
3407
|
+
function pathDirectories(target, ports) {
|
|
3408
|
+
const pending = target.split("/").reverse();
|
|
3409
|
+
let current = "/";
|
|
3410
|
+
const directories = [];
|
|
3411
|
+
let hops = 0;
|
|
3412
|
+
for (let name = pending.pop(); name !== void 0; name = pending.pop()) {
|
|
3413
|
+
if (name === "" || name === ".") {
|
|
3414
|
+
continue;
|
|
3415
|
+
}
|
|
3416
|
+
if (name === "..") {
|
|
3417
|
+
current = import_node_path12.default.dirname(current);
|
|
3418
|
+
continue;
|
|
3419
|
+
}
|
|
3420
|
+
if (!directories.includes(current)) {
|
|
3421
|
+
directories.push(current);
|
|
3422
|
+
}
|
|
3423
|
+
const entry = import_node_path12.default.join(current, name);
|
|
3424
|
+
if (pending.length > 0 && ports.lstat(entry)?.kind === "symlink") {
|
|
3425
|
+
hops += 1;
|
|
3426
|
+
if (hops > MAX_SYMLINK_HOPS) {
|
|
3427
|
+
return `the symlinks on the allowlist file's path go more than ${String(MAX_SYMLINK_HOPS)} deep`;
|
|
3428
|
+
}
|
|
3429
|
+
const linkTarget = ports.readlink(entry);
|
|
3430
|
+
if (import_node_path12.default.isAbsolute(linkTarget)) {
|
|
3431
|
+
current = "/";
|
|
3432
|
+
}
|
|
3433
|
+
pending.push(...linkTarget.split("/").reverse());
|
|
3434
|
+
} else if (pending.length > 0) {
|
|
3435
|
+
current = entry;
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3438
|
+
return directories;
|
|
3439
|
+
}
|
|
3440
|
+
function headroomDirectoryRefusal(directory, stat, uid, remedy) {
|
|
3441
|
+
if (stat?.kind !== "dir") {
|
|
3442
|
+
return `the directory ${directory} on the allowlist file's path is ${stat === void 0 ? "missing" : "not a directory"}, so headroom refuses the file`;
|
|
3443
|
+
}
|
|
3444
|
+
if (stat.uid !== uid && stat.uid !== ROOT_UID) {
|
|
3445
|
+
return `the directory ${directory} on the allowlist file's path is owned by uid ${String(stat.uid)}, not by this user (uid ${String(uid)}) or root, so headroom refuses the file${remedy ? `; ${MOVE_ROOT_REMEDY}` : ""}`;
|
|
3446
|
+
}
|
|
3447
|
+
if ((stat.mode & GROUP_OR_OTHER_WRITE_BITS) !== 0) {
|
|
3448
|
+
return `the directory ${directory} on the allowlist file's path is writable by group or others (mode ${stat.mode.toString(OCTAL_RADIX).padStart(MODE_DIGITS, "0")}), so headroom refuses the file${remedy ? `; ${stat.uid === uid && (stat.mode & STICKY_BIT) === 0 ? `run \`chmod go-w ${directory}\`` : MOVE_ROOT_REMEDY}` : ""}`;
|
|
3449
|
+
}
|
|
3450
|
+
return void 0;
|
|
3451
|
+
}
|
|
3452
|
+
function reportableAllowlistFileProblem(allowlistFile, ports, served) {
|
|
3453
|
+
const problem = verifyAllowlistFile(allowlistFile, ports);
|
|
3454
|
+
return problem?.repairable === false || served ? problem : void 0;
|
|
3455
|
+
}
|
|
3456
|
+
function verifyAllowlistFile(allowlistFile, ports) {
|
|
3457
|
+
const uid = ports.currentUid();
|
|
3458
|
+
const directories = pathDirectories(allowlistFile, ports);
|
|
3459
|
+
if (typeof directories === "string") {
|
|
3460
|
+
return { message: directories, repairable: false };
|
|
3461
|
+
}
|
|
3462
|
+
const socketDirectory = directories.at(-1);
|
|
3463
|
+
const headroomDirectory = socketDirectory === void 0 ? void 0 : import_node_path12.default.dirname(socketDirectory);
|
|
3464
|
+
for (const directory of directories) {
|
|
3465
|
+
const stat = ports.lstat(directory);
|
|
3466
|
+
if (directory === socketDirectory) {
|
|
3467
|
+
const refusal4 = ownerOnlyRefusal("allowlist directory", directory, stat, "dir", uid);
|
|
3468
|
+
if (refusal4 !== void 0) {
|
|
3469
|
+
return { message: refusal4, repairable: true };
|
|
3470
|
+
}
|
|
3471
|
+
continue;
|
|
3472
|
+
}
|
|
3473
|
+
const own = directory === headroomDirectory;
|
|
3474
|
+
const refusal3 = headroomDirectoryRefusal(directory, stat, uid, !own);
|
|
3475
|
+
if (refusal3 !== void 0) {
|
|
3476
|
+
return { message: refusal3, repairable: own };
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
const fileStat = ports.lstat(allowlistFile);
|
|
3480
|
+
const refusal2 = ownerOnlyRefusal("allowlist file", allowlistFile, fileStat, "file", uid);
|
|
3481
|
+
if (refusal2 === void 0) {
|
|
3482
|
+
return void 0;
|
|
3483
|
+
}
|
|
3484
|
+
const replaceable = fileStat === void 0 || fileStat.kind === "file" || fileStat.kind === "symlink";
|
|
3485
|
+
return { message: refusal2, repairable: replaceable };
|
|
3486
|
+
}
|
|
3132
3487
|
function prepareHeadroomSocket(fs12, ports, paths, supervisorPid) {
|
|
3133
3488
|
const unsupported = platformRefusal(ports.platform);
|
|
3134
3489
|
if (unsupported !== void 0) {
|
|
@@ -3160,7 +3515,7 @@ function pruneStaleHeadroomSockets(fs12, paths, isRunning) {
|
|
|
3160
3515
|
}
|
|
3161
3516
|
return removed;
|
|
3162
3517
|
}
|
|
3163
|
-
var import_node_path12, GROUP_OR_OTHER_BITS, OCTAL_RADIX, MODE_DIGITS, HEADROOM_SOCKET_SUFFIX, HEADROOM_SOCKET_NAME, UNIX_SOCKET_PATH_MAX_BYTES, PLATFORMS_WITHOUT_UNIX_SOCKETS;
|
|
3518
|
+
var import_node_path12, GROUP_OR_OTHER_BITS, OCTAL_RADIX, MODE_DIGITS, HEADROOM_SOCKET_SUFFIX, HEADROOM_SOCKET_NAME, UNIX_SOCKET_PATH_MAX_BYTES, PLATFORMS_WITHOUT_UNIX_SOCKETS, KIND_NAMES, MAX_SYMLINK_HOPS, ROOT_UID, GROUP_OR_OTHER_WRITE_BITS, STICKY_BIT, MOVE_ROOT_REMEDY;
|
|
3164
3519
|
var init_socket = __esm({
|
|
3165
3520
|
"src/headroom/socket.ts"() {
|
|
3166
3521
|
"use strict";
|
|
@@ -3172,6 +3527,12 @@ var init_socket = __esm({
|
|
|
3172
3527
|
HEADROOM_SOCKET_NAME = /^(\d+)\.sock$/;
|
|
3173
3528
|
UNIX_SOCKET_PATH_MAX_BYTES = 103;
|
|
3174
3529
|
PLATFORMS_WITHOUT_UNIX_SOCKETS = ["win32"];
|
|
3530
|
+
KIND_NAMES = { dir: "directory", file: "file", socket: "socket" };
|
|
3531
|
+
MAX_SYMLINK_HOPS = 40;
|
|
3532
|
+
ROOT_UID = 0;
|
|
3533
|
+
GROUP_OR_OTHER_WRITE_BITS = 18;
|
|
3534
|
+
STICKY_BIT = 512;
|
|
3535
|
+
MOVE_ROOT_REMEDY = "move the agent-shim root (AGENT_SHIM_HOME) to where every directory above it is owned by this user or root and not writable by group or others";
|
|
3175
3536
|
}
|
|
3176
3537
|
});
|
|
3177
3538
|
|
|
@@ -3288,6 +3649,36 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3288
3649
|
ports.log(`agent-shim headroom supervisor: ${message}`);
|
|
3289
3650
|
return 1;
|
|
3290
3651
|
};
|
|
3652
|
+
const syncAllowlistFile = (allowlist) => {
|
|
3653
|
+
try {
|
|
3654
|
+
if (fs12.readFileUtf8(paths.headroomAllowlistFile) !== formatAllowlistFile(allowlist)) {
|
|
3655
|
+
writeAllowlistFile(fs12, paths.headroomAllowlistFile, allowlist);
|
|
3656
|
+
ports.log(`agent-shim headroom supervisor: wrote allowlist [${allowlist.join(", ")}] to ${paths.headroomAllowlistFile}`);
|
|
3657
|
+
}
|
|
3658
|
+
return void 0;
|
|
3659
|
+
} catch (error) {
|
|
3660
|
+
return `could not write the headroom allowlist file ${paths.headroomAllowlistFile}: ${error instanceof Error ? error.message : String(error)}`;
|
|
3661
|
+
}
|
|
3662
|
+
};
|
|
3663
|
+
const allowlistFileRefusal = (allowlist) => {
|
|
3664
|
+
const problem = verifyAllowlistFile(paths.headroomAllowlistFile, ports.socketTrust);
|
|
3665
|
+
if (problem === void 0) {
|
|
3666
|
+
return void 0;
|
|
3667
|
+
}
|
|
3668
|
+
if (!problem.repairable) {
|
|
3669
|
+
return `headroom would refuse its allowlist file, and agent-shim cannot repair it: ${problem.message}`;
|
|
3670
|
+
}
|
|
3671
|
+
ports.log(`agent-shim headroom supervisor: repairing the allowlist file: ${problem.message}`);
|
|
3672
|
+
try {
|
|
3673
|
+
fs12.mkdirPrivate(paths.headroomDir);
|
|
3674
|
+
fs12.mkdirPrivate(import_node_path13.default.dirname(paths.headroomAllowlistFile));
|
|
3675
|
+
writeAllowlistFile(fs12, paths.headroomAllowlistFile, allowlist);
|
|
3676
|
+
} catch (error) {
|
|
3677
|
+
return `could not write the headroom allowlist file ${paths.headroomAllowlistFile}: ${error instanceof Error ? error.message : String(error)}`;
|
|
3678
|
+
}
|
|
3679
|
+
const remaining = verifyAllowlistFile(paths.headroomAllowlistFile, ports.socketTrust);
|
|
3680
|
+
return remaining === void 0 ? void 0 : `the allowlist file breaks agent-shim's rules for it, and rewriting it did not repair it: ${remaining.message}`;
|
|
3681
|
+
};
|
|
3291
3682
|
const ensureInstalled = () => {
|
|
3292
3683
|
const version2 = ports.headroomVersion();
|
|
3293
3684
|
const versionOk = version2 !== void 0 && versionSatisfies(version2, config.source);
|
|
@@ -3311,14 +3702,20 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3311
3702
|
}
|
|
3312
3703
|
const { socketPath } = socket;
|
|
3313
3704
|
pruneStaleHeadroomSockets(fs12, paths, ports.isRunning);
|
|
3705
|
+
pruneStaleAllowlistTemporaries(fs12, paths.headroomAllowlistFile, ports.isRunning);
|
|
3314
3706
|
if (!ensureInstalled()) {
|
|
3315
3707
|
return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
|
|
3316
3708
|
}
|
|
3317
3709
|
const version = ports.headroomVersion() ?? "unknown";
|
|
3318
3710
|
writeOwnState({ supervisorPid: ports.ownPid, version, installedSource });
|
|
3319
|
-
ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${
|
|
3711
|
+
ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${currentHeadroomAllowlistInputs(fs12, paths, ports.frontDoorLiveness).frontDoorOrigins.join(", ")}]`);
|
|
3320
3712
|
const orphanPid = previousState?.headroomPid;
|
|
3321
|
-
|
|
3713
|
+
const orphanSocket = previousState?.socketPath ?? (previousState?.supervisorPid === void 0 ? void 0 : headroomSocketPath(paths, previousState.supervisorPid));
|
|
3714
|
+
const orphanIdentity = orphanPid === void 0 || orphanSocket === void 0 || !ports.isRunning(orphanPid) ? void 0 : daemonIdentity(ports.daemonCommandLine(orphanPid), orphanSocket);
|
|
3715
|
+
if (orphanPid !== void 0 && (orphanIdentity === "not-headroom" || orphanIdentity === "unreadable")) {
|
|
3716
|
+
ports.log(`agent-shim headroom supervisor: leaving pid ${String(orphanPid)} alone: the state records it as the previous daemon, but it ${orphanIdentity === "unreadable" ? "cannot be identified" : "is no longer a headroom proxy on that generation's socket"}`);
|
|
3717
|
+
}
|
|
3718
|
+
if (orphanPid !== void 0 && (orphanIdentity === "this-release" || orphanIdentity === "earlier-release")) {
|
|
3322
3719
|
ports.log(`agent-shim headroom supervisor: stopping daemon pid ${String(orphanPid)} left behind by the previous supervisor`);
|
|
3323
3720
|
ports.stopProcess(orphanPid);
|
|
3324
3721
|
}
|
|
@@ -3326,9 +3723,19 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3326
3723
|
let runningHash;
|
|
3327
3724
|
let runningSettingsHash;
|
|
3328
3725
|
let consecutiveFailures = 0;
|
|
3726
|
+
let lastExitOutput;
|
|
3329
3727
|
let idleSince;
|
|
3330
3728
|
let superseded = false;
|
|
3331
3729
|
let ticks = 0;
|
|
3730
|
+
const servingState = (pid) => ({
|
|
3731
|
+
supervisorPid: ports.ownPid,
|
|
3732
|
+
headroomPid: pid,
|
|
3733
|
+
socketPath,
|
|
3734
|
+
version,
|
|
3735
|
+
allowlistHash: runningHash,
|
|
3736
|
+
settingsHash: runningSettingsHash,
|
|
3737
|
+
installedSource
|
|
3738
|
+
});
|
|
3332
3739
|
for (; ; ) {
|
|
3333
3740
|
if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
|
|
3334
3741
|
return HEADROOM_SUPERVISOR_STILL_RUNNING;
|
|
@@ -3336,7 +3743,10 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3336
3743
|
ticks += 1;
|
|
3337
3744
|
config = ports.readConfig();
|
|
3338
3745
|
const settingsHash = hashSettings(config.settings);
|
|
3339
|
-
const
|
|
3746
|
+
const inputs = currentHeadroomAllowlistInputs(fs12, paths, ports.frontDoorLiveness);
|
|
3747
|
+
pruneDeadFrontDoorDirectRecords(fs12, paths.frontdoorDirectRecordsDir, inputs.frontDoorRecords, inputs.frontDoorLiveness);
|
|
3748
|
+
pruneMalformedFrontDoorDirectFiles(fs12, paths.frontdoorDirectRecordsDir, ports.isRunning);
|
|
3749
|
+
const allowlist = inputs.frontDoorOrigins;
|
|
3340
3750
|
const allowlistHash = hashAllowlist(allowlist);
|
|
3341
3751
|
pruneDeadSessions(fs12, paths.headroomSessionsDir, ports.isRunning);
|
|
3342
3752
|
const ownsNow = ownsState();
|
|
@@ -3344,6 +3754,13 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3344
3754
|
ports.log("agent-shim headroom supervisor: another supervisor now owns the state file; serving this daemon's own sessions until they end");
|
|
3345
3755
|
}
|
|
3346
3756
|
superseded = !ownsNow;
|
|
3757
|
+
const allowlistFailure = ownsNow ? syncAllowlistFile(allowlist) ?? allowlistFileRefusal(allowlist) : void 0;
|
|
3758
|
+
if (allowlistFailure !== void 0) {
|
|
3759
|
+
if (headroomPid !== void 0 && ports.isRunning(headroomPid)) {
|
|
3760
|
+
ports.stopProcess(headroomPid);
|
|
3761
|
+
}
|
|
3762
|
+
return fail(allowlistFailure);
|
|
3763
|
+
}
|
|
3347
3764
|
const crashed = headroomPid !== void 0 && !ports.isRunning(headroomPid);
|
|
3348
3765
|
if (headroomPid === void 0 || crashed) {
|
|
3349
3766
|
if (crashed) {
|
|
@@ -3358,43 +3775,53 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3358
3775
|
});
|
|
3359
3776
|
}
|
|
3360
3777
|
if (consecutiveFailures >= HEADROOM_START_RETRY_BUDGET) {
|
|
3361
|
-
return fail(
|
|
3778
|
+
return fail(
|
|
3779
|
+
`headroom failed to become ready ${String(consecutiveFailures)} times in a row; giving up` + (lastExitOutput === void 0 ? "" : `; the last attempt exited before it was ready, and its log ends: ${lastExitOutput}`)
|
|
3780
|
+
);
|
|
3362
3781
|
}
|
|
3363
3782
|
if (installedSource !== config.source && !ensureInstalled()) {
|
|
3364
3783
|
return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
|
|
3365
3784
|
}
|
|
3366
|
-
const
|
|
3367
|
-
const
|
|
3368
|
-
|
|
3785
|
+
const logOffset = ports.daemonLogSize();
|
|
3786
|
+
const pid = ports.spawnHeadroom(socketPath, paths.headroomAllowlistFile, config.settings);
|
|
3787
|
+
writeOwnState({ supervisorPid: ports.ownPid, headroomPid: pid, version, installedSource });
|
|
3788
|
+
const outcome = await waitUntilReady(ports, socketPath, pid);
|
|
3789
|
+
if (outcome === "ready") {
|
|
3369
3790
|
consecutiveFailures = 0;
|
|
3791
|
+
lastExitOutput = void 0;
|
|
3370
3792
|
headroomPid = pid;
|
|
3371
3793
|
runningHash = allowlistHash;
|
|
3372
3794
|
runningSettingsHash = settingsHash;
|
|
3373
|
-
const recorded = writeOwnState(
|
|
3374
|
-
supervisorPid: ports.ownPid,
|
|
3375
|
-
headroomPid: pid,
|
|
3376
|
-
socketPath,
|
|
3377
|
-
version,
|
|
3378
|
-
allowlistHash,
|
|
3379
|
-
settingsHash,
|
|
3380
|
-
installedSource: config.source
|
|
3381
|
-
});
|
|
3795
|
+
const recorded = writeOwnState(servingState(pid));
|
|
3382
3796
|
if (recorded) {
|
|
3383
3797
|
fs12.removeRecursive(paths.headroomLockFile);
|
|
3384
3798
|
}
|
|
3385
3799
|
idleSince = void 0;
|
|
3386
3800
|
ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on unix socket ${socketPath}`);
|
|
3387
3801
|
} else {
|
|
3388
|
-
ports.stopProcess(pid);
|
|
3389
3802
|
consecutiveFailures += 1;
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3803
|
+
if (outcome === "exited") {
|
|
3804
|
+
lastExitOutput = lastLines(ports.readDaemonLogTail(logOffset, DAEMON_LOG_TAIL_BYTES));
|
|
3805
|
+
ports.log(
|
|
3806
|
+
`agent-shim headroom supervisor: headroom exited before it was ready on unix socket ${socketPath} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
|
|
3807
|
+
);
|
|
3808
|
+
} else {
|
|
3809
|
+
lastExitOutput = void 0;
|
|
3810
|
+
ports.stopProcess(pid);
|
|
3811
|
+
ports.log(
|
|
3812
|
+
`agent-shim headroom supervisor: headroom did not become ready on unix socket ${socketPath} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
|
|
3813
|
+
);
|
|
3814
|
+
}
|
|
3393
3815
|
await ports.sleep(backoffForAttempt(consecutiveFailures));
|
|
3394
3816
|
continue;
|
|
3395
3817
|
}
|
|
3396
3818
|
} else {
|
|
3397
|
-
if (runningHash !== allowlistHash
|
|
3819
|
+
if (runningHash !== allowlistHash) {
|
|
3820
|
+
runningHash = allowlistHash;
|
|
3821
|
+
writeOwnState(servingState(headroomPid));
|
|
3822
|
+
ports.log(`agent-shim headroom supervisor: headroom pid ${String(headroomPid)} now serves allowlist [${allowlist.join(", ")}]`);
|
|
3823
|
+
}
|
|
3824
|
+
if (runningSettingsHash !== settingsHash || installedSource !== config.source) {
|
|
3398
3825
|
if (sessionsForSupervisor(fs12, paths.headroomSessionsDir, ports.ownPid).length === 0) {
|
|
3399
3826
|
ports.log("agent-shim headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
|
|
3400
3827
|
ports.stopProcess(headroomPid);
|
|
@@ -3423,45 +3850,66 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3423
3850
|
await ports.sleep(HEADROOM_POLL_MS);
|
|
3424
3851
|
}
|
|
3425
3852
|
}
|
|
3426
|
-
function
|
|
3853
|
+
function undeterminedFrontDoors(inputs) {
|
|
3854
|
+
return inputs.frontDoorRecords.flatMap((record) => {
|
|
3855
|
+
const reason = inputs.frontDoorLiveness.unknown.get(record.pid);
|
|
3856
|
+
return reason === void 0 ? [] : [{ pid: record.pid, origin: directOrigin(record.directPort), reason }];
|
|
3857
|
+
});
|
|
3858
|
+
}
|
|
3859
|
+
function currentHeadroomAllowlistInputs(fs12, paths, frontDoorLiveness) {
|
|
3860
|
+
const named = frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile));
|
|
3861
|
+
const records = listFrontDoorDirectRecords(fs12, paths.frontdoorDirectRecordsDir);
|
|
3862
|
+
const liveness = frontDoorLiveness(records.map((record) => record.pid));
|
|
3863
|
+
const live = liveFrontDoorDirectRecords(records, liveness).map((record) => directOrigin(record.directPort));
|
|
3427
3864
|
return {
|
|
3428
|
-
|
|
3429
|
-
|
|
3865
|
+
frontDoorRecords: records,
|
|
3866
|
+
frontDoorLiveness: liveness,
|
|
3867
|
+
frontDoorOrigins: [.../* @__PURE__ */ new Set([...named === void 0 ? [] : [named], ...live])].sort()
|
|
3430
3868
|
};
|
|
3431
3869
|
}
|
|
3432
|
-
function
|
|
3433
|
-
const
|
|
3434
|
-
return
|
|
3435
|
-
}
|
|
3436
|
-
function allowlistOf(ports) {
|
|
3437
|
-
return currentHeadroomAllowlist(ports.fs, ports.paths);
|
|
3870
|
+
function launchRequiredUpstreams(fs12, paths) {
|
|
3871
|
+
const door = frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile));
|
|
3872
|
+
return door === void 0 ? [] : [door];
|
|
3438
3873
|
}
|
|
3439
|
-
async function waitUntilReady(ports, socketPath) {
|
|
3874
|
+
async function waitUntilReady(ports, socketPath, pid) {
|
|
3440
3875
|
const deadline = ports.now() + HEADROOM_READY_TIMEOUT_MS;
|
|
3441
3876
|
for (; ; ) {
|
|
3442
3877
|
if (await ports.ready(socketPath)) {
|
|
3443
|
-
return
|
|
3878
|
+
return "ready";
|
|
3879
|
+
}
|
|
3880
|
+
if (!ports.isRunning(pid)) {
|
|
3881
|
+
return "exited";
|
|
3444
3882
|
}
|
|
3445
3883
|
if (ports.now() >= deadline) {
|
|
3446
|
-
return
|
|
3884
|
+
return "timed-out";
|
|
3447
3885
|
}
|
|
3448
3886
|
await ports.sleep(HEADROOM_POLL_MS);
|
|
3449
3887
|
}
|
|
3450
3888
|
}
|
|
3451
|
-
|
|
3889
|
+
function lastLines(output) {
|
|
3890
|
+
const lines = redactText(output).split("\n").map((line) => line.trim()).filter((line) => line !== "").map((line) => line.length > DAEMON_EXIT_LOG_LINE_CHARS ? `${line.slice(0, DAEMON_EXIT_LOG_LINE_CHARS)}...` : line);
|
|
3891
|
+
return lines.length === 0 ? "(the daemon wrote nothing)" : lines.slice(-DAEMON_EXIT_LOG_LINES).join(" | ");
|
|
3892
|
+
}
|
|
3893
|
+
var import_node_path13, HEADROOM_BACKOFF_BASE_MS, HEADROOM_BACKOFF_CAP_MS, HEADROOM_START_RETRY_BUDGET, HEADROOM_READY_TIMEOUT_MS, DAEMON_EXIT_LOG_LINES, DAEMON_EXIT_LOG_LINE_CHARS, DAEMON_LOG_TAIL_BYTES, HEADROOM_POLL_MS, MS_PER_MINUTE2, HEADROOM_SUPERVISOR_STILL_RUNNING;
|
|
3452
3894
|
var init_supervisor = __esm({
|
|
3453
3895
|
"src/headroom/supervisor.ts"() {
|
|
3454
3896
|
"use strict";
|
|
3897
|
+
import_node_path13 = __toESM(require("node:path"), 1);
|
|
3455
3898
|
init_schema();
|
|
3456
3899
|
init_state();
|
|
3457
3900
|
init_settings();
|
|
3901
|
+
init_capture();
|
|
3458
3902
|
init_socket();
|
|
3903
|
+
init_earlierRelease();
|
|
3459
3904
|
init_source();
|
|
3460
3905
|
init_state2();
|
|
3461
3906
|
HEADROOM_BACKOFF_BASE_MS = 500;
|
|
3462
3907
|
HEADROOM_BACKOFF_CAP_MS = 3e4;
|
|
3463
3908
|
HEADROOM_START_RETRY_BUDGET = 5;
|
|
3464
3909
|
HEADROOM_READY_TIMEOUT_MS = 15e3;
|
|
3910
|
+
DAEMON_EXIT_LOG_LINES = 6;
|
|
3911
|
+
DAEMON_EXIT_LOG_LINE_CHARS = 400;
|
|
3912
|
+
DAEMON_LOG_TAIL_BYTES = 8192;
|
|
3465
3913
|
HEADROOM_POLL_MS = 1e3;
|
|
3466
3914
|
MS_PER_MINUTE2 = 6e4;
|
|
3467
3915
|
HEADROOM_SUPERVISOR_STILL_RUNNING = -1;
|
|
@@ -3497,8 +3945,18 @@ function realIsFrontDoorSupervisor(pid) {
|
|
|
3497
3945
|
const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "pid=,command=", "-p", String(pid)], { encoding: "utf8" });
|
|
3498
3946
|
return result.status === 0 && parseFrontDoorSupervisorPids(result.stdout).includes(pid);
|
|
3499
3947
|
}
|
|
3948
|
+
function realProcessCommandLine(pid) {
|
|
3949
|
+
const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
|
|
3950
|
+
return result.status === 0 ? result.stdout.trim() : void 0;
|
|
3951
|
+
}
|
|
3952
|
+
function realFrontDoorLiveness(pids) {
|
|
3953
|
+
return frontDoorLivenessOf(pids, (asked) => {
|
|
3954
|
+
const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "pid=,stat=,command=", "-p", asked.map(String).join(",")], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
|
|
3955
|
+
return { status: result.status, stdout: result.stdout, stderr: result.stderr, ...result.error === void 0 ? {} : { error: result.error } };
|
|
3956
|
+
});
|
|
3957
|
+
}
|
|
3500
3958
|
function expandHome2(filePath) {
|
|
3501
|
-
return filePath.startsWith("~/") ?
|
|
3959
|
+
return filePath.startsWith("~/") ? import_node_path14.default.join(import_node_os2.default.homedir(), filePath.slice(1)) : filePath;
|
|
3502
3960
|
}
|
|
3503
3961
|
function hasDesktopSession() {
|
|
3504
3962
|
if (process.platform === "darwin") {
|
|
@@ -3542,7 +4000,7 @@ function spawnDaemonThroughScript(script) {
|
|
|
3542
4000
|
return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: process.execPath, args: [script, subcommand] }, paths, subcommand, logPath);
|
|
3543
4001
|
}
|
|
3544
4002
|
function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
|
|
3545
|
-
import_node_fs2.default.mkdirSync(
|
|
4003
|
+
import_node_fs2.default.mkdirSync(import_node_path14.default.dirname(logPath), { recursive: true });
|
|
3546
4004
|
const logFd = import_node_fs2.default.openSync(logPath, "a");
|
|
3547
4005
|
try {
|
|
3548
4006
|
const child = (0, import_node_child_process2.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
|
|
@@ -3564,13 +4022,14 @@ function realHeadroomPort(paths, options) {
|
|
|
3564
4022
|
const up = ensureHeadroom({
|
|
3565
4023
|
paths,
|
|
3566
4024
|
launcherPid: process.pid,
|
|
3567
|
-
...routesProvider ? {
|
|
4025
|
+
...routesProvider ? { requiredUpstreams: () => launchRequiredUpstreams(realFarmFs, paths) } : {},
|
|
3568
4026
|
ports: {
|
|
3569
4027
|
fs: realFarmFs,
|
|
3570
4028
|
// Zombie-aware on purpose: a supervisor that died while still a child of this launcher sits unreaped until the launcher itself exits, and a defunct supervisor answering signal 0 as alive would stretch every launch to the full start timeout.
|
|
3571
4029
|
isRunning: realIsProcessRunning,
|
|
3572
4030
|
now: () => Date.now(),
|
|
3573
4031
|
sleep: realSleepSync,
|
|
4032
|
+
daemonCommandLine: realProcessCommandLine,
|
|
3574
4033
|
spawnSupervisor: (layout) => spawnHeadroomSupervisor(layout, options.spawnDaemon)
|
|
3575
4034
|
}
|
|
3576
4035
|
});
|
|
@@ -3595,7 +4054,7 @@ function listVersionsDir(dir) {
|
|
|
3595
4054
|
throw error;
|
|
3596
4055
|
}
|
|
3597
4056
|
return entries.filter((entry) => entry.isFile()).map((entry) => {
|
|
3598
|
-
const fullPath =
|
|
4057
|
+
const fullPath = import_node_path14.default.join(dir, entry.name);
|
|
3599
4058
|
const stat = import_node_fs2.default.statSync(fullPath);
|
|
3600
4059
|
return {
|
|
3601
4060
|
name: entry.name,
|
|
@@ -3609,7 +4068,7 @@ function windowsPathExtensions(pathext) {
|
|
|
3609
4068
|
return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
|
|
3610
4069
|
}
|
|
3611
4070
|
function resolveExecutableCandidate(dir, name, env) {
|
|
3612
|
-
const candidate =
|
|
4071
|
+
const candidate = import_node_path14.default.join(dir, name);
|
|
3613
4072
|
if (env.platform === "win32") {
|
|
3614
4073
|
const extensions = windowsPathExtensions(env.pathext);
|
|
3615
4074
|
const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
|
|
@@ -3658,13 +4117,13 @@ function resolveOwnExecutablePath(env) {
|
|
|
3658
4117
|
if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
|
|
3659
4118
|
return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
|
|
3660
4119
|
}
|
|
3661
|
-
const candidate = env.argv1 === void 0 ? env.execPath :
|
|
3662
|
-
const candidateDir =
|
|
3663
|
-
const candidateDirOnPath = env.pathDirs.some((dir) =>
|
|
4120
|
+
const candidate = env.argv1 === void 0 ? env.execPath : import_node_path14.default.resolve(env.cwd, env.argv1);
|
|
4121
|
+
const candidateDir = import_node_path14.default.dirname(candidate);
|
|
4122
|
+
const candidateDirOnPath = env.pathDirs.some((dir) => import_node_path14.default.resolve(dir) === candidateDir);
|
|
3664
4123
|
if (candidateDirOnPath) {
|
|
3665
4124
|
return candidate;
|
|
3666
4125
|
}
|
|
3667
|
-
const viaPath = searchPathForExecutable(env.pathDirs,
|
|
4126
|
+
const viaPath = searchPathForExecutable(env.pathDirs, import_node_path14.default.basename(candidate), env.findExecutableInDir);
|
|
3668
4127
|
return viaPath ?? candidate;
|
|
3669
4128
|
}
|
|
3670
4129
|
function realOwnExecutablePath() {
|
|
@@ -3672,7 +4131,7 @@ function realOwnExecutablePath() {
|
|
|
3672
4131
|
argv1: process.argv[1],
|
|
3673
4132
|
execPath: process.execPath,
|
|
3674
4133
|
cwd: process.cwd(),
|
|
3675
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
4134
|
+
pathDirs: (process.env.PATH ?? "").split(import_node_path14.default.delimiter).filter((dir) => dir !== ""),
|
|
3676
4135
|
findExecutableInDir
|
|
3677
4136
|
});
|
|
3678
4137
|
}
|
|
@@ -3685,7 +4144,7 @@ function realContentSourcePath() {
|
|
|
3685
4144
|
function realResolveClaudeBinary(isOwnBinary) {
|
|
3686
4145
|
return (request4) => discoverClaudeBinary({
|
|
3687
4146
|
listVersionsDir,
|
|
3688
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
4147
|
+
pathDirs: (process.env.PATH ?? "").split(import_node_path14.default.delimiter).filter((dir) => dir !== ""),
|
|
3689
4148
|
findExecutableInDir,
|
|
3690
4149
|
isOwnBinary,
|
|
3691
4150
|
...request4?.version === void 0 ? {} : { version: request4.version }
|
|
@@ -3694,7 +4153,7 @@ function realResolveClaudeBinary(isOwnBinary) {
|
|
|
3694
4153
|
function realInstalledClaudeVersions() {
|
|
3695
4154
|
return installedVersions(listVersionsDir(defaultVersionsDir()));
|
|
3696
4155
|
}
|
|
3697
|
-
var import_node_child_process2, import_node_crypto8, import_node_fs2, import_node_os2,
|
|
4156
|
+
var import_node_child_process2, import_node_crypto8, import_node_fs2, import_node_os2, import_node_path14, import_node_sea, realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, realFarmFs, INT32_BYTE_LENGTH, PS_TIMEOUT_MS, realRunPort, MACOS_GUI_SESSION_MANAGER, realCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
|
|
3698
4157
|
var init_realPorts = __esm({
|
|
3699
4158
|
"src/realPorts.ts"() {
|
|
3700
4159
|
"use strict";
|
|
@@ -3702,7 +4161,7 @@ var init_realPorts = __esm({
|
|
|
3702
4161
|
import_node_crypto8 = require("node:crypto");
|
|
3703
4162
|
import_node_fs2 = __toESM(require("node:fs"), 1);
|
|
3704
4163
|
import_node_os2 = __toESM(require("node:os"), 1);
|
|
3705
|
-
|
|
4164
|
+
import_node_path14 = __toESM(require("node:path"), 1);
|
|
3706
4165
|
import_node_sea = require("node:sea");
|
|
3707
4166
|
init_load();
|
|
3708
4167
|
init_versionDiscovery();
|
|
@@ -3794,9 +4253,14 @@ var init_realPorts = __esm({
|
|
|
3794
4253
|
},
|
|
3795
4254
|
writeFilePrivate(filePath, contents) {
|
|
3796
4255
|
const temp = `${filePath}.${String(process.pid)}.tmp`;
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
4256
|
+
try {
|
|
4257
|
+
import_node_fs2.default.writeFileSync(temp, contents, { encoding: "utf8", mode: OWNER_ONLY_FILE_MODE });
|
|
4258
|
+
import_node_fs2.default.chmodSync(temp, OWNER_ONLY_FILE_MODE);
|
|
4259
|
+
import_node_fs2.default.renameSync(temp, filePath);
|
|
4260
|
+
} catch (error) {
|
|
4261
|
+
import_node_fs2.default.rmSync(temp, { force: true });
|
|
4262
|
+
throw error;
|
|
4263
|
+
}
|
|
3800
4264
|
},
|
|
3801
4265
|
appendFilePrivate(filePath, contents) {
|
|
3802
4266
|
const descriptor = import_node_fs2.default.openSync(filePath, "a", OWNER_ONLY_FILE_MODE);
|
|
@@ -3836,6 +4300,7 @@ var init_realPorts = __esm({
|
|
|
3836
4300
|
}
|
|
3837
4301
|
};
|
|
3838
4302
|
INT32_BYTE_LENGTH = 4;
|
|
4303
|
+
PS_TIMEOUT_MS = 2e3;
|
|
3839
4304
|
realRunPort = {
|
|
3840
4305
|
run(command, args) {
|
|
3841
4306
|
const result = (0, import_node_child_process2.spawnSync)(command, [...args], { encoding: "utf8" });
|
|
@@ -3874,7 +4339,7 @@ var init_realPorts = __esm({
|
|
|
3874
4339
|
},
|
|
3875
4340
|
personPresent: () => process.stdin.isTTY || hasDesktopSession()
|
|
3876
4341
|
};
|
|
3877
|
-
SOCKET_PERMISSION_BITS =
|
|
4342
|
+
SOCKET_PERMISSION_BITS = 4095;
|
|
3878
4343
|
realHeadroomSocketTrust = {
|
|
3879
4344
|
platform: process.platform,
|
|
3880
4345
|
currentUid: () => {
|
|
@@ -3893,9 +4358,10 @@ var init_realPorts = __esm({
|
|
|
3893
4358
|
}
|
|
3894
4359
|
throw error;
|
|
3895
4360
|
}
|
|
3896
|
-
const kind = stat.isSymbolicLink() ? "symlink" : stat.isDirectory() ? "dir" : stat.isSocket() ? "socket" : "other";
|
|
4361
|
+
const kind = stat.isSymbolicLink() ? "symlink" : stat.isDirectory() ? "dir" : stat.isFile() ? "file" : stat.isSocket() ? "socket" : "other";
|
|
3897
4362
|
return { kind, uid: stat.uid, mode: stat.mode & SOCKET_PERMISSION_BITS };
|
|
3898
|
-
}
|
|
4363
|
+
},
|
|
4364
|
+
readlink: (target) => import_node_fs2.default.readlinkSync(target, "utf8")
|
|
3899
4365
|
};
|
|
3900
4366
|
realSpawnPort = {
|
|
3901
4367
|
spawnSync(command, args, options) {
|
|
@@ -3919,18 +4385,18 @@ function expandTilde(value, home) {
|
|
|
3919
4385
|
return home;
|
|
3920
4386
|
}
|
|
3921
4387
|
if (value.startsWith("~/")) {
|
|
3922
|
-
return
|
|
4388
|
+
return import_node_path15.default.join(home, value.slice(2));
|
|
3923
4389
|
}
|
|
3924
4390
|
return value;
|
|
3925
4391
|
}
|
|
3926
4392
|
function normaliseRulePath(rulePath, home) {
|
|
3927
|
-
return
|
|
4393
|
+
return import_node_path15.default.resolve(expandTilde(rulePath, home));
|
|
3928
4394
|
}
|
|
3929
|
-
var
|
|
4395
|
+
var import_node_path15;
|
|
3930
4396
|
var init_pathNorm = __esm({
|
|
3931
4397
|
"src/pathNorm.ts"() {
|
|
3932
4398
|
"use strict";
|
|
3933
|
-
|
|
4399
|
+
import_node_path15 = __toESM(require("node:path"), 1);
|
|
3934
4400
|
}
|
|
3935
4401
|
});
|
|
3936
4402
|
|
|
@@ -3939,7 +4405,7 @@ function loadCascadeInput(params) {
|
|
|
3939
4405
|
const globalConfig = loadConfigFile(params.paths.globalConfigFile, GlobalConfigSchema, params.read);
|
|
3940
4406
|
const directoryRules = loadConfigFile(params.paths.directoryRulesFile, DirectoryRulesSchema, params.read);
|
|
3941
4407
|
const loadProfile = (name) => {
|
|
3942
|
-
const filepath =
|
|
4408
|
+
const filepath = import_node_path16.default.join(params.paths.configProfilesDir, `${name}.json`);
|
|
3943
4409
|
const loaded = loadConfigFile(filepath, ConfigProfileSchema, params.read);
|
|
3944
4410
|
if (loaded === void 0) {
|
|
3945
4411
|
return void 0;
|
|
@@ -3954,8 +4420,8 @@ function loadCascadeInput(params) {
|
|
|
3954
4420
|
});
|
|
3955
4421
|
const levels = [];
|
|
3956
4422
|
for (const dir of dirs) {
|
|
3957
|
-
const portable = loadConfigFile(
|
|
3958
|
-
const portableLocal = loadConfigFile(
|
|
4423
|
+
const portable = loadConfigFile(import_node_path16.default.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path16.default.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
4424
|
+
const portableLocal = loadConfigFile(import_node_path16.default.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path16.default.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
3959
4425
|
const rules = (directoryRules?.config.rules ?? []).map((rule, index) => ({ rule, index })).filter(({ rule }) => normaliseRulePath(rule.path, params.home) === dir).map(({ rule, index }) => {
|
|
3960
4426
|
const entryOrder = directoryRules?.ruleEntryOrders[index];
|
|
3961
4427
|
return {
|
|
@@ -4002,11 +4468,11 @@ function readDirectorySelections(loaded) {
|
|
|
4002
4468
|
}
|
|
4003
4469
|
return { ...identity === void 0 ? {} : { identity }, ...configProfile === void 0 ? {} : { configProfile } };
|
|
4004
4470
|
}
|
|
4005
|
-
var
|
|
4471
|
+
var import_node_path16, PORTABLE_CONFIG_FILENAME, PORTABLE_LOCAL_CONFIG_FILENAME;
|
|
4006
4472
|
var init_cascade = __esm({
|
|
4007
4473
|
"src/launcher/cascade.ts"() {
|
|
4008
4474
|
"use strict";
|
|
4009
|
-
|
|
4475
|
+
import_node_path16 = __toESM(require("node:path"), 1);
|
|
4010
4476
|
init_load();
|
|
4011
4477
|
init_schema();
|
|
4012
4478
|
init_pathNorm();
|
|
@@ -4070,13 +4536,13 @@ function decideConfigProfile(params) {
|
|
|
4070
4536
|
return { source: "none" };
|
|
4071
4537
|
}
|
|
4072
4538
|
function loadIdentity(identitiesDir, name, fs12) {
|
|
4073
|
-
return loadConfigFile(
|
|
4539
|
+
return loadConfigFile(import_node_path17.default.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
|
|
4074
4540
|
}
|
|
4075
|
-
var
|
|
4541
|
+
var import_node_path17, IDENTITY_DECISION_SOURCES, CONFIG_PROFILE_DECISION_SOURCES;
|
|
4076
4542
|
var init_identity = __esm({
|
|
4077
4543
|
"src/launcher/identity.ts"() {
|
|
4078
4544
|
"use strict";
|
|
4079
|
-
|
|
4545
|
+
import_node_path17 = __toESM(require("node:path"), 1);
|
|
4080
4546
|
init_load();
|
|
4081
4547
|
init_schema();
|
|
4082
4548
|
IDENTITY_DECISION_SOURCES = [
|
|
@@ -4298,7 +4764,7 @@ function isIdentityName(name) {
|
|
|
4298
4764
|
return IdentitySchema.shape.name.safeParse(name).success;
|
|
4299
4765
|
}
|
|
4300
4766
|
function claudeJsonPath(identitiesDir, identity) {
|
|
4301
|
-
return
|
|
4767
|
+
return import_node_path18.default.join(identitiesDir, identity, CLAUDE_JSON);
|
|
4302
4768
|
}
|
|
4303
4769
|
function readAccountMetadata(fs12, identitiesDir, identity) {
|
|
4304
4770
|
if (!isIdentityName(identity)) {
|
|
@@ -4352,11 +4818,11 @@ function createAccountReader(fs12, identitiesDir) {
|
|
|
4352
4818
|
return account;
|
|
4353
4819
|
};
|
|
4354
4820
|
}
|
|
4355
|
-
var
|
|
4821
|
+
var import_node_path18, CLAUDE_JSON, AccountMetadataError;
|
|
4356
4822
|
var init_account = __esm({
|
|
4357
4823
|
"src/usage/account.ts"() {
|
|
4358
4824
|
"use strict";
|
|
4359
|
-
|
|
4825
|
+
import_node_path18 = __toESM(require("node:path"), 1);
|
|
4360
4826
|
init_cliError();
|
|
4361
4827
|
init_schema();
|
|
4362
4828
|
init_schema2();
|
|
@@ -4915,7 +5381,7 @@ function readUsageLog(fs12, logDir, options = {}) {
|
|
|
4915
5381
|
if (sinceMs !== void 0 && segment.endsAt <= sinceMs) {
|
|
4916
5382
|
continue;
|
|
4917
5383
|
}
|
|
4918
|
-
const contents = fs12.readFileUtf8(
|
|
5384
|
+
const contents = fs12.readFileUtf8(import_node_path19.default.join(logDir, segment.name));
|
|
4919
5385
|
if (contents === void 0) {
|
|
4920
5386
|
continue;
|
|
4921
5387
|
}
|
|
@@ -4949,7 +5415,7 @@ function snapshotPath(snapshotsDir, identity) {
|
|
|
4949
5415
|
if (!isIdentityName(identity)) {
|
|
4950
5416
|
throw new Error(`"${identity}" is not a valid identity name.`);
|
|
4951
5417
|
}
|
|
4952
|
-
return
|
|
5418
|
+
return import_node_path19.default.join(snapshotsDir, `${identity}.json`);
|
|
4953
5419
|
}
|
|
4954
5420
|
function readUsageSnapshot(fs12, snapshotsDir, identity) {
|
|
4955
5421
|
const file = snapshotPath(snapshotsDir, identity);
|
|
@@ -4982,11 +5448,11 @@ function listUsageSnapshots(fs12, snapshotsDir) {
|
|
|
4982
5448
|
return snapshot === void 0 ? [] : [snapshot];
|
|
4983
5449
|
}).sort((left, right) => left.identity.localeCompare(right.identity));
|
|
4984
5450
|
}
|
|
4985
|
-
var
|
|
5451
|
+
var import_node_path19, SEGMENT_RE, DAY_MS, UsageSnapshotError;
|
|
4986
5452
|
var init_read = __esm({
|
|
4987
5453
|
"src/usage/read.ts"() {
|
|
4988
5454
|
"use strict";
|
|
4989
|
-
|
|
5455
|
+
import_node_path19 = __toESM(require("node:path"), 1);
|
|
4990
5456
|
init_account();
|
|
4991
5457
|
init_schema2();
|
|
4992
5458
|
SEGMENT_RE = /^(\d{4}-\d{2}-\d{2})\.(\d+)\.jsonl$/;
|
|
@@ -5007,7 +5473,7 @@ function pruneUsageLog(fs12, logDir, nowMs) {
|
|
|
5007
5473
|
const cutoff = nowMs - USAGE_RETENTION_MS;
|
|
5008
5474
|
for (const segment of listLogSegments(fs12, logDir)) {
|
|
5009
5475
|
if (segment.endsAt <= cutoff) {
|
|
5010
|
-
fs12.removeRecursive(
|
|
5476
|
+
fs12.removeRecursive(import_node_path20.default.join(logDir, segment.name));
|
|
5011
5477
|
}
|
|
5012
5478
|
}
|
|
5013
5479
|
}
|
|
@@ -5089,7 +5555,7 @@ function createUsageStore(deps) {
|
|
|
5089
5555
|
pruneUsageLog(fs12, paths.usageLogDir, nowMs);
|
|
5090
5556
|
prunedDay = day;
|
|
5091
5557
|
}
|
|
5092
|
-
fs12.appendFilePrivate(
|
|
5558
|
+
fs12.appendFilePrivate(import_node_path20.default.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record)}
|
|
5093
5559
|
`);
|
|
5094
5560
|
if (record.identity !== void 0) {
|
|
5095
5561
|
rewriteSnapshot(record.identity, (current) => ({ ...current?.providers, [record.provider]: foldProviderState(current?.providers[record.provider], record) }));
|
|
@@ -5112,11 +5578,11 @@ function createUsageStore(deps) {
|
|
|
5112
5578
|
})
|
|
5113
5579
|
};
|
|
5114
5580
|
}
|
|
5115
|
-
var
|
|
5581
|
+
var import_node_path20, DAY_MS2, DAYS_IN_WEEK, USAGE_RETENTION_MS;
|
|
5116
5582
|
var init_store2 = __esm({
|
|
5117
5583
|
"src/usage/store.ts"() {
|
|
5118
5584
|
"use strict";
|
|
5119
|
-
|
|
5585
|
+
import_node_path20 = __toESM(require("node:path"), 1);
|
|
5120
5586
|
init_account();
|
|
5121
5587
|
init_rateLimit();
|
|
5122
5588
|
init_read();
|
|
@@ -5254,15 +5720,15 @@ function recordStickyPick(fs12, picksFile, directory, identity, nowMs) {
|
|
|
5254
5720
|
const current = readPicksFile(fs12, picksFile).file.picks;
|
|
5255
5721
|
const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
|
|
5256
5722
|
const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
|
|
5257
|
-
fs12.mkdirPrivate(
|
|
5723
|
+
fs12.mkdirPrivate(import_node_path21.default.dirname(picksFile));
|
|
5258
5724
|
fs12.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
|
|
5259
5725
|
`);
|
|
5260
5726
|
}
|
|
5261
|
-
var
|
|
5727
|
+
var import_node_path21, import_zod13, PoolGraphError, SCHEMA_VERSION, PickEntrySchema, PicksFileSchema;
|
|
5262
5728
|
var init_poolPick = __esm({
|
|
5263
5729
|
"src/usage/poolPick.ts"() {
|
|
5264
5730
|
"use strict";
|
|
5265
|
-
|
|
5731
|
+
import_node_path21 = __toESM(require("node:path"), 1);
|
|
5266
5732
|
import_zod13 = require("zod");
|
|
5267
5733
|
init_cliError();
|
|
5268
5734
|
init_identity();
|
|
@@ -5293,8 +5759,8 @@ function resolveAgentShimHome(env = process.env, home = import_node_os4.default.
|
|
|
5293
5759
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
5294
5760
|
return fromEnv;
|
|
5295
5761
|
}
|
|
5296
|
-
const current =
|
|
5297
|
-
const legacy =
|
|
5762
|
+
const current = import_node_path23.default.join(home, HOME_DIRNAME);
|
|
5763
|
+
const legacy = import_node_path23.default.join(home, LEGACY_HOME_DIRNAME);
|
|
5298
5764
|
return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
|
|
5299
5765
|
}
|
|
5300
5766
|
function isExistingDirectory(candidate) {
|
|
@@ -5305,59 +5771,61 @@ function resolveClaudeHome() {
|
|
|
5305
5771
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
5306
5772
|
return fromEnv;
|
|
5307
5773
|
}
|
|
5308
|
-
return
|
|
5774
|
+
return import_node_path23.default.join(import_node_os4.default.homedir(), ".claude");
|
|
5309
5775
|
}
|
|
5310
5776
|
function buildLayoutPaths(root) {
|
|
5311
5777
|
return {
|
|
5312
5778
|
root,
|
|
5313
|
-
identitiesDir:
|
|
5314
|
-
configProfilesDir:
|
|
5315
|
-
providersDir:
|
|
5316
|
-
directoryRulesFile:
|
|
5317
|
-
activeIdentityFile:
|
|
5318
|
-
globalConfigFile:
|
|
5319
|
-
categoriesLocalFile:
|
|
5320
|
-
claudeShimFile:
|
|
5321
|
-
headroomDir:
|
|
5322
|
-
headroomStateFile:
|
|
5323
|
-
headroomLegacyStateFile:
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5779
|
+
identitiesDir: import_node_path23.default.join(root, "identities"),
|
|
5780
|
+
configProfilesDir: import_node_path23.default.join(root, "config-profiles"),
|
|
5781
|
+
providersDir: import_node_path23.default.join(root, "providers"),
|
|
5782
|
+
directoryRulesFile: import_node_path23.default.join(root, "directory-rules.json"),
|
|
5783
|
+
activeIdentityFile: import_node_path23.default.join(root, "active-identity"),
|
|
5784
|
+
globalConfigFile: import_node_path23.default.join(root, "config.json"),
|
|
5785
|
+
categoriesLocalFile: import_node_path23.default.join(root, "categories.local.json"),
|
|
5786
|
+
claudeShimFile: import_node_path23.default.join(root, "claude-shim.json"),
|
|
5787
|
+
headroomDir: import_node_path23.default.join(root, "headroom"),
|
|
5788
|
+
headroomStateFile: import_node_path23.default.join(root, "headroom", "state.json"),
|
|
5789
|
+
headroomLegacyStateFile: import_node_path23.default.join(root, "headroom", "state.v2.json"),
|
|
5790
|
+
headroomAllowlistFile: import_node_path23.default.join(root, "headroom", "run", "allowlist.txt"),
|
|
5791
|
+
headroomSocketDir: import_node_path23.default.join(root, "headroom", "run"),
|
|
5792
|
+
headroomLockFile: import_node_path23.default.join(root, "headroom", "start.lock"),
|
|
5793
|
+
headroomSessionsDir: import_node_path23.default.join(root, "headroom", "sessions"),
|
|
5794
|
+
logsDir: import_node_path23.default.join(root, "logs"),
|
|
5795
|
+
headroomLogPath: import_node_path23.default.join(root, "logs", "headroom.log"),
|
|
5796
|
+
frontdoorDir: import_node_path23.default.join(root, "frontdoor"),
|
|
5797
|
+
frontdoorCaDir: import_node_path23.default.join(root, "frontdoor", "ca"),
|
|
5798
|
+
frontdoorCaCertFile: import_node_path23.default.join(root, "frontdoor", "ca", "ca.pem"),
|
|
5799
|
+
frontdoorCaKeyFile: import_node_path23.default.join(root, "frontdoor", "ca", "ca.key"),
|
|
5800
|
+
frontdoorCaBundlesDir: import_node_path23.default.join(root, "frontdoor", "ca", "bundles"),
|
|
5801
|
+
chatgptSignInFile: import_node_path23.default.join(root, "codex", "chatgpt-sign-in.json"),
|
|
5802
|
+
frontdoorStateFile: import_node_path23.default.join(root, "frontdoor", "state.json"),
|
|
5803
|
+
frontdoorLockFile: import_node_path23.default.join(root, "frontdoor", "start.lock"),
|
|
5804
|
+
frontdoorControlTokenFile: import_node_path23.default.join(root, "frontdoor", "control-token"),
|
|
5805
|
+
frontdoorSessionsDir: import_node_path23.default.join(root, "frontdoor", "sessions"),
|
|
5806
|
+
frontdoorDirectRecordsDir: import_node_path23.default.join(root, "frontdoor", "direct"),
|
|
5807
|
+
frontdoorRcCredentialsDir: import_node_path23.default.join(root, "frontdoor", "rc-credentials"),
|
|
5808
|
+
frontdoorLogPath: import_node_path23.default.join(root, "logs", "frontdoor.log"),
|
|
5809
|
+
usageDir: import_node_path23.default.join(root, "usage"),
|
|
5810
|
+
usageLogDir: import_node_path23.default.join(root, "usage", "log"),
|
|
5811
|
+
usageSnapshotsDir: import_node_path23.default.join(root, "usage", "snapshots"),
|
|
5812
|
+
usagePicksFile: import_node_path23.default.join(root, "usage", "picks.json"),
|
|
5813
|
+
usageAnchorsFile: import_node_path23.default.join(root, "usage", "anchors.json"),
|
|
5814
|
+
usageJobsFile: import_node_path23.default.join(root, "usage", "jobs.json"),
|
|
5815
|
+
jobLogsDir: import_node_path23.default.join(root, "logs", "jobs"),
|
|
5816
|
+
mcpPermissionsFile: import_node_path23.default.join(root, "mcp", "permissions.json")
|
|
5349
5817
|
};
|
|
5350
5818
|
}
|
|
5351
5819
|
function resolveLayoutPaths() {
|
|
5352
5820
|
return buildLayoutPaths(resolveAgentShimHome());
|
|
5353
5821
|
}
|
|
5354
|
-
var import_node_fs4, import_node_os4,
|
|
5822
|
+
var import_node_fs4, import_node_os4, import_node_path23;
|
|
5355
5823
|
var init_paths = __esm({
|
|
5356
5824
|
"src/paths.ts"() {
|
|
5357
5825
|
"use strict";
|
|
5358
5826
|
import_node_fs4 = __toESM(require("node:fs"), 1);
|
|
5359
5827
|
import_node_os4 = __toESM(require("node:os"), 1);
|
|
5360
|
-
|
|
5828
|
+
import_node_path23 = __toESM(require("node:path"), 1);
|
|
5361
5829
|
init_legacy();
|
|
5362
5830
|
}
|
|
5363
5831
|
});
|
|
@@ -5462,8 +5930,8 @@ function security(args, stdin) {
|
|
|
5462
5930
|
return { status: result.status, stdout: result.stdout };
|
|
5463
5931
|
}
|
|
5464
5932
|
function createRealCredentialCache(root) {
|
|
5465
|
-
const dir =
|
|
5466
|
-
const filePath = (owner) =>
|
|
5933
|
+
const dir = import_node_path24.default.join(root, "credential-cache");
|
|
5934
|
+
const filePath = (owner) => import_node_path24.default.join(dir, cacheFileNameFor(owner));
|
|
5467
5935
|
return {
|
|
5468
5936
|
read(store, owner) {
|
|
5469
5937
|
if (store === "file") {
|
|
@@ -5509,13 +5977,13 @@ function createRealCredentialCache(root) {
|
|
|
5509
5977
|
function realCredentialCacheEnv(paths) {
|
|
5510
5978
|
return { port: createRealCredentialCache(paths.root), platform: process.platform, now: () => Date.now() };
|
|
5511
5979
|
}
|
|
5512
|
-
var import_node_child_process3, import_node_fs5,
|
|
5980
|
+
var import_node_child_process3, import_node_fs5, import_node_path24, KEYCHAIN_CACHE_SERVICE, CACHE_DIR_MODE, CACHE_FILE_MODE;
|
|
5513
5981
|
var init_realCredentialCache = __esm({
|
|
5514
5982
|
"src/realCredentialCache.ts"() {
|
|
5515
5983
|
"use strict";
|
|
5516
5984
|
import_node_child_process3 = require("node:child_process");
|
|
5517
5985
|
import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
5518
|
-
|
|
5986
|
+
import_node_path24 = __toESM(require("node:path"), 1);
|
|
5519
5987
|
init_credentialCache();
|
|
5520
5988
|
KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
|
|
5521
5989
|
CACHE_DIR_MODE = 448;
|
|
@@ -5698,7 +6166,7 @@ var init_credential = __esm({
|
|
|
5698
6166
|
|
|
5699
6167
|
// src/providersStore.ts
|
|
5700
6168
|
function providerJsonPath(paths, name) {
|
|
5701
|
-
return
|
|
6169
|
+
return import_node_path25.default.join(paths.providersDir, `${name}.json`);
|
|
5702
6170
|
}
|
|
5703
6171
|
function providerExists(paths, name) {
|
|
5704
6172
|
return import_node_fs6.default.existsSync(providerJsonPath(paths, name));
|
|
@@ -5758,7 +6226,7 @@ function readProvider(paths, name) {
|
|
|
5758
6226
|
return parseProviderFile(filePath, raw);
|
|
5759
6227
|
}
|
|
5760
6228
|
function loadProvider(providersDir, name, port) {
|
|
5761
|
-
const filePath =
|
|
6229
|
+
const filePath = import_node_path25.default.join(providersDir, `${name}.json`);
|
|
5762
6230
|
const raw = port.readConfigFile(filePath);
|
|
5763
6231
|
return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
|
|
5764
6232
|
}
|
|
@@ -5920,12 +6388,12 @@ function resolveProvider(params) {
|
|
|
5920
6388
|
}
|
|
5921
6389
|
return { ok: true, provider: { name, definition, credential: resolution.credential }, warnings: resolution.credential.warnings };
|
|
5922
6390
|
}
|
|
5923
|
-
var import_node_fs6,
|
|
6391
|
+
var import_node_fs6, import_node_path25, ProviderNotFoundError, ProviderAlreadyExistsError, InvalidProviderNameError, PROVIDER_NAME_RE, LEGACY_PROVIDER_FIELDS, LEGACY_ENV_CREDENTIAL_KEYS, LEGACY_LITERAL_PLACEHOLDER, LegacyProviderFileError, ProviderKindMismatchError;
|
|
5924
6392
|
var init_providersStore = __esm({
|
|
5925
6393
|
"src/providersStore.ts"() {
|
|
5926
6394
|
"use strict";
|
|
5927
6395
|
import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
5928
|
-
|
|
6396
|
+
import_node_path25 = __toESM(require("node:path"), 1);
|
|
5929
6397
|
init_load();
|
|
5930
6398
|
init_store();
|
|
5931
6399
|
init_schema();
|
|
@@ -6137,10 +6605,10 @@ function commandFilename(ownExecutablePath, commandName) {
|
|
|
6137
6605
|
}
|
|
6138
6606
|
function resolveOwnBinaryCheck(paths, contentSourcePath) {
|
|
6139
6607
|
const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
6140
|
-
const recordedTarget = state === void 0 ? void 0 :
|
|
6608
|
+
const recordedTarget = state === void 0 ? void 0 : import_node_path27.default.resolve(state.targetPath);
|
|
6141
6609
|
let ownStat;
|
|
6142
6610
|
return (candidate) => {
|
|
6143
|
-
if (recordedTarget !== void 0 &&
|
|
6611
|
+
if (recordedTarget !== void 0 && import_node_path27.default.resolve(candidate) === recordedTarget) {
|
|
6144
6612
|
return true;
|
|
6145
6613
|
}
|
|
6146
6614
|
ownStat ??= statOrUndefined(contentSourcePath);
|
|
@@ -6163,22 +6631,22 @@ function statOrUndefined(target) {
|
|
|
6163
6631
|
}
|
|
6164
6632
|
}
|
|
6165
6633
|
function findPathShadow(params) {
|
|
6166
|
-
const resolvedTargetDir =
|
|
6634
|
+
const resolvedTargetDir = import_node_path27.default.resolve(params.targetDir);
|
|
6167
6635
|
for (const dir of params.pathDirs) {
|
|
6168
6636
|
const found = params.findExecutableInDir(dir, params.targetFilename);
|
|
6169
6637
|
if (found === void 0) {
|
|
6170
6638
|
continue;
|
|
6171
6639
|
}
|
|
6172
|
-
return
|
|
6640
|
+
return import_node_path27.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
|
|
6173
6641
|
}
|
|
6174
|
-
return params.pathDirs.some((dir) =>
|
|
6642
|
+
return params.pathDirs.some((dir) => import_node_path27.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
|
|
6175
6643
|
}
|
|
6176
|
-
var import_node_fs7,
|
|
6644
|
+
var import_node_fs7, import_node_path27, import_zod19, ClaudeShimStateSchema, nodeLinkFs;
|
|
6177
6645
|
var init_claudeShim = __esm({
|
|
6178
6646
|
"src/claudeShim.ts"() {
|
|
6179
6647
|
"use strict";
|
|
6180
6648
|
import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
6181
|
-
|
|
6649
|
+
import_node_path27 = __toESM(require("node:path"), 1);
|
|
6182
6650
|
import_zod19 = require("zod");
|
|
6183
6651
|
init_commandDeps();
|
|
6184
6652
|
init_store();
|
|
@@ -6692,7 +7160,7 @@ function buildEnv(params) {
|
|
|
6692
7160
|
const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
6693
7161
|
let providerCustomHeaders;
|
|
6694
7162
|
if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
|
|
6695
|
-
env.CLAUDE_CONFIG_DIR =
|
|
7163
|
+
env.CLAUDE_CONFIG_DIR = import_node_path36.default.join(params.identitiesDir, params.resolvedIdentityName);
|
|
6696
7164
|
}
|
|
6697
7165
|
if (params.provider !== void 0) {
|
|
6698
7166
|
const providerEnv = params.provider.definition.env ?? {};
|
|
@@ -6736,11 +7204,11 @@ function buildEnv(params) {
|
|
|
6736
7204
|
}
|
|
6737
7205
|
return env;
|
|
6738
7206
|
}
|
|
6739
|
-
var
|
|
7207
|
+
var import_node_path36, LOOPBACK_HOSTS;
|
|
6740
7208
|
var init_flags = __esm({
|
|
6741
7209
|
"src/launcher/flags.ts"() {
|
|
6742
7210
|
"use strict";
|
|
6743
|
-
|
|
7211
|
+
import_node_path36 = __toESM(require("node:path"), 1);
|
|
6744
7212
|
init_envBool();
|
|
6745
7213
|
init_credential();
|
|
6746
7214
|
init_headers();
|
|
@@ -7073,7 +7541,7 @@ function decideLaunch(params, readOnly) {
|
|
|
7073
7541
|
identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
|
|
7074
7542
|
globalDefaultConfigProfile: params.globalDefaultConfigProfile
|
|
7075
7543
|
});
|
|
7076
|
-
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(
|
|
7544
|
+
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(import_node_path37.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
|
|
7077
7545
|
log.error(
|
|
7078
7546
|
`agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
|
|
7079
7547
|
);
|
|
@@ -7185,7 +7653,7 @@ function decideLaunch(params, readOnly) {
|
|
|
7185
7653
|
extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
|
|
7186
7654
|
passthrough: parsedArgv.rest
|
|
7187
7655
|
});
|
|
7188
|
-
const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR :
|
|
7656
|
+
const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR : import_node_path37.default.join(paths.identitiesDir, identityDecision.name);
|
|
7189
7657
|
const decision = {
|
|
7190
7658
|
identitySource: identityDecision.source,
|
|
7191
7659
|
configDirEscapeHatch: identityDecision.configDirEscapeHatch,
|
|
@@ -7226,7 +7694,7 @@ function prepareLaunch(params) {
|
|
|
7226
7694
|
);
|
|
7227
7695
|
const updateCheck = runLaunchUpdateCheck({
|
|
7228
7696
|
mode: params.updateMode ?? "off",
|
|
7229
|
-
checkPath:
|
|
7697
|
+
checkPath: import_node_path37.default.join(paths.root, "update.check"),
|
|
7230
7698
|
currentVersion: package_default.version,
|
|
7231
7699
|
port: params.update
|
|
7232
7700
|
});
|
|
@@ -7357,12 +7825,12 @@ function runLaunchPlan(plan, spawn3) {
|
|
|
7357
7825
|
function runLauncher(params) {
|
|
7358
7826
|
params.proc.exit(runLaunchPlan(prepareLaunch(params), params.spawn));
|
|
7359
7827
|
}
|
|
7360
|
-
var import_node_crypto10,
|
|
7828
|
+
var import_node_crypto10, import_node_path37;
|
|
7361
7829
|
var init_launcher = __esm({
|
|
7362
7830
|
"src/launcher.ts"() {
|
|
7363
7831
|
"use strict";
|
|
7364
7832
|
import_node_crypto10 = require("node:crypto");
|
|
7365
|
-
|
|
7833
|
+
import_node_path37 = __toESM(require("node:path"), 1);
|
|
7366
7834
|
init_package();
|
|
7367
7835
|
init_envBool();
|
|
7368
7836
|
init_argv();
|
|
@@ -7393,13 +7861,13 @@ function agentShimCliPath(distDir = typeof __AGENT_SHIM_DIST_DIR__ === "string"
|
|
|
7393
7861
|
if (distDir === void 0) {
|
|
7394
7862
|
throw new OwnCliPathUnknownError();
|
|
7395
7863
|
}
|
|
7396
|
-
return
|
|
7864
|
+
return import_node_path38.default.join(distDir, OWN_CLI_FILE_NAME);
|
|
7397
7865
|
}
|
|
7398
|
-
var
|
|
7866
|
+
var import_node_path38, OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
|
|
7399
7867
|
var init_ownCli = __esm({
|
|
7400
7868
|
"src/ownCli.ts"() {
|
|
7401
7869
|
"use strict";
|
|
7402
|
-
|
|
7870
|
+
import_node_path38 = __toESM(require("node:path"), 1);
|
|
7403
7871
|
init_cliError();
|
|
7404
7872
|
OWN_CLI_FILE_NAME = "cli.cjs";
|
|
7405
7873
|
OwnCliPathUnknownError = class extends CliError {
|
|
@@ -7484,7 +7952,7 @@ request.on("error", (error) => finish(failed, (error.code ? error.code + ": " :
|
|
|
7484
7952
|
// src/frontdoor/trust.ts
|
|
7485
7953
|
function resolveTrustBundle(params) {
|
|
7486
7954
|
const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
|
|
7487
|
-
if (inherited === void 0 || inherited === "" ||
|
|
7955
|
+
if (inherited === void 0 || inherited === "" || import_node_path39.default.resolve(inherited) === import_node_path39.default.resolve(caCertFile)) {
|
|
7488
7956
|
return { path: caCertFile };
|
|
7489
7957
|
}
|
|
7490
7958
|
const caPem = fs12.readFileUtf8(caCertFile);
|
|
@@ -7502,19 +7970,19 @@ function resolveTrustBundle(params) {
|
|
|
7502
7970
|
}
|
|
7503
7971
|
const combined = `${inheritedPem.trimEnd()}
|
|
7504
7972
|
${caPem}`;
|
|
7505
|
-
const bundle =
|
|
7973
|
+
const bundle = import_node_path39.default.join(bundlesDir, `${(0, import_node_crypto11.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
|
|
7506
7974
|
if (!fs12.exists(bundle)) {
|
|
7507
7975
|
fs12.mkdirp(bundlesDir);
|
|
7508
7976
|
fs12.writeFileAtomic(bundle, combined);
|
|
7509
7977
|
}
|
|
7510
7978
|
return { path: bundle };
|
|
7511
7979
|
}
|
|
7512
|
-
var import_node_crypto11,
|
|
7980
|
+
var import_node_crypto11, import_node_path39, BUNDLE_NAME_HEX_DIGITS;
|
|
7513
7981
|
var init_trust = __esm({
|
|
7514
7982
|
"src/frontdoor/trust.ts"() {
|
|
7515
7983
|
"use strict";
|
|
7516
7984
|
import_node_crypto11 = require("node:crypto");
|
|
7517
|
-
|
|
7985
|
+
import_node_path39 = __toESM(require("node:path"), 1);
|
|
7518
7986
|
BUNDLE_NAME_HEX_DIGITS = 16;
|
|
7519
7987
|
}
|
|
7520
7988
|
});
|
|
@@ -8308,6 +8776,7 @@ __export(index_exports, {
|
|
|
8308
8776
|
isRcReadFileEncoding: () => isRcReadFileEncoding,
|
|
8309
8777
|
lateRcEventDial: () => lateRcEventDial,
|
|
8310
8778
|
lateRcStreamDial: () => lateRcStreamDial,
|
|
8779
|
+
launchRequiredUpstreams: () => launchRequiredUpstreams,
|
|
8311
8780
|
listDirectoryRules: () => listDirectoryRules,
|
|
8312
8781
|
listIdentities: () => listIdentities,
|
|
8313
8782
|
listProfiles: () => listProfiles,
|
|
@@ -8748,6 +9217,7 @@ function pumpTapSession(secure, openUpstream, tap, prefix = Buffer.alloc(0)) {
|
|
|
8748
9217
|
// src/frontdoor/connect.ts
|
|
8749
9218
|
init_capability();
|
|
8750
9219
|
init_route();
|
|
9220
|
+
init_state();
|
|
8751
9221
|
|
|
8752
9222
|
// src/frontdoor/supervisor.ts
|
|
8753
9223
|
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
@@ -8819,9 +9289,10 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
8819
9289
|
return fail(`could not start the direct listener: ${error instanceof Error ? error.message : String(error)}`);
|
|
8820
9290
|
}
|
|
8821
9291
|
if (previousStickyDirect !== void 0 && direct.port !== previousStickyDirect) {
|
|
8822
|
-
ports.log(`agent-shim frontdoor supervisor: sticky direct port ${String(previousStickyDirect)} was occupied; moving to ${String(direct.port)} (headroom
|
|
9292
|
+
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)`);
|
|
8823
9293
|
}
|
|
8824
9294
|
lastDirectPort = direct.port;
|
|
9295
|
+
writeFrontDoorDirectRecord(fs12, paths.frontdoorDirectRecordsDir, { pid: ports.ownPid, directPort: direct.port });
|
|
8825
9296
|
writeFrontDoorState(fs12, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http3.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
|
|
8826
9297
|
ports.doorHealth.generation({ providerPort: http3.port, connectPort: connect3.port, directPort: direct.port });
|
|
8827
9298
|
fs12.removeRecursive(paths.frontdoorLockFile);
|
|
@@ -8843,6 +9314,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
8843
9314
|
await connect3.close();
|
|
8844
9315
|
await http3.close();
|
|
8845
9316
|
ports.closeRcStreamHub();
|
|
9317
|
+
removeFrontDoorDirectRecord(fs12, paths.frontdoorDirectRecordsDir, ports.ownPid);
|
|
8846
9318
|
};
|
|
8847
9319
|
const shutdown = async () => {
|
|
8848
9320
|
await closeServing();
|
|
@@ -8906,7 +9378,6 @@ var CONNECT_INTERCEPT_HOST = "api.anthropic.com";
|
|
|
8906
9378
|
var CONNECT_INTERCEPT_HOSTS = [CONNECT_INTERCEPT_HOST, "platform.claude.com"];
|
|
8907
9379
|
var ROUTED_PATH_PREFIX = "/v1/";
|
|
8908
9380
|
var HTTPS_PORT = 443;
|
|
8909
|
-
var MAX_PORT = 65535;
|
|
8910
9381
|
var HTTP_BAD_GATEWAY = 502;
|
|
8911
9382
|
var CA_KEY_FILE_MODE = 384;
|
|
8912
9383
|
var CONNECT_LINE_TOKENS = 3;
|
|
@@ -8938,7 +9409,7 @@ function parseConnectTarget(authority) {
|
|
|
8938
9409
|
}
|
|
8939
9410
|
const host = authority.slice(0, colon).trim().toLowerCase();
|
|
8940
9411
|
const port = Number.parseInt(authority.slice(colon + 1), 10);
|
|
8941
|
-
if (host === "" || !Number.isInteger(port) || port <= 0 || port >
|
|
9412
|
+
if (host === "" || !Number.isInteger(port) || port <= 0 || port > MAX_TCP_PORT) {
|
|
8942
9413
|
return void 0;
|
|
8943
9414
|
}
|
|
8944
9415
|
return { host, port };
|
|
@@ -8946,8 +9417,8 @@ function parseConnectTarget(authority) {
|
|
|
8946
9417
|
function isInterceptedHost(host, interceptHosts) {
|
|
8947
9418
|
return interceptHosts.includes(host);
|
|
8948
9419
|
}
|
|
8949
|
-
function servedByPipeline(
|
|
8950
|
-
return
|
|
9420
|
+
function servedByPipeline(path40) {
|
|
9421
|
+
return path40?.startsWith(ROUTED_PATH_PREFIX) === true;
|
|
8951
9422
|
}
|
|
8952
9423
|
var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
8953
9424
|
"connection",
|
|
@@ -9741,11 +10212,11 @@ function createRcSessionTracker(deps) {
|
|
|
9741
10212
|
};
|
|
9742
10213
|
const observeExchange = (request4) => {
|
|
9743
10214
|
const method = (request4.method ?? "").toUpperCase();
|
|
9744
|
-
const
|
|
9745
|
-
if (!
|
|
10215
|
+
const path40 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
|
|
10216
|
+
if (!path40.startsWith(RC_SESSIONS_PATH_PREFIX)) {
|
|
9746
10217
|
return void 0;
|
|
9747
10218
|
}
|
|
9748
|
-
const tail =
|
|
10219
|
+
const tail = path40.slice(RC_SESSIONS_PATH_PREFIX.length);
|
|
9749
10220
|
const facts = {
|
|
9750
10221
|
oauthAuthorization: oauthAuthorizationOf(request4.headers),
|
|
9751
10222
|
anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
|
|
@@ -10135,8 +10606,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
|
|
|
10135
10606
|
function isRcReadFileEncoding(value) {
|
|
10136
10607
|
return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
|
|
10137
10608
|
}
|
|
10138
|
-
function buildRcReadFilePayload(requestId,
|
|
10139
|
-
return buildRcControlRequestPayload(requestId, { subtype: "read_file", path:
|
|
10609
|
+
function buildRcReadFilePayload(requestId, path40, options) {
|
|
10610
|
+
return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path40, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
|
|
10140
10611
|
}
|
|
10141
10612
|
function buildRcFileSuggestionsPayload(requestId, query) {
|
|
10142
10613
|
return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
|
|
@@ -10238,15 +10709,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
|
|
|
10238
10709
|
const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
|
|
10239
10710
|
return result.ok ? { ...result, requestId } : result;
|
|
10240
10711
|
}
|
|
10241
|
-
async function readRcSessionFile(deps, sessionId,
|
|
10242
|
-
if (
|
|
10712
|
+
async function readRcSessionFile(deps, sessionId, path40, options) {
|
|
10713
|
+
if (path40 === "") {
|
|
10243
10714
|
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" };
|
|
10244
10715
|
}
|
|
10245
10716
|
if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
|
|
10246
10717
|
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" };
|
|
10247
10718
|
}
|
|
10248
10719
|
const requestId = deps.newUuid();
|
|
10249
|
-
const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId,
|
|
10720
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path40, options), `read ${path40} from session ${sessionId}`);
|
|
10250
10721
|
return result.ok ? { ...result, requestId } : result;
|
|
10251
10722
|
}
|
|
10252
10723
|
async function suggestRcSessionFiles(deps, sessionId, query) {
|
|
@@ -10415,11 +10886,11 @@ function createRcControlHandler(deps) {
|
|
|
10415
10886
|
path: "read-file",
|
|
10416
10887
|
read: (body) => {
|
|
10417
10888
|
const session = bodyString(body, "session");
|
|
10418
|
-
const
|
|
10889
|
+
const path40 = bodyString(body, "path");
|
|
10419
10890
|
const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
|
|
10420
10891
|
const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
|
|
10421
|
-
const refused2 = session === void 0 ||
|
|
10422
|
-
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,
|
|
10892
|
+
const refused2 = session === void 0 || path40 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
|
|
10893
|
+
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, path40, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
|
|
10423
10894
|
}
|
|
10424
10895
|
},
|
|
10425
10896
|
{
|
|
@@ -10729,9 +11200,9 @@ function requestIdOfBody(body) {
|
|
|
10729
11200
|
}
|
|
10730
11201
|
function frontDoorRcControl(transport, token) {
|
|
10731
11202
|
const headers = { authorization: `Bearer ${token}` };
|
|
10732
|
-
const listAnswerOf = async (
|
|
11203
|
+
const listAnswerOf = async (path40, what) => {
|
|
10733
11204
|
try {
|
|
10734
|
-
return await transport.request({ method: "GET", path:
|
|
11205
|
+
return await transport.request({ method: "GET", path: path40, headers });
|
|
10735
11206
|
} catch (error) {
|
|
10736
11207
|
throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
10737
11208
|
}
|
|
@@ -10803,10 +11274,10 @@ function frontDoorRcControl(transport, token) {
|
|
|
10803
11274
|
}
|
|
10804
11275
|
return pending;
|
|
10805
11276
|
};
|
|
10806
|
-
const writeOf = async (
|
|
11277
|
+
const writeOf = async (path40, body, describeFailure2) => {
|
|
10807
11278
|
let answer;
|
|
10808
11279
|
try {
|
|
10809
|
-
answer = await transport.request({ method: "POST", path:
|
|
11280
|
+
answer = await transport.request({ method: "POST", path: path40, headers: { ...headers, "content-type": "application/json" }, body });
|
|
10810
11281
|
} catch (error) {
|
|
10811
11282
|
return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
|
|
10812
11283
|
}
|
|
@@ -10837,10 +11308,10 @@ function frontDoorRcControl(transport, token) {
|
|
|
10837
11308
|
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}`),
|
|
10838
11309
|
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}`),
|
|
10839
11310
|
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}`),
|
|
10840
|
-
readFile: async (sessionId,
|
|
11311
|
+
readFile: async (sessionId, path40, options) => await writeOf(
|
|
10841
11312
|
`${CONTROL_PATH_PREFIX}/read-file`,
|
|
10842
|
-
JSON.stringify({ session: sessionId, path:
|
|
10843
|
-
(status, message) => `reading ${
|
|
11313
|
+
JSON.stringify({ session: sessionId, path: path40, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
|
|
11314
|
+
(status, message) => `reading ${path40} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
|
|
10844
11315
|
),
|
|
10845
11316
|
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}`),
|
|
10846
11317
|
keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
|
|
@@ -10999,12 +11470,12 @@ function tlsFacts(options) {
|
|
|
10999
11470
|
}
|
|
11000
11471
|
function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
|
|
11001
11472
|
const agent = new ExemptTlsAgent();
|
|
11002
|
-
const post = async (
|
|
11473
|
+
const post = async (path40, headers, body) => await new Promise((resolve, reject) => {
|
|
11003
11474
|
const options = {
|
|
11004
11475
|
host: target.host,
|
|
11005
11476
|
port: target.port,
|
|
11006
11477
|
method: "POST",
|
|
11007
|
-
path:
|
|
11478
|
+
path: path40,
|
|
11008
11479
|
// 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.
|
|
11009
11480
|
headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
|
|
11010
11481
|
agent
|
|
@@ -11069,12 +11540,12 @@ function lateRcStreamDial(resolve) {
|
|
|
11069
11540
|
}
|
|
11070
11541
|
function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
|
|
11071
11542
|
const agent = new ExemptTlsAgent();
|
|
11072
|
-
const request4 = async (method,
|
|
11543
|
+
const request4 = async (method, path40, headers, body, signal) => await new Promise((resolve, reject) => {
|
|
11073
11544
|
const options = {
|
|
11074
11545
|
host: target.host,
|
|
11075
11546
|
port: target.port,
|
|
11076
11547
|
method,
|
|
11077
|
-
path:
|
|
11548
|
+
path: path40,
|
|
11078
11549
|
// 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.
|
|
11079
11550
|
headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
|
|
11080
11551
|
agent,
|
|
@@ -11116,9 +11587,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
|
|
|
11116
11587
|
return { status, body: await readAll(response) };
|
|
11117
11588
|
},
|
|
11118
11589
|
openStream: async (sessionId, headers, resume, signal) => {
|
|
11119
|
-
const
|
|
11590
|
+
const path40 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
|
|
11120
11591
|
const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
|
|
11121
|
-
const { status, response } = await request4("GET",
|
|
11592
|
+
const { status, response } = await request4("GET", path40, streamHeaders, void 0, signal);
|
|
11122
11593
|
if (!isSuccessful2(status)) {
|
|
11123
11594
|
await readAll(response);
|
|
11124
11595
|
return { status, chunks: NO_CHUNKS };
|
|
@@ -12058,7 +12529,7 @@ init_cliError();
|
|
|
12058
12529
|
|
|
12059
12530
|
// src/configProfilesStore.ts
|
|
12060
12531
|
var import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
12061
|
-
var
|
|
12532
|
+
var import_node_path22 = __toESM(require("node:path"), 1);
|
|
12062
12533
|
init_store();
|
|
12063
12534
|
init_schema();
|
|
12064
12535
|
init_cliError();
|
|
@@ -12088,7 +12559,7 @@ var InvalidCategoryNameError = class extends CliError {
|
|
|
12088
12559
|
categoryName;
|
|
12089
12560
|
};
|
|
12090
12561
|
function profileJsonPath(paths, name) {
|
|
12091
|
-
return
|
|
12562
|
+
return import_node_path22.default.join(paths.configProfilesDir, `${name}.json`);
|
|
12092
12563
|
}
|
|
12093
12564
|
function profileExists(paths, name) {
|
|
12094
12565
|
return import_node_fs3.default.existsSync(profileJsonPath(paths, name));
|
|
@@ -12270,19 +12741,19 @@ function writePools(paths, pools) {
|
|
|
12270
12741
|
applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
|
|
12271
12742
|
}
|
|
12272
12743
|
function poolCycleOf(pools, name) {
|
|
12273
|
-
const walk = (current,
|
|
12744
|
+
const walk = (current, path40) => {
|
|
12274
12745
|
for (const entry of pools[current]?.identities ?? []) {
|
|
12275
12746
|
const nested = poolNameOf(poolMemberIdentity(entry));
|
|
12276
12747
|
if (nested === void 0) {
|
|
12277
12748
|
continue;
|
|
12278
12749
|
}
|
|
12279
12750
|
if (nested === name) {
|
|
12280
|
-
return [...
|
|
12751
|
+
return [...path40, nested];
|
|
12281
12752
|
}
|
|
12282
|
-
if (
|
|
12753
|
+
if (path40.includes(nested)) {
|
|
12283
12754
|
continue;
|
|
12284
12755
|
}
|
|
12285
|
-
const found = walk(nested, [...
|
|
12756
|
+
const found = walk(nested, [...path40, nested]);
|
|
12286
12757
|
if (found !== void 0) {
|
|
12287
12758
|
return found;
|
|
12288
12759
|
}
|
|
@@ -12381,7 +12852,7 @@ init_paths();
|
|
|
12381
12852
|
init_realCredentialCache();
|
|
12382
12853
|
init_providersStore();
|
|
12383
12854
|
init_realPorts();
|
|
12384
|
-
var
|
|
12855
|
+
var import_node_path26 = __toESM(require("node:path"), 1);
|
|
12385
12856
|
var import_zod15 = require("zod");
|
|
12386
12857
|
init_envBool();
|
|
12387
12858
|
init_load();
|
|
@@ -12730,10 +13201,10 @@ function collectCheckReport(params) {
|
|
|
12730
13201
|
}).input;
|
|
12731
13202
|
const providerName = cascadeProviderName(cascade);
|
|
12732
13203
|
const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
|
|
12733
|
-
const farmRoot = identityDecision.name === void 0 ? void 0 :
|
|
13204
|
+
const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path26.default.join(paths.identitiesDir, identityDecision.name);
|
|
12734
13205
|
const settingsFiles = {
|
|
12735
|
-
"settings.json": realFsPort.readFileUtf8(
|
|
12736
|
-
"settings.local.json": realFsPort.readFileUtf8(
|
|
13206
|
+
"settings.json": realFsPort.readFileUtf8(import_node_path26.default.join(claudeHome, "settings.json")),
|
|
13207
|
+
"settings.local.json": realFsPort.readFileUtf8(import_node_path26.default.join(claudeHome, "settings.local.json"))
|
|
12737
13208
|
};
|
|
12738
13209
|
const report = runCheck({
|
|
12739
13210
|
cwd,
|
|
@@ -13025,7 +13496,7 @@ var ResetRowSchema = import_zod18.z.strictObject({
|
|
|
13025
13496
|
var ResetScheduleSchema = import_zod18.z.strictObject({ resets: import_zod18.z.readonly(import_zod18.z.array(ResetRowSchema)) });
|
|
13026
13497
|
|
|
13027
13498
|
// src/frontdoor/controlSchemas.ts
|
|
13028
|
-
var
|
|
13499
|
+
var import_node_path31 = __toESM(require("node:path"), 1);
|
|
13029
13500
|
var import_zod23 = require("zod");
|
|
13030
13501
|
|
|
13031
13502
|
// src/doctorReport.ts
|
|
@@ -13034,7 +13505,7 @@ init_store();
|
|
|
13034
13505
|
|
|
13035
13506
|
// src/identityStore.ts
|
|
13036
13507
|
var import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
13037
|
-
var
|
|
13508
|
+
var import_node_path28 = __toESM(require("node:path"), 1);
|
|
13038
13509
|
init_load();
|
|
13039
13510
|
init_store();
|
|
13040
13511
|
init_schema();
|
|
@@ -13068,7 +13539,7 @@ var InvalidIdentityNameError = class extends CliError {
|
|
|
13068
13539
|
attemptedName;
|
|
13069
13540
|
};
|
|
13070
13541
|
function identityJsonPath(paths, name) {
|
|
13071
|
-
return
|
|
13542
|
+
return import_node_path28.default.join(paths.identitiesDir, name, "identity.json");
|
|
13072
13543
|
}
|
|
13073
13544
|
function requireIdentityNames(paths, names) {
|
|
13074
13545
|
const existing = new Set(listIdentities(paths).map((entry) => entry.name));
|
|
@@ -13183,7 +13654,7 @@ function setIdentityCredential(paths, identityName, change) {
|
|
|
13183
13654
|
});
|
|
13184
13655
|
}
|
|
13185
13656
|
function belongsToIdentity(entry, name) {
|
|
13186
|
-
return entry === name || entry ===
|
|
13657
|
+
return entry === name || entry === import_node_path28.default.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
|
|
13187
13658
|
}
|
|
13188
13659
|
function removeIdentity(paths, name) {
|
|
13189
13660
|
if (!identityExists(paths, name)) {
|
|
@@ -13191,7 +13662,7 @@ function removeIdentity(paths, name) {
|
|
|
13191
13662
|
}
|
|
13192
13663
|
for (const entry of import_node_fs8.default.readdirSync(paths.identitiesDir)) {
|
|
13193
13664
|
if (belongsToIdentity(entry, name)) {
|
|
13194
|
-
import_node_fs8.default.rmSync(
|
|
13665
|
+
import_node_fs8.default.rmSync(import_node_path28.default.join(paths.identitiesDir, entry), { recursive: true, force: true });
|
|
13195
13666
|
}
|
|
13196
13667
|
}
|
|
13197
13668
|
if (readActiveIdentity2(paths) === name) {
|
|
@@ -13202,10 +13673,10 @@ function removeIdentity(paths, name) {
|
|
|
13202
13673
|
// src/doctorReport.ts
|
|
13203
13674
|
init_realPorts();
|
|
13204
13675
|
var import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
13205
|
-
var
|
|
13676
|
+
var import_node_path30 = __toESM(require("node:path"), 1);
|
|
13206
13677
|
|
|
13207
13678
|
// src/usage/signIn.ts
|
|
13208
|
-
var
|
|
13679
|
+
var import_node_path29 = __toESM(require("node:path"), 1);
|
|
13209
13680
|
var CREDENTIALS_FILE = ".credentials.json";
|
|
13210
13681
|
function keychainHasItem(run, account) {
|
|
13211
13682
|
return run.run("security", ["find-generic-password", "-a", account]).status === 0;
|
|
@@ -13223,7 +13694,7 @@ function decideSignIn(facts) {
|
|
|
13223
13694
|
return { state: "signed-out", detail: facts.platform === "darwin" ? `no Keychain item and no ${CREDENTIALS_FILE}` : `no ${CREDENTIALS_FILE}` };
|
|
13224
13695
|
}
|
|
13225
13696
|
function credentialsFilePath(farmRoot) {
|
|
13226
|
-
return
|
|
13697
|
+
return import_node_path29.default.join(farmRoot, CREDENTIALS_FILE);
|
|
13227
13698
|
}
|
|
13228
13699
|
|
|
13229
13700
|
// src/codex/siwcStore.ts
|
|
@@ -13312,17 +13783,75 @@ init_realCredentialCache();
|
|
|
13312
13783
|
init_source();
|
|
13313
13784
|
|
|
13314
13785
|
// src/headroom/allowlistDrift.ts
|
|
13786
|
+
init_earlierRelease();
|
|
13315
13787
|
init_state2();
|
|
13316
13788
|
function diagnoseAllowlistDrift(params) {
|
|
13317
|
-
const {
|
|
13318
|
-
if (recordedHash === void 0
|
|
13789
|
+
const { allowlist, fileContent, recordedHash, earlierRelease } = params;
|
|
13790
|
+
if (recordedHash === void 0) {
|
|
13791
|
+
return void 0;
|
|
13792
|
+
}
|
|
13793
|
+
if (earlierRelease !== void 0) {
|
|
13794
|
+
return earlierRelease.admitsServingDoor ? void 0 : { startedByEarlierRelease: true };
|
|
13795
|
+
}
|
|
13796
|
+
const served = fileContent === void 0 ? [] : parseAllowlistFile(fileContent);
|
|
13797
|
+
const listed = new Set(served);
|
|
13798
|
+
const computed = new Set(allowlist);
|
|
13799
|
+
const missingFromFile = allowlist.filter((entry) => !listed.has(entry));
|
|
13800
|
+
const staleInFile = served.filter((entry) => !computed.has(entry)).sort();
|
|
13801
|
+
const hashLags = recordedHash !== (fileContent === void 0 ? void 0 : hashAllowlistFile(fileContent));
|
|
13802
|
+
if (missingFromFile.length === 0 && staleInFile.length === 0 && !hashLags) {
|
|
13319
13803
|
return void 0;
|
|
13320
13804
|
}
|
|
13321
|
-
|
|
13322
|
-
|
|
13323
|
-
|
|
13805
|
+
return { missingFromFile, staleInFile, hashLags };
|
|
13806
|
+
}
|
|
13807
|
+
function describeAllowlistDrift(params) {
|
|
13808
|
+
const { drift, allowlistFile, liveSupervisorPid } = params;
|
|
13809
|
+
if (drift.startedByEarlierRelease === true) {
|
|
13810
|
+
return `the daemon was ${EARLIER_RELEASE_ALLOWLIST}, its allowlist cannot be shown to admit the serving front door (the door moved, or a provider changed, since it started), and until then provider launches are refused`;
|
|
13811
|
+
}
|
|
13812
|
+
const parts = [];
|
|
13813
|
+
if (drift.missingFromFile.length > 0) {
|
|
13814
|
+
parts.push(`${allowlistFile} lacks ${drift.missingFromFile.join(", ")} (live front doors' direct origins, so the daemon refuses every request a provider launch sends back through those doors)`);
|
|
13815
|
+
}
|
|
13816
|
+
if (drift.staleInFile.length > 0) {
|
|
13817
|
+
parts.push(`${allowlistFile} still lists ${drift.staleInFile.join(", ")}`);
|
|
13818
|
+
}
|
|
13819
|
+
if (drift.hashLags) {
|
|
13820
|
+
parts.push("the supervisor has not yet recorded the file's allowlist as served, and provider launches through headroom wait until it does");
|
|
13821
|
+
}
|
|
13822
|
+
const healing = liveSupervisorPid === void 0 ? "the supervisor is not running, so nothing rewrites the file until the next launch through headroom starts one" : `supervisor ${String(liveSupervisorPid)} rewrites the file on its next tick, so drift that persists means it cannot write it (see ${params.logPath})`;
|
|
13823
|
+
return `${parts.join("; ")}; ${healing}`;
|
|
13824
|
+
}
|
|
13825
|
+
|
|
13826
|
+
// src/doctorReport.ts
|
|
13827
|
+
init_earlierRelease();
|
|
13828
|
+
init_socket();
|
|
13829
|
+
|
|
13830
|
+
// src/doctorHeadroomAllowlist.ts
|
|
13831
|
+
function pushRefusedAllowlistFile(push, allowlist) {
|
|
13832
|
+
const problem = allowlist.fileProblem;
|
|
13833
|
+
if (problem?.repairable === false) {
|
|
13834
|
+
push("headroom", "fail", `Headroom refuses its allowlist file, so it admits nothing and every provider request through headroom fails: ${problem.message}.`, allowlist.file);
|
|
13835
|
+
}
|
|
13836
|
+
}
|
|
13837
|
+
function pushHeadroomAllowlist(push, allowlist, daemon) {
|
|
13838
|
+
const { drift } = allowlist;
|
|
13839
|
+
const problem = allowlist.fileProblem;
|
|
13840
|
+
if (problem?.repairable === true) {
|
|
13841
|
+
push("headroom", "warn", `Headroom's allowlist file breaks agent-shim's owner-only rule for it: ${problem.message}. Its supervisor repairs this on its next tick, and stops the daemon if it cannot.`, allowlist.file);
|
|
13842
|
+
}
|
|
13843
|
+
if (drift !== void 0) {
|
|
13844
|
+
const blocking = drift.startedByEarlierRelease === true || drift.missingFromFile.length > 0 || drift.hashLags;
|
|
13845
|
+
push(
|
|
13846
|
+
"headroom",
|
|
13847
|
+
blocking ? "fail" : "warn",
|
|
13848
|
+
`Headroom daemon ${String(daemon.headroomPid)}'s allowlist lags the current one: ` + describeAllowlistDrift({ drift, allowlistFile: allowlist.file, liveSupervisorPid: daemon.liveSupervisorPid, logPath: allowlist.logPath }) + ". `--no-headroom` launches are unaffected.",
|
|
13849
|
+
String(daemon.headroomPid)
|
|
13850
|
+
);
|
|
13851
|
+
}
|
|
13852
|
+
for (const door of allowlist.undeterminedFrontDoors) {
|
|
13853
|
+
push("headroom", "warn", `Could not tell whether front door ${String(door.pid)} is still running (${door.reason}), so headroom keeps admitting its direct origin ${door.origin} until a later read can.`, String(door.pid));
|
|
13324
13854
|
}
|
|
13325
|
-
return recordedHash === hashAllowlist(headroomAllowlist(headroomUpstreams(providers, void 0))) ? ["front-door-origin"] : ["provider-files", "front-door-origin"];
|
|
13326
13855
|
}
|
|
13327
13856
|
|
|
13328
13857
|
// src/doctorReport.ts
|
|
@@ -13331,7 +13860,7 @@ init_supervisor();
|
|
|
13331
13860
|
init_state();
|
|
13332
13861
|
|
|
13333
13862
|
// src/doctorFrontDoor.ts
|
|
13334
|
-
function pushFrontDoor(push, supervisors, registeredPid) {
|
|
13863
|
+
function pushFrontDoor(push, supervisors, registeredPid, liveSessions) {
|
|
13335
13864
|
if (!supervisors.ok) {
|
|
13336
13865
|
push("frontdoor", "warn", `Could not list processes to look for duplicate front door supervisors: ${supervisors.message}.`);
|
|
13337
13866
|
return;
|
|
@@ -13348,6 +13877,16 @@ function pushFrontDoor(push, supervisors, registeredPid) {
|
|
|
13348
13877
|
}
|
|
13349
13878
|
const serving = registeredPid !== void 0 && pids.includes(registeredPid) ? `The front door state file names pid ${String(registeredPid)} as the serving supervisor.` : "The front door state file names no running supervisor.";
|
|
13350
13879
|
for (const pid of pids.filter((candidate) => candidate !== registeredPid)) {
|
|
13880
|
+
const served = liveSessions.filter((session) => session.supervisorPid === pid).length;
|
|
13881
|
+
if (registeredPid !== void 0 && pids.includes(registeredPid) && served > 0) {
|
|
13882
|
+
push(
|
|
13883
|
+
"frontdoor",
|
|
13884
|
+
"warn",
|
|
13885
|
+
`Front door supervisor pid ${String(pid)} has been superseded by pid ${String(registeredPid)} and still serves ${String(served)} launch${served === 1 ? "" : "es"} registered against it; it exits once they end.`,
|
|
13886
|
+
String(pid)
|
|
13887
|
+
);
|
|
13888
|
+
continue;
|
|
13889
|
+
}
|
|
13351
13890
|
push(
|
|
13352
13891
|
"frontdoor",
|
|
13353
13892
|
"fail",
|
|
@@ -13417,7 +13956,7 @@ function tcpPortEraRecord(raw) {
|
|
|
13417
13956
|
return (has("port") || has("lastPort")) && !has("socketPath");
|
|
13418
13957
|
}
|
|
13419
13958
|
function pushPathResolution(push, resolution) {
|
|
13420
|
-
const ownDir =
|
|
13959
|
+
const ownDir = import_node_path30.default.dirname(resolution.ownExecutablePath);
|
|
13421
13960
|
switch (resolution.agentShim.status) {
|
|
13422
13961
|
case "ok":
|
|
13423
13962
|
push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
|
|
@@ -13516,14 +14055,14 @@ function pushProvider(push, entry, cacheEnv, signIn) {
|
|
|
13516
14055
|
}
|
|
13517
14056
|
function pushLegacyName(push, params) {
|
|
13518
14057
|
const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
|
|
13519
|
-
if (legacyVariables.length === 0 &&
|
|
14058
|
+
if (legacyVariables.length === 0 && import_node_path30.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
|
|
13520
14059
|
push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
|
|
13521
14060
|
return;
|
|
13522
14061
|
}
|
|
13523
14062
|
for (const name of legacyVariables) {
|
|
13524
14063
|
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);
|
|
13525
14064
|
}
|
|
13526
|
-
if (
|
|
14065
|
+
if (import_node_path30.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
|
|
13527
14066
|
push(
|
|
13528
14067
|
"legacy-name",
|
|
13529
14068
|
"warn",
|
|
@@ -13779,15 +14318,11 @@ function runDoctor(params) {
|
|
|
13779
14318
|
);
|
|
13780
14319
|
}
|
|
13781
14320
|
const allowlist = params.headroom.allowlist;
|
|
13782
|
-
if (
|
|
13783
|
-
|
|
13784
|
-
|
|
13785
|
-
|
|
13786
|
-
|
|
13787
|
-
"fail",
|
|
13788
|
-
`Headroom daemon ${String(state.headroomPid)} was started with an allowlist that ${certainty} the serving front door's direct origin ${origin}, so it refuses every request a provider launch sends back through the door. Its supervisor restarts it once no launch is registered against it; \`agent-shim headroom status\` lists the registered launches, and \`--no-headroom\` launches are unaffected.`,
|
|
13789
|
-
String(state.headroomPid)
|
|
13790
|
-
);
|
|
14321
|
+
if (allowlist !== void 0) {
|
|
14322
|
+
pushRefusedAllowlistFile(push, allowlist);
|
|
14323
|
+
}
|
|
14324
|
+
if (allowlist !== void 0 && headroomAlive && state.headroomPid !== void 0) {
|
|
14325
|
+
pushHeadroomAllowlist(push, allowlist, { headroomPid: state.headroomPid, liveSupervisorPid: supervisorAlive ? state.supervisorPid : void 0 });
|
|
13791
14326
|
}
|
|
13792
14327
|
if (state.lastError !== void 0 && supervisorAlive) {
|
|
13793
14328
|
push("headroom", "warn", `Headroom recorded a previous error: ${state.lastError}`);
|
|
@@ -13803,7 +14338,7 @@ function runDoctor(params) {
|
|
|
13803
14338
|
}
|
|
13804
14339
|
if (params.frontDoor !== void 0) {
|
|
13805
14340
|
const validated3 = params.frontDoor.state.raw === void 0 ? void 0 : validateJson(FrontDoorStateSchema, params.frontDoor.state);
|
|
13806
|
-
pushFrontDoor(push, params.frontDoor.supervisors, validated3?.ok === true ? validated3.data.supervisorPid : void 0);
|
|
14341
|
+
pushFrontDoor(push, params.frontDoor.supervisors, validated3?.ok === true ? validated3.data.supervisorPid : void 0, params.frontDoor.liveSessions);
|
|
13807
14342
|
}
|
|
13808
14343
|
if (params.activeIdentity.raw === void 0) {
|
|
13809
14344
|
push("active-identity", "pass", "No active identity set.");
|
|
@@ -13896,18 +14431,18 @@ function collectDoctorReport(params) {
|
|
|
13896
14431
|
const { paths } = params;
|
|
13897
14432
|
const identityNames = import_node_fs9.default.existsSync(paths.identitiesDir) ? import_node_fs9.default.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
|
|
13898
14433
|
const identities = identityNames.map((name) => {
|
|
13899
|
-
const farmRoot =
|
|
13900
|
-
const identityPath =
|
|
14434
|
+
const farmRoot = import_node_path30.default.join(paths.identitiesDir, name);
|
|
14435
|
+
const identityPath = import_node_path30.default.join(farmRoot, "identity.json");
|
|
13901
14436
|
return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot, credentialsFilePresent: import_node_fs9.default.existsSync(credentialsFilePath(farmRoot)) };
|
|
13902
14437
|
});
|
|
13903
14438
|
const profileNames = import_node_fs9.default.existsSync(paths.configProfilesDir) ? import_node_fs9.default.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
13904
14439
|
const configProfiles = profileNames.map((name) => {
|
|
13905
|
-
const profilePath =
|
|
14440
|
+
const profilePath = import_node_path30.default.join(paths.configProfilesDir, `${name}.json`);
|
|
13906
14441
|
return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
|
|
13907
14442
|
});
|
|
13908
14443
|
const providerNames = import_node_fs9.default.existsSync(paths.providersDir) ? import_node_fs9.default.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
13909
14444
|
const providers = providerNames.map((name) => {
|
|
13910
|
-
const providerPath =
|
|
14445
|
+
const providerPath = import_node_path30.default.join(paths.providersDir, `${name}.json`);
|
|
13911
14446
|
return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
|
|
13912
14447
|
});
|
|
13913
14448
|
const ownExecutablePath = realOwnExecutablePath();
|
|
@@ -13919,20 +14454,24 @@ function collectDoctorReport(params) {
|
|
|
13919
14454
|
binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
|
|
13920
14455
|
}
|
|
13921
14456
|
const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
13922
|
-
const pathDirs = (params.env.PATH ?? "").split(
|
|
14457
|
+
const pathDirs = (params.env.PATH ?? "").split(import_node_path30.default.delimiter).filter((dir) => dir !== "");
|
|
13923
14458
|
const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
|
|
13924
14459
|
findPathShadow({
|
|
13925
14460
|
pathDirs,
|
|
13926
|
-
targetDir:
|
|
13927
|
-
targetFilename:
|
|
14461
|
+
targetDir: import_node_path30.default.dirname(shimState.targetPath),
|
|
14462
|
+
targetFilename: import_node_path30.default.basename(shimState.targetPath),
|
|
13928
14463
|
findExecutableInDir
|
|
13929
14464
|
}),
|
|
13930
14465
|
shimState.targetPath,
|
|
13931
14466
|
realpathOrSelf
|
|
13932
14467
|
);
|
|
13933
14468
|
const uid = process.getuid?.();
|
|
13934
|
-
const
|
|
14469
|
+
const allowlistContent = realFarmFs.readFileUtf8(paths.headroomAllowlistFile);
|
|
14470
|
+
const allowlistInputs = currentHeadroomAllowlistInputs(realFarmFs, paths, realFrontDoorLiveness);
|
|
13935
14471
|
const servingHeadroom = resolveServingHeadroomState(realFarmFs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, realIsProcessRunning);
|
|
14472
|
+
const servingState = servingHeadroom?.state;
|
|
14473
|
+
const servingDaemon = servingState?.headroomPid !== void 0 && servingState.socketPath !== void 0 && realIsProcessRunning(servingState.headroomPid) ? { pid: servingState.headroomPid, socketPath: servingState.socketPath } : void 0;
|
|
14474
|
+
const servingEarlierRelease = servingDaemon === void 0 ? void 0 : earlierReleaseDaemon(realFarmFs, paths, { commandLine: realProcessCommandLine(servingDaemon.pid), socketPath: servingDaemon.socketPath, recordedHash: servingState?.allowlistHash });
|
|
13936
14475
|
const report = runDoctor({
|
|
13937
14476
|
env: params.env,
|
|
13938
14477
|
credentialCache: realCredentialCacheEnv(paths),
|
|
@@ -13953,7 +14492,7 @@ function collectDoctorReport(params) {
|
|
|
13953
14492
|
agentShim: refinePathShadow(
|
|
13954
14493
|
findPathShadow({
|
|
13955
14494
|
pathDirs,
|
|
13956
|
-
targetDir:
|
|
14495
|
+
targetDir: import_node_path30.default.dirname(ownExecutablePath),
|
|
13957
14496
|
targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
|
|
13958
14497
|
findExecutableInDir
|
|
13959
14498
|
}),
|
|
@@ -13973,11 +14512,20 @@ function collectDoctorReport(params) {
|
|
|
13973
14512
|
})(),
|
|
13974
14513
|
isRunning: realIsProcessRunning,
|
|
13975
14514
|
allowlist: {
|
|
13976
|
-
|
|
13977
|
-
|
|
14515
|
+
drift: diagnoseAllowlistDrift({
|
|
14516
|
+
allowlist: allowlistInputs.frontDoorOrigins,
|
|
14517
|
+
fileContent: allowlistContent,
|
|
14518
|
+
recordedHash: servingHeadroom?.state.allowlistHash,
|
|
14519
|
+
earlierRelease: servingEarlierRelease
|
|
14520
|
+
}),
|
|
14521
|
+
file: paths.headroomAllowlistFile,
|
|
14522
|
+
undeterminedFrontDoors: undeterminedFrontDoors(allowlistInputs),
|
|
14523
|
+
// An earlier release's daemon reads no allowlist file, so there is nothing to check while one serves.
|
|
14524
|
+
fileProblem: servingEarlierRelease === void 0 ? reportableAllowlistFileProblem(paths.headroomAllowlistFile, realHeadroomSocketTrust, servingHeadroom?.state.allowlistHash !== void 0) : void 0,
|
|
14525
|
+
logPath: paths.headroomLogPath
|
|
13978
14526
|
}
|
|
13979
14527
|
},
|
|
13980
|
-
...uid === void 0 ? {} : { frontDoor: { state: { path: paths.frontdoorStateFile, raw: realFsPort.readFileUtf8(paths.frontdoorStateFile) }, supervisors: listFrontDoorSupervisors(realRunPort, uid) } }
|
|
14528
|
+
...uid === void 0 ? {} : { frontDoor: { state: { path: paths.frontdoorStateFile, raw: realFsPort.readFileUtf8(paths.frontdoorStateFile) }, supervisors: listFrontDoorSupervisors(realRunPort, uid), liveSessions: listFrontDoorSessions(realFarmFs, paths.frontdoorSessionsDir).filter((session) => realIsProcessRunning(session.pid)) } }
|
|
13981
14529
|
});
|
|
13982
14530
|
return report;
|
|
13983
14531
|
}
|
|
@@ -14032,11 +14580,11 @@ var FrontDoorSessionsOutputSchema = import_zod23.z.strictObject({ sessions: impo
|
|
|
14032
14580
|
var CheckRunInputSchema = import_zod23.z.strictObject({
|
|
14033
14581
|
path: import_zod23.z.string().min(1),
|
|
14034
14582
|
identity: import_zod23.z.string().min(1).optional()
|
|
14035
|
-
}).refine((input) =>
|
|
14583
|
+
}).refine((input) => import_node_path31.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
14036
14584
|
var PoolPickInputSchema = import_zod23.z.strictObject({
|
|
14037
14585
|
pool: import_zod23.z.string().min(1),
|
|
14038
14586
|
path: import_zod23.z.string().min(1)
|
|
14039
|
-
}).refine((input) =>
|
|
14587
|
+
}).refine((input) => import_node_path31.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
14040
14588
|
var DoctorFindingSchema = import_zod23.z.strictObject({
|
|
14041
14589
|
section: import_zod23.z.enum(DOCTOR_SECTIONS),
|
|
14042
14590
|
subject: import_zod23.z.string().optional(),
|
|
@@ -14416,7 +14964,7 @@ function profileValue(name, paths) {
|
|
|
14416
14964
|
function createConfigApiRouter(deps) {
|
|
14417
14965
|
const authed = doorApiAuth(deps.expectedToken);
|
|
14418
14966
|
const { paths } = deps;
|
|
14419
|
-
const route = (
|
|
14967
|
+
const route = (path40, summary) => authed.meta((0, import_openapi3.openapi)({ method: "POST", path: path40, summary, tags: [CONFIG_API_TAG] }));
|
|
14420
14968
|
return {
|
|
14421
14969
|
config: {
|
|
14422
14970
|
identity: {
|
|
@@ -14780,7 +15328,7 @@ var import_openapi6 = require("@orpc/openapi");
|
|
|
14780
15328
|
init_cliError();
|
|
14781
15329
|
|
|
14782
15330
|
// src/frontdoor/launchSchemas.ts
|
|
14783
|
-
var
|
|
15331
|
+
var import_node_path32 = __toESM(require("node:path"), 1);
|
|
14784
15332
|
var import_zod26 = require("zod");
|
|
14785
15333
|
init_claudeVersion();
|
|
14786
15334
|
init_identity();
|
|
@@ -14790,7 +15338,7 @@ var LaunchResolveInputSchema = import_zod26.z.strictObject({
|
|
|
14790
15338
|
argv: import_zod26.z.readonly(import_zod26.z.array(import_zod26.z.string())).optional(),
|
|
14791
15339
|
/** 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. */
|
|
14792
15340
|
env: import_zod26.z.record(import_zod26.z.string(), import_zod26.z.string()).optional()
|
|
14793
|
-
}).refine((input) =>
|
|
15341
|
+
}).refine((input) => import_node_path32.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
14794
15342
|
var LaunchPoolDecisionSchema = import_zod26.z.strictObject({
|
|
14795
15343
|
name: import_zod26.z.string(),
|
|
14796
15344
|
reasons: import_zod26.z.readonly(import_zod26.z.array(import_zod26.z.string())),
|
|
@@ -16957,7 +17505,7 @@ data: ${JSON.stringify(envelope)}
|
|
|
16957
17505
|
}
|
|
16958
17506
|
|
|
16959
17507
|
// src/frontdoor/rcSelfHostMint.ts
|
|
16960
|
-
var
|
|
17508
|
+
var import_node_path33 = __toESM(require("node:path"), 1);
|
|
16961
17509
|
init_account();
|
|
16962
17510
|
var CREDENTIALS_FILE2 = ".credentials.json";
|
|
16963
17511
|
var CLAUDE_JSON2 = ".claude.json";
|
|
@@ -16982,7 +17530,7 @@ function readJsonObject(fs12, file) {
|
|
|
16982
17530
|
return isRecord12(parsed) ? parsed : void 0;
|
|
16983
17531
|
}
|
|
16984
17532
|
function readRcSelfHostRecord(fs12, frontdoorDir) {
|
|
16985
|
-
const parsed = readJsonObject(fs12,
|
|
17533
|
+
const parsed = readJsonObject(fs12, import_node_path33.default.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
|
|
16986
17534
|
if (parsed === void 0) {
|
|
16987
17535
|
return void 0;
|
|
16988
17536
|
}
|
|
@@ -16996,11 +17544,11 @@ function mintRcSelfHostCredential(deps) {
|
|
|
16996
17544
|
if (!isIdentityName(deps.identity)) {
|
|
16997
17545
|
throw new Error(`"${deps.identity}" is not a valid identity name.`);
|
|
16998
17546
|
}
|
|
16999
|
-
const identityDir =
|
|
17000
|
-
const credentialsFile =
|
|
17001
|
-
const claudeJsonFile =
|
|
17002
|
-
const recordDir =
|
|
17003
|
-
const recordFile =
|
|
17547
|
+
const identityDir = import_node_path33.default.join(deps.identitiesDir, deps.identity);
|
|
17548
|
+
const credentialsFile = import_node_path33.default.join(identityDir, CREDENTIALS_FILE2);
|
|
17549
|
+
const claudeJsonFile = import_node_path33.default.join(identityDir, CLAUDE_JSON2);
|
|
17550
|
+
const recordDir = import_node_path33.default.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
|
|
17551
|
+
const recordFile = import_node_path33.default.join(recordDir, RC_SELF_HOST_RECORD_FILE);
|
|
17004
17552
|
const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
|
|
17005
17553
|
const existingCredentials = readJsonObject(deps.fs, credentialsFile);
|
|
17006
17554
|
const existingOauth = isRecord12(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
|
|
@@ -17016,7 +17564,7 @@ function mintRcSelfHostCredential(deps) {
|
|
|
17016
17564
|
const organizationUuid = deps.newUuid();
|
|
17017
17565
|
const accountUuid = deps.newUuid();
|
|
17018
17566
|
const mintedAt = new Date(deps.now()).toISOString();
|
|
17019
|
-
deps.fs.mkdirPrivate(
|
|
17567
|
+
deps.fs.mkdirPrivate(import_node_path33.default.dirname(credentialsFile));
|
|
17020
17568
|
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)}
|
|
17021
17569
|
`);
|
|
17022
17570
|
const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
|
|
@@ -17058,7 +17606,7 @@ init_plan2();
|
|
|
17058
17606
|
init_poolPick();
|
|
17059
17607
|
|
|
17060
17608
|
// src/agents/read.ts
|
|
17061
|
-
var
|
|
17609
|
+
var import_node_path34 = __toESM(require("node:path"), 1);
|
|
17062
17610
|
var import_zod28 = require("zod");
|
|
17063
17611
|
var PROJECTS_DIR = "projects";
|
|
17064
17612
|
var TASKS_DIR = "tasks";
|
|
@@ -17084,15 +17632,15 @@ function parseEntry2(project, entry) {
|
|
|
17084
17632
|
}
|
|
17085
17633
|
function listSessions2(fs12, configDir) {
|
|
17086
17634
|
const found = [];
|
|
17087
|
-
for (const project of fs12.readdir(
|
|
17088
|
-
const projectDir =
|
|
17635
|
+
for (const project of fs12.readdir(import_node_path34.default.join(configDir, PROJECTS_DIR))) {
|
|
17636
|
+
const projectDir = import_node_path34.default.join(configDir, PROJECTS_DIR, project);
|
|
17089
17637
|
const entries = /* @__PURE__ */ new Set();
|
|
17090
17638
|
for (const name of fs12.readdir(projectDir)) {
|
|
17091
17639
|
if (name.endsWith(TRANSCRIPT_SUFFIX)) {
|
|
17092
17640
|
entries.add(name.slice(0, -TRANSCRIPT_SUFFIX.length));
|
|
17093
17641
|
continue;
|
|
17094
17642
|
}
|
|
17095
|
-
const children = fs12.readdir(
|
|
17643
|
+
const children = fs12.readdir(import_node_path34.default.join(projectDir, name));
|
|
17096
17644
|
if (children.includes(SUBAGENTS_DIR) || children.includes(WORKFLOWS_DIR)) {
|
|
17097
17645
|
entries.add(name);
|
|
17098
17646
|
}
|
|
@@ -17112,8 +17660,8 @@ function locateAgents(fs12, configDir, relativeDir, workflowRunId, report) {
|
|
|
17112
17660
|
const id = name.slice(AGENT_FILE_PREFIX.length, -META_SUFFIX.length);
|
|
17113
17661
|
located.push({
|
|
17114
17662
|
id,
|
|
17115
|
-
metaPath:
|
|
17116
|
-
transcriptPath:
|
|
17663
|
+
metaPath: import_node_path34.default.join(relativeDir, name),
|
|
17664
|
+
transcriptPath: import_node_path34.default.join(relativeDir, `${AGENT_FILE_PREFIX}${id}${TRANSCRIPT_SUFFIX}`),
|
|
17117
17665
|
workflowRunId
|
|
17118
17666
|
});
|
|
17119
17667
|
}
|
|
@@ -17156,7 +17704,7 @@ function describeFailure(error) {
|
|
|
17156
17704
|
}
|
|
17157
17705
|
function readFileOrReport(fs12, configDir, relative, report) {
|
|
17158
17706
|
try {
|
|
17159
|
-
return fs12.readFileUtf8(
|
|
17707
|
+
return fs12.readFileUtf8(import_node_path34.default.join(configDir, relative));
|
|
17160
17708
|
} catch (error) {
|
|
17161
17709
|
report({ path: relative, reason: `could not be read: ${describeFailure(error)}` });
|
|
17162
17710
|
return void 0;
|
|
@@ -17164,7 +17712,7 @@ function readFileOrReport(fs12, configDir, relative, report) {
|
|
|
17164
17712
|
}
|
|
17165
17713
|
function listDirOrReport(fs12, configDir, relative, report) {
|
|
17166
17714
|
try {
|
|
17167
|
-
return fs12.readdir(
|
|
17715
|
+
return fs12.readdir(import_node_path34.default.join(configDir, relative));
|
|
17168
17716
|
} catch (error) {
|
|
17169
17717
|
report({ path: relative, reason: `could not be listed: ${describeFailure(error)}` });
|
|
17170
17718
|
return [];
|
|
@@ -17188,18 +17736,18 @@ var WorkflowRunFileSchema = import_zod28.z.object({
|
|
|
17188
17736
|
summary: import_zod28.z.string().optional()
|
|
17189
17737
|
});
|
|
17190
17738
|
function summariseSession(fs12, configDir, ref) {
|
|
17191
|
-
const sessionRelative =
|
|
17192
|
-
const subagentsRelative =
|
|
17193
|
-
const workflowsUnderSubagents =
|
|
17739
|
+
const sessionRelative = import_node_path34.default.join(PROJECTS_DIR, ref.project, ref.entry);
|
|
17740
|
+
const subagentsRelative = import_node_path34.default.join(sessionRelative, SUBAGENTS_DIR);
|
|
17741
|
+
const workflowsUnderSubagents = import_node_path34.default.join(subagentsRelative, WORKFLOWS_DIR);
|
|
17194
17742
|
const isMeta = (name) => name.startsWith(AGENT_FILE_PREFIX) && name.endsWith(META_SUFFIX);
|
|
17195
|
-
let agentCount = fs12.readdir(
|
|
17196
|
-
for (const runDir of fs12.readdir(
|
|
17743
|
+
let agentCount = fs12.readdir(import_node_path34.default.join(configDir, subagentsRelative)).filter(isMeta).length;
|
|
17744
|
+
for (const runDir of fs12.readdir(import_node_path34.default.join(configDir, workflowsUnderSubagents))) {
|
|
17197
17745
|
if (runDir.startsWith(WORKFLOW_RUN_PREFIX)) {
|
|
17198
|
-
agentCount += fs12.readdir(
|
|
17746
|
+
agentCount += fs12.readdir(import_node_path34.default.join(configDir, workflowsUnderSubagents, runDir)).filter(isMeta).length;
|
|
17199
17747
|
}
|
|
17200
17748
|
}
|
|
17201
|
-
const workflowRunCount = fs12.readdir(
|
|
17202
|
-
const transcript = fs12.lstat(
|
|
17749
|
+
const workflowRunCount = fs12.readdir(import_node_path34.default.join(configDir, sessionRelative, WORKFLOWS_DIR)).filter((name) => name.startsWith(WORKFLOW_RUN_PREFIX) && name.endsWith(JSON_SUFFIX)).length;
|
|
17750
|
+
const transcript = fs12.lstat(import_node_path34.default.join(configDir, PROJECTS_DIR, ref.project, `${ref.entry}${TRANSCRIPT_SUFFIX}`));
|
|
17203
17751
|
return { ...ref, agentCount, workflowRunCount, ...transcript === void 0 ? {} : { updatedAt: new Date(transcript.mtimeMs).toISOString() } };
|
|
17204
17752
|
}
|
|
17205
17753
|
function readSessionAgentTree(fs12, configDir, ref, options = {}) {
|
|
@@ -17207,13 +17755,13 @@ function readSessionAgentTree(fs12, configDir, ref, options = {}) {
|
|
|
17207
17755
|
const report = (problem) => {
|
|
17208
17756
|
problems.push(problem);
|
|
17209
17757
|
};
|
|
17210
|
-
const sessionRelative =
|
|
17211
|
-
const subagentsRelative =
|
|
17212
|
-
const workflowsUnderSubagents =
|
|
17758
|
+
const sessionRelative = import_node_path34.default.join(PROJECTS_DIR, ref.project, ref.entry);
|
|
17759
|
+
const subagentsRelative = import_node_path34.default.join(sessionRelative, SUBAGENTS_DIR);
|
|
17760
|
+
const workflowsUnderSubagents = import_node_path34.default.join(subagentsRelative, WORKFLOWS_DIR);
|
|
17213
17761
|
const located = locateAgents(fs12, configDir, subagentsRelative, void 0, report);
|
|
17214
17762
|
for (const runDir of listDirOrReport(fs12, configDir, workflowsUnderSubagents, report)) {
|
|
17215
17763
|
if (runDir.startsWith(WORKFLOW_RUN_PREFIX)) {
|
|
17216
|
-
located.push(...locateAgents(fs12, configDir,
|
|
17764
|
+
located.push(...locateAgents(fs12, configDir, import_node_path34.default.join(workflowsUnderSubagents, runDir), runDir, report));
|
|
17217
17765
|
}
|
|
17218
17766
|
}
|
|
17219
17767
|
const agents = /* @__PURE__ */ new Map();
|
|
@@ -17254,7 +17802,7 @@ function readSessionAgentTree(fs12, configDir, ref, options = {}) {
|
|
|
17254
17802
|
superseded: ref.superseded,
|
|
17255
17803
|
agents: roots.sort().map(build),
|
|
17256
17804
|
tasks: readTasks(fs12, configDir, ownTaskLists(ref.sessionId), [.../* @__PURE__ */ new Set([...teamNames, ...options.taskListIds ?? []])].filter((id) => !ownTaskLists(ref.sessionId).includes(id)), report),
|
|
17257
|
-
workflowRuns: readWorkflowRuns(fs12, configDir,
|
|
17805
|
+
workflowRuns: readWorkflowRuns(fs12, configDir, import_node_path34.default.join(sessionRelative, WORKFLOWS_DIR), report),
|
|
17258
17806
|
problems
|
|
17259
17807
|
};
|
|
17260
17808
|
}
|
|
@@ -17319,12 +17867,12 @@ function ownTaskLists(sessionId) {
|
|
|
17319
17867
|
function readTasks(fs12, configDir, ownLists, sharedLists, report) {
|
|
17320
17868
|
const tasks = [];
|
|
17321
17869
|
[...ownLists, ...sharedLists].forEach((scope, index) => {
|
|
17322
|
-
const relativeDir =
|
|
17870
|
+
const relativeDir = import_node_path34.default.join(TASKS_DIR, scope);
|
|
17323
17871
|
for (const name of [...listDirOrReport(fs12, configDir, relativeDir, report)].sort()) {
|
|
17324
17872
|
if (name.startsWith(".") || !name.endsWith(JSON_SUFFIX)) {
|
|
17325
17873
|
continue;
|
|
17326
17874
|
}
|
|
17327
|
-
const relative =
|
|
17875
|
+
const relative = import_node_path34.default.join(relativeDir, name);
|
|
17328
17876
|
const text = readFileOrReport(fs12, configDir, relative, report);
|
|
17329
17877
|
const parsed = TaskFileSchema.safeParse(text === void 0 ? void 0 : parseJson2(text));
|
|
17330
17878
|
if (parsed.success) {
|
|
@@ -17342,7 +17890,7 @@ function readWorkflowRuns(fs12, configDir, relativeDir, report) {
|
|
|
17342
17890
|
if (!name.startsWith(WORKFLOW_RUN_PREFIX) || !name.endsWith(JSON_SUFFIX)) {
|
|
17343
17891
|
continue;
|
|
17344
17892
|
}
|
|
17345
|
-
const relative =
|
|
17893
|
+
const relative = import_node_path34.default.join(relativeDir, name);
|
|
17346
17894
|
const text = readFileOrReport(fs12, configDir, relative, report);
|
|
17347
17895
|
const parsed = WorkflowRunFileSchema.safeParse(text === void 0 ? void 0 : parseJson2(text));
|
|
17348
17896
|
if (!parsed.success) {
|
|
@@ -17358,7 +17906,7 @@ function readWorkflowRuns(fs12, configDir, relativeDir, report) {
|
|
|
17358
17906
|
}
|
|
17359
17907
|
|
|
17360
17908
|
// src/agents/sessions.ts
|
|
17361
|
-
var
|
|
17909
|
+
var import_node_path35 = __toESM(require("node:path"), 1);
|
|
17362
17910
|
init_cliError();
|
|
17363
17911
|
var SessionLookupError = class extends CliError {
|
|
17364
17912
|
constructor(message) {
|
|
@@ -17367,13 +17915,13 @@ var SessionLookupError = class extends CliError {
|
|
|
17367
17915
|
}
|
|
17368
17916
|
};
|
|
17369
17917
|
function identityConfigDir(identitiesDir, identity) {
|
|
17370
|
-
return
|
|
17918
|
+
return import_node_path35.default.join(identitiesDir, identity);
|
|
17371
17919
|
}
|
|
17372
17920
|
function historyStores(fs12, identitiesDir, identities) {
|
|
17373
17921
|
const byRealPath = /* @__PURE__ */ new Map();
|
|
17374
17922
|
for (const identity of identities) {
|
|
17375
17923
|
const configDir = identityConfigDir(identitiesDir, identity);
|
|
17376
|
-
const real = fs12.realpath(
|
|
17924
|
+
const real = fs12.realpath(import_node_path35.default.join(configDir, "projects"));
|
|
17377
17925
|
if (real === void 0) {
|
|
17378
17926
|
continue;
|
|
17379
17927
|
}
|
|
@@ -17826,6 +18374,7 @@ init_ownCli();
|
|
|
17826
18374
|
isRcReadFileEncoding,
|
|
17827
18375
|
lateRcEventDial,
|
|
17828
18376
|
lateRcStreamDial,
|
|
18377
|
+
launchRequiredUpstreams,
|
|
17829
18378
|
listDirectoryRules,
|
|
17830
18379
|
listIdentities,
|
|
17831
18380
|
listProfiles,
|