claude-use 9.19.1 → 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.mjs
CHANGED
|
@@ -450,7 +450,7 @@ var init_schema = __esm({
|
|
|
450
450
|
context.addIssue({ code: "custom", path: ["readMaturation"], message: "readMaturation needs rolloutChannel beta or dev" });
|
|
451
451
|
}
|
|
452
452
|
});
|
|
453
|
-
HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@
|
|
453
|
+
HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@ca7589c574bfd52919503a74f09f4d1fe5ecf106";
|
|
454
454
|
HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES = 15;
|
|
455
455
|
FrontDoorGlobalConfigSchema = z.strictObject({
|
|
456
456
|
/** How long the front door may sit with no registered sessions before it closes and exits. Defaults to FRONTDOOR_DEFAULT_IDLE_SHUTDOWN_MINUTES. */
|
|
@@ -2585,9 +2585,71 @@ function writeFrontDoorState(fs12, stateFile, state) {
|
|
|
2585
2585
|
fs12.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
|
|
2586
2586
|
`);
|
|
2587
2587
|
}
|
|
2588
|
+
function directOrigin(port) {
|
|
2589
|
+
return `http://127.0.0.1:${String(port)}`;
|
|
2590
|
+
}
|
|
2588
2591
|
function frontDoorOrigin(state) {
|
|
2589
2592
|
const port = state?.directPort ?? state?.lastDirectPort;
|
|
2590
|
-
return port === void 0 ? void 0 :
|
|
2593
|
+
return port === void 0 ? void 0 : directOrigin(port);
|
|
2594
|
+
}
|
|
2595
|
+
function writeFrontDoorDirectRecord(fs12, recordsDir, record) {
|
|
2596
|
+
fs12.mkdirp(recordsDir);
|
|
2597
|
+
fs12.writeFilePrivate(path8.join(recordsDir, `${String(record.pid)}.json`), `${JSON.stringify({ directPort: record.directPort })}
|
|
2598
|
+
`);
|
|
2599
|
+
}
|
|
2600
|
+
function removeFrontDoorDirectRecord(fs12, recordsDir, pid) {
|
|
2601
|
+
fs12.removeRecursive(path8.join(recordsDir, `${String(pid)}.json`));
|
|
2602
|
+
}
|
|
2603
|
+
function recordPid(file) {
|
|
2604
|
+
const pidText = /^([1-9]\d*)\.json$/.exec(file)?.[1];
|
|
2605
|
+
const pid = pidText === void 0 ? void 0 : Number(pidText);
|
|
2606
|
+
return pid !== void 0 && Number.isSafeInteger(pid) ? pid : void 0;
|
|
2607
|
+
}
|
|
2608
|
+
function readDirectRecordEntry(fs12, recordsDir, file) {
|
|
2609
|
+
const pid = recordPid(file);
|
|
2610
|
+
if (pid === void 0) {
|
|
2611
|
+
return void 0;
|
|
2612
|
+
}
|
|
2613
|
+
let raw;
|
|
2614
|
+
try {
|
|
2615
|
+
raw = fs12.readFileUtf8(path8.join(recordsDir, file));
|
|
2616
|
+
} catch {
|
|
2617
|
+
return void 0;
|
|
2618
|
+
}
|
|
2619
|
+
if (raw === void 0) {
|
|
2620
|
+
return void 0;
|
|
2621
|
+
}
|
|
2622
|
+
try {
|
|
2623
|
+
const parsed = FrontDoorDirectRecordSchema.safeParse(JSON.parse(raw));
|
|
2624
|
+
return parsed.success ? { record: { pid, directPort: parsed.data.directPort } } : { malformed: true };
|
|
2625
|
+
} catch {
|
|
2626
|
+
return { malformed: true };
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
function listFrontDoorDirectRecords(fs12, recordsDir) {
|
|
2630
|
+
return fs12.readdir(recordsDir).flatMap((file) => {
|
|
2631
|
+
const entry = readDirectRecordEntry(fs12, recordsDir, file);
|
|
2632
|
+
return entry?.record === void 0 ? [] : [entry.record];
|
|
2633
|
+
}).sort((a, b) => a.pid - b.pid);
|
|
2634
|
+
}
|
|
2635
|
+
function pruneMalformedFrontDoorDirectFiles(fs12, recordsDir, isRunning) {
|
|
2636
|
+
for (const file of fs12.readdir(recordsDir)) {
|
|
2637
|
+
const writer = RECORD_TEMPORARY_FILE.exec(file)?.[1];
|
|
2638
|
+
const stale = writer !== void 0 && !isRunning(Number(writer));
|
|
2639
|
+
if (stale || readDirectRecordEntry(fs12, recordsDir, file)?.malformed === true) {
|
|
2640
|
+
fs12.removeRecursive(path8.join(recordsDir, file));
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
function liveFrontDoorDirectRecords(records, liveness) {
|
|
2645
|
+
return records.filter((record) => liveness.doors.has(record.pid) || liveness.unknown.has(record.pid));
|
|
2646
|
+
}
|
|
2647
|
+
function pruneDeadFrontDoorDirectRecords(fs12, recordsDir, records, liveness) {
|
|
2648
|
+
for (const record of records) {
|
|
2649
|
+
if (!liveness.doors.has(record.pid) && !liveness.unknown.has(record.pid)) {
|
|
2650
|
+
removeFrontDoorDirectRecord(fs12, recordsDir, record.pid);
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2591
2653
|
}
|
|
2592
2654
|
function writeFrontDoorSession(fs12, sessionsDir, session) {
|
|
2593
2655
|
fs12.mkdirPrivate(sessionsDir);
|
|
@@ -2624,7 +2686,7 @@ function pruneDeadFrontDoorSessions(fs12, sessionsDir, isRunning) {
|
|
|
2624
2686
|
}
|
|
2625
2687
|
return removed;
|
|
2626
2688
|
}
|
|
2627
|
-
var FRONT_DOOR_PROTOCOL, FrontDoorSessionSchema, FrontDoorStateSchema;
|
|
2689
|
+
var FRONT_DOOR_PROTOCOL, FrontDoorSessionSchema, FrontDoorStateSchema, MAX_TCP_PORT, FrontDoorDirectRecordSchema, RECORD_TEMPORARY_FILE;
|
|
2628
2690
|
var init_state = __esm({
|
|
2629
2691
|
"src/frontdoor/state.ts"() {
|
|
2630
2692
|
"use strict";
|
|
@@ -2652,7 +2714,7 @@ var init_state = __esm({
|
|
|
2652
2714
|
*/
|
|
2653
2715
|
lastConnectPort: z3.number().int().positive().optional(),
|
|
2654
2716
|
/**
|
|
2655
|
-
* 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
|
|
2717
|
+
* 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.
|
|
2656
2718
|
*/
|
|
2657
2719
|
directPort: z3.number().int().positive().optional(),
|
|
2658
2720
|
/** The sticky port preference for the direct listener, for the reason `directPort` gives. */
|
|
@@ -2660,6 +2722,9 @@ var init_state = __esm({
|
|
|
2660
2722
|
/** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
|
|
2661
2723
|
lastError: z3.string().optional()
|
|
2662
2724
|
});
|
|
2725
|
+
MAX_TCP_PORT = 65535;
|
|
2726
|
+
FrontDoorDirectRecordSchema = z3.strictObject({ directPort: z3.number().int().positive().max(MAX_TCP_PORT) });
|
|
2727
|
+
RECORD_TEMPORARY_FILE = /^[1-9]\d*\.json\.([1-9]\d*)\.tmp$/;
|
|
2663
2728
|
}
|
|
2664
2729
|
});
|
|
2665
2730
|
|
|
@@ -2669,7 +2734,7 @@ var init_package = __esm({
|
|
|
2669
2734
|
"package.json"() {
|
|
2670
2735
|
package_default = {
|
|
2671
2736
|
name: "claude-use",
|
|
2672
|
-
version: "
|
|
2737
|
+
version: "10.0.0",
|
|
2673
2738
|
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.",
|
|
2674
2739
|
license: "MIT",
|
|
2675
2740
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -2794,11 +2859,75 @@ function listFrontDoorSupervisors(run, uid) {
|
|
|
2794
2859
|
}
|
|
2795
2860
|
return { ok: true, pids: parseFrontDoorSupervisorPids(result.stdout) };
|
|
2796
2861
|
}
|
|
2797
|
-
|
|
2862
|
+
function frontDoorLivenessFromPs(run, asked) {
|
|
2863
|
+
if (refusedEveryPidAsTooLarge(run, asked)) {
|
|
2864
|
+
return { doors: /* @__PURE__ */ new Set(), unknown: /* @__PURE__ */ new Map() };
|
|
2865
|
+
}
|
|
2866
|
+
const failure = psFailure(run);
|
|
2867
|
+
if (failure !== void 0) {
|
|
2868
|
+
return { doors: /* @__PURE__ */ new Set(), unknown: new Map(asked.map((pid) => [pid, failure])) };
|
|
2869
|
+
}
|
|
2870
|
+
const askedSet = new Set(asked);
|
|
2871
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2872
|
+
const doors = /* @__PURE__ */ new Set();
|
|
2873
|
+
for (const line of run.stdout.split("\n")) {
|
|
2874
|
+
const [pidText, stat, ...argumentsList] = line.trim().split(/\s+/);
|
|
2875
|
+
const pid = Number(pidText);
|
|
2876
|
+
if (!askedSet.has(pid) || seen.has(pid)) {
|
|
2877
|
+
continue;
|
|
2878
|
+
}
|
|
2879
|
+
seen.add(pid);
|
|
2880
|
+
if (stat !== void 0 && !stat.startsWith("Z") && argumentsList.includes(FRONT_DOOR_SUPERVISOR_ARGUMENT)) {
|
|
2881
|
+
doors.add(pid);
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
return { doors, unknown: /* @__PURE__ */ new Map() };
|
|
2885
|
+
}
|
|
2886
|
+
function refusedEveryPidAsTooLarge(run, asked) {
|
|
2887
|
+
const lines = run.stderr.split("\n").filter((line) => line.trim() !== "");
|
|
2888
|
+
const tooLarge = new Set(lines.map((line) => Number(PID_TOO_LARGE.exec(line.trim())?.[1])));
|
|
2889
|
+
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));
|
|
2890
|
+
}
|
|
2891
|
+
function psFailure(run) {
|
|
2892
|
+
if (run.error !== void 0) {
|
|
2893
|
+
return run.error.message;
|
|
2894
|
+
}
|
|
2895
|
+
if (run.status === null) {
|
|
2896
|
+
return "ps was terminated before it answered";
|
|
2897
|
+
}
|
|
2898
|
+
const noneExist = run.status === 1 && run.stdout.trim() === "" && run.stderr.trim() === "";
|
|
2899
|
+
if (run.status !== 0 && !noneExist) {
|
|
2900
|
+
return `ps exited ${String(run.status)}${run.stderr.trim() === "" ? "" : `: ${run.stderr.trim()}`}`;
|
|
2901
|
+
}
|
|
2902
|
+
return void 0;
|
|
2903
|
+
}
|
|
2904
|
+
function frontDoorLivenessOf(pids, runPs) {
|
|
2905
|
+
if (pids.length === 0) {
|
|
2906
|
+
return { doors: /* @__PURE__ */ new Set(), unknown: /* @__PURE__ */ new Map() };
|
|
2907
|
+
}
|
|
2908
|
+
const batch = frontDoorLivenessFromPs(runPs(pids), pids);
|
|
2909
|
+
if (batch.unknown.size === 0 || pids.length === 1) {
|
|
2910
|
+
return batch;
|
|
2911
|
+
}
|
|
2912
|
+
const doors = /* @__PURE__ */ new Set();
|
|
2913
|
+
const unknown = /* @__PURE__ */ new Map();
|
|
2914
|
+
for (const pid of pids) {
|
|
2915
|
+
const single = frontDoorLivenessFromPs(runPs([pid]), [pid]);
|
|
2916
|
+
for (const door of single.doors) {
|
|
2917
|
+
doors.add(door);
|
|
2918
|
+
}
|
|
2919
|
+
for (const [unanswered, reason] of single.unknown) {
|
|
2920
|
+
unknown.set(unanswered, reason);
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
return { doors, unknown };
|
|
2924
|
+
}
|
|
2925
|
+
var FRONT_DOOR_SUPERVISOR_ARGUMENT, PID_TOO_LARGE;
|
|
2798
2926
|
var init_supervisorProcesses = __esm({
|
|
2799
2927
|
"src/frontdoor/supervisorProcesses.ts"() {
|
|
2800
2928
|
"use strict";
|
|
2801
2929
|
FRONT_DOOR_SUPERVISOR_ARGUMENT = "__frontdoor-supervisor";
|
|
2930
|
+
PID_TOO_LARGE = /^ps: process id too large: (\d+)$/;
|
|
2802
2931
|
}
|
|
2803
2932
|
});
|
|
2804
2933
|
|
|
@@ -2851,22 +2980,49 @@ function migrateHeadroomState(fs12, files, isRunning) {
|
|
|
2851
2980
|
}
|
|
2852
2981
|
fs12.removeRecursive(files.legacyStateFile);
|
|
2853
2982
|
}
|
|
2854
|
-
function
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2983
|
+
function hashAllowlist(allowlist) {
|
|
2984
|
+
return createHash3("sha256").update(allowlist.join("\n")).digest("hex");
|
|
2985
|
+
}
|
|
2986
|
+
function formatAllowlistFile(allowlist) {
|
|
2987
|
+
return allowlist.map((entry) => `${entry}
|
|
2988
|
+
`).join("");
|
|
2989
|
+
}
|
|
2990
|
+
function hashAllowlistFile(content) {
|
|
2991
|
+
return hashAllowlist([...new Set(parseAllowlistFile(content))].sort());
|
|
2992
|
+
}
|
|
2993
|
+
function isBareHost(entry) {
|
|
2994
|
+
if (/[/?#@]/.test(entry)) {
|
|
2995
|
+
return false;
|
|
2996
|
+
}
|
|
2997
|
+
if (entry.startsWith("[")) {
|
|
2998
|
+
const close = entry.indexOf("]");
|
|
2999
|
+
return close > 1 && !entry.slice(close + 1).includes(":");
|
|
2858
3000
|
}
|
|
2859
|
-
return
|
|
3001
|
+
return entry !== "" && !entry.includes(":");
|
|
2860
3002
|
}
|
|
2861
|
-
function
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
3003
|
+
function isAdmissibleUrl(entry) {
|
|
3004
|
+
try {
|
|
3005
|
+
const url = new URL(entry);
|
|
3006
|
+
return ALLOWLIST_SAFE_SCHEMES.has(url.protocol) && url.hostname !== "";
|
|
3007
|
+
} catch {
|
|
3008
|
+
return false;
|
|
2865
3009
|
}
|
|
2866
|
-
return upstreams;
|
|
2867
3010
|
}
|
|
2868
|
-
function
|
|
2869
|
-
return
|
|
3011
|
+
function parseAllowlistFile(content) {
|
|
3012
|
+
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)));
|
|
3013
|
+
}
|
|
3014
|
+
function writeAllowlistFile(fs12, allowlistFile, allowlist) {
|
|
3015
|
+
fs12.mkdirPrivate(path11.dirname(allowlistFile));
|
|
3016
|
+
fs12.writeFilePrivate(allowlistFile, formatAllowlistFile(allowlist));
|
|
3017
|
+
}
|
|
3018
|
+
function pruneStaleAllowlistTemporaries(fs12, allowlistFile, isRunning) {
|
|
3019
|
+
const prefix = `${path11.basename(allowlistFile)}.`;
|
|
3020
|
+
for (const name of fs12.readdir(path11.dirname(allowlistFile))) {
|
|
3021
|
+
const writer = name.startsWith(prefix) ? /^([1-9]\d*)\.tmp$/.exec(name.slice(prefix.length))?.[1] : void 0;
|
|
3022
|
+
if (writer !== void 0 && !isRunning(Number(writer))) {
|
|
3023
|
+
fs12.removeRecursive(path11.join(path11.dirname(allowlistFile), name));
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
2870
3026
|
}
|
|
2871
3027
|
function readAllProviders(fs12, providersDir) {
|
|
2872
3028
|
const result = [];
|
|
@@ -2930,16 +3086,15 @@ function readStartLock(fs12, lockFile) {
|
|
|
2930
3086
|
return void 0;
|
|
2931
3087
|
}
|
|
2932
3088
|
}
|
|
2933
|
-
var
|
|
3089
|
+
var 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;
|
|
2934
3090
|
var init_state2 = __esm({
|
|
2935
3091
|
"src/headroom/state.ts"() {
|
|
2936
3092
|
"use strict";
|
|
2937
3093
|
init_schema();
|
|
2938
|
-
HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
|
|
2939
3094
|
HeadroomStateSchema = z8.strictObject({
|
|
2940
3095
|
/** The supervisor process owning the daemon. Alive means someone is keeping headroom running. */
|
|
2941
3096
|
supervisorPid: z8.number().int().positive().optional(),
|
|
2942
|
-
/** The headroom proxy process itself. Absent while the supervisor is between restarts. */
|
|
3097
|
+
/** 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. */
|
|
2943
3098
|
headroomPid: z8.number().int().positive().optional(),
|
|
2944
3099
|
/**
|
|
2945
3100
|
* 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.
|
|
@@ -2947,7 +3102,9 @@ var init_state2 = __esm({
|
|
|
2947
3102
|
socketPath: z8.string().min(1).optional(),
|
|
2948
3103
|
/** The `headroom --version` output of the running install. */
|
|
2949
3104
|
version: z8.string().optional(),
|
|
2950
|
-
/**
|
|
3105
|
+
/**
|
|
3106
|
+
* 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`).
|
|
3107
|
+
*/
|
|
2951
3108
|
allowlistHash: z8.string().optional(),
|
|
2952
3109
|
/** Hash of the token-saving settings the running proxy was started with, so a settings change is detected as drift. */
|
|
2953
3110
|
settingsHash: z8.string().optional(),
|
|
@@ -2958,33 +3115,133 @@ var init_state2 = __esm({
|
|
|
2958
3115
|
});
|
|
2959
3116
|
HeadroomSessionSchema = z8.strictObject({ pid: z8.number().int().positive(), startedAt: z8.number(), supervisorPid: z8.number().int().positive() });
|
|
2960
3117
|
HeadroomLockSchema = z8.strictObject({ pid: z8.number().int().positive(), at: z8.number() });
|
|
3118
|
+
HEADROOM_ALLOWLIST_FILE_FLAG = "--allowed-base-urls-file";
|
|
3119
|
+
ALLOWLIST_LINE_BREAKS = "\\n\\r\\u000b\\u000c\\u001c\\u001d\\u001e\\u0085\\u2028\\u2029";
|
|
3120
|
+
ALLOWLIST_WHITESPACE = "\\t\\n\\u000b\\u000c\\r\\u001c-\\u001f \\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000";
|
|
3121
|
+
ALLOWLIST_FILE_SEPARATORS = new RegExp(`[,\\t${ALLOWLIST_LINE_BREAKS}]`, "u");
|
|
3122
|
+
ALLOWLIST_FILE_COMMENT = new RegExp(`(?:^|(?<=[${ALLOWLIST_WHITESPACE}]))#[^${ALLOWLIST_LINE_BREAKS}]*`, "gu");
|
|
3123
|
+
ALLOWLIST_ENTRY_WHITESPACE = new RegExp(`[${ALLOWLIST_WHITESPACE}]`, "u");
|
|
3124
|
+
ALLOWLIST_SURROUNDING_WHITESPACE = new RegExp(`^[${ALLOWLIST_WHITESPACE}]+|[${ALLOWLIST_WHITESPACE}]+$`, "gu");
|
|
3125
|
+
ALLOWLIST_SAFE_SCHEMES = /* @__PURE__ */ new Set(["http:", "https:", "ws:", "wss:"]);
|
|
3126
|
+
}
|
|
3127
|
+
});
|
|
3128
|
+
|
|
3129
|
+
// src/headroom/earlierRelease.ts
|
|
3130
|
+
function withoutOurSocket(commandLine, socketPath) {
|
|
3131
|
+
for (const argument of [`--uds ${socketPath}`, `--uds=${socketPath}`]) {
|
|
3132
|
+
let from = 0;
|
|
3133
|
+
for (; ; ) {
|
|
3134
|
+
const index = commandLine.indexOf(argument, from);
|
|
3135
|
+
if (index === -1) {
|
|
3136
|
+
break;
|
|
3137
|
+
}
|
|
3138
|
+
const end = index + argument.length;
|
|
3139
|
+
const startsArgument = index === 0 || /\s/.test(commandLine.charAt(index - 1));
|
|
3140
|
+
const endsArgument = end === commandLine.length || /\s/.test(commandLine.charAt(end));
|
|
3141
|
+
if (startsArgument && endsArgument) {
|
|
3142
|
+
return `${commandLine.slice(0, index)} ${commandLine.slice(end)}`;
|
|
3143
|
+
}
|
|
3144
|
+
from = index + 1;
|
|
3145
|
+
}
|
|
3146
|
+
}
|
|
3147
|
+
return void 0;
|
|
3148
|
+
}
|
|
3149
|
+
function daemonIdentity(commandLine, socketPath) {
|
|
3150
|
+
if (commandLine === void 0) {
|
|
3151
|
+
return "unreadable";
|
|
3152
|
+
}
|
|
3153
|
+
const rest = withoutOurSocket(commandLine, socketPath);
|
|
3154
|
+
const argumentsList = rest === void 0 ? [] : rest.trim().split(/\s+/);
|
|
3155
|
+
if (rest === void 0 || !argumentsList.includes("proxy")) {
|
|
3156
|
+
return "not-headroom";
|
|
3157
|
+
}
|
|
3158
|
+
return argumentsList.some((argument) => argument === HEADROOM_ALLOWLIST_FILE_FLAG || argument.startsWith(`${HEADROOM_ALLOWLIST_FILE_FLAG}=`)) ? "this-release" : "earlier-release";
|
|
3159
|
+
}
|
|
3160
|
+
function earlierReleaseAllowlistHash(providers, doorOrigin) {
|
|
3161
|
+
const entries = /* @__PURE__ */ new Set([EARLIER_RELEASE_ANTHROPIC_UPSTREAM]);
|
|
3162
|
+
for (const provider of providers) {
|
|
3163
|
+
if (!isCodexProvider(provider)) {
|
|
3164
|
+
entries.add(provider.baseUrl);
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
if (providers.length > 0 && doorOrigin !== void 0) {
|
|
3168
|
+
entries.add(doorOrigin);
|
|
3169
|
+
}
|
|
3170
|
+
return hashAllowlist([...entries].sort());
|
|
3171
|
+
}
|
|
3172
|
+
function earlierReleaseDaemon(fs12, paths, daemon) {
|
|
3173
|
+
if (daemonIdentity(daemon.commandLine, daemon.socketPath) !== "earlier-release") {
|
|
3174
|
+
return void 0;
|
|
3175
|
+
}
|
|
3176
|
+
const providers = readAllProviders(fs12, paths.providersDir).map((entry) => entry.provider);
|
|
3177
|
+
const expected = earlierReleaseAllowlistHash(providers, frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile)));
|
|
3178
|
+
return { admitsServingDoor: daemon.recordedHash === expected };
|
|
3179
|
+
}
|
|
3180
|
+
var EARLIER_RELEASE_ALLOWLIST, EARLIER_RELEASE_ANTHROPIC_UPSTREAM;
|
|
3181
|
+
var init_earlierRelease = __esm({
|
|
3182
|
+
"src/headroom/earlierRelease.ts"() {
|
|
3183
|
+
"use strict";
|
|
3184
|
+
init_schema();
|
|
3185
|
+
init_state();
|
|
3186
|
+
init_state2();
|
|
3187
|
+
EARLIER_RELEASE_ALLOWLIST = "started by an earlier release with an allowlist fixed at start; it restarts once its sessions end";
|
|
3188
|
+
EARLIER_RELEASE_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
|
|
2961
3189
|
}
|
|
2962
3190
|
});
|
|
2963
3191
|
|
|
2964
3192
|
// src/headroom/ensure.ts
|
|
3193
|
+
function awaitingCause(daemonPid, identity, allowlistFile) {
|
|
3194
|
+
if (identity === "unreadable") {
|
|
3195
|
+
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`;
|
|
3196
|
+
}
|
|
3197
|
+
if (identity === "not-headroom") {
|
|
3198
|
+
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`;
|
|
3199
|
+
}
|
|
3200
|
+
return `the headroom supervisor has not written an allowlist admitting this launch's upstreams to ${allowlistFile} within ${String(HEADROOM_START_TIMEOUT_MS)}ms`;
|
|
3201
|
+
}
|
|
3202
|
+
function daemonAdmits(fs12, allowlistFile, recordedHash, required) {
|
|
3203
|
+
const content = fs12.readFileUtf8(allowlistFile);
|
|
3204
|
+
if (content === void 0 || recordedHash === void 0) {
|
|
3205
|
+
return false;
|
|
3206
|
+
}
|
|
3207
|
+
const served = parseAllowlistFile(content);
|
|
3208
|
+
return recordedHash === hashAllowlistFile(content) && required.every((upstream) => served.includes(upstream));
|
|
3209
|
+
}
|
|
2965
3210
|
function ensureHeadroom(params) {
|
|
2966
3211
|
const { paths, ports } = params;
|
|
2967
3212
|
const deadline = ports.now() + HEADROOM_START_TIMEOUT_MS;
|
|
2968
3213
|
let spawnedSupervisor = false;
|
|
2969
|
-
let awaitingAllowlist = false;
|
|
2970
3214
|
migrateHeadroomState(ports.fs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning);
|
|
3215
|
+
const commandLines = /* @__PURE__ */ new Map();
|
|
3216
|
+
const commandLineOf = (pid) => {
|
|
3217
|
+
if (!commandLines.has(pid)) {
|
|
3218
|
+
commandLines.set(pid, ports.daemonCommandLine(pid));
|
|
3219
|
+
}
|
|
3220
|
+
return commandLines.get(pid);
|
|
3221
|
+
};
|
|
2971
3222
|
for (; ; ) {
|
|
3223
|
+
let awaiting;
|
|
2972
3224
|
const state = resolveServingHeadroomState(ports.fs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning)?.state;
|
|
2973
3225
|
if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
|
|
2974
3226
|
const daemonUp = state.socketPath !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
|
|
2975
|
-
if (daemonUp && state.socketPath !== void 0) {
|
|
2976
|
-
const required = params.
|
|
2977
|
-
if (required === void 0 || state.allowlistHash
|
|
3227
|
+
if (daemonUp && state.socketPath !== void 0 && state.headroomPid !== void 0) {
|
|
3228
|
+
const required = params.requiredUpstreams?.();
|
|
3229
|
+
if (required === void 0 || daemonAdmits(ports.fs, paths.headroomAllowlistFile, state.allowlistHash, required)) {
|
|
2978
3230
|
writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
|
|
2979
3231
|
return { socketPath: state.socketPath };
|
|
2980
3232
|
}
|
|
2981
|
-
const
|
|
2982
|
-
|
|
3233
|
+
const commandLine = commandLineOf(state.headroomPid);
|
|
3234
|
+
const earlierRelease = earlierReleaseDaemon(ports.fs, paths, { commandLine, socketPath: state.socketPath, recordedHash: state.allowlistHash });
|
|
3235
|
+
if (earlierRelease !== void 0) {
|
|
3236
|
+
if (earlierRelease.admitsServingDoor) {
|
|
3237
|
+
writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
|
|
3238
|
+
return { socketPath: state.socketPath };
|
|
3239
|
+
}
|
|
2983
3240
|
throw new HeadroomStartError(
|
|
2984
|
-
`the running headroom daemon was
|
|
3241
|
+
`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}`
|
|
2985
3242
|
);
|
|
2986
3243
|
}
|
|
2987
|
-
|
|
3244
|
+
awaiting = { daemonPid: state.headroomPid, identity: daemonIdentity(commandLine, state.socketPath) };
|
|
2988
3245
|
}
|
|
2989
3246
|
if (state.lastError !== void 0) {
|
|
2990
3247
|
throw new HeadroomStartError(
|
|
@@ -3010,10 +3267,11 @@ function ensureHeadroom(params) {
|
|
|
3010
3267
|
}
|
|
3011
3268
|
}
|
|
3012
3269
|
if (ports.now() >= deadline) {
|
|
3013
|
-
const lastError = state?.lastError
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3270
|
+
const lastError = state?.lastError === void 0 ? "" : ` (last error: ${state.lastError})`;
|
|
3271
|
+
if (awaiting !== void 0) {
|
|
3272
|
+
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}`);
|
|
3273
|
+
}
|
|
3274
|
+
throw new HeadroomStartError(`the headroom daemon did not become ready within ${String(HEADROOM_START_TIMEOUT_MS)}ms${lastError}. Daemon log: ${paths.headroomLogPath}`);
|
|
3017
3275
|
}
|
|
3018
3276
|
ports.sleep(HEADROOM_LAUNCHER_POLL_MS);
|
|
3019
3277
|
}
|
|
@@ -3023,6 +3281,7 @@ var init_ensure = __esm({
|
|
|
3023
3281
|
"src/headroom/ensure.ts"() {
|
|
3024
3282
|
"use strict";
|
|
3025
3283
|
init_cliError();
|
|
3284
|
+
init_earlierRelease();
|
|
3026
3285
|
init_state2();
|
|
3027
3286
|
HEADROOM_START_TIMEOUT_MS = 12e4;
|
|
3028
3287
|
HEADROOM_LAUNCHER_POLL_MS = 250;
|
|
@@ -3069,6 +3328,22 @@ var init_settings = __esm({
|
|
|
3069
3328
|
}
|
|
3070
3329
|
});
|
|
3071
3330
|
|
|
3331
|
+
// src/frontdoor/capture.ts
|
|
3332
|
+
function redactText(text) {
|
|
3333
|
+
return SECRET_BODY_PATTERNS.reduce((accumulated, { pattern, replacement }) => accumulated.replace(pattern, replacement), text);
|
|
3334
|
+
}
|
|
3335
|
+
var SECRET_BODY_PATTERNS;
|
|
3336
|
+
var init_capture = __esm({
|
|
3337
|
+
"src/frontdoor/capture.ts"() {
|
|
3338
|
+
"use strict";
|
|
3339
|
+
SECRET_BODY_PATTERNS = [
|
|
3340
|
+
{ pattern: /sk-ant-[A-Za-z0-9_-]{8,}/g, replacement: "<redacted>" },
|
|
3341
|
+
{ pattern: /Bearer\s+[A-Za-z0-9._~+/=-]{8,}/gi, replacement: "Bearer <redacted>" },
|
|
3342
|
+
{ pattern: /eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{8,}/g, replacement: "<redacted>" }
|
|
3343
|
+
];
|
|
3344
|
+
}
|
|
3345
|
+
});
|
|
3346
|
+
|
|
3072
3347
|
// src/headroom/socket.ts
|
|
3073
3348
|
import path12 from "node:path";
|
|
3074
3349
|
function headroomSocketPath(paths, supervisorPid) {
|
|
@@ -3082,10 +3357,10 @@ function ownerOnlyRefusal(label, target, stat, expected, uid) {
|
|
|
3082
3357
|
return `the headroom ${label} ${target} does not exist`;
|
|
3083
3358
|
}
|
|
3084
3359
|
if (stat.kind === "symlink") {
|
|
3085
|
-
return `the headroom ${label} ${target} is a symlink; it must be the real ${expected
|
|
3360
|
+
return `the headroom ${label} ${target} is a symlink; it must be the real ${KIND_NAMES[expected]}`;
|
|
3086
3361
|
}
|
|
3087
3362
|
if (stat.kind !== expected) {
|
|
3088
|
-
return `the headroom ${label} ${target} is not a ${expected
|
|
3363
|
+
return `the headroom ${label} ${target} is not a ${KIND_NAMES[expected]}`;
|
|
3089
3364
|
}
|
|
3090
3365
|
if (stat.uid !== uid) {
|
|
3091
3366
|
return `the headroom ${label} ${target} is owned by uid ${String(stat.uid)}, not by this user (uid ${String(uid)})`;
|
|
@@ -3105,6 +3380,86 @@ function verifyHeadroomSocket(socketPath, ports) {
|
|
|
3105
3380
|
const refusal2 = ownerOnlyRefusal("socket directory", directory, ports.lstat(directory), "dir", uid) ?? ownerOnlyRefusal("socket", socketPath, ports.lstat(socketPath), "socket", uid);
|
|
3106
3381
|
return refusal2 === void 0 ? { socketPath } : { refused: refusal2 };
|
|
3107
3382
|
}
|
|
3383
|
+
function pathDirectories(target, ports) {
|
|
3384
|
+
const pending = target.split("/").reverse();
|
|
3385
|
+
let current = "/";
|
|
3386
|
+
const directories = [];
|
|
3387
|
+
let hops = 0;
|
|
3388
|
+
for (let name = pending.pop(); name !== void 0; name = pending.pop()) {
|
|
3389
|
+
if (name === "" || name === ".") {
|
|
3390
|
+
continue;
|
|
3391
|
+
}
|
|
3392
|
+
if (name === "..") {
|
|
3393
|
+
current = path12.dirname(current);
|
|
3394
|
+
continue;
|
|
3395
|
+
}
|
|
3396
|
+
if (!directories.includes(current)) {
|
|
3397
|
+
directories.push(current);
|
|
3398
|
+
}
|
|
3399
|
+
const entry = path12.join(current, name);
|
|
3400
|
+
if (pending.length > 0 && ports.lstat(entry)?.kind === "symlink") {
|
|
3401
|
+
hops += 1;
|
|
3402
|
+
if (hops > MAX_SYMLINK_HOPS) {
|
|
3403
|
+
return `the symlinks on the allowlist file's path go more than ${String(MAX_SYMLINK_HOPS)} deep`;
|
|
3404
|
+
}
|
|
3405
|
+
const linkTarget = ports.readlink(entry);
|
|
3406
|
+
if (path12.isAbsolute(linkTarget)) {
|
|
3407
|
+
current = "/";
|
|
3408
|
+
}
|
|
3409
|
+
pending.push(...linkTarget.split("/").reverse());
|
|
3410
|
+
} else if (pending.length > 0) {
|
|
3411
|
+
current = entry;
|
|
3412
|
+
}
|
|
3413
|
+
}
|
|
3414
|
+
return directories;
|
|
3415
|
+
}
|
|
3416
|
+
function headroomDirectoryRefusal(directory, stat, uid, remedy) {
|
|
3417
|
+
if (stat?.kind !== "dir") {
|
|
3418
|
+
return `the directory ${directory} on the allowlist file's path is ${stat === void 0 ? "missing" : "not a directory"}, so headroom refuses the file`;
|
|
3419
|
+
}
|
|
3420
|
+
if (stat.uid !== uid && stat.uid !== ROOT_UID) {
|
|
3421
|
+
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}` : ""}`;
|
|
3422
|
+
}
|
|
3423
|
+
if ((stat.mode & GROUP_OR_OTHER_WRITE_BITS) !== 0) {
|
|
3424
|
+
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}` : ""}`;
|
|
3425
|
+
}
|
|
3426
|
+
return void 0;
|
|
3427
|
+
}
|
|
3428
|
+
function reportableAllowlistFileProblem(allowlistFile, ports, served) {
|
|
3429
|
+
const problem = verifyAllowlistFile(allowlistFile, ports);
|
|
3430
|
+
return problem?.repairable === false || served ? problem : void 0;
|
|
3431
|
+
}
|
|
3432
|
+
function verifyAllowlistFile(allowlistFile, ports) {
|
|
3433
|
+
const uid = ports.currentUid();
|
|
3434
|
+
const directories = pathDirectories(allowlistFile, ports);
|
|
3435
|
+
if (typeof directories === "string") {
|
|
3436
|
+
return { message: directories, repairable: false };
|
|
3437
|
+
}
|
|
3438
|
+
const socketDirectory = directories.at(-1);
|
|
3439
|
+
const headroomDirectory = socketDirectory === void 0 ? void 0 : path12.dirname(socketDirectory);
|
|
3440
|
+
for (const directory of directories) {
|
|
3441
|
+
const stat = ports.lstat(directory);
|
|
3442
|
+
if (directory === socketDirectory) {
|
|
3443
|
+
const refusal4 = ownerOnlyRefusal("allowlist directory", directory, stat, "dir", uid);
|
|
3444
|
+
if (refusal4 !== void 0) {
|
|
3445
|
+
return { message: refusal4, repairable: true };
|
|
3446
|
+
}
|
|
3447
|
+
continue;
|
|
3448
|
+
}
|
|
3449
|
+
const own = directory === headroomDirectory;
|
|
3450
|
+
const refusal3 = headroomDirectoryRefusal(directory, stat, uid, !own);
|
|
3451
|
+
if (refusal3 !== void 0) {
|
|
3452
|
+
return { message: refusal3, repairable: own };
|
|
3453
|
+
}
|
|
3454
|
+
}
|
|
3455
|
+
const fileStat = ports.lstat(allowlistFile);
|
|
3456
|
+
const refusal2 = ownerOnlyRefusal("allowlist file", allowlistFile, fileStat, "file", uid);
|
|
3457
|
+
if (refusal2 === void 0) {
|
|
3458
|
+
return void 0;
|
|
3459
|
+
}
|
|
3460
|
+
const replaceable = fileStat === void 0 || fileStat.kind === "file" || fileStat.kind === "symlink";
|
|
3461
|
+
return { message: refusal2, repairable: replaceable };
|
|
3462
|
+
}
|
|
3108
3463
|
function prepareHeadroomSocket(fs12, ports, paths, supervisorPid) {
|
|
3109
3464
|
const unsupported = platformRefusal(ports.platform);
|
|
3110
3465
|
if (unsupported !== void 0) {
|
|
@@ -3136,7 +3491,7 @@ function pruneStaleHeadroomSockets(fs12, paths, isRunning) {
|
|
|
3136
3491
|
}
|
|
3137
3492
|
return removed;
|
|
3138
3493
|
}
|
|
3139
|
-
var GROUP_OR_OTHER_BITS, OCTAL_RADIX, MODE_DIGITS, HEADROOM_SOCKET_SUFFIX, HEADROOM_SOCKET_NAME, UNIX_SOCKET_PATH_MAX_BYTES, PLATFORMS_WITHOUT_UNIX_SOCKETS;
|
|
3494
|
+
var 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;
|
|
3140
3495
|
var init_socket = __esm({
|
|
3141
3496
|
"src/headroom/socket.ts"() {
|
|
3142
3497
|
"use strict";
|
|
@@ -3147,6 +3502,12 @@ var init_socket = __esm({
|
|
|
3147
3502
|
HEADROOM_SOCKET_NAME = /^(\d+)\.sock$/;
|
|
3148
3503
|
UNIX_SOCKET_PATH_MAX_BYTES = 103;
|
|
3149
3504
|
PLATFORMS_WITHOUT_UNIX_SOCKETS = ["win32"];
|
|
3505
|
+
KIND_NAMES = { dir: "directory", file: "file", socket: "socket" };
|
|
3506
|
+
MAX_SYMLINK_HOPS = 40;
|
|
3507
|
+
ROOT_UID = 0;
|
|
3508
|
+
GROUP_OR_OTHER_WRITE_BITS = 18;
|
|
3509
|
+
STICKY_BIT = 512;
|
|
3510
|
+
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";
|
|
3150
3511
|
}
|
|
3151
3512
|
});
|
|
3152
3513
|
|
|
@@ -3175,6 +3536,7 @@ var init_source = __esm({
|
|
|
3175
3536
|
});
|
|
3176
3537
|
|
|
3177
3538
|
// src/headroom/supervisor.ts
|
|
3539
|
+
import path13 from "node:path";
|
|
3178
3540
|
function resolveSupervisorConfig(configured) {
|
|
3179
3541
|
return {
|
|
3180
3542
|
source: configured.source ?? HEADROOM_DEFAULT_SOURCE,
|
|
@@ -3263,6 +3625,36 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3263
3625
|
ports.log(`agent-shim headroom supervisor: ${message}`);
|
|
3264
3626
|
return 1;
|
|
3265
3627
|
};
|
|
3628
|
+
const syncAllowlistFile = (allowlist) => {
|
|
3629
|
+
try {
|
|
3630
|
+
if (fs12.readFileUtf8(paths.headroomAllowlistFile) !== formatAllowlistFile(allowlist)) {
|
|
3631
|
+
writeAllowlistFile(fs12, paths.headroomAllowlistFile, allowlist);
|
|
3632
|
+
ports.log(`agent-shim headroom supervisor: wrote allowlist [${allowlist.join(", ")}] to ${paths.headroomAllowlistFile}`);
|
|
3633
|
+
}
|
|
3634
|
+
return void 0;
|
|
3635
|
+
} catch (error) {
|
|
3636
|
+
return `could not write the headroom allowlist file ${paths.headroomAllowlistFile}: ${error instanceof Error ? error.message : String(error)}`;
|
|
3637
|
+
}
|
|
3638
|
+
};
|
|
3639
|
+
const allowlistFileRefusal = (allowlist) => {
|
|
3640
|
+
const problem = verifyAllowlistFile(paths.headroomAllowlistFile, ports.socketTrust);
|
|
3641
|
+
if (problem === void 0) {
|
|
3642
|
+
return void 0;
|
|
3643
|
+
}
|
|
3644
|
+
if (!problem.repairable) {
|
|
3645
|
+
return `headroom would refuse its allowlist file, and agent-shim cannot repair it: ${problem.message}`;
|
|
3646
|
+
}
|
|
3647
|
+
ports.log(`agent-shim headroom supervisor: repairing the allowlist file: ${problem.message}`);
|
|
3648
|
+
try {
|
|
3649
|
+
fs12.mkdirPrivate(paths.headroomDir);
|
|
3650
|
+
fs12.mkdirPrivate(path13.dirname(paths.headroomAllowlistFile));
|
|
3651
|
+
writeAllowlistFile(fs12, paths.headroomAllowlistFile, allowlist);
|
|
3652
|
+
} catch (error) {
|
|
3653
|
+
return `could not write the headroom allowlist file ${paths.headroomAllowlistFile}: ${error instanceof Error ? error.message : String(error)}`;
|
|
3654
|
+
}
|
|
3655
|
+
const remaining = verifyAllowlistFile(paths.headroomAllowlistFile, ports.socketTrust);
|
|
3656
|
+
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}`;
|
|
3657
|
+
};
|
|
3266
3658
|
const ensureInstalled = () => {
|
|
3267
3659
|
const version2 = ports.headroomVersion();
|
|
3268
3660
|
const versionOk = version2 !== void 0 && versionSatisfies(version2, config.source);
|
|
@@ -3286,14 +3678,20 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3286
3678
|
}
|
|
3287
3679
|
const { socketPath } = socket;
|
|
3288
3680
|
pruneStaleHeadroomSockets(fs12, paths, ports.isRunning);
|
|
3681
|
+
pruneStaleAllowlistTemporaries(fs12, paths.headroomAllowlistFile, ports.isRunning);
|
|
3289
3682
|
if (!ensureInstalled()) {
|
|
3290
3683
|
return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
|
|
3291
3684
|
}
|
|
3292
3685
|
const version = ports.headroomVersion() ?? "unknown";
|
|
3293
3686
|
writeOwnState({ supervisorPid: ports.ownPid, version, installedSource });
|
|
3294
|
-
ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${
|
|
3687
|
+
ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${currentHeadroomAllowlistInputs(fs12, paths, ports.frontDoorLiveness).frontDoorOrigins.join(", ")}]`);
|
|
3295
3688
|
const orphanPid = previousState?.headroomPid;
|
|
3296
|
-
|
|
3689
|
+
const orphanSocket = previousState?.socketPath ?? (previousState?.supervisorPid === void 0 ? void 0 : headroomSocketPath(paths, previousState.supervisorPid));
|
|
3690
|
+
const orphanIdentity = orphanPid === void 0 || orphanSocket === void 0 || !ports.isRunning(orphanPid) ? void 0 : daemonIdentity(ports.daemonCommandLine(orphanPid), orphanSocket);
|
|
3691
|
+
if (orphanPid !== void 0 && (orphanIdentity === "not-headroom" || orphanIdentity === "unreadable")) {
|
|
3692
|
+
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"}`);
|
|
3693
|
+
}
|
|
3694
|
+
if (orphanPid !== void 0 && (orphanIdentity === "this-release" || orphanIdentity === "earlier-release")) {
|
|
3297
3695
|
ports.log(`agent-shim headroom supervisor: stopping daemon pid ${String(orphanPid)} left behind by the previous supervisor`);
|
|
3298
3696
|
ports.stopProcess(orphanPid);
|
|
3299
3697
|
}
|
|
@@ -3301,9 +3699,19 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3301
3699
|
let runningHash;
|
|
3302
3700
|
let runningSettingsHash;
|
|
3303
3701
|
let consecutiveFailures = 0;
|
|
3702
|
+
let lastExitOutput;
|
|
3304
3703
|
let idleSince;
|
|
3305
3704
|
let superseded = false;
|
|
3306
3705
|
let ticks = 0;
|
|
3706
|
+
const servingState = (pid) => ({
|
|
3707
|
+
supervisorPid: ports.ownPid,
|
|
3708
|
+
headroomPid: pid,
|
|
3709
|
+
socketPath,
|
|
3710
|
+
version,
|
|
3711
|
+
allowlistHash: runningHash,
|
|
3712
|
+
settingsHash: runningSettingsHash,
|
|
3713
|
+
installedSource
|
|
3714
|
+
});
|
|
3307
3715
|
for (; ; ) {
|
|
3308
3716
|
if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
|
|
3309
3717
|
return HEADROOM_SUPERVISOR_STILL_RUNNING;
|
|
@@ -3311,7 +3719,10 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3311
3719
|
ticks += 1;
|
|
3312
3720
|
config = ports.readConfig();
|
|
3313
3721
|
const settingsHash = hashSettings(config.settings);
|
|
3314
|
-
const
|
|
3722
|
+
const inputs = currentHeadroomAllowlistInputs(fs12, paths, ports.frontDoorLiveness);
|
|
3723
|
+
pruneDeadFrontDoorDirectRecords(fs12, paths.frontdoorDirectRecordsDir, inputs.frontDoorRecords, inputs.frontDoorLiveness);
|
|
3724
|
+
pruneMalformedFrontDoorDirectFiles(fs12, paths.frontdoorDirectRecordsDir, ports.isRunning);
|
|
3725
|
+
const allowlist = inputs.frontDoorOrigins;
|
|
3315
3726
|
const allowlistHash = hashAllowlist(allowlist);
|
|
3316
3727
|
pruneDeadSessions(fs12, paths.headroomSessionsDir, ports.isRunning);
|
|
3317
3728
|
const ownsNow = ownsState();
|
|
@@ -3319,6 +3730,13 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3319
3730
|
ports.log("agent-shim headroom supervisor: another supervisor now owns the state file; serving this daemon's own sessions until they end");
|
|
3320
3731
|
}
|
|
3321
3732
|
superseded = !ownsNow;
|
|
3733
|
+
const allowlistFailure = ownsNow ? syncAllowlistFile(allowlist) ?? allowlistFileRefusal(allowlist) : void 0;
|
|
3734
|
+
if (allowlistFailure !== void 0) {
|
|
3735
|
+
if (headroomPid !== void 0 && ports.isRunning(headroomPid)) {
|
|
3736
|
+
ports.stopProcess(headroomPid);
|
|
3737
|
+
}
|
|
3738
|
+
return fail(allowlistFailure);
|
|
3739
|
+
}
|
|
3322
3740
|
const crashed = headroomPid !== void 0 && !ports.isRunning(headroomPid);
|
|
3323
3741
|
if (headroomPid === void 0 || crashed) {
|
|
3324
3742
|
if (crashed) {
|
|
@@ -3333,43 +3751,53 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3333
3751
|
});
|
|
3334
3752
|
}
|
|
3335
3753
|
if (consecutiveFailures >= HEADROOM_START_RETRY_BUDGET) {
|
|
3336
|
-
return fail(
|
|
3754
|
+
return fail(
|
|
3755
|
+
`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}`)
|
|
3756
|
+
);
|
|
3337
3757
|
}
|
|
3338
3758
|
if (installedSource !== config.source && !ensureInstalled()) {
|
|
3339
3759
|
return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
|
|
3340
3760
|
}
|
|
3341
|
-
const
|
|
3342
|
-
const
|
|
3343
|
-
|
|
3761
|
+
const logOffset = ports.daemonLogSize();
|
|
3762
|
+
const pid = ports.spawnHeadroom(socketPath, paths.headroomAllowlistFile, config.settings);
|
|
3763
|
+
writeOwnState({ supervisorPid: ports.ownPid, headroomPid: pid, version, installedSource });
|
|
3764
|
+
const outcome = await waitUntilReady(ports, socketPath, pid);
|
|
3765
|
+
if (outcome === "ready") {
|
|
3344
3766
|
consecutiveFailures = 0;
|
|
3767
|
+
lastExitOutput = void 0;
|
|
3345
3768
|
headroomPid = pid;
|
|
3346
3769
|
runningHash = allowlistHash;
|
|
3347
3770
|
runningSettingsHash = settingsHash;
|
|
3348
|
-
const recorded = writeOwnState(
|
|
3349
|
-
supervisorPid: ports.ownPid,
|
|
3350
|
-
headroomPid: pid,
|
|
3351
|
-
socketPath,
|
|
3352
|
-
version,
|
|
3353
|
-
allowlistHash,
|
|
3354
|
-
settingsHash,
|
|
3355
|
-
installedSource: config.source
|
|
3356
|
-
});
|
|
3771
|
+
const recorded = writeOwnState(servingState(pid));
|
|
3357
3772
|
if (recorded) {
|
|
3358
3773
|
fs12.removeRecursive(paths.headroomLockFile);
|
|
3359
3774
|
}
|
|
3360
3775
|
idleSince = void 0;
|
|
3361
3776
|
ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on unix socket ${socketPath}`);
|
|
3362
3777
|
} else {
|
|
3363
|
-
ports.stopProcess(pid);
|
|
3364
3778
|
consecutiveFailures += 1;
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3779
|
+
if (outcome === "exited") {
|
|
3780
|
+
lastExitOutput = lastLines(ports.readDaemonLogTail(logOffset, DAEMON_LOG_TAIL_BYTES));
|
|
3781
|
+
ports.log(
|
|
3782
|
+
`agent-shim headroom supervisor: headroom exited before it was ready on unix socket ${socketPath} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
|
|
3783
|
+
);
|
|
3784
|
+
} else {
|
|
3785
|
+
lastExitOutput = void 0;
|
|
3786
|
+
ports.stopProcess(pid);
|
|
3787
|
+
ports.log(
|
|
3788
|
+
`agent-shim headroom supervisor: headroom did not become ready on unix socket ${socketPath} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
|
|
3789
|
+
);
|
|
3790
|
+
}
|
|
3368
3791
|
await ports.sleep(backoffForAttempt(consecutiveFailures));
|
|
3369
3792
|
continue;
|
|
3370
3793
|
}
|
|
3371
3794
|
} else {
|
|
3372
|
-
if (runningHash !== allowlistHash
|
|
3795
|
+
if (runningHash !== allowlistHash) {
|
|
3796
|
+
runningHash = allowlistHash;
|
|
3797
|
+
writeOwnState(servingState(headroomPid));
|
|
3798
|
+
ports.log(`agent-shim headroom supervisor: headroom pid ${String(headroomPid)} now serves allowlist [${allowlist.join(", ")}]`);
|
|
3799
|
+
}
|
|
3800
|
+
if (runningSettingsHash !== settingsHash || installedSource !== config.source) {
|
|
3373
3801
|
if (sessionsForSupervisor(fs12, paths.headroomSessionsDir, ports.ownPid).length === 0) {
|
|
3374
3802
|
ports.log("agent-shim headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
|
|
3375
3803
|
ports.stopProcess(headroomPid);
|
|
@@ -3398,45 +3826,65 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3398
3826
|
await ports.sleep(HEADROOM_POLL_MS);
|
|
3399
3827
|
}
|
|
3400
3828
|
}
|
|
3401
|
-
function
|
|
3829
|
+
function undeterminedFrontDoors(inputs) {
|
|
3830
|
+
return inputs.frontDoorRecords.flatMap((record) => {
|
|
3831
|
+
const reason = inputs.frontDoorLiveness.unknown.get(record.pid);
|
|
3832
|
+
return reason === void 0 ? [] : [{ pid: record.pid, origin: directOrigin(record.directPort), reason }];
|
|
3833
|
+
});
|
|
3834
|
+
}
|
|
3835
|
+
function currentHeadroomAllowlistInputs(fs12, paths, frontDoorLiveness) {
|
|
3836
|
+
const named = frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile));
|
|
3837
|
+
const records = listFrontDoorDirectRecords(fs12, paths.frontdoorDirectRecordsDir);
|
|
3838
|
+
const liveness = frontDoorLiveness(records.map((record) => record.pid));
|
|
3839
|
+
const live = liveFrontDoorDirectRecords(records, liveness).map((record) => directOrigin(record.directPort));
|
|
3402
3840
|
return {
|
|
3403
|
-
|
|
3404
|
-
|
|
3841
|
+
frontDoorRecords: records,
|
|
3842
|
+
frontDoorLiveness: liveness,
|
|
3843
|
+
frontDoorOrigins: [.../* @__PURE__ */ new Set([...named === void 0 ? [] : [named], ...live])].sort()
|
|
3405
3844
|
};
|
|
3406
3845
|
}
|
|
3407
|
-
function
|
|
3408
|
-
const
|
|
3409
|
-
return
|
|
3410
|
-
}
|
|
3411
|
-
function allowlistOf(ports) {
|
|
3412
|
-
return currentHeadroomAllowlist(ports.fs, ports.paths);
|
|
3846
|
+
function launchRequiredUpstreams(fs12, paths) {
|
|
3847
|
+
const door = frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile));
|
|
3848
|
+
return door === void 0 ? [] : [door];
|
|
3413
3849
|
}
|
|
3414
|
-
async function waitUntilReady(ports, socketPath) {
|
|
3850
|
+
async function waitUntilReady(ports, socketPath, pid) {
|
|
3415
3851
|
const deadline = ports.now() + HEADROOM_READY_TIMEOUT_MS;
|
|
3416
3852
|
for (; ; ) {
|
|
3417
3853
|
if (await ports.ready(socketPath)) {
|
|
3418
|
-
return
|
|
3854
|
+
return "ready";
|
|
3855
|
+
}
|
|
3856
|
+
if (!ports.isRunning(pid)) {
|
|
3857
|
+
return "exited";
|
|
3419
3858
|
}
|
|
3420
3859
|
if (ports.now() >= deadline) {
|
|
3421
|
-
return
|
|
3860
|
+
return "timed-out";
|
|
3422
3861
|
}
|
|
3423
3862
|
await ports.sleep(HEADROOM_POLL_MS);
|
|
3424
3863
|
}
|
|
3425
3864
|
}
|
|
3426
|
-
|
|
3865
|
+
function lastLines(output) {
|
|
3866
|
+
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);
|
|
3867
|
+
return lines.length === 0 ? "(the daemon wrote nothing)" : lines.slice(-DAEMON_EXIT_LOG_LINES).join(" | ");
|
|
3868
|
+
}
|
|
3869
|
+
var 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;
|
|
3427
3870
|
var init_supervisor = __esm({
|
|
3428
3871
|
"src/headroom/supervisor.ts"() {
|
|
3429
3872
|
"use strict";
|
|
3430
3873
|
init_schema();
|
|
3431
3874
|
init_state();
|
|
3432
3875
|
init_settings();
|
|
3876
|
+
init_capture();
|
|
3433
3877
|
init_socket();
|
|
3878
|
+
init_earlierRelease();
|
|
3434
3879
|
init_source();
|
|
3435
3880
|
init_state2();
|
|
3436
3881
|
HEADROOM_BACKOFF_BASE_MS = 500;
|
|
3437
3882
|
HEADROOM_BACKOFF_CAP_MS = 3e4;
|
|
3438
3883
|
HEADROOM_START_RETRY_BUDGET = 5;
|
|
3439
3884
|
HEADROOM_READY_TIMEOUT_MS = 15e3;
|
|
3885
|
+
DAEMON_EXIT_LOG_LINES = 6;
|
|
3886
|
+
DAEMON_EXIT_LOG_LINE_CHARS = 400;
|
|
3887
|
+
DAEMON_LOG_TAIL_BYTES = 8192;
|
|
3440
3888
|
HEADROOM_POLL_MS = 1e3;
|
|
3441
3889
|
MS_PER_MINUTE2 = 6e4;
|
|
3442
3890
|
HEADROOM_SUPERVISOR_STILL_RUNNING = -1;
|
|
@@ -3448,7 +3896,7 @@ import { spawn as spawn2, spawnSync } from "node:child_process";
|
|
|
3448
3896
|
import { createHash as createHash5 } from "node:crypto";
|
|
3449
3897
|
import fs3 from "node:fs";
|
|
3450
3898
|
import os3 from "node:os";
|
|
3451
|
-
import
|
|
3899
|
+
import path14 from "node:path";
|
|
3452
3900
|
import { isSea } from "node:sea";
|
|
3453
3901
|
function isEnoent3(error) {
|
|
3454
3902
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
@@ -3478,8 +3926,18 @@ function realIsFrontDoorSupervisor(pid) {
|
|
|
3478
3926
|
const result = spawnSync("ps", ["-o", "pid=,command=", "-p", String(pid)], { encoding: "utf8" });
|
|
3479
3927
|
return result.status === 0 && parseFrontDoorSupervisorPids(result.stdout).includes(pid);
|
|
3480
3928
|
}
|
|
3929
|
+
function realProcessCommandLine(pid) {
|
|
3930
|
+
const result = spawnSync("ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
|
|
3931
|
+
return result.status === 0 ? result.stdout.trim() : void 0;
|
|
3932
|
+
}
|
|
3933
|
+
function realFrontDoorLiveness(pids) {
|
|
3934
|
+
return frontDoorLivenessOf(pids, (asked) => {
|
|
3935
|
+
const result = spawnSync("ps", ["-o", "pid=,stat=,command=", "-p", asked.map(String).join(",")], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
|
|
3936
|
+
return { status: result.status, stdout: result.stdout, stderr: result.stderr, ...result.error === void 0 ? {} : { error: result.error } };
|
|
3937
|
+
});
|
|
3938
|
+
}
|
|
3481
3939
|
function expandHome2(filePath) {
|
|
3482
|
-
return filePath.startsWith("~/") ?
|
|
3940
|
+
return filePath.startsWith("~/") ? path14.join(os3.homedir(), filePath.slice(1)) : filePath;
|
|
3483
3941
|
}
|
|
3484
3942
|
function hasDesktopSession() {
|
|
3485
3943
|
if (process.platform === "darwin") {
|
|
@@ -3523,7 +3981,7 @@ function spawnDaemonThroughScript(script) {
|
|
|
3523
3981
|
return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: process.execPath, args: [script, subcommand] }, paths, subcommand, logPath);
|
|
3524
3982
|
}
|
|
3525
3983
|
function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
|
|
3526
|
-
fs3.mkdirSync(
|
|
3984
|
+
fs3.mkdirSync(path14.dirname(logPath), { recursive: true });
|
|
3527
3985
|
const logFd = fs3.openSync(logPath, "a");
|
|
3528
3986
|
try {
|
|
3529
3987
|
const child = spawn2(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
|
|
@@ -3545,13 +4003,14 @@ function realHeadroomPort(paths, options) {
|
|
|
3545
4003
|
const up = ensureHeadroom({
|
|
3546
4004
|
paths,
|
|
3547
4005
|
launcherPid: process.pid,
|
|
3548
|
-
...routesProvider ? {
|
|
4006
|
+
...routesProvider ? { requiredUpstreams: () => launchRequiredUpstreams(realFarmFs, paths) } : {},
|
|
3549
4007
|
ports: {
|
|
3550
4008
|
fs: realFarmFs,
|
|
3551
4009
|
// 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.
|
|
3552
4010
|
isRunning: realIsProcessRunning,
|
|
3553
4011
|
now: () => Date.now(),
|
|
3554
4012
|
sleep: realSleepSync,
|
|
4013
|
+
daemonCommandLine: realProcessCommandLine,
|
|
3555
4014
|
spawnSupervisor: (layout) => spawnHeadroomSupervisor(layout, options.spawnDaemon)
|
|
3556
4015
|
}
|
|
3557
4016
|
});
|
|
@@ -3576,7 +4035,7 @@ function listVersionsDir(dir) {
|
|
|
3576
4035
|
throw error;
|
|
3577
4036
|
}
|
|
3578
4037
|
return entries.filter((entry) => entry.isFile()).map((entry) => {
|
|
3579
|
-
const fullPath =
|
|
4038
|
+
const fullPath = path14.join(dir, entry.name);
|
|
3580
4039
|
const stat = fs3.statSync(fullPath);
|
|
3581
4040
|
return {
|
|
3582
4041
|
name: entry.name,
|
|
@@ -3590,7 +4049,7 @@ function windowsPathExtensions(pathext) {
|
|
|
3590
4049
|
return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
|
|
3591
4050
|
}
|
|
3592
4051
|
function resolveExecutableCandidate(dir, name, env) {
|
|
3593
|
-
const candidate =
|
|
4052
|
+
const candidate = path14.join(dir, name);
|
|
3594
4053
|
if (env.platform === "win32") {
|
|
3595
4054
|
const extensions = windowsPathExtensions(env.pathext);
|
|
3596
4055
|
const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
|
|
@@ -3639,13 +4098,13 @@ function resolveOwnExecutablePath(env) {
|
|
|
3639
4098
|
if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
|
|
3640
4099
|
return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
|
|
3641
4100
|
}
|
|
3642
|
-
const candidate = env.argv1 === void 0 ? env.execPath :
|
|
3643
|
-
const candidateDir =
|
|
3644
|
-
const candidateDirOnPath = env.pathDirs.some((dir) =>
|
|
4101
|
+
const candidate = env.argv1 === void 0 ? env.execPath : path14.resolve(env.cwd, env.argv1);
|
|
4102
|
+
const candidateDir = path14.dirname(candidate);
|
|
4103
|
+
const candidateDirOnPath = env.pathDirs.some((dir) => path14.resolve(dir) === candidateDir);
|
|
3645
4104
|
if (candidateDirOnPath) {
|
|
3646
4105
|
return candidate;
|
|
3647
4106
|
}
|
|
3648
|
-
const viaPath = searchPathForExecutable(env.pathDirs,
|
|
4107
|
+
const viaPath = searchPathForExecutable(env.pathDirs, path14.basename(candidate), env.findExecutableInDir);
|
|
3649
4108
|
return viaPath ?? candidate;
|
|
3650
4109
|
}
|
|
3651
4110
|
function realOwnExecutablePath() {
|
|
@@ -3653,7 +4112,7 @@ function realOwnExecutablePath() {
|
|
|
3653
4112
|
argv1: process.argv[1],
|
|
3654
4113
|
execPath: process.execPath,
|
|
3655
4114
|
cwd: process.cwd(),
|
|
3656
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
4115
|
+
pathDirs: (process.env.PATH ?? "").split(path14.delimiter).filter((dir) => dir !== ""),
|
|
3657
4116
|
findExecutableInDir
|
|
3658
4117
|
});
|
|
3659
4118
|
}
|
|
@@ -3666,7 +4125,7 @@ function realContentSourcePath() {
|
|
|
3666
4125
|
function realResolveClaudeBinary(isOwnBinary) {
|
|
3667
4126
|
return (request4) => discoverClaudeBinary({
|
|
3668
4127
|
listVersionsDir,
|
|
3669
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
4128
|
+
pathDirs: (process.env.PATH ?? "").split(path14.delimiter).filter((dir) => dir !== ""),
|
|
3670
4129
|
findExecutableInDir,
|
|
3671
4130
|
isOwnBinary,
|
|
3672
4131
|
...request4?.version === void 0 ? {} : { version: request4.version }
|
|
@@ -3675,7 +4134,7 @@ function realResolveClaudeBinary(isOwnBinary) {
|
|
|
3675
4134
|
function realInstalledClaudeVersions() {
|
|
3676
4135
|
return installedVersions(listVersionsDir(defaultVersionsDir()));
|
|
3677
4136
|
}
|
|
3678
|
-
var realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, realFarmFs, INT32_BYTE_LENGTH, realRunPort, MACOS_GUI_SESSION_MANAGER, realCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
|
|
4137
|
+
var 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;
|
|
3679
4138
|
var init_realPorts = __esm({
|
|
3680
4139
|
"src/realPorts.ts"() {
|
|
3681
4140
|
"use strict";
|
|
@@ -3769,9 +4228,14 @@ var init_realPorts = __esm({
|
|
|
3769
4228
|
},
|
|
3770
4229
|
writeFilePrivate(filePath, contents) {
|
|
3771
4230
|
const temp = `${filePath}.${String(process.pid)}.tmp`;
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
4231
|
+
try {
|
|
4232
|
+
fs3.writeFileSync(temp, contents, { encoding: "utf8", mode: OWNER_ONLY_FILE_MODE });
|
|
4233
|
+
fs3.chmodSync(temp, OWNER_ONLY_FILE_MODE);
|
|
4234
|
+
fs3.renameSync(temp, filePath);
|
|
4235
|
+
} catch (error) {
|
|
4236
|
+
fs3.rmSync(temp, { force: true });
|
|
4237
|
+
throw error;
|
|
4238
|
+
}
|
|
3775
4239
|
},
|
|
3776
4240
|
appendFilePrivate(filePath, contents) {
|
|
3777
4241
|
const descriptor = fs3.openSync(filePath, "a", OWNER_ONLY_FILE_MODE);
|
|
@@ -3811,6 +4275,7 @@ var init_realPorts = __esm({
|
|
|
3811
4275
|
}
|
|
3812
4276
|
};
|
|
3813
4277
|
INT32_BYTE_LENGTH = 4;
|
|
4278
|
+
PS_TIMEOUT_MS = 2e3;
|
|
3814
4279
|
realRunPort = {
|
|
3815
4280
|
run(command, args) {
|
|
3816
4281
|
const result = spawnSync(command, [...args], { encoding: "utf8" });
|
|
@@ -3849,7 +4314,7 @@ var init_realPorts = __esm({
|
|
|
3849
4314
|
},
|
|
3850
4315
|
personPresent: () => process.stdin.isTTY || hasDesktopSession()
|
|
3851
4316
|
};
|
|
3852
|
-
SOCKET_PERMISSION_BITS =
|
|
4317
|
+
SOCKET_PERMISSION_BITS = 4095;
|
|
3853
4318
|
realHeadroomSocketTrust = {
|
|
3854
4319
|
platform: process.platform,
|
|
3855
4320
|
currentUid: () => {
|
|
@@ -3868,9 +4333,10 @@ var init_realPorts = __esm({
|
|
|
3868
4333
|
}
|
|
3869
4334
|
throw error;
|
|
3870
4335
|
}
|
|
3871
|
-
const kind = stat.isSymbolicLink() ? "symlink" : stat.isDirectory() ? "dir" : stat.isSocket() ? "socket" : "other";
|
|
4336
|
+
const kind = stat.isSymbolicLink() ? "symlink" : stat.isDirectory() ? "dir" : stat.isFile() ? "file" : stat.isSocket() ? "socket" : "other";
|
|
3872
4337
|
return { kind, uid: stat.uid, mode: stat.mode & SOCKET_PERMISSION_BITS };
|
|
3873
|
-
}
|
|
4338
|
+
},
|
|
4339
|
+
readlink: (target) => fs3.readlinkSync(target, "utf8")
|
|
3874
4340
|
};
|
|
3875
4341
|
realSpawnPort = {
|
|
3876
4342
|
spawnSync(command, args, options) {
|
|
@@ -3889,18 +4355,18 @@ var init_realPorts = __esm({
|
|
|
3889
4355
|
});
|
|
3890
4356
|
|
|
3891
4357
|
// src/pathNorm.ts
|
|
3892
|
-
import
|
|
4358
|
+
import path15 from "node:path";
|
|
3893
4359
|
function expandTilde(value, home) {
|
|
3894
4360
|
if (value === "~") {
|
|
3895
4361
|
return home;
|
|
3896
4362
|
}
|
|
3897
4363
|
if (value.startsWith("~/")) {
|
|
3898
|
-
return
|
|
4364
|
+
return path15.join(home, value.slice(2));
|
|
3899
4365
|
}
|
|
3900
4366
|
return value;
|
|
3901
4367
|
}
|
|
3902
4368
|
function normaliseRulePath(rulePath, home) {
|
|
3903
|
-
return
|
|
4369
|
+
return path15.resolve(expandTilde(rulePath, home));
|
|
3904
4370
|
}
|
|
3905
4371
|
var init_pathNorm = __esm({
|
|
3906
4372
|
"src/pathNorm.ts"() {
|
|
@@ -3909,12 +4375,12 @@ var init_pathNorm = __esm({
|
|
|
3909
4375
|
});
|
|
3910
4376
|
|
|
3911
4377
|
// src/launcher/cascade.ts
|
|
3912
|
-
import
|
|
4378
|
+
import path16 from "node:path";
|
|
3913
4379
|
function loadCascadeInput(params) {
|
|
3914
4380
|
const globalConfig = loadConfigFile(params.paths.globalConfigFile, GlobalConfigSchema, params.read);
|
|
3915
4381
|
const directoryRules = loadConfigFile(params.paths.directoryRulesFile, DirectoryRulesSchema, params.read);
|
|
3916
4382
|
const loadProfile = (name) => {
|
|
3917
|
-
const filepath =
|
|
4383
|
+
const filepath = path16.join(params.paths.configProfilesDir, `${name}.json`);
|
|
3918
4384
|
const loaded = loadConfigFile(filepath, ConfigProfileSchema, params.read);
|
|
3919
4385
|
if (loaded === void 0) {
|
|
3920
4386
|
return void 0;
|
|
@@ -3929,8 +4395,8 @@ function loadCascadeInput(params) {
|
|
|
3929
4395
|
});
|
|
3930
4396
|
const levels = [];
|
|
3931
4397
|
for (const dir of dirs) {
|
|
3932
|
-
const portable = loadConfigFile(
|
|
3933
|
-
const portableLocal = loadConfigFile(
|
|
4398
|
+
const portable = loadConfigFile(path16.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path16.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
4399
|
+
const portableLocal = loadConfigFile(path16.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path16.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
3934
4400
|
const rules = (directoryRules?.config.rules ?? []).map((rule, index) => ({ rule, index })).filter(({ rule }) => normaliseRulePath(rule.path, params.home) === dir).map(({ rule, index }) => {
|
|
3935
4401
|
const entryOrder = directoryRules?.ruleEntryOrders[index];
|
|
3936
4402
|
return {
|
|
@@ -3992,7 +4458,7 @@ var init_cascade = __esm({
|
|
|
3992
4458
|
});
|
|
3993
4459
|
|
|
3994
4460
|
// src/launcher/identity.ts
|
|
3995
|
-
import
|
|
4461
|
+
import path17 from "node:path";
|
|
3996
4462
|
function poolNameOf(selector) {
|
|
3997
4463
|
return selector.startsWith(POOL_SELECTOR_PREFIX) ? selector.slice(POOL_SELECTOR_PREFIX.length) : void 0;
|
|
3998
4464
|
}
|
|
@@ -4045,7 +4511,7 @@ function decideConfigProfile(params) {
|
|
|
4045
4511
|
return { source: "none" };
|
|
4046
4512
|
}
|
|
4047
4513
|
function loadIdentity(identitiesDir, name, fs12) {
|
|
4048
|
-
return loadConfigFile(
|
|
4514
|
+
return loadConfigFile(path17.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
|
|
4049
4515
|
}
|
|
4050
4516
|
var IDENTITY_DECISION_SOURCES, CONFIG_PROFILE_DECISION_SOURCES;
|
|
4051
4517
|
var init_identity = __esm({
|
|
@@ -4265,7 +4731,7 @@ var init_schema2 = __esm({
|
|
|
4265
4731
|
});
|
|
4266
4732
|
|
|
4267
4733
|
// src/usage/account.ts
|
|
4268
|
-
import
|
|
4734
|
+
import path18 from "node:path";
|
|
4269
4735
|
function isObject(value) {
|
|
4270
4736
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4271
4737
|
}
|
|
@@ -4273,7 +4739,7 @@ function isIdentityName(name) {
|
|
|
4273
4739
|
return IdentitySchema.shape.name.safeParse(name).success;
|
|
4274
4740
|
}
|
|
4275
4741
|
function claudeJsonPath(identitiesDir, identity) {
|
|
4276
|
-
return
|
|
4742
|
+
return path18.join(identitiesDir, identity, CLAUDE_JSON);
|
|
4277
4743
|
}
|
|
4278
4744
|
function readAccountMetadata(fs12, identitiesDir, identity) {
|
|
4279
4745
|
if (!isIdentityName(identity)) {
|
|
@@ -4865,7 +5331,7 @@ var init_pick = __esm({
|
|
|
4865
5331
|
});
|
|
4866
5332
|
|
|
4867
5333
|
// src/usage/read.ts
|
|
4868
|
-
import
|
|
5334
|
+
import path19 from "node:path";
|
|
4869
5335
|
function segmentDay(epochMs) {
|
|
4870
5336
|
return new Date(epochMs).toISOString().slice(0, "YYYY-MM-DD".length);
|
|
4871
5337
|
}
|
|
@@ -4890,7 +5356,7 @@ function readUsageLog(fs12, logDir, options = {}) {
|
|
|
4890
5356
|
if (sinceMs !== void 0 && segment.endsAt <= sinceMs) {
|
|
4891
5357
|
continue;
|
|
4892
5358
|
}
|
|
4893
|
-
const contents = fs12.readFileUtf8(
|
|
5359
|
+
const contents = fs12.readFileUtf8(path19.join(logDir, segment.name));
|
|
4894
5360
|
if (contents === void 0) {
|
|
4895
5361
|
continue;
|
|
4896
5362
|
}
|
|
@@ -4924,7 +5390,7 @@ function snapshotPath(snapshotsDir, identity) {
|
|
|
4924
5390
|
if (!isIdentityName(identity)) {
|
|
4925
5391
|
throw new Error(`"${identity}" is not a valid identity name.`);
|
|
4926
5392
|
}
|
|
4927
|
-
return
|
|
5393
|
+
return path19.join(snapshotsDir, `${identity}.json`);
|
|
4928
5394
|
}
|
|
4929
5395
|
function readUsageSnapshot(fs12, snapshotsDir, identity) {
|
|
4930
5396
|
const file = snapshotPath(snapshotsDir, identity);
|
|
@@ -4977,12 +5443,12 @@ var init_read = __esm({
|
|
|
4977
5443
|
});
|
|
4978
5444
|
|
|
4979
5445
|
// src/usage/store.ts
|
|
4980
|
-
import
|
|
5446
|
+
import path20 from "node:path";
|
|
4981
5447
|
function pruneUsageLog(fs12, logDir, nowMs) {
|
|
4982
5448
|
const cutoff = nowMs - USAGE_RETENTION_MS;
|
|
4983
5449
|
for (const segment of listLogSegments(fs12, logDir)) {
|
|
4984
5450
|
if (segment.endsAt <= cutoff) {
|
|
4985
|
-
fs12.removeRecursive(
|
|
5451
|
+
fs12.removeRecursive(path20.join(logDir, segment.name));
|
|
4986
5452
|
}
|
|
4987
5453
|
}
|
|
4988
5454
|
}
|
|
@@ -5064,7 +5530,7 @@ function createUsageStore(deps) {
|
|
|
5064
5530
|
pruneUsageLog(fs12, paths.usageLogDir, nowMs);
|
|
5065
5531
|
prunedDay = day;
|
|
5066
5532
|
}
|
|
5067
|
-
fs12.appendFilePrivate(
|
|
5533
|
+
fs12.appendFilePrivate(path20.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record)}
|
|
5068
5534
|
`);
|
|
5069
5535
|
if (record.identity !== void 0) {
|
|
5070
5536
|
rewriteSnapshot(record.identity, (current) => ({ ...current?.providers, [record.provider]: foldProviderState(current?.providers[record.provider], record) }));
|
|
@@ -5102,7 +5568,7 @@ var init_store2 = __esm({
|
|
|
5102
5568
|
});
|
|
5103
5569
|
|
|
5104
5570
|
// src/usage/poolPick.ts
|
|
5105
|
-
import
|
|
5571
|
+
import path21 from "node:path";
|
|
5106
5572
|
import { z as z13 } from "zod";
|
|
5107
5573
|
function errorMessage(error) {
|
|
5108
5574
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -5230,7 +5696,7 @@ function recordStickyPick(fs12, picksFile, directory, identity, nowMs) {
|
|
|
5230
5696
|
const current = readPicksFile(fs12, picksFile).file.picks;
|
|
5231
5697
|
const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
|
|
5232
5698
|
const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
|
|
5233
|
-
fs12.mkdirPrivate(
|
|
5699
|
+
fs12.mkdirPrivate(path21.dirname(picksFile));
|
|
5234
5700
|
fs12.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
|
|
5235
5701
|
`);
|
|
5236
5702
|
}
|
|
@@ -5264,14 +5730,14 @@ var init_poolPick = __esm({
|
|
|
5264
5730
|
// src/paths.ts
|
|
5265
5731
|
import fs5 from "node:fs";
|
|
5266
5732
|
import os5 from "node:os";
|
|
5267
|
-
import
|
|
5733
|
+
import path23 from "node:path";
|
|
5268
5734
|
function resolveAgentShimHome(env = process.env, home = os5.homedir(), isDirectory = isExistingDirectory) {
|
|
5269
5735
|
const fromEnv = env.AGENT_SHIM_HOME;
|
|
5270
5736
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
5271
5737
|
return fromEnv;
|
|
5272
5738
|
}
|
|
5273
|
-
const current =
|
|
5274
|
-
const legacy =
|
|
5739
|
+
const current = path23.join(home, HOME_DIRNAME);
|
|
5740
|
+
const legacy = path23.join(home, LEGACY_HOME_DIRNAME);
|
|
5275
5741
|
return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
|
|
5276
5742
|
}
|
|
5277
5743
|
function isExistingDirectory(candidate) {
|
|
@@ -5282,47 +5748,49 @@ function resolveClaudeHome() {
|
|
|
5282
5748
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
5283
5749
|
return fromEnv;
|
|
5284
5750
|
}
|
|
5285
|
-
return
|
|
5751
|
+
return path23.join(os5.homedir(), ".claude");
|
|
5286
5752
|
}
|
|
5287
5753
|
function buildLayoutPaths(root) {
|
|
5288
5754
|
return {
|
|
5289
5755
|
root,
|
|
5290
|
-
identitiesDir:
|
|
5291
|
-
configProfilesDir:
|
|
5292
|
-
providersDir:
|
|
5293
|
-
directoryRulesFile:
|
|
5294
|
-
activeIdentityFile:
|
|
5295
|
-
globalConfigFile:
|
|
5296
|
-
categoriesLocalFile:
|
|
5297
|
-
claudeShimFile:
|
|
5298
|
-
headroomDir:
|
|
5299
|
-
headroomStateFile:
|
|
5300
|
-
headroomLegacyStateFile:
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5756
|
+
identitiesDir: path23.join(root, "identities"),
|
|
5757
|
+
configProfilesDir: path23.join(root, "config-profiles"),
|
|
5758
|
+
providersDir: path23.join(root, "providers"),
|
|
5759
|
+
directoryRulesFile: path23.join(root, "directory-rules.json"),
|
|
5760
|
+
activeIdentityFile: path23.join(root, "active-identity"),
|
|
5761
|
+
globalConfigFile: path23.join(root, "config.json"),
|
|
5762
|
+
categoriesLocalFile: path23.join(root, "categories.local.json"),
|
|
5763
|
+
claudeShimFile: path23.join(root, "claude-shim.json"),
|
|
5764
|
+
headroomDir: path23.join(root, "headroom"),
|
|
5765
|
+
headroomStateFile: path23.join(root, "headroom", "state.json"),
|
|
5766
|
+
headroomLegacyStateFile: path23.join(root, "headroom", "state.v2.json"),
|
|
5767
|
+
headroomAllowlistFile: path23.join(root, "headroom", "run", "allowlist.txt"),
|
|
5768
|
+
headroomSocketDir: path23.join(root, "headroom", "run"),
|
|
5769
|
+
headroomLockFile: path23.join(root, "headroom", "start.lock"),
|
|
5770
|
+
headroomSessionsDir: path23.join(root, "headroom", "sessions"),
|
|
5771
|
+
logsDir: path23.join(root, "logs"),
|
|
5772
|
+
headroomLogPath: path23.join(root, "logs", "headroom.log"),
|
|
5773
|
+
frontdoorDir: path23.join(root, "frontdoor"),
|
|
5774
|
+
frontdoorCaDir: path23.join(root, "frontdoor", "ca"),
|
|
5775
|
+
frontdoorCaCertFile: path23.join(root, "frontdoor", "ca", "ca.pem"),
|
|
5776
|
+
frontdoorCaKeyFile: path23.join(root, "frontdoor", "ca", "ca.key"),
|
|
5777
|
+
frontdoorCaBundlesDir: path23.join(root, "frontdoor", "ca", "bundles"),
|
|
5778
|
+
chatgptSignInFile: path23.join(root, "codex", "chatgpt-sign-in.json"),
|
|
5779
|
+
frontdoorStateFile: path23.join(root, "frontdoor", "state.json"),
|
|
5780
|
+
frontdoorLockFile: path23.join(root, "frontdoor", "start.lock"),
|
|
5781
|
+
frontdoorControlTokenFile: path23.join(root, "frontdoor", "control-token"),
|
|
5782
|
+
frontdoorSessionsDir: path23.join(root, "frontdoor", "sessions"),
|
|
5783
|
+
frontdoorDirectRecordsDir: path23.join(root, "frontdoor", "direct"),
|
|
5784
|
+
frontdoorRcCredentialsDir: path23.join(root, "frontdoor", "rc-credentials"),
|
|
5785
|
+
frontdoorLogPath: path23.join(root, "logs", "frontdoor.log"),
|
|
5786
|
+
usageDir: path23.join(root, "usage"),
|
|
5787
|
+
usageLogDir: path23.join(root, "usage", "log"),
|
|
5788
|
+
usageSnapshotsDir: path23.join(root, "usage", "snapshots"),
|
|
5789
|
+
usagePicksFile: path23.join(root, "usage", "picks.json"),
|
|
5790
|
+
usageAnchorsFile: path23.join(root, "usage", "anchors.json"),
|
|
5791
|
+
usageJobsFile: path23.join(root, "usage", "jobs.json"),
|
|
5792
|
+
jobLogsDir: path23.join(root, "logs", "jobs"),
|
|
5793
|
+
mcpPermissionsFile: path23.join(root, "mcp", "permissions.json")
|
|
5326
5794
|
};
|
|
5327
5795
|
}
|
|
5328
5796
|
function resolveLayoutPaths() {
|
|
@@ -5414,7 +5882,7 @@ var init_credentialCache = __esm({
|
|
|
5414
5882
|
// src/realCredentialCache.ts
|
|
5415
5883
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
5416
5884
|
import fs6 from "node:fs";
|
|
5417
|
-
import
|
|
5885
|
+
import path24 from "node:path";
|
|
5418
5886
|
function cacheFileNameFor(owner) {
|
|
5419
5887
|
return `${owner.replace(/[^A-Za-z0-9._-]/g, "_")}.json`;
|
|
5420
5888
|
}
|
|
@@ -5438,8 +5906,8 @@ function security(args, stdin) {
|
|
|
5438
5906
|
return { status: result.status, stdout: result.stdout };
|
|
5439
5907
|
}
|
|
5440
5908
|
function createRealCredentialCache(root) {
|
|
5441
|
-
const dir =
|
|
5442
|
-
const filePath = (owner) =>
|
|
5909
|
+
const dir = path24.join(root, "credential-cache");
|
|
5910
|
+
const filePath = (owner) => path24.join(dir, cacheFileNameFor(owner));
|
|
5443
5911
|
return {
|
|
5444
5912
|
read(store, owner) {
|
|
5445
5913
|
if (store === "file") {
|
|
@@ -5671,9 +6139,9 @@ var init_credential = __esm({
|
|
|
5671
6139
|
|
|
5672
6140
|
// src/providersStore.ts
|
|
5673
6141
|
import fs7 from "node:fs";
|
|
5674
|
-
import
|
|
6142
|
+
import path25 from "node:path";
|
|
5675
6143
|
function providerJsonPath(paths, name) {
|
|
5676
|
-
return
|
|
6144
|
+
return path25.join(paths.providersDir, `${name}.json`);
|
|
5677
6145
|
}
|
|
5678
6146
|
function providerExists(paths, name) {
|
|
5679
6147
|
return fs7.existsSync(providerJsonPath(paths, name));
|
|
@@ -5733,7 +6201,7 @@ function readProvider(paths, name) {
|
|
|
5733
6201
|
return parseProviderFile(filePath, raw);
|
|
5734
6202
|
}
|
|
5735
6203
|
function loadProvider(providersDir, name, port) {
|
|
5736
|
-
const filePath =
|
|
6204
|
+
const filePath = path25.join(providersDir, `${name}.json`);
|
|
5737
6205
|
const raw = port.readConfigFile(filePath);
|
|
5738
6206
|
return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
|
|
5739
6207
|
}
|
|
@@ -6106,17 +6574,17 @@ var init_commandDeps = __esm({
|
|
|
6106
6574
|
|
|
6107
6575
|
// src/claudeShim.ts
|
|
6108
6576
|
import fs8 from "node:fs";
|
|
6109
|
-
import
|
|
6577
|
+
import path27 from "node:path";
|
|
6110
6578
|
import { z as z19 } from "zod";
|
|
6111
6579
|
function commandFilename(ownExecutablePath, commandName) {
|
|
6112
6580
|
return ownExecutablePath.toLowerCase().endsWith(".exe") ? `${commandName}.exe` : commandName;
|
|
6113
6581
|
}
|
|
6114
6582
|
function resolveOwnBinaryCheck(paths, contentSourcePath) {
|
|
6115
6583
|
const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
6116
|
-
const recordedTarget = state === void 0 ? void 0 :
|
|
6584
|
+
const recordedTarget = state === void 0 ? void 0 : path27.resolve(state.targetPath);
|
|
6117
6585
|
let ownStat;
|
|
6118
6586
|
return (candidate) => {
|
|
6119
|
-
if (recordedTarget !== void 0 &&
|
|
6587
|
+
if (recordedTarget !== void 0 && path27.resolve(candidate) === recordedTarget) {
|
|
6120
6588
|
return true;
|
|
6121
6589
|
}
|
|
6122
6590
|
ownStat ??= statOrUndefined(contentSourcePath);
|
|
@@ -6139,15 +6607,15 @@ function statOrUndefined(target) {
|
|
|
6139
6607
|
}
|
|
6140
6608
|
}
|
|
6141
6609
|
function findPathShadow(params) {
|
|
6142
|
-
const resolvedTargetDir =
|
|
6610
|
+
const resolvedTargetDir = path27.resolve(params.targetDir);
|
|
6143
6611
|
for (const dir of params.pathDirs) {
|
|
6144
6612
|
const found = params.findExecutableInDir(dir, params.targetFilename);
|
|
6145
6613
|
if (found === void 0) {
|
|
6146
6614
|
continue;
|
|
6147
6615
|
}
|
|
6148
|
-
return
|
|
6616
|
+
return path27.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
|
|
6149
6617
|
}
|
|
6150
|
-
return params.pathDirs.some((dir) =>
|
|
6618
|
+
return params.pathDirs.some((dir) => path27.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
|
|
6151
6619
|
}
|
|
6152
6620
|
var ClaudeShimStateSchema, nodeLinkFs;
|
|
6153
6621
|
var init_claudeShim = __esm({
|
|
@@ -6635,7 +7103,7 @@ var init_headers = __esm({
|
|
|
6635
7103
|
});
|
|
6636
7104
|
|
|
6637
7105
|
// src/launcher/flags.ts
|
|
6638
|
-
import
|
|
7106
|
+
import path36 from "node:path";
|
|
6639
7107
|
function resolveLaunchFlags(params) {
|
|
6640
7108
|
return {
|
|
6641
7109
|
skipPermissions: params.flags?.skipPermissions ?? parseEnvBool("AGENT_SHIM_SKIP_PERMISSIONS", params.env.AGENT_SHIM_SKIP_PERMISSIONS) ?? params.cascade?.skipPermissions ?? false,
|
|
@@ -6666,7 +7134,7 @@ function buildEnv(params) {
|
|
|
6666
7134
|
const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
6667
7135
|
let providerCustomHeaders;
|
|
6668
7136
|
if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
|
|
6669
|
-
env.CLAUDE_CONFIG_DIR =
|
|
7137
|
+
env.CLAUDE_CONFIG_DIR = path36.join(params.identitiesDir, params.resolvedIdentityName);
|
|
6670
7138
|
}
|
|
6671
7139
|
if (params.provider !== void 0) {
|
|
6672
7140
|
const providerEnv = params.provider.definition.env ?? {};
|
|
@@ -6938,7 +7406,7 @@ var init_launchHook = __esm({
|
|
|
6938
7406
|
|
|
6939
7407
|
// src/launcher.ts
|
|
6940
7408
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
6941
|
-
import
|
|
7409
|
+
import path37 from "node:path";
|
|
6942
7410
|
function resolveIdentityCredential(identity, credential, env, port) {
|
|
6943
7411
|
if (port === void 0) {
|
|
6944
7412
|
return { ok: false, status: 1, message: `agent-shim: identity ${identity} needs its credential resolved, but this launcher has no credential port wired` };
|
|
@@ -7048,7 +7516,7 @@ function decideLaunch(params, readOnly) {
|
|
|
7048
7516
|
identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
|
|
7049
7517
|
globalDefaultConfigProfile: params.globalDefaultConfigProfile
|
|
7050
7518
|
});
|
|
7051
|
-
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(
|
|
7519
|
+
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path37.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
|
|
7052
7520
|
log.error(
|
|
7053
7521
|
`agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
|
|
7054
7522
|
);
|
|
@@ -7160,7 +7628,7 @@ function decideLaunch(params, readOnly) {
|
|
|
7160
7628
|
extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
|
|
7161
7629
|
passthrough: parsedArgv.rest
|
|
7162
7630
|
});
|
|
7163
|
-
const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR :
|
|
7631
|
+
const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR : path37.join(paths.identitiesDir, identityDecision.name);
|
|
7164
7632
|
const decision = {
|
|
7165
7633
|
identitySource: identityDecision.source,
|
|
7166
7634
|
configDirEscapeHatch: identityDecision.configDirEscapeHatch,
|
|
@@ -7201,7 +7669,7 @@ function prepareLaunch(params) {
|
|
|
7201
7669
|
);
|
|
7202
7670
|
const updateCheck = runLaunchUpdateCheck({
|
|
7203
7671
|
mode: params.updateMode ?? "off",
|
|
7204
|
-
checkPath:
|
|
7672
|
+
checkPath: path37.join(paths.root, "update.check"),
|
|
7205
7673
|
currentVersion: package_default.version,
|
|
7206
7674
|
port: params.update
|
|
7207
7675
|
});
|
|
@@ -7361,12 +7829,12 @@ var init_launcher = __esm({
|
|
|
7361
7829
|
});
|
|
7362
7830
|
|
|
7363
7831
|
// src/ownCli.ts
|
|
7364
|
-
import
|
|
7832
|
+
import path38 from "node:path";
|
|
7365
7833
|
function agentShimCliPath(distDir = typeof __AGENT_SHIM_DIST_DIR__ === "string" ? __AGENT_SHIM_DIST_DIR__ : void 0) {
|
|
7366
7834
|
if (distDir === void 0) {
|
|
7367
7835
|
throw new OwnCliPathUnknownError();
|
|
7368
7836
|
}
|
|
7369
|
-
return
|
|
7837
|
+
return path38.join(distDir, OWN_CLI_FILE_NAME);
|
|
7370
7838
|
}
|
|
7371
7839
|
var OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
|
|
7372
7840
|
var init_ownCli = __esm({
|
|
@@ -7455,10 +7923,10 @@ request.on("error", (error) => finish(failed, (error.code ? error.code + ": " :
|
|
|
7455
7923
|
|
|
7456
7924
|
// src/frontdoor/trust.ts
|
|
7457
7925
|
import { createHash as createHash6 } from "node:crypto";
|
|
7458
|
-
import
|
|
7926
|
+
import path39 from "node:path";
|
|
7459
7927
|
function resolveTrustBundle(params) {
|
|
7460
7928
|
const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
|
|
7461
|
-
if (inherited === void 0 || inherited === "" ||
|
|
7929
|
+
if (inherited === void 0 || inherited === "" || path39.resolve(inherited) === path39.resolve(caCertFile)) {
|
|
7462
7930
|
return { path: caCertFile };
|
|
7463
7931
|
}
|
|
7464
7932
|
const caPem = fs12.readFileUtf8(caCertFile);
|
|
@@ -7476,7 +7944,7 @@ function resolveTrustBundle(params) {
|
|
|
7476
7944
|
}
|
|
7477
7945
|
const combined = `${inheritedPem.trimEnd()}
|
|
7478
7946
|
${caPem}`;
|
|
7479
|
-
const bundle =
|
|
7947
|
+
const bundle = path39.join(bundlesDir, `${createHash6("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
|
|
7480
7948
|
if (!fs12.exists(bundle)) {
|
|
7481
7949
|
fs12.mkdirp(bundlesDir);
|
|
7482
7950
|
fs12.writeFileAtomic(bundle, combined);
|
|
@@ -8337,6 +8805,7 @@ function pumpTapSession(secure, openUpstream, tap, prefix = Buffer.alloc(0)) {
|
|
|
8337
8805
|
// src/frontdoor/connect.ts
|
|
8338
8806
|
init_capability();
|
|
8339
8807
|
init_route();
|
|
8808
|
+
init_state();
|
|
8340
8809
|
|
|
8341
8810
|
// src/frontdoor/supervisor.ts
|
|
8342
8811
|
init_state();
|
|
@@ -8408,9 +8877,10 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
8408
8877
|
return fail(`could not start the direct listener: ${error instanceof Error ? error.message : String(error)}`);
|
|
8409
8878
|
}
|
|
8410
8879
|
if (previousStickyDirect !== void 0 && direct.port !== previousStickyDirect) {
|
|
8411
|
-
ports.log(`agent-shim frontdoor supervisor: sticky direct port ${String(previousStickyDirect)} was occupied; moving to ${String(direct.port)} (headroom
|
|
8880
|
+
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)`);
|
|
8412
8881
|
}
|
|
8413
8882
|
lastDirectPort = direct.port;
|
|
8883
|
+
writeFrontDoorDirectRecord(fs12, paths.frontdoorDirectRecordsDir, { pid: ports.ownPid, directPort: direct.port });
|
|
8414
8884
|
writeFrontDoorState(fs12, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http3.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
|
|
8415
8885
|
ports.doorHealth.generation({ providerPort: http3.port, connectPort: connect3.port, directPort: direct.port });
|
|
8416
8886
|
fs12.removeRecursive(paths.frontdoorLockFile);
|
|
@@ -8432,6 +8902,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
8432
8902
|
await connect3.close();
|
|
8433
8903
|
await http3.close();
|
|
8434
8904
|
ports.closeRcStreamHub();
|
|
8905
|
+
removeFrontDoorDirectRecord(fs12, paths.frontdoorDirectRecordsDir, ports.ownPid);
|
|
8435
8906
|
};
|
|
8436
8907
|
const shutdown = async () => {
|
|
8437
8908
|
await closeServing();
|
|
@@ -8495,7 +8966,6 @@ var CONNECT_INTERCEPT_HOST = "api.anthropic.com";
|
|
|
8495
8966
|
var CONNECT_INTERCEPT_HOSTS = [CONNECT_INTERCEPT_HOST, "platform.claude.com"];
|
|
8496
8967
|
var ROUTED_PATH_PREFIX = "/v1/";
|
|
8497
8968
|
var HTTPS_PORT = 443;
|
|
8498
|
-
var MAX_PORT = 65535;
|
|
8499
8969
|
var HTTP_BAD_GATEWAY = 502;
|
|
8500
8970
|
var CA_KEY_FILE_MODE = 384;
|
|
8501
8971
|
var CONNECT_LINE_TOKENS = 3;
|
|
@@ -8527,7 +8997,7 @@ function parseConnectTarget(authority) {
|
|
|
8527
8997
|
}
|
|
8528
8998
|
const host = authority.slice(0, colon).trim().toLowerCase();
|
|
8529
8999
|
const port = Number.parseInt(authority.slice(colon + 1), 10);
|
|
8530
|
-
if (host === "" || !Number.isInteger(port) || port <= 0 || port >
|
|
9000
|
+
if (host === "" || !Number.isInteger(port) || port <= 0 || port > MAX_TCP_PORT) {
|
|
8531
9001
|
return void 0;
|
|
8532
9002
|
}
|
|
8533
9003
|
return { host, port };
|
|
@@ -8535,8 +9005,8 @@ function parseConnectTarget(authority) {
|
|
|
8535
9005
|
function isInterceptedHost(host, interceptHosts) {
|
|
8536
9006
|
return interceptHosts.includes(host);
|
|
8537
9007
|
}
|
|
8538
|
-
function servedByPipeline(
|
|
8539
|
-
return
|
|
9008
|
+
function servedByPipeline(path40) {
|
|
9009
|
+
return path40?.startsWith(ROUTED_PATH_PREFIX) === true;
|
|
8540
9010
|
}
|
|
8541
9011
|
var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
8542
9012
|
"connection",
|
|
@@ -9330,11 +9800,11 @@ function createRcSessionTracker(deps) {
|
|
|
9330
9800
|
};
|
|
9331
9801
|
const observeExchange = (request4) => {
|
|
9332
9802
|
const method = (request4.method ?? "").toUpperCase();
|
|
9333
|
-
const
|
|
9334
|
-
if (!
|
|
9803
|
+
const path40 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
|
|
9804
|
+
if (!path40.startsWith(RC_SESSIONS_PATH_PREFIX)) {
|
|
9335
9805
|
return void 0;
|
|
9336
9806
|
}
|
|
9337
|
-
const tail =
|
|
9807
|
+
const tail = path40.slice(RC_SESSIONS_PATH_PREFIX.length);
|
|
9338
9808
|
const facts = {
|
|
9339
9809
|
oauthAuthorization: oauthAuthorizationOf(request4.headers),
|
|
9340
9810
|
anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
|
|
@@ -9724,8 +10194,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
|
|
|
9724
10194
|
function isRcReadFileEncoding(value) {
|
|
9725
10195
|
return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
|
|
9726
10196
|
}
|
|
9727
|
-
function buildRcReadFilePayload(requestId,
|
|
9728
|
-
return buildRcControlRequestPayload(requestId, { subtype: "read_file", path:
|
|
10197
|
+
function buildRcReadFilePayload(requestId, path40, options) {
|
|
10198
|
+
return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path40, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
|
|
9729
10199
|
}
|
|
9730
10200
|
function buildRcFileSuggestionsPayload(requestId, query) {
|
|
9731
10201
|
return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
|
|
@@ -9827,15 +10297,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
|
|
|
9827
10297
|
const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
|
|
9828
10298
|
return result.ok ? { ...result, requestId } : result;
|
|
9829
10299
|
}
|
|
9830
|
-
async function readRcSessionFile(deps, sessionId,
|
|
9831
|
-
if (
|
|
10300
|
+
async function readRcSessionFile(deps, sessionId, path40, options) {
|
|
10301
|
+
if (path40 === "") {
|
|
9832
10302
|
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" };
|
|
9833
10303
|
}
|
|
9834
10304
|
if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
|
|
9835
10305
|
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" };
|
|
9836
10306
|
}
|
|
9837
10307
|
const requestId = deps.newUuid();
|
|
9838
|
-
const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId,
|
|
10308
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path40, options), `read ${path40} from session ${sessionId}`);
|
|
9839
10309
|
return result.ok ? { ...result, requestId } : result;
|
|
9840
10310
|
}
|
|
9841
10311
|
async function suggestRcSessionFiles(deps, sessionId, query) {
|
|
@@ -10004,11 +10474,11 @@ function createRcControlHandler(deps) {
|
|
|
10004
10474
|
path: "read-file",
|
|
10005
10475
|
read: (body) => {
|
|
10006
10476
|
const session = bodyString(body, "session");
|
|
10007
|
-
const
|
|
10477
|
+
const path40 = bodyString(body, "path");
|
|
10008
10478
|
const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
|
|
10009
10479
|
const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
|
|
10010
|
-
const refused2 = session === void 0 ||
|
|
10011
|
-
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,
|
|
10480
|
+
const refused2 = session === void 0 || path40 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
|
|
10481
|
+
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 } }) };
|
|
10012
10482
|
}
|
|
10013
10483
|
},
|
|
10014
10484
|
{
|
|
@@ -10318,9 +10788,9 @@ function requestIdOfBody(body) {
|
|
|
10318
10788
|
}
|
|
10319
10789
|
function frontDoorRcControl(transport, token) {
|
|
10320
10790
|
const headers = { authorization: `Bearer ${token}` };
|
|
10321
|
-
const listAnswerOf = async (
|
|
10791
|
+
const listAnswerOf = async (path40, what) => {
|
|
10322
10792
|
try {
|
|
10323
|
-
return await transport.request({ method: "GET", path:
|
|
10793
|
+
return await transport.request({ method: "GET", path: path40, headers });
|
|
10324
10794
|
} catch (error) {
|
|
10325
10795
|
throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
10326
10796
|
}
|
|
@@ -10392,10 +10862,10 @@ function frontDoorRcControl(transport, token) {
|
|
|
10392
10862
|
}
|
|
10393
10863
|
return pending;
|
|
10394
10864
|
};
|
|
10395
|
-
const writeOf = async (
|
|
10865
|
+
const writeOf = async (path40, body, describeFailure2) => {
|
|
10396
10866
|
let answer;
|
|
10397
10867
|
try {
|
|
10398
|
-
answer = await transport.request({ method: "POST", path:
|
|
10868
|
+
answer = await transport.request({ method: "POST", path: path40, headers: { ...headers, "content-type": "application/json" }, body });
|
|
10399
10869
|
} catch (error) {
|
|
10400
10870
|
return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
|
|
10401
10871
|
}
|
|
@@ -10426,10 +10896,10 @@ function frontDoorRcControl(transport, token) {
|
|
|
10426
10896
|
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}`),
|
|
10427
10897
|
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}`),
|
|
10428
10898
|
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}`),
|
|
10429
|
-
readFile: async (sessionId,
|
|
10899
|
+
readFile: async (sessionId, path40, options) => await writeOf(
|
|
10430
10900
|
`${CONTROL_PATH_PREFIX}/read-file`,
|
|
10431
|
-
JSON.stringify({ session: sessionId, path:
|
|
10432
|
-
(status, message) => `reading ${
|
|
10901
|
+
JSON.stringify({ session: sessionId, path: path40, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
|
|
10902
|
+
(status, message) => `reading ${path40} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
|
|
10433
10903
|
),
|
|
10434
10904
|
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}`),
|
|
10435
10905
|
keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
|
|
@@ -10588,12 +11058,12 @@ function tlsFacts(options) {
|
|
|
10588
11058
|
}
|
|
10589
11059
|
function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
|
|
10590
11060
|
const agent = new ExemptTlsAgent();
|
|
10591
|
-
const post = async (
|
|
11061
|
+
const post = async (path40, headers, body) => await new Promise((resolve, reject) => {
|
|
10592
11062
|
const options = {
|
|
10593
11063
|
host: target.host,
|
|
10594
11064
|
port: target.port,
|
|
10595
11065
|
method: "POST",
|
|
10596
|
-
path:
|
|
11066
|
+
path: path40,
|
|
10597
11067
|
// 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.
|
|
10598
11068
|
headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
|
|
10599
11069
|
agent
|
|
@@ -10658,12 +11128,12 @@ function lateRcStreamDial(resolve) {
|
|
|
10658
11128
|
}
|
|
10659
11129
|
function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
|
|
10660
11130
|
const agent = new ExemptTlsAgent();
|
|
10661
|
-
const request4 = async (method,
|
|
11131
|
+
const request4 = async (method, path40, headers, body, signal) => await new Promise((resolve, reject) => {
|
|
10662
11132
|
const options = {
|
|
10663
11133
|
host: target.host,
|
|
10664
11134
|
port: target.port,
|
|
10665
11135
|
method,
|
|
10666
|
-
path:
|
|
11136
|
+
path: path40,
|
|
10667
11137
|
// 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.
|
|
10668
11138
|
headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
|
|
10669
11139
|
agent,
|
|
@@ -10705,9 +11175,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
|
|
|
10705
11175
|
return { status, body: await readAll(response) };
|
|
10706
11176
|
},
|
|
10707
11177
|
openStream: async (sessionId, headers, resume, signal) => {
|
|
10708
|
-
const
|
|
11178
|
+
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)}`;
|
|
10709
11179
|
const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
|
|
10710
|
-
const { status, response } = await request4("GET",
|
|
11180
|
+
const { status, response } = await request4("GET", path40, streamHeaders, void 0, signal);
|
|
10711
11181
|
if (!isSuccessful2(status)) {
|
|
10712
11182
|
await readAll(response);
|
|
10713
11183
|
return { status, chunks: NO_CHUNKS };
|
|
@@ -11651,7 +12121,7 @@ init_schema();
|
|
|
11651
12121
|
init_cliError();
|
|
11652
12122
|
init_load();
|
|
11653
12123
|
import fs4 from "node:fs";
|
|
11654
|
-
import
|
|
12124
|
+
import path22 from "node:path";
|
|
11655
12125
|
var ProfileNotFoundError = class extends CliError {
|
|
11656
12126
|
constructor(profileName) {
|
|
11657
12127
|
super(`No configuration profile named "${profileName}". Run \`agent-shim profile add ${profileName}\` first.`);
|
|
@@ -11677,7 +12147,7 @@ var InvalidCategoryNameError = class extends CliError {
|
|
|
11677
12147
|
categoryName;
|
|
11678
12148
|
};
|
|
11679
12149
|
function profileJsonPath(paths, name) {
|
|
11680
|
-
return
|
|
12150
|
+
return path22.join(paths.configProfilesDir, `${name}.json`);
|
|
11681
12151
|
}
|
|
11682
12152
|
function profileExists(paths, name) {
|
|
11683
12153
|
return fs4.existsSync(profileJsonPath(paths, name));
|
|
@@ -11859,19 +12329,19 @@ function writePools(paths, pools) {
|
|
|
11859
12329
|
applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
|
|
11860
12330
|
}
|
|
11861
12331
|
function poolCycleOf(pools, name) {
|
|
11862
|
-
const walk = (current,
|
|
12332
|
+
const walk = (current, path40) => {
|
|
11863
12333
|
for (const entry of pools[current]?.identities ?? []) {
|
|
11864
12334
|
const nested = poolNameOf(poolMemberIdentity(entry));
|
|
11865
12335
|
if (nested === void 0) {
|
|
11866
12336
|
continue;
|
|
11867
12337
|
}
|
|
11868
12338
|
if (nested === name) {
|
|
11869
|
-
return [...
|
|
12339
|
+
return [...path40, nested];
|
|
11870
12340
|
}
|
|
11871
|
-
if (
|
|
12341
|
+
if (path40.includes(nested)) {
|
|
11872
12342
|
continue;
|
|
11873
12343
|
}
|
|
11874
|
-
const found = walk(nested, [...
|
|
12344
|
+
const found = walk(nested, [...path40, nested]);
|
|
11875
12345
|
if (found !== void 0) {
|
|
11876
12346
|
return found;
|
|
11877
12347
|
}
|
|
@@ -11981,7 +12451,7 @@ init_guard();
|
|
|
11981
12451
|
init_providersStore();
|
|
11982
12452
|
init_projects();
|
|
11983
12453
|
init_pipeline();
|
|
11984
|
-
import
|
|
12454
|
+
import path26 from "node:path";
|
|
11985
12455
|
import { z as z15 } from "zod";
|
|
11986
12456
|
var HISTORY_PROJECTS_KEY_PREFIX = "history/projects/";
|
|
11987
12457
|
function projectFragmentOf(rawKey) {
|
|
@@ -12319,10 +12789,10 @@ function collectCheckReport(params) {
|
|
|
12319
12789
|
}).input;
|
|
12320
12790
|
const providerName = cascadeProviderName(cascade);
|
|
12321
12791
|
const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
|
|
12322
|
-
const farmRoot = identityDecision.name === void 0 ? void 0 :
|
|
12792
|
+
const farmRoot = identityDecision.name === void 0 ? void 0 : path26.join(paths.identitiesDir, identityDecision.name);
|
|
12323
12793
|
const settingsFiles = {
|
|
12324
|
-
"settings.json": realFsPort.readFileUtf8(
|
|
12325
|
-
"settings.local.json": realFsPort.readFileUtf8(
|
|
12794
|
+
"settings.json": realFsPort.readFileUtf8(path26.join(claudeHome, "settings.json")),
|
|
12795
|
+
"settings.local.json": realFsPort.readFileUtf8(path26.join(claudeHome, "settings.local.json"))
|
|
12326
12796
|
};
|
|
12327
12797
|
const report = runCheck({
|
|
12328
12798
|
cwd,
|
|
@@ -12614,7 +13084,7 @@ var ResetRowSchema = z18.strictObject({
|
|
|
12614
13084
|
var ResetScheduleSchema = z18.strictObject({ resets: z18.readonly(z18.array(ResetRowSchema)) });
|
|
12615
13085
|
|
|
12616
13086
|
// src/frontdoor/controlSchemas.ts
|
|
12617
|
-
import
|
|
13087
|
+
import path31 from "node:path";
|
|
12618
13088
|
import { z as z23 } from "zod";
|
|
12619
13089
|
|
|
12620
13090
|
// src/doctorReport.ts
|
|
@@ -12628,7 +13098,7 @@ init_schema();
|
|
|
12628
13098
|
init_cliError();
|
|
12629
13099
|
init_identity();
|
|
12630
13100
|
import fs9 from "node:fs";
|
|
12631
|
-
import
|
|
13101
|
+
import path28 from "node:path";
|
|
12632
13102
|
init_lock();
|
|
12633
13103
|
var IdentityNotFoundError = class extends CliError {
|
|
12634
13104
|
constructor(name) {
|
|
@@ -12657,7 +13127,7 @@ var InvalidIdentityNameError = class extends CliError {
|
|
|
12657
13127
|
attemptedName;
|
|
12658
13128
|
};
|
|
12659
13129
|
function identityJsonPath(paths, name) {
|
|
12660
|
-
return
|
|
13130
|
+
return path28.join(paths.identitiesDir, name, "identity.json");
|
|
12661
13131
|
}
|
|
12662
13132
|
function requireIdentityNames(paths, names) {
|
|
12663
13133
|
const existing = new Set(listIdentities(paths).map((entry) => entry.name));
|
|
@@ -12772,7 +13242,7 @@ function setIdentityCredential(paths, identityName, change) {
|
|
|
12772
13242
|
});
|
|
12773
13243
|
}
|
|
12774
13244
|
function belongsToIdentity(entry, name) {
|
|
12775
|
-
return entry === name || entry ===
|
|
13245
|
+
return entry === name || entry === path28.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
|
|
12776
13246
|
}
|
|
12777
13247
|
function removeIdentity(paths, name) {
|
|
12778
13248
|
if (!identityExists(paths, name)) {
|
|
@@ -12780,7 +13250,7 @@ function removeIdentity(paths, name) {
|
|
|
12780
13250
|
}
|
|
12781
13251
|
for (const entry of fs9.readdirSync(paths.identitiesDir)) {
|
|
12782
13252
|
if (belongsToIdentity(entry, name)) {
|
|
12783
|
-
fs9.rmSync(
|
|
13253
|
+
fs9.rmSync(path28.join(paths.identitiesDir, entry), { recursive: true, force: true });
|
|
12784
13254
|
}
|
|
12785
13255
|
}
|
|
12786
13256
|
if (readActiveIdentity2(paths) === name) {
|
|
@@ -12791,10 +13261,10 @@ function removeIdentity(paths, name) {
|
|
|
12791
13261
|
// src/doctorReport.ts
|
|
12792
13262
|
init_realPorts();
|
|
12793
13263
|
import fs10 from "node:fs";
|
|
12794
|
-
import
|
|
13264
|
+
import path30 from "node:path";
|
|
12795
13265
|
|
|
12796
13266
|
// src/usage/signIn.ts
|
|
12797
|
-
import
|
|
13267
|
+
import path29 from "node:path";
|
|
12798
13268
|
var CREDENTIALS_FILE = ".credentials.json";
|
|
12799
13269
|
function keychainHasItem(run, account) {
|
|
12800
13270
|
return run.run("security", ["find-generic-password", "-a", account]).status === 0;
|
|
@@ -12812,7 +13282,7 @@ function decideSignIn(facts) {
|
|
|
12812
13282
|
return { state: "signed-out", detail: facts.platform === "darwin" ? `no Keychain item and no ${CREDENTIALS_FILE}` : `no ${CREDENTIALS_FILE}` };
|
|
12813
13283
|
}
|
|
12814
13284
|
function credentialsFilePath(farmRoot) {
|
|
12815
|
-
return
|
|
13285
|
+
return path29.join(farmRoot, CREDENTIALS_FILE);
|
|
12816
13286
|
}
|
|
12817
13287
|
|
|
12818
13288
|
// src/codex/siwcStore.ts
|
|
@@ -12901,17 +13371,75 @@ init_realCredentialCache();
|
|
|
12901
13371
|
init_source();
|
|
12902
13372
|
|
|
12903
13373
|
// src/headroom/allowlistDrift.ts
|
|
13374
|
+
init_earlierRelease();
|
|
12904
13375
|
init_state2();
|
|
12905
13376
|
function diagnoseAllowlistDrift(params) {
|
|
12906
|
-
const {
|
|
12907
|
-
if (recordedHash === void 0
|
|
13377
|
+
const { allowlist, fileContent, recordedHash, earlierRelease } = params;
|
|
13378
|
+
if (recordedHash === void 0) {
|
|
12908
13379
|
return void 0;
|
|
12909
13380
|
}
|
|
12910
|
-
|
|
12911
|
-
|
|
12912
|
-
|
|
13381
|
+
if (earlierRelease !== void 0) {
|
|
13382
|
+
return earlierRelease.admitsServingDoor ? void 0 : { startedByEarlierRelease: true };
|
|
13383
|
+
}
|
|
13384
|
+
const served = fileContent === void 0 ? [] : parseAllowlistFile(fileContent);
|
|
13385
|
+
const listed = new Set(served);
|
|
13386
|
+
const computed = new Set(allowlist);
|
|
13387
|
+
const missingFromFile = allowlist.filter((entry) => !listed.has(entry));
|
|
13388
|
+
const staleInFile = served.filter((entry) => !computed.has(entry)).sort();
|
|
13389
|
+
const hashLags = recordedHash !== (fileContent === void 0 ? void 0 : hashAllowlistFile(fileContent));
|
|
13390
|
+
if (missingFromFile.length === 0 && staleInFile.length === 0 && !hashLags) {
|
|
13391
|
+
return void 0;
|
|
13392
|
+
}
|
|
13393
|
+
return { missingFromFile, staleInFile, hashLags };
|
|
13394
|
+
}
|
|
13395
|
+
function describeAllowlistDrift(params) {
|
|
13396
|
+
const { drift, allowlistFile, liveSupervisorPid } = params;
|
|
13397
|
+
if (drift.startedByEarlierRelease === true) {
|
|
13398
|
+
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`;
|
|
13399
|
+
}
|
|
13400
|
+
const parts = [];
|
|
13401
|
+
if (drift.missingFromFile.length > 0) {
|
|
13402
|
+
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)`);
|
|
13403
|
+
}
|
|
13404
|
+
if (drift.staleInFile.length > 0) {
|
|
13405
|
+
parts.push(`${allowlistFile} still lists ${drift.staleInFile.join(", ")}`);
|
|
13406
|
+
}
|
|
13407
|
+
if (drift.hashLags) {
|
|
13408
|
+
parts.push("the supervisor has not yet recorded the file's allowlist as served, and provider launches through headroom wait until it does");
|
|
13409
|
+
}
|
|
13410
|
+
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})`;
|
|
13411
|
+
return `${parts.join("; ")}; ${healing}`;
|
|
13412
|
+
}
|
|
13413
|
+
|
|
13414
|
+
// src/doctorReport.ts
|
|
13415
|
+
init_earlierRelease();
|
|
13416
|
+
init_socket();
|
|
13417
|
+
|
|
13418
|
+
// src/doctorHeadroomAllowlist.ts
|
|
13419
|
+
function pushRefusedAllowlistFile(push, allowlist) {
|
|
13420
|
+
const problem = allowlist.fileProblem;
|
|
13421
|
+
if (problem?.repairable === false) {
|
|
13422
|
+
push("headroom", "fail", `Headroom refuses its allowlist file, so it admits nothing and every provider request through headroom fails: ${problem.message}.`, allowlist.file);
|
|
13423
|
+
}
|
|
13424
|
+
}
|
|
13425
|
+
function pushHeadroomAllowlist(push, allowlist, daemon) {
|
|
13426
|
+
const { drift } = allowlist;
|
|
13427
|
+
const problem = allowlist.fileProblem;
|
|
13428
|
+
if (problem?.repairable === true) {
|
|
13429
|
+
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);
|
|
13430
|
+
}
|
|
13431
|
+
if (drift !== void 0) {
|
|
13432
|
+
const blocking = drift.startedByEarlierRelease === true || drift.missingFromFile.length > 0 || drift.hashLags;
|
|
13433
|
+
push(
|
|
13434
|
+
"headroom",
|
|
13435
|
+
blocking ? "fail" : "warn",
|
|
13436
|
+
`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.",
|
|
13437
|
+
String(daemon.headroomPid)
|
|
13438
|
+
);
|
|
13439
|
+
}
|
|
13440
|
+
for (const door of allowlist.undeterminedFrontDoors) {
|
|
13441
|
+
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));
|
|
12913
13442
|
}
|
|
12914
|
-
return recordedHash === hashAllowlist(headroomAllowlist(headroomUpstreams(providers, void 0))) ? ["front-door-origin"] : ["provider-files", "front-door-origin"];
|
|
12915
13443
|
}
|
|
12916
13444
|
|
|
12917
13445
|
// src/doctorReport.ts
|
|
@@ -12920,7 +13448,7 @@ init_supervisor();
|
|
|
12920
13448
|
init_state();
|
|
12921
13449
|
|
|
12922
13450
|
// src/doctorFrontDoor.ts
|
|
12923
|
-
function pushFrontDoor(push, supervisors, registeredPid) {
|
|
13451
|
+
function pushFrontDoor(push, supervisors, registeredPid, liveSessions) {
|
|
12924
13452
|
if (!supervisors.ok) {
|
|
12925
13453
|
push("frontdoor", "warn", `Could not list processes to look for duplicate front door supervisors: ${supervisors.message}.`);
|
|
12926
13454
|
return;
|
|
@@ -12937,6 +13465,16 @@ function pushFrontDoor(push, supervisors, registeredPid) {
|
|
|
12937
13465
|
}
|
|
12938
13466
|
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.";
|
|
12939
13467
|
for (const pid of pids.filter((candidate) => candidate !== registeredPid)) {
|
|
13468
|
+
const served = liveSessions.filter((session) => session.supervisorPid === pid).length;
|
|
13469
|
+
if (registeredPid !== void 0 && pids.includes(registeredPid) && served > 0) {
|
|
13470
|
+
push(
|
|
13471
|
+
"frontdoor",
|
|
13472
|
+
"warn",
|
|
13473
|
+
`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.`,
|
|
13474
|
+
String(pid)
|
|
13475
|
+
);
|
|
13476
|
+
continue;
|
|
13477
|
+
}
|
|
12940
13478
|
push(
|
|
12941
13479
|
"frontdoor",
|
|
12942
13480
|
"fail",
|
|
@@ -13006,7 +13544,7 @@ function tcpPortEraRecord(raw) {
|
|
|
13006
13544
|
return (has("port") || has("lastPort")) && !has("socketPath");
|
|
13007
13545
|
}
|
|
13008
13546
|
function pushPathResolution(push, resolution) {
|
|
13009
|
-
const ownDir =
|
|
13547
|
+
const ownDir = path30.dirname(resolution.ownExecutablePath);
|
|
13010
13548
|
switch (resolution.agentShim.status) {
|
|
13011
13549
|
case "ok":
|
|
13012
13550
|
push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
|
|
@@ -13105,14 +13643,14 @@ function pushProvider(push, entry, cacheEnv, signIn) {
|
|
|
13105
13643
|
}
|
|
13106
13644
|
function pushLegacyName(push, params) {
|
|
13107
13645
|
const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
|
|
13108
|
-
if (legacyVariables.length === 0 &&
|
|
13646
|
+
if (legacyVariables.length === 0 && path30.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
|
|
13109
13647
|
push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
|
|
13110
13648
|
return;
|
|
13111
13649
|
}
|
|
13112
13650
|
for (const name of legacyVariables) {
|
|
13113
13651
|
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);
|
|
13114
13652
|
}
|
|
13115
|
-
if (
|
|
13653
|
+
if (path30.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
|
|
13116
13654
|
push(
|
|
13117
13655
|
"legacy-name",
|
|
13118
13656
|
"warn",
|
|
@@ -13368,15 +13906,11 @@ function runDoctor(params) {
|
|
|
13368
13906
|
);
|
|
13369
13907
|
}
|
|
13370
13908
|
const allowlist = params.headroom.allowlist;
|
|
13371
|
-
if (
|
|
13372
|
-
|
|
13373
|
-
|
|
13374
|
-
|
|
13375
|
-
|
|
13376
|
-
"fail",
|
|
13377
|
-
`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.`,
|
|
13378
|
-
String(state.headroomPid)
|
|
13379
|
-
);
|
|
13909
|
+
if (allowlist !== void 0) {
|
|
13910
|
+
pushRefusedAllowlistFile(push, allowlist);
|
|
13911
|
+
}
|
|
13912
|
+
if (allowlist !== void 0 && headroomAlive && state.headroomPid !== void 0) {
|
|
13913
|
+
pushHeadroomAllowlist(push, allowlist, { headroomPid: state.headroomPid, liveSupervisorPid: supervisorAlive ? state.supervisorPid : void 0 });
|
|
13380
13914
|
}
|
|
13381
13915
|
if (state.lastError !== void 0 && supervisorAlive) {
|
|
13382
13916
|
push("headroom", "warn", `Headroom recorded a previous error: ${state.lastError}`);
|
|
@@ -13392,7 +13926,7 @@ function runDoctor(params) {
|
|
|
13392
13926
|
}
|
|
13393
13927
|
if (params.frontDoor !== void 0) {
|
|
13394
13928
|
const validated3 = params.frontDoor.state.raw === void 0 ? void 0 : validateJson(FrontDoorStateSchema, params.frontDoor.state);
|
|
13395
|
-
pushFrontDoor(push, params.frontDoor.supervisors, validated3?.ok === true ? validated3.data.supervisorPid : void 0);
|
|
13929
|
+
pushFrontDoor(push, params.frontDoor.supervisors, validated3?.ok === true ? validated3.data.supervisorPid : void 0, params.frontDoor.liveSessions);
|
|
13396
13930
|
}
|
|
13397
13931
|
if (params.activeIdentity.raw === void 0) {
|
|
13398
13932
|
push("active-identity", "pass", "No active identity set.");
|
|
@@ -13485,18 +14019,18 @@ function collectDoctorReport(params) {
|
|
|
13485
14019
|
const { paths } = params;
|
|
13486
14020
|
const identityNames = fs10.existsSync(paths.identitiesDir) ? fs10.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
|
|
13487
14021
|
const identities = identityNames.map((name) => {
|
|
13488
|
-
const farmRoot =
|
|
13489
|
-
const identityPath =
|
|
14022
|
+
const farmRoot = path30.join(paths.identitiesDir, name);
|
|
14023
|
+
const identityPath = path30.join(farmRoot, "identity.json");
|
|
13490
14024
|
return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot, credentialsFilePresent: fs10.existsSync(credentialsFilePath(farmRoot)) };
|
|
13491
14025
|
});
|
|
13492
14026
|
const profileNames = fs10.existsSync(paths.configProfilesDir) ? fs10.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
13493
14027
|
const configProfiles = profileNames.map((name) => {
|
|
13494
|
-
const profilePath =
|
|
14028
|
+
const profilePath = path30.join(paths.configProfilesDir, `${name}.json`);
|
|
13495
14029
|
return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
|
|
13496
14030
|
});
|
|
13497
14031
|
const providerNames = fs10.existsSync(paths.providersDir) ? fs10.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
13498
14032
|
const providers = providerNames.map((name) => {
|
|
13499
|
-
const providerPath =
|
|
14033
|
+
const providerPath = path30.join(paths.providersDir, `${name}.json`);
|
|
13500
14034
|
return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
|
|
13501
14035
|
});
|
|
13502
14036
|
const ownExecutablePath = realOwnExecutablePath();
|
|
@@ -13508,20 +14042,24 @@ function collectDoctorReport(params) {
|
|
|
13508
14042
|
binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
|
|
13509
14043
|
}
|
|
13510
14044
|
const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
13511
|
-
const pathDirs = (params.env.PATH ?? "").split(
|
|
14045
|
+
const pathDirs = (params.env.PATH ?? "").split(path30.delimiter).filter((dir) => dir !== "");
|
|
13512
14046
|
const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
|
|
13513
14047
|
findPathShadow({
|
|
13514
14048
|
pathDirs,
|
|
13515
|
-
targetDir:
|
|
13516
|
-
targetFilename:
|
|
14049
|
+
targetDir: path30.dirname(shimState.targetPath),
|
|
14050
|
+
targetFilename: path30.basename(shimState.targetPath),
|
|
13517
14051
|
findExecutableInDir
|
|
13518
14052
|
}),
|
|
13519
14053
|
shimState.targetPath,
|
|
13520
14054
|
realpathOrSelf
|
|
13521
14055
|
);
|
|
13522
14056
|
const uid = process.getuid?.();
|
|
13523
|
-
const
|
|
14057
|
+
const allowlistContent = realFarmFs.readFileUtf8(paths.headroomAllowlistFile);
|
|
14058
|
+
const allowlistInputs = currentHeadroomAllowlistInputs(realFarmFs, paths, realFrontDoorLiveness);
|
|
13524
14059
|
const servingHeadroom = resolveServingHeadroomState(realFarmFs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, realIsProcessRunning);
|
|
14060
|
+
const servingState = servingHeadroom?.state;
|
|
14061
|
+
const servingDaemon = servingState?.headroomPid !== void 0 && servingState.socketPath !== void 0 && realIsProcessRunning(servingState.headroomPid) ? { pid: servingState.headroomPid, socketPath: servingState.socketPath } : void 0;
|
|
14062
|
+
const servingEarlierRelease = servingDaemon === void 0 ? void 0 : earlierReleaseDaemon(realFarmFs, paths, { commandLine: realProcessCommandLine(servingDaemon.pid), socketPath: servingDaemon.socketPath, recordedHash: servingState?.allowlistHash });
|
|
13525
14063
|
const report = runDoctor({
|
|
13526
14064
|
env: params.env,
|
|
13527
14065
|
credentialCache: realCredentialCacheEnv(paths),
|
|
@@ -13542,7 +14080,7 @@ function collectDoctorReport(params) {
|
|
|
13542
14080
|
agentShim: refinePathShadow(
|
|
13543
14081
|
findPathShadow({
|
|
13544
14082
|
pathDirs,
|
|
13545
|
-
targetDir:
|
|
14083
|
+
targetDir: path30.dirname(ownExecutablePath),
|
|
13546
14084
|
targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
|
|
13547
14085
|
findExecutableInDir
|
|
13548
14086
|
}),
|
|
@@ -13562,11 +14100,20 @@ function collectDoctorReport(params) {
|
|
|
13562
14100
|
})(),
|
|
13563
14101
|
isRunning: realIsProcessRunning,
|
|
13564
14102
|
allowlist: {
|
|
13565
|
-
|
|
13566
|
-
|
|
14103
|
+
drift: diagnoseAllowlistDrift({
|
|
14104
|
+
allowlist: allowlistInputs.frontDoorOrigins,
|
|
14105
|
+
fileContent: allowlistContent,
|
|
14106
|
+
recordedHash: servingHeadroom?.state.allowlistHash,
|
|
14107
|
+
earlierRelease: servingEarlierRelease
|
|
14108
|
+
}),
|
|
14109
|
+
file: paths.headroomAllowlistFile,
|
|
14110
|
+
undeterminedFrontDoors: undeterminedFrontDoors(allowlistInputs),
|
|
14111
|
+
// An earlier release's daemon reads no allowlist file, so there is nothing to check while one serves.
|
|
14112
|
+
fileProblem: servingEarlierRelease === void 0 ? reportableAllowlistFileProblem(paths.headroomAllowlistFile, realHeadroomSocketTrust, servingHeadroom?.state.allowlistHash !== void 0) : void 0,
|
|
14113
|
+
logPath: paths.headroomLogPath
|
|
13567
14114
|
}
|
|
13568
14115
|
},
|
|
13569
|
-
...uid === void 0 ? {} : { frontDoor: { state: { path: paths.frontdoorStateFile, raw: realFsPort.readFileUtf8(paths.frontdoorStateFile) }, supervisors: listFrontDoorSupervisors(realRunPort, uid) } }
|
|
14116
|
+
...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)) } }
|
|
13570
14117
|
});
|
|
13571
14118
|
return report;
|
|
13572
14119
|
}
|
|
@@ -13621,11 +14168,11 @@ var FrontDoorSessionsOutputSchema = z23.strictObject({ sessions: z23.readonly(z2
|
|
|
13621
14168
|
var CheckRunInputSchema = z23.strictObject({
|
|
13622
14169
|
path: z23.string().min(1),
|
|
13623
14170
|
identity: z23.string().min(1).optional()
|
|
13624
|
-
}).refine((input) =>
|
|
14171
|
+
}).refine((input) => path31.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
13625
14172
|
var PoolPickInputSchema = z23.strictObject({
|
|
13626
14173
|
pool: z23.string().min(1),
|
|
13627
14174
|
path: z23.string().min(1)
|
|
13628
|
-
}).refine((input) =>
|
|
14175
|
+
}).refine((input) => path31.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
13629
14176
|
var DoctorFindingSchema = z23.strictObject({
|
|
13630
14177
|
section: z23.enum(DOCTOR_SECTIONS),
|
|
13631
14178
|
subject: z23.string().optional(),
|
|
@@ -14005,7 +14552,7 @@ function profileValue(name, paths) {
|
|
|
14005
14552
|
function createConfigApiRouter(deps) {
|
|
14006
14553
|
const authed = doorApiAuth(deps.expectedToken);
|
|
14007
14554
|
const { paths } = deps;
|
|
14008
|
-
const route = (
|
|
14555
|
+
const route = (path40, summary) => authed.meta(openapi3({ method: "POST", path: path40, summary, tags: [CONFIG_API_TAG] }));
|
|
14009
14556
|
return {
|
|
14010
14557
|
config: {
|
|
14011
14558
|
identity: {
|
|
@@ -14369,7 +14916,7 @@ import { ORPCError as ORPCError5 } from "@orpc/client";
|
|
|
14369
14916
|
import { openapi as openapi6 } from "@orpc/openapi";
|
|
14370
14917
|
|
|
14371
14918
|
// src/frontdoor/launchSchemas.ts
|
|
14372
|
-
import
|
|
14919
|
+
import path32 from "node:path";
|
|
14373
14920
|
import { z as z26 } from "zod";
|
|
14374
14921
|
init_claudeVersion();
|
|
14375
14922
|
init_identity();
|
|
@@ -14379,7 +14926,7 @@ var LaunchResolveInputSchema = z26.strictObject({
|
|
|
14379
14926
|
argv: z26.readonly(z26.array(z26.string())).optional(),
|
|
14380
14927
|
/** 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. */
|
|
14381
14928
|
env: z26.record(z26.string(), z26.string()).optional()
|
|
14382
|
-
}).refine((input) =>
|
|
14929
|
+
}).refine((input) => path32.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
14383
14930
|
var LaunchPoolDecisionSchema = z26.strictObject({
|
|
14384
14931
|
name: z26.string(),
|
|
14385
14932
|
reasons: z26.readonly(z26.array(z26.string())),
|
|
@@ -16547,7 +17094,7 @@ data: ${JSON.stringify(envelope)}
|
|
|
16547
17094
|
|
|
16548
17095
|
// src/frontdoor/rcSelfHostMint.ts
|
|
16549
17096
|
init_account();
|
|
16550
|
-
import
|
|
17097
|
+
import path33 from "node:path";
|
|
16551
17098
|
var CREDENTIALS_FILE2 = ".credentials.json";
|
|
16552
17099
|
var CLAUDE_JSON2 = ".claude.json";
|
|
16553
17100
|
var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
|
|
@@ -16571,7 +17118,7 @@ function readJsonObject(fs12, file) {
|
|
|
16571
17118
|
return isRecord12(parsed) ? parsed : void 0;
|
|
16572
17119
|
}
|
|
16573
17120
|
function readRcSelfHostRecord(fs12, frontdoorDir) {
|
|
16574
|
-
const parsed = readJsonObject(fs12,
|
|
17121
|
+
const parsed = readJsonObject(fs12, path33.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
|
|
16575
17122
|
if (parsed === void 0) {
|
|
16576
17123
|
return void 0;
|
|
16577
17124
|
}
|
|
@@ -16585,11 +17132,11 @@ function mintRcSelfHostCredential(deps) {
|
|
|
16585
17132
|
if (!isIdentityName(deps.identity)) {
|
|
16586
17133
|
throw new Error(`"${deps.identity}" is not a valid identity name.`);
|
|
16587
17134
|
}
|
|
16588
|
-
const identityDir =
|
|
16589
|
-
const credentialsFile =
|
|
16590
|
-
const claudeJsonFile =
|
|
16591
|
-
const recordDir =
|
|
16592
|
-
const recordFile =
|
|
17135
|
+
const identityDir = path33.join(deps.identitiesDir, deps.identity);
|
|
17136
|
+
const credentialsFile = path33.join(identityDir, CREDENTIALS_FILE2);
|
|
17137
|
+
const claudeJsonFile = path33.join(identityDir, CLAUDE_JSON2);
|
|
17138
|
+
const recordDir = path33.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
|
|
17139
|
+
const recordFile = path33.join(recordDir, RC_SELF_HOST_RECORD_FILE);
|
|
16593
17140
|
const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
|
|
16594
17141
|
const existingCredentials = readJsonObject(deps.fs, credentialsFile);
|
|
16595
17142
|
const existingOauth = isRecord12(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
|
|
@@ -16605,7 +17152,7 @@ function mintRcSelfHostCredential(deps) {
|
|
|
16605
17152
|
const organizationUuid = deps.newUuid();
|
|
16606
17153
|
const accountUuid = deps.newUuid();
|
|
16607
17154
|
const mintedAt = new Date(deps.now()).toISOString();
|
|
16608
|
-
deps.fs.mkdirPrivate(
|
|
17155
|
+
deps.fs.mkdirPrivate(path33.dirname(credentialsFile));
|
|
16609
17156
|
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)}
|
|
16610
17157
|
`);
|
|
16611
17158
|
const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
|
|
@@ -16647,7 +17194,7 @@ init_plan2();
|
|
|
16647
17194
|
init_poolPick();
|
|
16648
17195
|
|
|
16649
17196
|
// src/agents/read.ts
|
|
16650
|
-
import
|
|
17197
|
+
import path34 from "node:path";
|
|
16651
17198
|
import { z as z28 } from "zod";
|
|
16652
17199
|
var PROJECTS_DIR = "projects";
|
|
16653
17200
|
var TASKS_DIR = "tasks";
|
|
@@ -16673,15 +17220,15 @@ function parseEntry2(project, entry) {
|
|
|
16673
17220
|
}
|
|
16674
17221
|
function listSessions2(fs12, configDir) {
|
|
16675
17222
|
const found = [];
|
|
16676
|
-
for (const project of fs12.readdir(
|
|
16677
|
-
const projectDir =
|
|
17223
|
+
for (const project of fs12.readdir(path34.join(configDir, PROJECTS_DIR))) {
|
|
17224
|
+
const projectDir = path34.join(configDir, PROJECTS_DIR, project);
|
|
16678
17225
|
const entries = /* @__PURE__ */ new Set();
|
|
16679
17226
|
for (const name of fs12.readdir(projectDir)) {
|
|
16680
17227
|
if (name.endsWith(TRANSCRIPT_SUFFIX)) {
|
|
16681
17228
|
entries.add(name.slice(0, -TRANSCRIPT_SUFFIX.length));
|
|
16682
17229
|
continue;
|
|
16683
17230
|
}
|
|
16684
|
-
const children = fs12.readdir(
|
|
17231
|
+
const children = fs12.readdir(path34.join(projectDir, name));
|
|
16685
17232
|
if (children.includes(SUBAGENTS_DIR) || children.includes(WORKFLOWS_DIR)) {
|
|
16686
17233
|
entries.add(name);
|
|
16687
17234
|
}
|
|
@@ -16701,8 +17248,8 @@ function locateAgents(fs12, configDir, relativeDir, workflowRunId, report) {
|
|
|
16701
17248
|
const id = name.slice(AGENT_FILE_PREFIX.length, -META_SUFFIX.length);
|
|
16702
17249
|
located.push({
|
|
16703
17250
|
id,
|
|
16704
|
-
metaPath:
|
|
16705
|
-
transcriptPath:
|
|
17251
|
+
metaPath: path34.join(relativeDir, name),
|
|
17252
|
+
transcriptPath: path34.join(relativeDir, `${AGENT_FILE_PREFIX}${id}${TRANSCRIPT_SUFFIX}`),
|
|
16706
17253
|
workflowRunId
|
|
16707
17254
|
});
|
|
16708
17255
|
}
|
|
@@ -16745,7 +17292,7 @@ function describeFailure(error) {
|
|
|
16745
17292
|
}
|
|
16746
17293
|
function readFileOrReport(fs12, configDir, relative, report) {
|
|
16747
17294
|
try {
|
|
16748
|
-
return fs12.readFileUtf8(
|
|
17295
|
+
return fs12.readFileUtf8(path34.join(configDir, relative));
|
|
16749
17296
|
} catch (error) {
|
|
16750
17297
|
report({ path: relative, reason: `could not be read: ${describeFailure(error)}` });
|
|
16751
17298
|
return void 0;
|
|
@@ -16753,7 +17300,7 @@ function readFileOrReport(fs12, configDir, relative, report) {
|
|
|
16753
17300
|
}
|
|
16754
17301
|
function listDirOrReport(fs12, configDir, relative, report) {
|
|
16755
17302
|
try {
|
|
16756
|
-
return fs12.readdir(
|
|
17303
|
+
return fs12.readdir(path34.join(configDir, relative));
|
|
16757
17304
|
} catch (error) {
|
|
16758
17305
|
report({ path: relative, reason: `could not be listed: ${describeFailure(error)}` });
|
|
16759
17306
|
return [];
|
|
@@ -16777,18 +17324,18 @@ var WorkflowRunFileSchema = z28.object({
|
|
|
16777
17324
|
summary: z28.string().optional()
|
|
16778
17325
|
});
|
|
16779
17326
|
function summariseSession(fs12, configDir, ref) {
|
|
16780
|
-
const sessionRelative =
|
|
16781
|
-
const subagentsRelative =
|
|
16782
|
-
const workflowsUnderSubagents =
|
|
17327
|
+
const sessionRelative = path34.join(PROJECTS_DIR, ref.project, ref.entry);
|
|
17328
|
+
const subagentsRelative = path34.join(sessionRelative, SUBAGENTS_DIR);
|
|
17329
|
+
const workflowsUnderSubagents = path34.join(subagentsRelative, WORKFLOWS_DIR);
|
|
16783
17330
|
const isMeta = (name) => name.startsWith(AGENT_FILE_PREFIX) && name.endsWith(META_SUFFIX);
|
|
16784
|
-
let agentCount = fs12.readdir(
|
|
16785
|
-
for (const runDir of fs12.readdir(
|
|
17331
|
+
let agentCount = fs12.readdir(path34.join(configDir, subagentsRelative)).filter(isMeta).length;
|
|
17332
|
+
for (const runDir of fs12.readdir(path34.join(configDir, workflowsUnderSubagents))) {
|
|
16786
17333
|
if (runDir.startsWith(WORKFLOW_RUN_PREFIX)) {
|
|
16787
|
-
agentCount += fs12.readdir(
|
|
17334
|
+
agentCount += fs12.readdir(path34.join(configDir, workflowsUnderSubagents, runDir)).filter(isMeta).length;
|
|
16788
17335
|
}
|
|
16789
17336
|
}
|
|
16790
|
-
const workflowRunCount = fs12.readdir(
|
|
16791
|
-
const transcript = fs12.lstat(
|
|
17337
|
+
const workflowRunCount = fs12.readdir(path34.join(configDir, sessionRelative, WORKFLOWS_DIR)).filter((name) => name.startsWith(WORKFLOW_RUN_PREFIX) && name.endsWith(JSON_SUFFIX)).length;
|
|
17338
|
+
const transcript = fs12.lstat(path34.join(configDir, PROJECTS_DIR, ref.project, `${ref.entry}${TRANSCRIPT_SUFFIX}`));
|
|
16792
17339
|
return { ...ref, agentCount, workflowRunCount, ...transcript === void 0 ? {} : { updatedAt: new Date(transcript.mtimeMs).toISOString() } };
|
|
16793
17340
|
}
|
|
16794
17341
|
function readSessionAgentTree(fs12, configDir, ref, options = {}) {
|
|
@@ -16796,13 +17343,13 @@ function readSessionAgentTree(fs12, configDir, ref, options = {}) {
|
|
|
16796
17343
|
const report = (problem) => {
|
|
16797
17344
|
problems.push(problem);
|
|
16798
17345
|
};
|
|
16799
|
-
const sessionRelative =
|
|
16800
|
-
const subagentsRelative =
|
|
16801
|
-
const workflowsUnderSubagents =
|
|
17346
|
+
const sessionRelative = path34.join(PROJECTS_DIR, ref.project, ref.entry);
|
|
17347
|
+
const subagentsRelative = path34.join(sessionRelative, SUBAGENTS_DIR);
|
|
17348
|
+
const workflowsUnderSubagents = path34.join(subagentsRelative, WORKFLOWS_DIR);
|
|
16802
17349
|
const located = locateAgents(fs12, configDir, subagentsRelative, void 0, report);
|
|
16803
17350
|
for (const runDir of listDirOrReport(fs12, configDir, workflowsUnderSubagents, report)) {
|
|
16804
17351
|
if (runDir.startsWith(WORKFLOW_RUN_PREFIX)) {
|
|
16805
|
-
located.push(...locateAgents(fs12, configDir,
|
|
17352
|
+
located.push(...locateAgents(fs12, configDir, path34.join(workflowsUnderSubagents, runDir), runDir, report));
|
|
16806
17353
|
}
|
|
16807
17354
|
}
|
|
16808
17355
|
const agents = /* @__PURE__ */ new Map();
|
|
@@ -16843,7 +17390,7 @@ function readSessionAgentTree(fs12, configDir, ref, options = {}) {
|
|
|
16843
17390
|
superseded: ref.superseded,
|
|
16844
17391
|
agents: roots.sort().map(build),
|
|
16845
17392
|
tasks: readTasks(fs12, configDir, ownTaskLists(ref.sessionId), [.../* @__PURE__ */ new Set([...teamNames, ...options.taskListIds ?? []])].filter((id) => !ownTaskLists(ref.sessionId).includes(id)), report),
|
|
16846
|
-
workflowRuns: readWorkflowRuns(fs12, configDir,
|
|
17393
|
+
workflowRuns: readWorkflowRuns(fs12, configDir, path34.join(sessionRelative, WORKFLOWS_DIR), report),
|
|
16847
17394
|
problems
|
|
16848
17395
|
};
|
|
16849
17396
|
}
|
|
@@ -16908,12 +17455,12 @@ function ownTaskLists(sessionId) {
|
|
|
16908
17455
|
function readTasks(fs12, configDir, ownLists, sharedLists, report) {
|
|
16909
17456
|
const tasks = [];
|
|
16910
17457
|
[...ownLists, ...sharedLists].forEach((scope, index) => {
|
|
16911
|
-
const relativeDir =
|
|
17458
|
+
const relativeDir = path34.join(TASKS_DIR, scope);
|
|
16912
17459
|
for (const name of [...listDirOrReport(fs12, configDir, relativeDir, report)].sort()) {
|
|
16913
17460
|
if (name.startsWith(".") || !name.endsWith(JSON_SUFFIX)) {
|
|
16914
17461
|
continue;
|
|
16915
17462
|
}
|
|
16916
|
-
const relative =
|
|
17463
|
+
const relative = path34.join(relativeDir, name);
|
|
16917
17464
|
const text = readFileOrReport(fs12, configDir, relative, report);
|
|
16918
17465
|
const parsed = TaskFileSchema.safeParse(text === void 0 ? void 0 : parseJson2(text));
|
|
16919
17466
|
if (parsed.success) {
|
|
@@ -16931,7 +17478,7 @@ function readWorkflowRuns(fs12, configDir, relativeDir, report) {
|
|
|
16931
17478
|
if (!name.startsWith(WORKFLOW_RUN_PREFIX) || !name.endsWith(JSON_SUFFIX)) {
|
|
16932
17479
|
continue;
|
|
16933
17480
|
}
|
|
16934
|
-
const relative =
|
|
17481
|
+
const relative = path34.join(relativeDir, name);
|
|
16935
17482
|
const text = readFileOrReport(fs12, configDir, relative, report);
|
|
16936
17483
|
const parsed = WorkflowRunFileSchema.safeParse(text === void 0 ? void 0 : parseJson2(text));
|
|
16937
17484
|
if (!parsed.success) {
|
|
@@ -16948,7 +17495,7 @@ function readWorkflowRuns(fs12, configDir, relativeDir, report) {
|
|
|
16948
17495
|
|
|
16949
17496
|
// src/agents/sessions.ts
|
|
16950
17497
|
init_cliError();
|
|
16951
|
-
import
|
|
17498
|
+
import path35 from "node:path";
|
|
16952
17499
|
var SessionLookupError = class extends CliError {
|
|
16953
17500
|
constructor(message) {
|
|
16954
17501
|
super(message);
|
|
@@ -16956,13 +17503,13 @@ var SessionLookupError = class extends CliError {
|
|
|
16956
17503
|
}
|
|
16957
17504
|
};
|
|
16958
17505
|
function identityConfigDir(identitiesDir, identity) {
|
|
16959
|
-
return
|
|
17506
|
+
return path35.join(identitiesDir, identity);
|
|
16960
17507
|
}
|
|
16961
17508
|
function historyStores(fs12, identitiesDir, identities) {
|
|
16962
17509
|
const byRealPath = /* @__PURE__ */ new Map();
|
|
16963
17510
|
for (const identity of identities) {
|
|
16964
17511
|
const configDir = identityConfigDir(identitiesDir, identity);
|
|
16965
|
-
const real = fs12.realpath(
|
|
17512
|
+
const real = fs12.realpath(path35.join(configDir, "projects"));
|
|
16966
17513
|
if (real === void 0) {
|
|
16967
17514
|
continue;
|
|
16968
17515
|
}
|
|
@@ -17414,6 +17961,7 @@ export {
|
|
|
17414
17961
|
isRcReadFileEncoding,
|
|
17415
17962
|
lateRcEventDial,
|
|
17416
17963
|
lateRcStreamDial,
|
|
17964
|
+
launchRequiredUpstreams,
|
|
17417
17965
|
listDirectoryRules,
|
|
17418
17966
|
listIdentities,
|
|
17419
17967
|
listProfiles,
|