agent-shim 8.43.0 → 9.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 +377 -299
- package/dist/index.cjs +265 -193
- package/dist/index.mjs +247 -176
- package/dist/types/index.d.ts +32 -7
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2619,7 +2619,7 @@ var init_package = __esm({
|
|
|
2619
2619
|
"package.json"() {
|
|
2620
2620
|
package_default = {
|
|
2621
2621
|
name: "agent-shim",
|
|
2622
|
-
version: "
|
|
2622
|
+
version: "9.0.0",
|
|
2623
2623
|
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.",
|
|
2624
2624
|
license: "MIT",
|
|
2625
2625
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -2723,7 +2723,7 @@ var init_package = __esm({
|
|
|
2723
2723
|
|
|
2724
2724
|
// src/headroom/state.ts
|
|
2725
2725
|
import { createHash as createHash3 } from "node:crypto";
|
|
2726
|
-
import
|
|
2726
|
+
import path11 from "node:path";
|
|
2727
2727
|
import { z as z5 } from "zod";
|
|
2728
2728
|
function parseJson(raw, schema) {
|
|
2729
2729
|
if (raw === void 0 || raw.trim() === "") {
|
|
@@ -2740,10 +2740,36 @@ function readHeadroomState(fs12, stateFile) {
|
|
|
2740
2740
|
}
|
|
2741
2741
|
}
|
|
2742
2742
|
function writeHeadroomState(fs12, stateFile, state) {
|
|
2743
|
-
fs12.mkdirp(
|
|
2743
|
+
fs12.mkdirp(path11.dirname(stateFile));
|
|
2744
2744
|
fs12.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
|
|
2745
2745
|
`);
|
|
2746
2746
|
}
|
|
2747
|
+
function resolveServingHeadroomState(fs12, files, isRunning) {
|
|
2748
|
+
const current = readHeadroomState(fs12, files.stateFile);
|
|
2749
|
+
if (current !== void 0) {
|
|
2750
|
+
return { path: files.stateFile, state: current };
|
|
2751
|
+
}
|
|
2752
|
+
const legacy = readHeadroomState(fs12, files.legacyStateFile);
|
|
2753
|
+
if (legacy?.supervisorPid !== void 0 && isRunning(legacy.supervisorPid)) {
|
|
2754
|
+
return { path: files.legacyStateFile, state: legacy };
|
|
2755
|
+
}
|
|
2756
|
+
return void 0;
|
|
2757
|
+
}
|
|
2758
|
+
function migrateHeadroomState(fs12, files, isRunning) {
|
|
2759
|
+
const legacy = readHeadroomState(fs12, files.legacyStateFile);
|
|
2760
|
+
const legacyLive = legacy?.supervisorPid !== void 0 && isRunning(legacy.supervisorPid);
|
|
2761
|
+
const current = readHeadroomState(fs12, files.stateFile);
|
|
2762
|
+
if (current !== void 0 || legacyLive) {
|
|
2763
|
+
if (!legacyLive && fs12.readFileUtf8(files.legacyStateFile) !== void 0) {
|
|
2764
|
+
fs12.removeRecursive(files.legacyStateFile);
|
|
2765
|
+
}
|
|
2766
|
+
return;
|
|
2767
|
+
}
|
|
2768
|
+
if (legacy !== void 0) {
|
|
2769
|
+
writeHeadroomState(fs12, files.stateFile, legacy);
|
|
2770
|
+
}
|
|
2771
|
+
fs12.removeRecursive(files.legacyStateFile);
|
|
2772
|
+
}
|
|
2747
2773
|
function headroomAllowlist(providers) {
|
|
2748
2774
|
const urls = /* @__PURE__ */ new Set([HEADROOM_ANTHROPIC_UPSTREAM]);
|
|
2749
2775
|
for (const provider of providers) {
|
|
@@ -2768,7 +2794,7 @@ function readAllProviders(fs12, providersDir) {
|
|
|
2768
2794
|
continue;
|
|
2769
2795
|
}
|
|
2770
2796
|
try {
|
|
2771
|
-
const parsed = parseJson(fs12.readFileUtf8(
|
|
2797
|
+
const parsed = parseJson(fs12.readFileUtf8(path11.join(providersDir, name)), ProviderSchema);
|
|
2772
2798
|
if (parsed !== void 0) {
|
|
2773
2799
|
result.push({ name: name.slice(0, -".json".length), provider: parsed });
|
|
2774
2800
|
}
|
|
@@ -2780,11 +2806,11 @@ function readAllProviders(fs12, providersDir) {
|
|
|
2780
2806
|
}
|
|
2781
2807
|
function writeSession(fs12, sessionsDir, session) {
|
|
2782
2808
|
fs12.mkdirp(sessionsDir);
|
|
2783
|
-
fs12.writeFileUtf8(
|
|
2809
|
+
fs12.writeFileUtf8(path11.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
|
|
2784
2810
|
`);
|
|
2785
2811
|
}
|
|
2786
2812
|
function removeSession(fs12, sessionsDir, pid) {
|
|
2787
|
-
fs12.removeRecursive(
|
|
2813
|
+
fs12.removeRecursive(path11.join(sessionsDir, `${String(pid)}.json`));
|
|
2788
2814
|
}
|
|
2789
2815
|
function listSessions(fs12, sessionsDir) {
|
|
2790
2816
|
const sessions = [];
|
|
@@ -2793,7 +2819,7 @@ function listSessions(fs12, sessionsDir) {
|
|
|
2793
2819
|
continue;
|
|
2794
2820
|
}
|
|
2795
2821
|
try {
|
|
2796
|
-
const parsed = parseJson(fs12.readFileUtf8(
|
|
2822
|
+
const parsed = parseJson(fs12.readFileUtf8(path11.join(sessionsDir, name)), HeadroomSessionSchema);
|
|
2797
2823
|
if (parsed !== void 0) {
|
|
2798
2824
|
sessions.push(parsed);
|
|
2799
2825
|
}
|
|
@@ -2823,13 +2849,12 @@ function readStartLock(fs12, lockFile) {
|
|
|
2823
2849
|
return void 0;
|
|
2824
2850
|
}
|
|
2825
2851
|
}
|
|
2826
|
-
var HEADROOM_ANTHROPIC_UPSTREAM,
|
|
2852
|
+
var HEADROOM_ANTHROPIC_UPSTREAM, HeadroomStateSchema, HeadroomSessionSchema, HeadroomLockSchema;
|
|
2827
2853
|
var init_state2 = __esm({
|
|
2828
2854
|
"src/headroom/state.ts"() {
|
|
2829
2855
|
"use strict";
|
|
2830
2856
|
init_schema();
|
|
2831
2857
|
HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
|
|
2832
|
-
HEADROOM_STATE_SCHEMA_VERSION = 2;
|
|
2833
2858
|
HeadroomStateSchema = z5.strictObject({
|
|
2834
2859
|
/** The supervisor process owning the daemon. Alive means someone is keeping headroom running. */
|
|
2835
2860
|
supervisorPid: z5.number().int().positive().optional(),
|
|
@@ -2861,8 +2886,9 @@ function ensureHeadroom(params) {
|
|
|
2861
2886
|
const deadline = ports.now() + HEADROOM_START_TIMEOUT_MS;
|
|
2862
2887
|
let spawnedSupervisor = false;
|
|
2863
2888
|
let awaitingAllowlist = false;
|
|
2889
|
+
migrateHeadroomState(ports.fs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning);
|
|
2864
2890
|
for (; ; ) {
|
|
2865
|
-
const state =
|
|
2891
|
+
const state = resolveServingHeadroomState(ports.fs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning)?.state;
|
|
2866
2892
|
if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
|
|
2867
2893
|
const daemonUp = state.socketPath !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
|
|
2868
2894
|
if (daemonUp && state.socketPath !== void 0) {
|
|
@@ -2963,9 +2989,9 @@ var init_settings = __esm({
|
|
|
2963
2989
|
});
|
|
2964
2990
|
|
|
2965
2991
|
// src/headroom/socket.ts
|
|
2966
|
-
import
|
|
2992
|
+
import path12 from "node:path";
|
|
2967
2993
|
function headroomSocketPath(paths, supervisorPid) {
|
|
2968
|
-
return
|
|
2994
|
+
return path12.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
|
|
2969
2995
|
}
|
|
2970
2996
|
function platformRefusal(platform) {
|
|
2971
2997
|
return PLATFORMS_WITHOUT_UNIX_SOCKETS.includes(platform) ? `headroom routing needs a unix domain socket, which headroom cannot serve on ${platform}; agent-shim never falls back to a TCP port for this hop` : void 0;
|
|
@@ -2994,7 +3020,7 @@ function verifyHeadroomSocket(socketPath, ports) {
|
|
|
2994
3020
|
return { refused: unsupported };
|
|
2995
3021
|
}
|
|
2996
3022
|
const uid = ports.currentUid();
|
|
2997
|
-
const directory =
|
|
3023
|
+
const directory = path12.dirname(socketPath);
|
|
2998
3024
|
const refusal = ownerOnlyRefusal("socket directory", directory, ports.lstat(directory), "dir", uid) ?? ownerOnlyRefusal("socket", socketPath, ports.lstat(socketPath), "socket", uid);
|
|
2999
3025
|
return refusal === void 0 ? { socketPath } : { refused: refusal };
|
|
3000
3026
|
}
|
|
@@ -3024,7 +3050,7 @@ function pruneStaleHeadroomSockets(fs12, paths, isRunning) {
|
|
|
3024
3050
|
if (pid === void 0 || isRunning(Number.parseInt(pid, 10))) {
|
|
3025
3051
|
continue;
|
|
3026
3052
|
}
|
|
3027
|
-
fs12.removeRecursive(
|
|
3053
|
+
fs12.removeRecursive(path12.join(paths.headroomSocketDir, name));
|
|
3028
3054
|
removed.push(name);
|
|
3029
3055
|
}
|
|
3030
3056
|
return removed;
|
|
@@ -3131,7 +3157,8 @@ function compareVersions2(a, b) {
|
|
|
3131
3157
|
async function runSupervisor(initialConfig, ports, options = {}) {
|
|
3132
3158
|
const { fs: fs12, paths } = ports;
|
|
3133
3159
|
let config = initialConfig;
|
|
3134
|
-
|
|
3160
|
+
migrateHeadroomState(fs12, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning);
|
|
3161
|
+
const previousState = resolveServingHeadroomState(fs12, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, ports.isRunning)?.state;
|
|
3135
3162
|
if (previousState?.supervisorPid !== void 0 && previousState.supervisorPid !== ports.ownPid && ports.isRunning(previousState.supervisorPid)) {
|
|
3136
3163
|
ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: supervisor ${String(previousState.supervisorPid)} already owns the daemon; exiting`);
|
|
3137
3164
|
return 0;
|
|
@@ -3334,7 +3361,7 @@ import { spawn, spawnSync } from "node:child_process";
|
|
|
3334
3361
|
import { createHash as createHash5 } from "node:crypto";
|
|
3335
3362
|
import fs3 from "node:fs";
|
|
3336
3363
|
import os3 from "node:os";
|
|
3337
|
-
import
|
|
3364
|
+
import path13 from "node:path";
|
|
3338
3365
|
import { isSea } from "node:sea";
|
|
3339
3366
|
function isEnoent3(error) {
|
|
3340
3367
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
@@ -3361,7 +3388,7 @@ function realIsProcessRunning(pid) {
|
|
|
3361
3388
|
return realIsProcessAlive(pid) && !realIsProcessZombie(pid);
|
|
3362
3389
|
}
|
|
3363
3390
|
function expandHome2(filePath) {
|
|
3364
|
-
return filePath.startsWith("~/") ?
|
|
3391
|
+
return filePath.startsWith("~/") ? path13.join(os3.homedir(), filePath.slice(1)) : filePath;
|
|
3365
3392
|
}
|
|
3366
3393
|
function hasDesktopSession() {
|
|
3367
3394
|
if (process.platform === "darwin") {
|
|
@@ -3405,7 +3432,7 @@ function spawnDaemonThroughScript(script) {
|
|
|
3405
3432
|
return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: process.execPath, args: [script, subcommand] }, paths, subcommand, logPath);
|
|
3406
3433
|
}
|
|
3407
3434
|
function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
|
|
3408
|
-
fs3.mkdirSync(
|
|
3435
|
+
fs3.mkdirSync(path13.dirname(logPath), { recursive: true });
|
|
3409
3436
|
const logFd = fs3.openSync(logPath, "a");
|
|
3410
3437
|
try {
|
|
3411
3438
|
const child = spawn(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
|
|
@@ -3458,7 +3485,7 @@ function listVersionsDir(dir) {
|
|
|
3458
3485
|
throw error;
|
|
3459
3486
|
}
|
|
3460
3487
|
return entries.filter((entry) => entry.isFile()).map((entry) => {
|
|
3461
|
-
const fullPath =
|
|
3488
|
+
const fullPath = path13.join(dir, entry.name);
|
|
3462
3489
|
const stat = fs3.statSync(fullPath);
|
|
3463
3490
|
return {
|
|
3464
3491
|
name: entry.name,
|
|
@@ -3472,7 +3499,7 @@ function windowsPathExtensions(pathext) {
|
|
|
3472
3499
|
return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
|
|
3473
3500
|
}
|
|
3474
3501
|
function resolveExecutableCandidate(dir, name, env) {
|
|
3475
|
-
const candidate =
|
|
3502
|
+
const candidate = path13.join(dir, name);
|
|
3476
3503
|
if (env.platform === "win32") {
|
|
3477
3504
|
const extensions = windowsPathExtensions(env.pathext);
|
|
3478
3505
|
const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
|
|
@@ -3521,13 +3548,13 @@ function resolveOwnExecutablePath(env) {
|
|
|
3521
3548
|
if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
|
|
3522
3549
|
return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
|
|
3523
3550
|
}
|
|
3524
|
-
const candidate = env.argv1 === void 0 ? env.execPath :
|
|
3525
|
-
const candidateDir =
|
|
3526
|
-
const candidateDirOnPath = env.pathDirs.some((dir) =>
|
|
3551
|
+
const candidate = env.argv1 === void 0 ? env.execPath : path13.resolve(env.cwd, env.argv1);
|
|
3552
|
+
const candidateDir = path13.dirname(candidate);
|
|
3553
|
+
const candidateDirOnPath = env.pathDirs.some((dir) => path13.resolve(dir) === candidateDir);
|
|
3527
3554
|
if (candidateDirOnPath) {
|
|
3528
3555
|
return candidate;
|
|
3529
3556
|
}
|
|
3530
|
-
const viaPath = searchPathForExecutable(env.pathDirs,
|
|
3557
|
+
const viaPath = searchPathForExecutable(env.pathDirs, path13.basename(candidate), env.findExecutableInDir);
|
|
3531
3558
|
return viaPath ?? candidate;
|
|
3532
3559
|
}
|
|
3533
3560
|
function realOwnExecutablePath() {
|
|
@@ -3535,7 +3562,7 @@ function realOwnExecutablePath() {
|
|
|
3535
3562
|
argv1: process.argv[1],
|
|
3536
3563
|
execPath: process.execPath,
|
|
3537
3564
|
cwd: process.cwd(),
|
|
3538
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
3565
|
+
pathDirs: (process.env.PATH ?? "").split(path13.delimiter).filter((dir) => dir !== ""),
|
|
3539
3566
|
findExecutableInDir
|
|
3540
3567
|
});
|
|
3541
3568
|
}
|
|
@@ -3548,7 +3575,7 @@ function realContentSourcePath() {
|
|
|
3548
3575
|
function realResolveClaudeBinary(isOwnBinary) {
|
|
3549
3576
|
return (request4) => discoverClaudeBinary({
|
|
3550
3577
|
listVersionsDir,
|
|
3551
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
3578
|
+
pathDirs: (process.env.PATH ?? "").split(path13.delimiter).filter((dir) => dir !== ""),
|
|
3552
3579
|
findExecutableInDir,
|
|
3553
3580
|
isOwnBinary,
|
|
3554
3581
|
...request4?.version === void 0 ? {} : { version: request4.version }
|
|
@@ -3770,18 +3797,18 @@ var init_realPorts = __esm({
|
|
|
3770
3797
|
});
|
|
3771
3798
|
|
|
3772
3799
|
// src/pathNorm.ts
|
|
3773
|
-
import
|
|
3800
|
+
import path14 from "node:path";
|
|
3774
3801
|
function expandTilde(value, home) {
|
|
3775
3802
|
if (value === "~") {
|
|
3776
3803
|
return home;
|
|
3777
3804
|
}
|
|
3778
3805
|
if (value.startsWith("~/")) {
|
|
3779
|
-
return
|
|
3806
|
+
return path14.join(home, value.slice(2));
|
|
3780
3807
|
}
|
|
3781
3808
|
return value;
|
|
3782
3809
|
}
|
|
3783
3810
|
function normaliseRulePath(rulePath, home) {
|
|
3784
|
-
return
|
|
3811
|
+
return path14.resolve(expandTilde(rulePath, home));
|
|
3785
3812
|
}
|
|
3786
3813
|
var init_pathNorm = __esm({
|
|
3787
3814
|
"src/pathNorm.ts"() {
|
|
@@ -3790,12 +3817,12 @@ var init_pathNorm = __esm({
|
|
|
3790
3817
|
});
|
|
3791
3818
|
|
|
3792
3819
|
// src/launcher/cascade.ts
|
|
3793
|
-
import
|
|
3820
|
+
import path15 from "node:path";
|
|
3794
3821
|
function loadCascadeInput(params) {
|
|
3795
3822
|
const globalConfig = loadConfigFile(params.paths.globalConfigFile, GlobalConfigSchema, params.read);
|
|
3796
3823
|
const directoryRules = loadConfigFile(params.paths.directoryRulesFile, DirectoryRulesSchema, params.read);
|
|
3797
3824
|
const loadProfile = (name) => {
|
|
3798
|
-
const filepath =
|
|
3825
|
+
const filepath = path15.join(params.paths.configProfilesDir, `${name}.json`);
|
|
3799
3826
|
const loaded = loadConfigFile(filepath, ConfigProfileSchema, params.read);
|
|
3800
3827
|
if (loaded === void 0) {
|
|
3801
3828
|
return void 0;
|
|
@@ -3810,8 +3837,8 @@ function loadCascadeInput(params) {
|
|
|
3810
3837
|
});
|
|
3811
3838
|
const levels = [];
|
|
3812
3839
|
for (const dir of dirs) {
|
|
3813
|
-
const portable = loadConfigFile(
|
|
3814
|
-
const portableLocal = loadConfigFile(
|
|
3840
|
+
const portable = loadConfigFile(path15.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path15.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
3841
|
+
const portableLocal = loadConfigFile(path15.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path15.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
3815
3842
|
const rules = (directoryRules?.config.rules ?? []).map((rule, index) => ({ rule, index })).filter(({ rule }) => normaliseRulePath(rule.path, params.home) === dir).map(({ rule, index }) => {
|
|
3816
3843
|
const entryOrder = directoryRules?.ruleEntryOrders[index];
|
|
3817
3844
|
return {
|
|
@@ -3873,7 +3900,7 @@ var init_cascade = __esm({
|
|
|
3873
3900
|
});
|
|
3874
3901
|
|
|
3875
3902
|
// src/launcher/identity.ts
|
|
3876
|
-
import
|
|
3903
|
+
import path16 from "node:path";
|
|
3877
3904
|
function poolNameOf(selector) {
|
|
3878
3905
|
return selector.startsWith(POOL_SELECTOR_PREFIX) ? selector.slice(POOL_SELECTOR_PREFIX.length) : void 0;
|
|
3879
3906
|
}
|
|
@@ -3926,7 +3953,7 @@ function decideConfigProfile(params) {
|
|
|
3926
3953
|
return { source: "none" };
|
|
3927
3954
|
}
|
|
3928
3955
|
function loadIdentity(identitiesDir, name, fs12) {
|
|
3929
|
-
return loadConfigFile(
|
|
3956
|
+
return loadConfigFile(path16.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
|
|
3930
3957
|
}
|
|
3931
3958
|
var IDENTITY_DECISION_SOURCES, CONFIG_PROFILE_DECISION_SOURCES;
|
|
3932
3959
|
var init_identity = __esm({
|
|
@@ -4120,7 +4147,7 @@ var init_schema2 = __esm({
|
|
|
4120
4147
|
});
|
|
4121
4148
|
|
|
4122
4149
|
// src/usage/account.ts
|
|
4123
|
-
import
|
|
4150
|
+
import path17 from "node:path";
|
|
4124
4151
|
function isObject(value) {
|
|
4125
4152
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4126
4153
|
}
|
|
@@ -4128,7 +4155,7 @@ function isIdentityName(name) {
|
|
|
4128
4155
|
return IdentitySchema.shape.name.safeParse(name).success;
|
|
4129
4156
|
}
|
|
4130
4157
|
function claudeJsonPath(identitiesDir, identity) {
|
|
4131
|
-
return
|
|
4158
|
+
return path17.join(identitiesDir, identity, CLAUDE_JSON);
|
|
4132
4159
|
}
|
|
4133
4160
|
function readAccountMetadata(fs12, identitiesDir, identity) {
|
|
4134
4161
|
if (!isIdentityName(identity)) {
|
|
@@ -4627,7 +4654,7 @@ var init_pick = __esm({
|
|
|
4627
4654
|
});
|
|
4628
4655
|
|
|
4629
4656
|
// src/usage/read.ts
|
|
4630
|
-
import
|
|
4657
|
+
import path18 from "node:path";
|
|
4631
4658
|
function segmentDay(epochMs) {
|
|
4632
4659
|
return new Date(epochMs).toISOString().slice(0, "YYYY-MM-DD".length);
|
|
4633
4660
|
}
|
|
@@ -4652,7 +4679,7 @@ function readUsageLog(fs12, logDir, options = {}) {
|
|
|
4652
4679
|
if (sinceMs !== void 0 && segment.endsAt <= sinceMs) {
|
|
4653
4680
|
continue;
|
|
4654
4681
|
}
|
|
4655
|
-
const contents = fs12.readFileUtf8(
|
|
4682
|
+
const contents = fs12.readFileUtf8(path18.join(logDir, segment.name));
|
|
4656
4683
|
if (contents === void 0) {
|
|
4657
4684
|
continue;
|
|
4658
4685
|
}
|
|
@@ -4686,7 +4713,7 @@ function snapshotPath(snapshotsDir, identity) {
|
|
|
4686
4713
|
if (!isIdentityName(identity)) {
|
|
4687
4714
|
throw new Error(`"${identity}" is not a valid identity name.`);
|
|
4688
4715
|
}
|
|
4689
|
-
return
|
|
4716
|
+
return path18.join(snapshotsDir, `${identity}.json`);
|
|
4690
4717
|
}
|
|
4691
4718
|
function readUsageSnapshot(fs12, snapshotsDir, identity) {
|
|
4692
4719
|
const file = snapshotPath(snapshotsDir, identity);
|
|
@@ -4739,12 +4766,12 @@ var init_read = __esm({
|
|
|
4739
4766
|
});
|
|
4740
4767
|
|
|
4741
4768
|
// src/usage/store.ts
|
|
4742
|
-
import
|
|
4769
|
+
import path19 from "node:path";
|
|
4743
4770
|
function pruneUsageLog(fs12, logDir, nowMs) {
|
|
4744
4771
|
const cutoff = nowMs - USAGE_RETENTION_MS;
|
|
4745
4772
|
for (const segment of listLogSegments(fs12, logDir)) {
|
|
4746
4773
|
if (segment.endsAt <= cutoff) {
|
|
4747
|
-
fs12.removeRecursive(
|
|
4774
|
+
fs12.removeRecursive(path19.join(logDir, segment.name));
|
|
4748
4775
|
}
|
|
4749
4776
|
}
|
|
4750
4777
|
}
|
|
@@ -4826,7 +4853,7 @@ function createUsageStore(deps) {
|
|
|
4826
4853
|
pruneUsageLog(fs12, paths.usageLogDir, nowMs);
|
|
4827
4854
|
prunedDay = day;
|
|
4828
4855
|
}
|
|
4829
|
-
fs12.appendFilePrivate(
|
|
4856
|
+
fs12.appendFilePrivate(path19.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record)}
|
|
4830
4857
|
`);
|
|
4831
4858
|
if (record.identity !== void 0) {
|
|
4832
4859
|
rewriteSnapshot(record.identity, (current) => ({ ...current?.providers, [record.provider]: foldProviderState(current?.providers[record.provider], record) }));
|
|
@@ -4864,7 +4891,7 @@ var init_store2 = __esm({
|
|
|
4864
4891
|
});
|
|
4865
4892
|
|
|
4866
4893
|
// src/usage/poolPick.ts
|
|
4867
|
-
import
|
|
4894
|
+
import path20 from "node:path";
|
|
4868
4895
|
import { z as z10 } from "zod";
|
|
4869
4896
|
function errorMessage(error) {
|
|
4870
4897
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -4992,7 +5019,7 @@ function recordStickyPick(fs12, picksFile, directory, identity, nowMs) {
|
|
|
4992
5019
|
const current = readPicksFile(fs12, picksFile).file.picks;
|
|
4993
5020
|
const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
|
|
4994
5021
|
const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
|
|
4995
|
-
fs12.mkdirPrivate(
|
|
5022
|
+
fs12.mkdirPrivate(path20.dirname(picksFile));
|
|
4996
5023
|
fs12.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
|
|
4997
5024
|
`);
|
|
4998
5025
|
}
|
|
@@ -5026,14 +5053,14 @@ var init_poolPick = __esm({
|
|
|
5026
5053
|
// src/paths.ts
|
|
5027
5054
|
import fs5 from "node:fs";
|
|
5028
5055
|
import os5 from "node:os";
|
|
5029
|
-
import
|
|
5056
|
+
import path22 from "node:path";
|
|
5030
5057
|
function resolveAgentShimHome(env = process.env, home = os5.homedir(), isDirectory = isExistingDirectory) {
|
|
5031
5058
|
const fromEnv = env.AGENT_SHIM_HOME;
|
|
5032
5059
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
5033
5060
|
return fromEnv;
|
|
5034
5061
|
}
|
|
5035
|
-
const current =
|
|
5036
|
-
const legacy =
|
|
5062
|
+
const current = path22.join(home, HOME_DIRNAME);
|
|
5063
|
+
const legacy = path22.join(home, LEGACY_HOME_DIRNAME);
|
|
5037
5064
|
return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
|
|
5038
5065
|
}
|
|
5039
5066
|
function isExistingDirectory(candidate) {
|
|
@@ -5044,42 +5071,43 @@ function resolveClaudeHome() {
|
|
|
5044
5071
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
5045
5072
|
return fromEnv;
|
|
5046
5073
|
}
|
|
5047
|
-
return
|
|
5074
|
+
return path22.join(os5.homedir(), ".claude");
|
|
5048
5075
|
}
|
|
5049
5076
|
function buildLayoutPaths(root) {
|
|
5050
5077
|
return {
|
|
5051
5078
|
root,
|
|
5052
|
-
identitiesDir:
|
|
5053
|
-
configProfilesDir:
|
|
5054
|
-
providersDir:
|
|
5055
|
-
directoryRulesFile:
|
|
5056
|
-
activeIdentityFile:
|
|
5057
|
-
globalConfigFile:
|
|
5058
|
-
categoriesLocalFile:
|
|
5059
|
-
claudeShimFile:
|
|
5060
|
-
headroomDir:
|
|
5061
|
-
headroomStateFile:
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5079
|
+
identitiesDir: path22.join(root, "identities"),
|
|
5080
|
+
configProfilesDir: path22.join(root, "config-profiles"),
|
|
5081
|
+
providersDir: path22.join(root, "providers"),
|
|
5082
|
+
directoryRulesFile: path22.join(root, "directory-rules.json"),
|
|
5083
|
+
activeIdentityFile: path22.join(root, "active-identity"),
|
|
5084
|
+
globalConfigFile: path22.join(root, "config.json"),
|
|
5085
|
+
categoriesLocalFile: path22.join(root, "categories.local.json"),
|
|
5086
|
+
claudeShimFile: path22.join(root, "claude-shim.json"),
|
|
5087
|
+
headroomDir: path22.join(root, "headroom"),
|
|
5088
|
+
headroomStateFile: path22.join(root, "headroom", "state.json"),
|
|
5089
|
+
headroomLegacyStateFile: path22.join(root, "headroom", "state.v2.json"),
|
|
5090
|
+
headroomSocketDir: path22.join(root, "headroom", "run"),
|
|
5091
|
+
headroomLockFile: path22.join(root, "headroom", "start.lock"),
|
|
5092
|
+
headroomSessionsDir: path22.join(root, "headroom", "sessions"),
|
|
5093
|
+
logsDir: path22.join(root, "logs"),
|
|
5094
|
+
headroomLogPath: path22.join(root, "logs", "headroom.log"),
|
|
5095
|
+
frontdoorDir: path22.join(root, "frontdoor"),
|
|
5096
|
+
frontdoorCaDir: path22.join(root, "frontdoor", "ca"),
|
|
5097
|
+
frontdoorCaCertFile: path22.join(root, "frontdoor", "ca", "ca.pem"),
|
|
5098
|
+
frontdoorCaKeyFile: path22.join(root, "frontdoor", "ca", "ca.key"),
|
|
5099
|
+
frontdoorCaBundlesDir: path22.join(root, "frontdoor", "ca", "bundles"),
|
|
5100
|
+
chatgptSignInFile: path22.join(root, "codex", "chatgpt-sign-in.json"),
|
|
5101
|
+
frontdoorStateFile: path22.join(root, "frontdoor", "state.json"),
|
|
5102
|
+
frontdoorLockFile: path22.join(root, "frontdoor", "start.lock"),
|
|
5103
|
+
frontdoorControlTokenFile: path22.join(root, "frontdoor", "control-token"),
|
|
5104
|
+
frontdoorSessionsDir: path22.join(root, "frontdoor", "sessions"),
|
|
5105
|
+
frontdoorRcCredentialsDir: path22.join(root, "frontdoor", "rc-credentials"),
|
|
5106
|
+
frontdoorLogPath: path22.join(root, "logs", "frontdoor.log"),
|
|
5107
|
+
usageDir: path22.join(root, "usage"),
|
|
5108
|
+
usageLogDir: path22.join(root, "usage", "log"),
|
|
5109
|
+
usageSnapshotsDir: path22.join(root, "usage", "snapshots"),
|
|
5110
|
+
usagePicksFile: path22.join(root, "usage", "picks.json")
|
|
5083
5111
|
};
|
|
5084
5112
|
}
|
|
5085
5113
|
function resolveLayoutPaths() {
|
|
@@ -5088,7 +5116,6 @@ function resolveLayoutPaths() {
|
|
|
5088
5116
|
var init_paths = __esm({
|
|
5089
5117
|
"src/paths.ts"() {
|
|
5090
5118
|
"use strict";
|
|
5091
|
-
init_state2();
|
|
5092
5119
|
init_legacy();
|
|
5093
5120
|
}
|
|
5094
5121
|
});
|
|
@@ -5172,7 +5199,7 @@ var init_credentialCache = __esm({
|
|
|
5172
5199
|
// src/realCredentialCache.ts
|
|
5173
5200
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
5174
5201
|
import fs6 from "node:fs";
|
|
5175
|
-
import
|
|
5202
|
+
import path23 from "node:path";
|
|
5176
5203
|
function cacheFileNameFor(owner) {
|
|
5177
5204
|
return `${owner.replace(/[^A-Za-z0-9._-]/g, "_")}.json`;
|
|
5178
5205
|
}
|
|
@@ -5196,8 +5223,8 @@ function security(args, stdin) {
|
|
|
5196
5223
|
return { status: result.status, stdout: result.stdout };
|
|
5197
5224
|
}
|
|
5198
5225
|
function createRealCredentialCache(root) {
|
|
5199
|
-
const dir =
|
|
5200
|
-
const filePath = (owner) =>
|
|
5226
|
+
const dir = path23.join(root, "credential-cache");
|
|
5227
|
+
const filePath = (owner) => path23.join(dir, cacheFileNameFor(owner));
|
|
5201
5228
|
return {
|
|
5202
5229
|
read(store, owner) {
|
|
5203
5230
|
if (store === "file") {
|
|
@@ -5429,9 +5456,9 @@ var init_credential = __esm({
|
|
|
5429
5456
|
|
|
5430
5457
|
// src/providersStore.ts
|
|
5431
5458
|
import fs7 from "node:fs";
|
|
5432
|
-
import
|
|
5459
|
+
import path24 from "node:path";
|
|
5433
5460
|
function providerJsonPath(paths, name) {
|
|
5434
|
-
return
|
|
5461
|
+
return path24.join(paths.providersDir, `${name}.json`);
|
|
5435
5462
|
}
|
|
5436
5463
|
function providerExists(paths, name) {
|
|
5437
5464
|
return fs7.existsSync(providerJsonPath(paths, name));
|
|
@@ -5491,7 +5518,7 @@ function readProvider(paths, name) {
|
|
|
5491
5518
|
return parseProviderFile(filePath, raw);
|
|
5492
5519
|
}
|
|
5493
5520
|
function loadProvider(providersDir, name, port) {
|
|
5494
|
-
const filePath =
|
|
5521
|
+
const filePath = path24.join(providersDir, `${name}.json`);
|
|
5495
5522
|
const raw = port.readConfigFile(filePath);
|
|
5496
5523
|
return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
|
|
5497
5524
|
}
|
|
@@ -5856,17 +5883,17 @@ var init_commandDeps = __esm({
|
|
|
5856
5883
|
|
|
5857
5884
|
// src/claudeShim.ts
|
|
5858
5885
|
import fs8 from "node:fs";
|
|
5859
|
-
import
|
|
5886
|
+
import path26 from "node:path";
|
|
5860
5887
|
import { z as z15 } from "zod";
|
|
5861
5888
|
function commandFilename(ownExecutablePath, commandName) {
|
|
5862
5889
|
return ownExecutablePath.toLowerCase().endsWith(".exe") ? `${commandName}.exe` : commandName;
|
|
5863
5890
|
}
|
|
5864
5891
|
function resolveOwnBinaryCheck(paths, contentSourcePath) {
|
|
5865
5892
|
const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
5866
|
-
const recordedTarget = state === void 0 ? void 0 :
|
|
5893
|
+
const recordedTarget = state === void 0 ? void 0 : path26.resolve(state.targetPath);
|
|
5867
5894
|
let ownStat;
|
|
5868
5895
|
return (candidate) => {
|
|
5869
|
-
if (recordedTarget !== void 0 &&
|
|
5896
|
+
if (recordedTarget !== void 0 && path26.resolve(candidate) === recordedTarget) {
|
|
5870
5897
|
return true;
|
|
5871
5898
|
}
|
|
5872
5899
|
ownStat ??= statOrUndefined(contentSourcePath);
|
|
@@ -5889,15 +5916,15 @@ function statOrUndefined(target) {
|
|
|
5889
5916
|
}
|
|
5890
5917
|
}
|
|
5891
5918
|
function findPathShadow(params) {
|
|
5892
|
-
const resolvedTargetDir =
|
|
5919
|
+
const resolvedTargetDir = path26.resolve(params.targetDir);
|
|
5893
5920
|
for (const dir of params.pathDirs) {
|
|
5894
5921
|
const found = params.findExecutableInDir(dir, params.targetFilename);
|
|
5895
5922
|
if (found === void 0) {
|
|
5896
5923
|
continue;
|
|
5897
5924
|
}
|
|
5898
|
-
return
|
|
5925
|
+
return path26.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
|
|
5899
5926
|
}
|
|
5900
|
-
return params.pathDirs.some((dir) =>
|
|
5927
|
+
return params.pathDirs.some((dir) => path26.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
|
|
5901
5928
|
}
|
|
5902
5929
|
var ClaudeShimStateSchema, nodeLinkFs;
|
|
5903
5930
|
var init_claudeShim = __esm({
|
|
@@ -6321,7 +6348,7 @@ var init_headers = __esm({
|
|
|
6321
6348
|
});
|
|
6322
6349
|
|
|
6323
6350
|
// src/launcher/flags.ts
|
|
6324
|
-
import
|
|
6351
|
+
import path31 from "node:path";
|
|
6325
6352
|
function resolveLaunchFlags(params) {
|
|
6326
6353
|
return {
|
|
6327
6354
|
skipPermissions: params.flags?.skipPermissions ?? parseEnvBool("AGENT_SHIM_SKIP_PERMISSIONS", params.env.AGENT_SHIM_SKIP_PERMISSIONS) ?? params.cascade?.skipPermissions ?? false,
|
|
@@ -6352,7 +6379,7 @@ function buildEnv(params) {
|
|
|
6352
6379
|
const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
6353
6380
|
let providerCustomHeaders;
|
|
6354
6381
|
if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
|
|
6355
|
-
env.CLAUDE_CONFIG_DIR =
|
|
6382
|
+
env.CLAUDE_CONFIG_DIR = path31.join(params.identitiesDir, params.resolvedIdentityName);
|
|
6356
6383
|
}
|
|
6357
6384
|
if (params.provider !== void 0) {
|
|
6358
6385
|
const providerEnv = params.provider.definition.env ?? {};
|
|
@@ -6639,7 +6666,7 @@ var init_launchHook = __esm({
|
|
|
6639
6666
|
|
|
6640
6667
|
// src/launcher.ts
|
|
6641
6668
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
6642
|
-
import
|
|
6669
|
+
import path32 from "node:path";
|
|
6643
6670
|
function resolveIdentityCredential(identity, credential, env, port) {
|
|
6644
6671
|
if (port === void 0) {
|
|
6645
6672
|
return { ok: false, status: 1, message: `agent-shim: identity ${identity} needs its credential resolved, but this launcher has no credential port wired` };
|
|
@@ -6747,7 +6774,7 @@ function prepareLaunch(params) {
|
|
|
6747
6774
|
identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
|
|
6748
6775
|
globalDefaultConfigProfile: params.globalDefaultConfigProfile
|
|
6749
6776
|
});
|
|
6750
|
-
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(
|
|
6777
|
+
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path32.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
|
|
6751
6778
|
log.error(
|
|
6752
6779
|
`agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
|
|
6753
6780
|
);
|
|
@@ -6810,7 +6837,7 @@ function prepareLaunch(params) {
|
|
|
6810
6837
|
);
|
|
6811
6838
|
const updateCheck = runLaunchUpdateCheck({
|
|
6812
6839
|
mode: params.updateMode ?? "off",
|
|
6813
|
-
checkPath:
|
|
6840
|
+
checkPath: path32.join(paths.root, "update.check"),
|
|
6814
6841
|
currentVersion: package_default.version,
|
|
6815
6842
|
port: params.update
|
|
6816
6843
|
});
|
|
@@ -6976,12 +7003,12 @@ var init_launcher = __esm({
|
|
|
6976
7003
|
});
|
|
6977
7004
|
|
|
6978
7005
|
// src/ownCli.ts
|
|
6979
|
-
import
|
|
7006
|
+
import path33 from "node:path";
|
|
6980
7007
|
function agentShimCliPath(distDir = typeof __AGENT_SHIM_DIST_DIR__ === "string" ? __AGENT_SHIM_DIST_DIR__ : void 0) {
|
|
6981
7008
|
if (distDir === void 0) {
|
|
6982
7009
|
throw new OwnCliPathUnknownError();
|
|
6983
7010
|
}
|
|
6984
|
-
return
|
|
7011
|
+
return path33.join(distDir, OWN_CLI_FILE_NAME);
|
|
6985
7012
|
}
|
|
6986
7013
|
var OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
|
|
6987
7014
|
var init_ownCli = __esm({
|
|
@@ -7070,10 +7097,10 @@ request.on("error", (error) => finish(failed, (error.code ? error.code + ": " :
|
|
|
7070
7097
|
|
|
7071
7098
|
// src/frontdoor/trust.ts
|
|
7072
7099
|
import { createHash as createHash6 } from "node:crypto";
|
|
7073
|
-
import
|
|
7100
|
+
import path34 from "node:path";
|
|
7074
7101
|
function resolveTrustBundle(params) {
|
|
7075
7102
|
const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
|
|
7076
|
-
if (inherited === void 0 || inherited === "" ||
|
|
7103
|
+
if (inherited === void 0 || inherited === "" || path34.resolve(inherited) === path34.resolve(caCertFile)) {
|
|
7077
7104
|
return { path: caCertFile };
|
|
7078
7105
|
}
|
|
7079
7106
|
const caPem = fs12.readFileUtf8(caCertFile);
|
|
@@ -7091,7 +7118,7 @@ function resolveTrustBundle(params) {
|
|
|
7091
7118
|
}
|
|
7092
7119
|
const combined = `${inheritedPem.trimEnd()}
|
|
7093
7120
|
${caPem}`;
|
|
7094
|
-
const bundle =
|
|
7121
|
+
const bundle = path34.join(bundlesDir, `${createHash6("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
|
|
7095
7122
|
if (!fs12.exists(bundle)) {
|
|
7096
7123
|
fs12.mkdirp(bundlesDir);
|
|
7097
7124
|
fs12.writeFileAtomic(bundle, combined);
|
|
@@ -7897,11 +7924,21 @@ init_route();
|
|
|
7897
7924
|
|
|
7898
7925
|
// src/frontdoor/supervisor.ts
|
|
7899
7926
|
init_state();
|
|
7927
|
+
import path9 from "node:path";
|
|
7928
|
+
function watchedInstallEntry(resolvedOwnExecutablePath, siblingExists) {
|
|
7929
|
+
const parsed = path9.parse(resolvedOwnExecutablePath);
|
|
7930
|
+
if (parsed.name === "agent-shim") {
|
|
7931
|
+
return resolvedOwnExecutablePath;
|
|
7932
|
+
}
|
|
7933
|
+
const sibling = path9.join(parsed.dir, `agent-shim${parsed.ext}`);
|
|
7934
|
+
return siblingExists(sibling) ? sibling : resolvedOwnExecutablePath;
|
|
7935
|
+
}
|
|
7900
7936
|
var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
|
|
7901
7937
|
var FRONTDOOR_POLL_MS = 1e3;
|
|
7902
7938
|
var MS_PER_MINUTE = 6e4;
|
|
7903
7939
|
async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
|
|
7904
7940
|
const { fs: fs12, paths } = ports;
|
|
7941
|
+
const servingBinary = ports.statOwnExecutable();
|
|
7905
7942
|
const previous = readFrontDoorState(fs12, paths.frontdoorStateFile);
|
|
7906
7943
|
let lastPort = previous?.lastPort;
|
|
7907
7944
|
let lastConnectPort = previous?.lastConnectPort;
|
|
@@ -7964,6 +8001,18 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
7964
8001
|
ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http3.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
|
|
7965
8002
|
let idleSince;
|
|
7966
8003
|
let ticks = 0;
|
|
8004
|
+
const binaryReplaced = () => {
|
|
8005
|
+
const current = ports.statOwnExecutable();
|
|
8006
|
+
return current !== void 0 && servingBinary !== void 0 && (current.dev !== servingBinary.dev || current.ino !== servingBinary.ino || current.size !== servingBinary.size || current.mtimeMs !== servingBinary.mtimeMs);
|
|
8007
|
+
};
|
|
8008
|
+
const shutdown = async () => {
|
|
8009
|
+
await direct.close();
|
|
8010
|
+
await connect3.close();
|
|
8011
|
+
await http3.close();
|
|
8012
|
+
ports.closeRcStreamHub();
|
|
8013
|
+
writeFrontDoorState(fs12, paths.frontdoorStateFile, sticky());
|
|
8014
|
+
return 0;
|
|
8015
|
+
};
|
|
7967
8016
|
for (; ; ) {
|
|
7968
8017
|
if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
|
|
7969
8018
|
return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
|
|
@@ -7975,16 +8024,16 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
7975
8024
|
ports.checkQuotaExpiry();
|
|
7976
8025
|
const prunedPids = new Set(pruned);
|
|
7977
8026
|
if (listed.filter((session) => !prunedPids.has(session.pid)).length === 0) {
|
|
8027
|
+
if (ticks > 1 && binaryReplaced()) {
|
|
8028
|
+
ports.log("agent-shim frontdoor supervisor: the installed binary changed and no sessions are live; turning the door over for the next launch");
|
|
8029
|
+
ports.doorHealth.binaryTurnover();
|
|
8030
|
+
return await shutdown();
|
|
8031
|
+
}
|
|
7978
8032
|
idleSince ??= ports.now();
|
|
7979
8033
|
if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
|
|
7980
8034
|
ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
|
|
7981
8035
|
ports.doorHealth.idleShutdown();
|
|
7982
|
-
await
|
|
7983
|
-
await connect3.close();
|
|
7984
|
-
await http3.close();
|
|
7985
|
-
ports.closeRcStreamHub();
|
|
7986
|
-
writeFrontDoorState(fs12, paths.frontdoorStateFile, sticky());
|
|
7987
|
-
return 0;
|
|
8036
|
+
return await shutdown();
|
|
7988
8037
|
}
|
|
7989
8038
|
} else {
|
|
7990
8039
|
idleSince = void 0;
|
|
@@ -8038,8 +8087,8 @@ function parseConnectTarget(authority) {
|
|
|
8038
8087
|
function isInterceptedHost(host, interceptHosts) {
|
|
8039
8088
|
return interceptHosts.includes(host);
|
|
8040
8089
|
}
|
|
8041
|
-
function servedByPipeline(
|
|
8042
|
-
return
|
|
8090
|
+
function servedByPipeline(path35) {
|
|
8091
|
+
return path35?.startsWith(ROUTED_PATH_PREFIX) === true;
|
|
8043
8092
|
}
|
|
8044
8093
|
var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
8045
8094
|
"connection",
|
|
@@ -8573,11 +8622,11 @@ function createRcSessionTracker(deps) {
|
|
|
8573
8622
|
};
|
|
8574
8623
|
const observeExchange = (request4) => {
|
|
8575
8624
|
const method = (request4.method ?? "").toUpperCase();
|
|
8576
|
-
const
|
|
8577
|
-
if (!
|
|
8625
|
+
const path35 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
|
|
8626
|
+
if (!path35.startsWith(RC_SESSIONS_PATH_PREFIX)) {
|
|
8578
8627
|
return void 0;
|
|
8579
8628
|
}
|
|
8580
|
-
const tail =
|
|
8629
|
+
const tail = path35.slice(RC_SESSIONS_PATH_PREFIX.length);
|
|
8581
8630
|
const facts = {
|
|
8582
8631
|
oauthAuthorization: oauthAuthorizationOf(request4.headers),
|
|
8583
8632
|
anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
|
|
@@ -8959,8 +9008,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
|
|
|
8959
9008
|
function isRcReadFileEncoding(value) {
|
|
8960
9009
|
return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
|
|
8961
9010
|
}
|
|
8962
|
-
function buildRcReadFilePayload(requestId,
|
|
8963
|
-
return buildRcControlRequestPayload(requestId, { subtype: "read_file", path:
|
|
9011
|
+
function buildRcReadFilePayload(requestId, path35, options) {
|
|
9012
|
+
return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path35, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
|
|
8964
9013
|
}
|
|
8965
9014
|
function buildRcFileSuggestionsPayload(requestId, query) {
|
|
8966
9015
|
return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
|
|
@@ -9062,15 +9111,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
|
|
|
9062
9111
|
const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
|
|
9063
9112
|
return result.ok ? { ...result, requestId } : result;
|
|
9064
9113
|
}
|
|
9065
|
-
async function readRcSessionFile(deps, sessionId,
|
|
9066
|
-
if (
|
|
9114
|
+
async function readRcSessionFile(deps, sessionId, path35, options) {
|
|
9115
|
+
if (path35 === "") {
|
|
9067
9116
|
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" };
|
|
9068
9117
|
}
|
|
9069
9118
|
if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
|
|
9070
9119
|
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" };
|
|
9071
9120
|
}
|
|
9072
9121
|
const requestId = deps.newUuid();
|
|
9073
|
-
const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId,
|
|
9122
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path35, options), `read ${path35} from session ${sessionId}`);
|
|
9074
9123
|
return result.ok ? { ...result, requestId } : result;
|
|
9075
9124
|
}
|
|
9076
9125
|
async function suggestRcSessionFiles(deps, sessionId, query) {
|
|
@@ -9239,11 +9288,11 @@ function createRcControlHandler(deps) {
|
|
|
9239
9288
|
path: "read-file",
|
|
9240
9289
|
read: (body) => {
|
|
9241
9290
|
const session = bodyString(body, "session");
|
|
9242
|
-
const
|
|
9291
|
+
const path35 = bodyString(body, "path");
|
|
9243
9292
|
const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
|
|
9244
9293
|
const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
|
|
9245
|
-
const refused2 = session === void 0 ||
|
|
9246
|
-
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,
|
|
9294
|
+
const refused2 = session === void 0 || path35 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
|
|
9295
|
+
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, path35, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
|
|
9247
9296
|
}
|
|
9248
9297
|
},
|
|
9249
9298
|
{
|
|
@@ -9553,9 +9602,9 @@ function requestIdOfBody(body) {
|
|
|
9553
9602
|
}
|
|
9554
9603
|
function frontDoorRcControl(transport, token) {
|
|
9555
9604
|
const headers = { authorization: `Bearer ${token}` };
|
|
9556
|
-
const listAnswerOf = async (
|
|
9605
|
+
const listAnswerOf = async (path35, what) => {
|
|
9557
9606
|
try {
|
|
9558
|
-
return await transport.request({ method: "GET", path:
|
|
9607
|
+
return await transport.request({ method: "GET", path: path35, headers });
|
|
9559
9608
|
} catch (error) {
|
|
9560
9609
|
throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
9561
9610
|
}
|
|
@@ -9627,10 +9676,10 @@ function frontDoorRcControl(transport, token) {
|
|
|
9627
9676
|
}
|
|
9628
9677
|
return pending;
|
|
9629
9678
|
};
|
|
9630
|
-
const writeOf = async (
|
|
9679
|
+
const writeOf = async (path35, body, describeFailure) => {
|
|
9631
9680
|
let answer;
|
|
9632
9681
|
try {
|
|
9633
|
-
answer = await transport.request({ method: "POST", path:
|
|
9682
|
+
answer = await transport.request({ method: "POST", path: path35, headers: { ...headers, "content-type": "application/json" }, body });
|
|
9634
9683
|
} catch (error) {
|
|
9635
9684
|
return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
|
|
9636
9685
|
}
|
|
@@ -9661,10 +9710,10 @@ function frontDoorRcControl(transport, token) {
|
|
|
9661
9710
|
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}`),
|
|
9662
9711
|
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}`),
|
|
9663
9712
|
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}`),
|
|
9664
|
-
readFile: async (sessionId,
|
|
9713
|
+
readFile: async (sessionId, path35, options) => await writeOf(
|
|
9665
9714
|
`${CONTROL_PATH_PREFIX}/read-file`,
|
|
9666
|
-
JSON.stringify({ session: sessionId, path:
|
|
9667
|
-
(status, message) => `reading ${
|
|
9715
|
+
JSON.stringify({ session: sessionId, path: path35, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
|
|
9716
|
+
(status, message) => `reading ${path35} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
|
|
9668
9717
|
),
|
|
9669
9718
|
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}`),
|
|
9670
9719
|
keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
|
|
@@ -9819,12 +9868,12 @@ function tlsFacts(options) {
|
|
|
9819
9868
|
}
|
|
9820
9869
|
function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
|
|
9821
9870
|
const agent = new ExemptTlsAgent();
|
|
9822
|
-
const post = async (
|
|
9871
|
+
const post = async (path35, headers, body) => await new Promise((resolve, reject) => {
|
|
9823
9872
|
const options = {
|
|
9824
9873
|
host: target.host,
|
|
9825
9874
|
port: target.port,
|
|
9826
9875
|
method: "POST",
|
|
9827
|
-
path:
|
|
9876
|
+
path: path35,
|
|
9828
9877
|
// 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.
|
|
9829
9878
|
headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
|
|
9830
9879
|
agent
|
|
@@ -9889,12 +9938,12 @@ function lateRcStreamDial(resolve) {
|
|
|
9889
9938
|
}
|
|
9890
9939
|
function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
|
|
9891
9940
|
const agent = new ExemptTlsAgent();
|
|
9892
|
-
const request4 = async (method,
|
|
9941
|
+
const request4 = async (method, path35, headers, body, signal) => await new Promise((resolve, reject) => {
|
|
9893
9942
|
const options = {
|
|
9894
9943
|
host: target.host,
|
|
9895
9944
|
port: target.port,
|
|
9896
9945
|
method,
|
|
9897
|
-
path:
|
|
9946
|
+
path: path35,
|
|
9898
9947
|
// 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.
|
|
9899
9948
|
headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
|
|
9900
9949
|
agent,
|
|
@@ -9936,9 +9985,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
|
|
|
9936
9985
|
return { status, body: await readAll(response) };
|
|
9937
9986
|
},
|
|
9938
9987
|
openStream: async (sessionId, headers, resume, signal) => {
|
|
9939
|
-
const
|
|
9988
|
+
const path35 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
|
|
9940
9989
|
const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
|
|
9941
|
-
const { status, response } = await request4("GET",
|
|
9990
|
+
const { status, response } = await request4("GET", path35, streamHeaders, void 0, signal);
|
|
9942
9991
|
if (!isSuccessful2(status)) {
|
|
9943
9992
|
await readAll(response);
|
|
9944
9993
|
return { status, chunks: NO_CHUNKS };
|
|
@@ -10150,7 +10199,7 @@ function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
|
|
|
10150
10199
|
}
|
|
10151
10200
|
|
|
10152
10201
|
// src/frontdoor/rcCredentialStore.ts
|
|
10153
|
-
import
|
|
10202
|
+
import path10 from "node:path";
|
|
10154
10203
|
function isSafeSessionId(sessionId) {
|
|
10155
10204
|
return /^[A-Za-z0-9_-]+$/.test(sessionId);
|
|
10156
10205
|
}
|
|
@@ -10176,7 +10225,7 @@ function sequenceNumOfJson(value) {
|
|
|
10176
10225
|
}
|
|
10177
10226
|
function createRcCredentialStore(fs12, dir) {
|
|
10178
10227
|
fs12.mkdirPrivate(dir);
|
|
10179
|
-
const fileFor = (sessionId) =>
|
|
10228
|
+
const fileFor = (sessionId) => path10.join(dir, `${sessionId}.json`);
|
|
10180
10229
|
const readParsed = (sessionId) => {
|
|
10181
10230
|
const raw = fs12.readFileUtf8(fileFor(sessionId));
|
|
10182
10231
|
if (raw === void 0) {
|
|
@@ -10636,7 +10685,7 @@ init_schema();
|
|
|
10636
10685
|
init_cliError();
|
|
10637
10686
|
init_load();
|
|
10638
10687
|
import fs4 from "node:fs";
|
|
10639
|
-
import
|
|
10688
|
+
import path21 from "node:path";
|
|
10640
10689
|
var ProfileNotFoundError = class extends CliError {
|
|
10641
10690
|
constructor(profileName) {
|
|
10642
10691
|
super(`No configuration profile named "${profileName}". Run \`agent-shim profile add ${profileName}\` first.`);
|
|
@@ -10662,7 +10711,7 @@ var InvalidCategoryNameError = class extends CliError {
|
|
|
10662
10711
|
categoryName;
|
|
10663
10712
|
};
|
|
10664
10713
|
function profileJsonPath(paths, name) {
|
|
10665
|
-
return
|
|
10714
|
+
return path21.join(paths.configProfilesDir, `${name}.json`);
|
|
10666
10715
|
}
|
|
10667
10716
|
function profileExists(paths, name) {
|
|
10668
10717
|
return fs4.existsSync(profileJsonPath(paths, name));
|
|
@@ -10802,19 +10851,19 @@ function writePools(paths, pools) {
|
|
|
10802
10851
|
applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
|
|
10803
10852
|
}
|
|
10804
10853
|
function poolCycleOf(pools, name) {
|
|
10805
|
-
const walk = (current,
|
|
10854
|
+
const walk = (current, path35) => {
|
|
10806
10855
|
for (const entry of pools[current]?.identities ?? []) {
|
|
10807
10856
|
const nested = poolNameOf(poolMemberIdentity(entry));
|
|
10808
10857
|
if (nested === void 0) {
|
|
10809
10858
|
continue;
|
|
10810
10859
|
}
|
|
10811
10860
|
if (nested === name) {
|
|
10812
|
-
return [...
|
|
10861
|
+
return [...path35, nested];
|
|
10813
10862
|
}
|
|
10814
|
-
if (
|
|
10863
|
+
if (path35.includes(nested)) {
|
|
10815
10864
|
continue;
|
|
10816
10865
|
}
|
|
10817
|
-
const found = walk(nested, [...
|
|
10866
|
+
const found = walk(nested, [...path35, nested]);
|
|
10818
10867
|
if (found !== void 0) {
|
|
10819
10868
|
return found;
|
|
10820
10869
|
}
|
|
@@ -10924,7 +10973,7 @@ init_guard();
|
|
|
10924
10973
|
init_providersStore();
|
|
10925
10974
|
init_projects();
|
|
10926
10975
|
init_pipeline();
|
|
10927
|
-
import
|
|
10976
|
+
import path25 from "node:path";
|
|
10928
10977
|
import { z as z12 } from "zod";
|
|
10929
10978
|
var HISTORY_PROJECTS_KEY_PREFIX = "history/projects/";
|
|
10930
10979
|
function projectFragmentOf(rawKey) {
|
|
@@ -11262,10 +11311,10 @@ function collectCheckReport(params) {
|
|
|
11262
11311
|
}).input;
|
|
11263
11312
|
const providerName = cascadeProviderName(cascade);
|
|
11264
11313
|
const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
|
|
11265
|
-
const farmRoot = identityDecision.name === void 0 ? void 0 :
|
|
11314
|
+
const farmRoot = identityDecision.name === void 0 ? void 0 : path25.join(paths.identitiesDir, identityDecision.name);
|
|
11266
11315
|
const settingsFiles = {
|
|
11267
|
-
"settings.json": realFsPort.readFileUtf8(
|
|
11268
|
-
"settings.local.json": realFsPort.readFileUtf8(
|
|
11316
|
+
"settings.json": realFsPort.readFileUtf8(path25.join(claudeHome, "settings.json")),
|
|
11317
|
+
"settings.local.json": realFsPort.readFileUtf8(path25.join(claudeHome, "settings.local.json"))
|
|
11269
11318
|
};
|
|
11270
11319
|
const report = runCheck({
|
|
11271
11320
|
cwd,
|
|
@@ -11485,7 +11534,7 @@ init_middleware();
|
|
|
11485
11534
|
init_preflight();
|
|
11486
11535
|
|
|
11487
11536
|
// src/frontdoor/controlSchemas.ts
|
|
11488
|
-
import
|
|
11537
|
+
import path29 from "node:path";
|
|
11489
11538
|
import { z as z19 } from "zod";
|
|
11490
11539
|
|
|
11491
11540
|
// src/doctorReport.ts
|
|
@@ -11499,7 +11548,7 @@ init_schema();
|
|
|
11499
11548
|
init_cliError();
|
|
11500
11549
|
init_identity();
|
|
11501
11550
|
import fs9 from "node:fs";
|
|
11502
|
-
import
|
|
11551
|
+
import path27 from "node:path";
|
|
11503
11552
|
init_lock();
|
|
11504
11553
|
var IdentityNotFoundError = class extends CliError {
|
|
11505
11554
|
constructor(name) {
|
|
@@ -11528,7 +11577,7 @@ var InvalidIdentityNameError = class extends CliError {
|
|
|
11528
11577
|
attemptedName;
|
|
11529
11578
|
};
|
|
11530
11579
|
function identityJsonPath(paths, name) {
|
|
11531
|
-
return
|
|
11580
|
+
return path27.join(paths.identitiesDir, name, "identity.json");
|
|
11532
11581
|
}
|
|
11533
11582
|
function identityExists(paths, name) {
|
|
11534
11583
|
return fs9.existsSync(identityJsonPath(paths, name));
|
|
@@ -11629,7 +11678,7 @@ function setIdentityCredential(paths, identityName, change) {
|
|
|
11629
11678
|
});
|
|
11630
11679
|
}
|
|
11631
11680
|
function belongsToIdentity(entry, name) {
|
|
11632
|
-
return entry === name || entry ===
|
|
11681
|
+
return entry === name || entry === path27.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
|
|
11633
11682
|
}
|
|
11634
11683
|
function removeIdentity(paths, name) {
|
|
11635
11684
|
if (!identityExists(paths, name)) {
|
|
@@ -11637,7 +11686,7 @@ function removeIdentity(paths, name) {
|
|
|
11637
11686
|
}
|
|
11638
11687
|
for (const entry of fs9.readdirSync(paths.identitiesDir)) {
|
|
11639
11688
|
if (belongsToIdentity(entry, name)) {
|
|
11640
|
-
fs9.rmSync(
|
|
11689
|
+
fs9.rmSync(path27.join(paths.identitiesDir, entry), { recursive: true, force: true });
|
|
11641
11690
|
}
|
|
11642
11691
|
}
|
|
11643
11692
|
if (readActiveIdentity2(paths) === name) {
|
|
@@ -11648,7 +11697,7 @@ function removeIdentity(paths, name) {
|
|
|
11648
11697
|
// src/doctorReport.ts
|
|
11649
11698
|
init_realPorts();
|
|
11650
11699
|
import fs10 from "node:fs";
|
|
11651
|
-
import
|
|
11700
|
+
import path28 from "node:path";
|
|
11652
11701
|
|
|
11653
11702
|
// src/codex/siwcStore.ts
|
|
11654
11703
|
import { z as z18 } from "zod";
|
|
@@ -11780,8 +11829,18 @@ function validateJson(schema, input) {
|
|
|
11780
11829
|
}
|
|
11781
11830
|
return { ok: true, data: result.data };
|
|
11782
11831
|
}
|
|
11832
|
+
function tcpPortEraRecord(raw) {
|
|
11833
|
+
let parsed;
|
|
11834
|
+
try {
|
|
11835
|
+
parsed = JSON.parse(raw);
|
|
11836
|
+
} catch {
|
|
11837
|
+
return false;
|
|
11838
|
+
}
|
|
11839
|
+
const has = (key) => typeof parsed === "object" && parsed !== null && key in parsed;
|
|
11840
|
+
return (has("port") || has("lastPort")) && !has("socketPath");
|
|
11841
|
+
}
|
|
11783
11842
|
function pushPathResolution(push, resolution) {
|
|
11784
|
-
const ownDir =
|
|
11843
|
+
const ownDir = path28.dirname(resolution.ownExecutablePath);
|
|
11785
11844
|
switch (resolution.agentShim.status) {
|
|
11786
11845
|
case "ok":
|
|
11787
11846
|
push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
|
|
@@ -11880,14 +11939,14 @@ function pushProvider(push, entry, cacheEnv, signIn) {
|
|
|
11880
11939
|
}
|
|
11881
11940
|
function pushLegacyName(push, params) {
|
|
11882
11941
|
const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
|
|
11883
|
-
if (legacyVariables.length === 0 &&
|
|
11942
|
+
if (legacyVariables.length === 0 && path28.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
|
|
11884
11943
|
push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
|
|
11885
11944
|
return;
|
|
11886
11945
|
}
|
|
11887
11946
|
for (const name of legacyVariables) {
|
|
11888
11947
|
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);
|
|
11889
11948
|
}
|
|
11890
|
-
if (
|
|
11949
|
+
if (path28.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
|
|
11891
11950
|
push(
|
|
11892
11951
|
"legacy-name",
|
|
11893
11952
|
"warn",
|
|
@@ -12089,6 +12148,8 @@ function runDoctor(params) {
|
|
|
12089
12148
|
}
|
|
12090
12149
|
if (params.headroom.state.raw === void 0) {
|
|
12091
12150
|
push("headroom", "pass", "No headroom daemon has ever run; nothing to check.");
|
|
12151
|
+
} else if (tcpPortEraRecord(params.headroom.state.raw)) {
|
|
12152
|
+
push("headroom", "pass", `${params.headroom.state.path} holds a previous release's TCP-port state record; the next launch through headroom claims over it.`);
|
|
12092
12153
|
} else {
|
|
12093
12154
|
const validated2 = validateJson(HeadroomStateSchema, params.headroom.state);
|
|
12094
12155
|
if (!validated2.ok) {
|
|
@@ -12227,18 +12288,18 @@ function collectDoctorReport(params) {
|
|
|
12227
12288
|
const { paths } = params;
|
|
12228
12289
|
const identityNames = fs10.existsSync(paths.identitiesDir) ? fs10.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
|
|
12229
12290
|
const identities = identityNames.map((name) => {
|
|
12230
|
-
const farmRoot =
|
|
12231
|
-
const identityPath =
|
|
12291
|
+
const farmRoot = path28.join(paths.identitiesDir, name);
|
|
12292
|
+
const identityPath = path28.join(farmRoot, "identity.json");
|
|
12232
12293
|
return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
|
|
12233
12294
|
});
|
|
12234
12295
|
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() : [];
|
|
12235
12296
|
const configProfiles = profileNames.map((name) => {
|
|
12236
|
-
const profilePath =
|
|
12297
|
+
const profilePath = path28.join(paths.configProfilesDir, `${name}.json`);
|
|
12237
12298
|
return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
|
|
12238
12299
|
});
|
|
12239
12300
|
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() : [];
|
|
12240
12301
|
const providers = providerNames.map((name) => {
|
|
12241
|
-
const providerPath =
|
|
12302
|
+
const providerPath = path28.join(paths.providersDir, `${name}.json`);
|
|
12242
12303
|
return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
|
|
12243
12304
|
});
|
|
12244
12305
|
const ownExecutablePath = realOwnExecutablePath();
|
|
@@ -12250,12 +12311,12 @@ function collectDoctorReport(params) {
|
|
|
12250
12311
|
binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
|
|
12251
12312
|
}
|
|
12252
12313
|
const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
12253
|
-
const pathDirs = (params.env.PATH ?? "").split(
|
|
12314
|
+
const pathDirs = (params.env.PATH ?? "").split(path28.delimiter).filter((dir) => dir !== "");
|
|
12254
12315
|
const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
|
|
12255
12316
|
findPathShadow({
|
|
12256
12317
|
pathDirs,
|
|
12257
|
-
targetDir:
|
|
12258
|
-
targetFilename:
|
|
12318
|
+
targetDir: path28.dirname(shimState.targetPath),
|
|
12319
|
+
targetFilename: path28.basename(shimState.targetPath),
|
|
12259
12320
|
findExecutableInDir
|
|
12260
12321
|
}),
|
|
12261
12322
|
shimState.targetPath,
|
|
@@ -12281,7 +12342,7 @@ function collectDoctorReport(params) {
|
|
|
12281
12342
|
agentShim: refinePathShadow(
|
|
12282
12343
|
findPathShadow({
|
|
12283
12344
|
pathDirs,
|
|
12284
|
-
targetDir:
|
|
12345
|
+
targetDir: path28.dirname(ownExecutablePath),
|
|
12285
12346
|
targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
|
|
12286
12347
|
findExecutableInDir
|
|
12287
12348
|
}),
|
|
@@ -12293,7 +12354,12 @@ function collectDoctorReport(params) {
|
|
|
12293
12354
|
run: realRunPort,
|
|
12294
12355
|
platform: process.platform,
|
|
12295
12356
|
headroom: {
|
|
12296
|
-
|
|
12357
|
+
// Read-only resolution like `headroom status`: the doctor reports whichever record a launch would join, migrating nothing.
|
|
12358
|
+
state: (() => {
|
|
12359
|
+
const resolved = resolveServingHeadroomState(realFarmFs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, realIsProcessRunning);
|
|
12360
|
+
const statePath = resolved?.path ?? paths.headroomStateFile;
|
|
12361
|
+
return { path: statePath, raw: realFarmFs.readFileUtf8(statePath) };
|
|
12362
|
+
})(),
|
|
12297
12363
|
isRunning: realIsProcessRunning
|
|
12298
12364
|
}
|
|
12299
12365
|
});
|
|
@@ -12350,11 +12416,11 @@ var FrontDoorSessionsOutputSchema = z19.strictObject({ sessions: z19.readonly(z1
|
|
|
12350
12416
|
var CheckRunInputSchema = z19.strictObject({
|
|
12351
12417
|
path: z19.string().min(1),
|
|
12352
12418
|
identity: z19.string().min(1).optional()
|
|
12353
|
-
}).refine((input) =>
|
|
12419
|
+
}).refine((input) => path29.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
12354
12420
|
var PoolPickInputSchema = z19.strictObject({
|
|
12355
12421
|
pool: z19.string().min(1),
|
|
12356
12422
|
path: z19.string().min(1)
|
|
12357
|
-
}).refine((input) =>
|
|
12423
|
+
}).refine((input) => path29.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
12358
12424
|
var DoctorFindingSchema = z19.strictObject({
|
|
12359
12425
|
section: z19.enum(DOCTOR_SECTIONS),
|
|
12360
12426
|
subject: z19.string().optional(),
|
|
@@ -12396,6 +12462,7 @@ var LaunchLifecycleEventSchema = z20.strictObject({
|
|
|
12396
12462
|
var DoorHealthEventSchema = z20.discriminatedUnion("kind", [
|
|
12397
12463
|
z20.strictObject({ kind: z20.literal("generation"), pid: z20.number().int().positive(), providerPort: z20.number().int().positive(), connectPort: z20.number().int().positive(), directPort: z20.number().int().positive(), observedAt: z20.number() }),
|
|
12398
12464
|
z20.strictObject({ kind: z20.literal("listenerFailed"), pid: z20.number().int().positive(), listener: z20.enum(["provider", "connect", "direct"]), message: z20.string(), observedAt: z20.number() }),
|
|
12465
|
+
z20.strictObject({ kind: z20.literal("binaryTurnover"), pid: z20.number().int().positive(), observedAt: z20.number() }),
|
|
12399
12466
|
z20.strictObject({ kind: z20.literal("idleShutdown"), pid: z20.number().int().positive(), observedAt: z20.number() })
|
|
12400
12467
|
]);
|
|
12401
12468
|
var QuotaExpiringEventSchema = z20.strictObject({
|
|
@@ -12559,7 +12626,7 @@ init_socket();
|
|
|
12559
12626
|
init_state2();
|
|
12560
12627
|
init_state();
|
|
12561
12628
|
function headroomSocketTarget(fsPort, trust, paths) {
|
|
12562
|
-
const socketPath = readHeadroomState(fsPort, paths.headroomStateFile)?.socketPath;
|
|
12629
|
+
const socketPath = readHeadroomState(fsPort, paths.headroomStateFile)?.socketPath ?? readHeadroomState(fsPort, paths.headroomLegacyStateFile)?.socketPath;
|
|
12563
12630
|
return socketPath === void 0 ? void 0 : verifyHeadroomSocket(socketPath, trust);
|
|
12564
12631
|
}
|
|
12565
12632
|
function collectFrontDoorStatus(fsPort, socketTrust, paths, isRunning) {
|
|
@@ -12767,6 +12834,9 @@ function createDoorHealthPublisher(hub, now, pid) {
|
|
|
12767
12834
|
},
|
|
12768
12835
|
idleShutdown: () => {
|
|
12769
12836
|
publisher.publish({ kind: "idleShutdown", pid, observedAt: now() });
|
|
12837
|
+
},
|
|
12838
|
+
binaryTurnover: () => {
|
|
12839
|
+
publisher.publish({ kind: "binaryTurnover", pid, observedAt: now() });
|
|
12770
12840
|
}
|
|
12771
12841
|
};
|
|
12772
12842
|
}
|
|
@@ -14462,7 +14532,7 @@ data: ${JSON.stringify(envelope)}
|
|
|
14462
14532
|
|
|
14463
14533
|
// src/frontdoor/rcSelfHostMint.ts
|
|
14464
14534
|
init_account();
|
|
14465
|
-
import
|
|
14535
|
+
import path30 from "node:path";
|
|
14466
14536
|
var CREDENTIALS_FILE = ".credentials.json";
|
|
14467
14537
|
var CLAUDE_JSON2 = ".claude.json";
|
|
14468
14538
|
var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
|
|
@@ -14486,7 +14556,7 @@ function readJsonObject(fs12, file) {
|
|
|
14486
14556
|
return isRecord11(parsed) ? parsed : void 0;
|
|
14487
14557
|
}
|
|
14488
14558
|
function readRcSelfHostRecord(fs12, frontdoorDir) {
|
|
14489
|
-
const parsed = readJsonObject(fs12,
|
|
14559
|
+
const parsed = readJsonObject(fs12, path30.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
|
|
14490
14560
|
if (parsed === void 0) {
|
|
14491
14561
|
return void 0;
|
|
14492
14562
|
}
|
|
@@ -14500,11 +14570,11 @@ function mintRcSelfHostCredential(deps) {
|
|
|
14500
14570
|
if (!isIdentityName(deps.identity)) {
|
|
14501
14571
|
throw new Error(`"${deps.identity}" is not a valid identity name.`);
|
|
14502
14572
|
}
|
|
14503
|
-
const identityDir =
|
|
14504
|
-
const credentialsFile =
|
|
14505
|
-
const claudeJsonFile =
|
|
14506
|
-
const recordDir =
|
|
14507
|
-
const recordFile =
|
|
14573
|
+
const identityDir = path30.join(deps.identitiesDir, deps.identity);
|
|
14574
|
+
const credentialsFile = path30.join(identityDir, CREDENTIALS_FILE);
|
|
14575
|
+
const claudeJsonFile = path30.join(identityDir, CLAUDE_JSON2);
|
|
14576
|
+
const recordDir = path30.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
|
|
14577
|
+
const recordFile = path30.join(recordDir, RC_SELF_HOST_RECORD_FILE);
|
|
14508
14578
|
const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
|
|
14509
14579
|
const existingCredentials = readJsonObject(deps.fs, credentialsFile);
|
|
14510
14580
|
const existingOauth = isRecord11(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
|
|
@@ -14520,7 +14590,7 @@ function mintRcSelfHostCredential(deps) {
|
|
|
14520
14590
|
const organizationUuid = deps.newUuid();
|
|
14521
14591
|
const accountUuid = deps.newUuid();
|
|
14522
14592
|
const mintedAt = new Date(deps.now()).toISOString();
|
|
14523
|
-
deps.fs.mkdirPrivate(
|
|
14593
|
+
deps.fs.mkdirPrivate(path30.dirname(credentialsFile));
|
|
14524
14594
|
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)}
|
|
14525
14595
|
`);
|
|
14526
14596
|
const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
|
|
@@ -15052,5 +15122,6 @@ export {
|
|
|
15052
15122
|
updateDirectoryRule,
|
|
15053
15123
|
updateProvider,
|
|
15054
15124
|
useIdentity,
|
|
15125
|
+
watchedInstallEntry,
|
|
15055
15126
|
writeDirectoryRules
|
|
15056
15127
|
};
|