claude-use 6.2.3 → 7.1.1
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/LICENSE +21 -201
- package/README.md +91 -80
- package/dist/cli.cjs +535 -474
- package/dist/index.cjs +42 -39
- package/dist/index.mjs +42 -39
- package/dist/types/cliError.d.ts +1 -1
- package/dist/types/config/classify.d.ts +3 -3
- package/dist/types/config/schema.d.ts +13 -13
- package/dist/types/frontdoor/capability.d.ts +3 -3
- package/dist/types/frontdoor/connect.d.ts +2 -2
- package/dist/types/frontdoor/ensure.d.ts +2 -2
- package/dist/types/frontdoor/probe.d.ts +1 -1
- package/dist/types/frontdoor/supervisor.d.ts +1 -1
- package/dist/types/frontdoor/x509.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/launcher/farm.d.ts +5 -5
- package/dist/types/launcher/guard.d.ts +3 -3
- package/dist/types/launcher/lock.d.ts +1 -1
- package/dist/types/launcher/ports.d.ts +3 -3
- package/dist/types/legacy.d.ts +24 -0
- package/dist/types/paths.d.ts +12 -10
- package/dist/types/resolve/conditions.d.ts +1 -1
- package/dist/types/resolve/match.d.ts +1 -1
- package/dist/types/resolve/reconcile.d.ts +1 -1
- package/dist/types/resolve/types.d.ts +3 -3
- package/dist/types/resolve/walk.d.ts +6 -6
- package/dist/types/usage/read.d.ts +1 -1
- package/dist/types/usage/schema.d.ts +2 -2
- package/package.json +6 -5
package/dist/cli.cjs
CHANGED
|
@@ -35168,18 +35168,18 @@ function reportFatalError(error62, io) {
|
|
|
35168
35168
|
return error62.exitCode === 0 ? 0 : EXIT_USAGE;
|
|
35169
35169
|
}
|
|
35170
35170
|
if (error62 instanceof CliError) {
|
|
35171
|
-
io.writeErr(`
|
|
35171
|
+
io.writeErr(`agent-shim: ${error62.message}`);
|
|
35172
35172
|
return error62.exitCode;
|
|
35173
35173
|
}
|
|
35174
35174
|
const message = error62 instanceof Error ? error62.message : String(error62);
|
|
35175
|
-
io.writeErr(`
|
|
35175
|
+
io.writeErr(`agent-shim: ${message}`);
|
|
35176
35176
|
if (error62 instanceof Error && error62.stack !== void 0 && debugEnabled(io.env)) {
|
|
35177
35177
|
io.writeErr(error62.stack);
|
|
35178
35178
|
}
|
|
35179
35179
|
return EXIT_FAILURE;
|
|
35180
35180
|
}
|
|
35181
35181
|
function debugEnabled(env) {
|
|
35182
|
-
return env.
|
|
35182
|
+
return env.AGENT_SHIM_DEBUG !== void 0 && parseBoolWord(env.AGENT_SHIM_DEBUG) === true;
|
|
35183
35183
|
}
|
|
35184
35184
|
|
|
35185
35185
|
// src/claudeShim.ts
|
|
@@ -54890,7 +54890,7 @@ var import_node_crypto = require("node:crypto");
|
|
|
54890
54890
|
|
|
54891
54891
|
// src/config/load.ts
|
|
54892
54892
|
var import_cosmiconfig = __toESM(require_dist(), 1);
|
|
54893
|
-
function createExplorer(moduleName = "
|
|
54893
|
+
function createExplorer(moduleName = "agent-shim") {
|
|
54894
54894
|
return (0, import_cosmiconfig.cosmiconfigSync)(moduleName, { searchPlaces: [] });
|
|
54895
54895
|
}
|
|
54896
54896
|
function isRecord(value) {
|
|
@@ -55135,7 +55135,7 @@ function expandAllCategoryKey(pairs) {
|
|
|
55135
55135
|
if (all === void 0) {
|
|
55136
55136
|
return { ...rest };
|
|
55137
55137
|
}
|
|
55138
|
-
const expanded = Object.fromEntries(OVERRIDABLE_CATEGORIES.map((category) => [category, all]));
|
|
55138
|
+
const expanded = Object.fromEntries(OVERRIDABLE_CATEGORIES.filter((category) => !all || category !== "runtime").map((category) => [category, all]));
|
|
55139
55139
|
return { ...expanded, ...rest };
|
|
55140
55140
|
}
|
|
55141
55141
|
var CategoryMapSchema = external_exports.strictObject({
|
|
@@ -55209,7 +55209,7 @@ var CredentialSchema = external_exports.strictObject({
|
|
|
55209
55209
|
var ProviderCredentialSchema = CredentialSchema.extend({ target: external_exports.enum(PROVIDER_CREDENTIAL_TARGETS).optional() });
|
|
55210
55210
|
var RESERVED_PROVIDER_ENV_KEYS = Object.values(CREDENTIAL_TARGET_VARS);
|
|
55211
55211
|
var ProviderEnvSchema = external_exports.record(external_exports.string().min(1), external_exports.string()).refine((env) => !Object.keys(env).some((key) => RESERVED_PROVIDER_ENV_KEYS.includes(key)), {
|
|
55212
|
-
message: `env may not set ${RESERVED_PROVIDER_ENV_KEYS.join(", ")}: the credential block's target sets one and
|
|
55212
|
+
message: `env may not set ${RESERVED_PROVIDER_ENV_KEYS.join(", ")}: the credential block's target sets one and agent-shim removes the others`
|
|
55213
55213
|
});
|
|
55214
55214
|
var PROVIDER_KINDS = ["http", "codex"];
|
|
55215
55215
|
var CODEX_TIERS = ["fable", "opus", "sonnet", "haiku"];
|
|
@@ -55399,16 +55399,16 @@ function parseJson(raw, schema) {
|
|
|
55399
55399
|
const parsed = schema.safeParse(JSON.parse(raw));
|
|
55400
55400
|
return parsed.success ? parsed.data : void 0;
|
|
55401
55401
|
}
|
|
55402
|
-
function readHeadroomState(
|
|
55402
|
+
function readHeadroomState(fs17, stateFile) {
|
|
55403
55403
|
try {
|
|
55404
|
-
return parseJson(
|
|
55404
|
+
return parseJson(fs17.readFileUtf8(stateFile), HeadroomStateSchema);
|
|
55405
55405
|
} catch {
|
|
55406
55406
|
return void 0;
|
|
55407
55407
|
}
|
|
55408
55408
|
}
|
|
55409
|
-
function writeHeadroomState(
|
|
55410
|
-
|
|
55411
|
-
|
|
55409
|
+
function writeHeadroomState(fs17, stateFile, state) {
|
|
55410
|
+
fs17.mkdirp(import_node_path5.default.dirname(stateFile));
|
|
55411
|
+
fs17.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
|
|
55412
55412
|
`);
|
|
55413
55413
|
}
|
|
55414
55414
|
function headroomAllowlist(providers) {
|
|
@@ -55428,14 +55428,14 @@ function headroomUpstreams(providers, frontDoorOrigin2) {
|
|
|
55428
55428
|
function hashAllowlist(allowlist) {
|
|
55429
55429
|
return (0, import_node_crypto2.createHash)("sha256").update(allowlist.join("\n")).digest("hex");
|
|
55430
55430
|
}
|
|
55431
|
-
function readAllProviders(
|
|
55431
|
+
function readAllProviders(fs17, providersDir) {
|
|
55432
55432
|
const result = [];
|
|
55433
|
-
for (const name of
|
|
55433
|
+
for (const name of fs17.readdir(providersDir)) {
|
|
55434
55434
|
if (!name.endsWith(".json")) {
|
|
55435
55435
|
continue;
|
|
55436
55436
|
}
|
|
55437
55437
|
try {
|
|
55438
|
-
const parsed = parseJson(
|
|
55438
|
+
const parsed = parseJson(fs17.readFileUtf8(import_node_path5.default.join(providersDir, name)), ProviderSchema);
|
|
55439
55439
|
if (parsed !== void 0) {
|
|
55440
55440
|
result.push({ name: name.slice(0, -".json".length), provider: parsed });
|
|
55441
55441
|
}
|
|
@@ -55445,22 +55445,22 @@ function readAllProviders(fs16, providersDir) {
|
|
|
55445
55445
|
}
|
|
55446
55446
|
return result;
|
|
55447
55447
|
}
|
|
55448
|
-
function writeSession(
|
|
55449
|
-
|
|
55450
|
-
|
|
55448
|
+
function writeSession(fs17, sessionsDir, session) {
|
|
55449
|
+
fs17.mkdirp(sessionsDir);
|
|
55450
|
+
fs17.writeFileUtf8(import_node_path5.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
|
|
55451
55451
|
`);
|
|
55452
55452
|
}
|
|
55453
|
-
function removeSession(
|
|
55454
|
-
|
|
55453
|
+
function removeSession(fs17, sessionsDir, pid) {
|
|
55454
|
+
fs17.removeRecursive(import_node_path5.default.join(sessionsDir, `${String(pid)}.json`));
|
|
55455
55455
|
}
|
|
55456
|
-
function listSessions(
|
|
55456
|
+
function listSessions(fs17, sessionsDir) {
|
|
55457
55457
|
const sessions = [];
|
|
55458
|
-
for (const name of
|
|
55458
|
+
for (const name of fs17.readdir(sessionsDir)) {
|
|
55459
55459
|
if (!name.endsWith(".json")) {
|
|
55460
55460
|
continue;
|
|
55461
55461
|
}
|
|
55462
55462
|
try {
|
|
55463
|
-
const parsed = parseJson(
|
|
55463
|
+
const parsed = parseJson(fs17.readFileUtf8(import_node_path5.default.join(sessionsDir, name)), HeadroomSessionSchema);
|
|
55464
55464
|
if (parsed !== void 0) {
|
|
55465
55465
|
sessions.push(parsed);
|
|
55466
55466
|
}
|
|
@@ -55470,22 +55470,22 @@ function listSessions(fs16, sessionsDir) {
|
|
|
55470
55470
|
}
|
|
55471
55471
|
return sessions.sort((a2, b) => a2.pid - b.pid);
|
|
55472
55472
|
}
|
|
55473
|
-
function sessionsForSupervisor(
|
|
55474
|
-
return listSessions(
|
|
55473
|
+
function sessionsForSupervisor(fs17, sessionsDir, supervisorPid) {
|
|
55474
|
+
return listSessions(fs17, sessionsDir).filter((session) => session.supervisorPid === supervisorPid);
|
|
55475
55475
|
}
|
|
55476
|
-
function pruneDeadSessions(
|
|
55476
|
+
function pruneDeadSessions(fs17, sessionsDir, isRunning) {
|
|
55477
55477
|
const removed = [];
|
|
55478
|
-
for (const session of listSessions(
|
|
55478
|
+
for (const session of listSessions(fs17, sessionsDir)) {
|
|
55479
55479
|
if (!isRunning(session.pid)) {
|
|
55480
|
-
removeSession(
|
|
55480
|
+
removeSession(fs17, sessionsDir, session.pid);
|
|
55481
55481
|
removed.push(session.pid);
|
|
55482
55482
|
}
|
|
55483
55483
|
}
|
|
55484
55484
|
return removed;
|
|
55485
55485
|
}
|
|
55486
|
-
function readStartLock(
|
|
55486
|
+
function readStartLock(fs17, lockFile) {
|
|
55487
55487
|
try {
|
|
55488
|
-
return parseJson(
|
|
55488
|
+
return parseJson(fs17.readFileUtf8(lockFile), HeadroomLockSchema);
|
|
55489
55489
|
} catch {
|
|
55490
55490
|
return void 0;
|
|
55491
55491
|
}
|
|
@@ -55514,7 +55514,7 @@ function ensureHeadroom(params) {
|
|
|
55514
55514
|
}
|
|
55515
55515
|
if (state.lastError !== void 0) {
|
|
55516
55516
|
throw new HeadroomStartError(
|
|
55517
|
-
`
|
|
55517
|
+
`agent-shim: the headroom daemon reported a fatal error and is not serving: ${state.lastError} (daemon log: ${paths.headroomLogPath})`
|
|
55518
55518
|
);
|
|
55519
55519
|
}
|
|
55520
55520
|
} else if (!spawnedSupervisor) {
|
|
@@ -55538,7 +55538,7 @@ function ensureHeadroom(params) {
|
|
|
55538
55538
|
if (ports.now() >= deadline) {
|
|
55539
55539
|
const lastError = state?.lastError;
|
|
55540
55540
|
throw new HeadroomStartError(
|
|
55541
|
-
`
|
|
55541
|
+
`agent-shim: the headroom daemon did not become ready within ${String(HEADROOM_START_TIMEOUT_MS)}ms` + (lastError === void 0 ? "" : ` (last error: ${lastError})`) + `. Daemon log: ${paths.headroomLogPath}`
|
|
55542
55542
|
);
|
|
55543
55543
|
}
|
|
55544
55544
|
ports.sleep(HEADROOM_LAUNCHER_POLL_MS);
|
|
@@ -55780,7 +55780,7 @@ function spawnDetachedSupervisor(paths, subcommand, logPath) {
|
|
|
55780
55780
|
const logFd = import_node_fs3.default.openSync(logPath, "a");
|
|
55781
55781
|
try {
|
|
55782
55782
|
const invocation = selfInvocation([subcommand]);
|
|
55783
|
-
const child = (0, import_node_child_process2.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env,
|
|
55783
|
+
const child = (0, import_node_child_process2.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
|
|
55784
55784
|
child.unref();
|
|
55785
55785
|
if (child.pid === void 0) {
|
|
55786
55786
|
throw new Error(`spawning ${subcommand} returned no pid`);
|
|
@@ -55974,7 +55974,7 @@ var ClaudeShimStateSchema = external_exports.strictObject({
|
|
|
55974
55974
|
var ForeignClaudeEntryError = class extends CliError {
|
|
55975
55975
|
constructor(targetPath, action) {
|
|
55976
55976
|
super(
|
|
55977
|
-
`${targetPath} already exists and does not look like something
|
|
55977
|
+
`${targetPath} already exists and does not look like something agent-shim created. Refusing to ${action === "enable" ? "overwrite" : "remove"} it automatically \u2014 inspect it yourself, or pass --force if you're sure.`
|
|
55978
55978
|
);
|
|
55979
55979
|
this.targetPath = targetPath;
|
|
55980
55980
|
this.action = action;
|
|
@@ -55986,7 +55986,7 @@ var ForeignClaudeEntryError = class extends CliError {
|
|
|
55986
55986
|
var UnsupportedShimSourceError = class extends CliError {
|
|
55987
55987
|
constructor(contentSourcePath) {
|
|
55988
55988
|
super(
|
|
55989
|
-
`Cannot create a working \`claude\` command from ${contentSourcePath} on Windows: an npm-installed
|
|
55989
|
+
`Cannot create a working \`claude\` command from ${contentSourcePath} on Windows: an npm-installed agent-shim running under Node.js has no .exe to hardlink/copy, and Windows has no shebang-based dispatch the way POSIX does. Install agent-shim via Scoop instead (see README), which ships a real agent-shim.exe this command can link from.`
|
|
55990
55990
|
);
|
|
55991
55991
|
this.contentSourcePath = contentSourcePath;
|
|
55992
55992
|
this.name = "UnsupportedShimSourceError";
|
|
@@ -56100,11 +56100,11 @@ function registerShimCommand(program2, deps) {
|
|
|
56100
56100
|
const { paths } = deps;
|
|
56101
56101
|
const shim = withExamples(
|
|
56102
56102
|
program2.command("shim").description(
|
|
56103
|
-
"Manage the `claude` command shim: an optional, explicit way to also invoke this launcher as `claude` instead of `
|
|
56103
|
+
"Manage the `claude` command shim: an optional, explicit way to also invoke this launcher as `claude` instead of `agent-shim run`. Off by default; every installer ships only `agent-shim`."
|
|
56104
56104
|
),
|
|
56105
|
-
["
|
|
56105
|
+
["agent-shim shim enable", "agent-shim shim disable"]
|
|
56106
56106
|
);
|
|
56107
|
-
const enable = shim.command("enable").description("Create a `claude`-named copy of this same executable, alongside
|
|
56107
|
+
const enable = shim.command("enable").description("Create a `claude`-named copy of this same executable, alongside agent-shim by default.").option("--dir <path>", "Enable into this directory instead of alongside the running agent-shim executable.").option("--force", "Overwrite the target even if it doesn't look like agent-shim's own doing.").action((options) => {
|
|
56108
56108
|
const ownExecutablePath = realOwnExecutablePath();
|
|
56109
56109
|
const contentSourcePath = realContentSourcePath();
|
|
56110
56110
|
const result = enableClaudeShim({
|
|
@@ -56123,15 +56123,15 @@ function registerShimCommand(program2, deps) {
|
|
|
56123
56123
|
findExecutableInDir
|
|
56124
56124
|
});
|
|
56125
56125
|
if (shadow.status === "not-on-path") {
|
|
56126
|
-
console.warn(`warning: ${import_node_path7.default.dirname(result.targetPath)} is not on PATH \u2014 add it, or use \`
|
|
56126
|
+
console.warn(`warning: ${import_node_path7.default.dirname(result.targetPath)} is not on PATH \u2014 add it, or use \`agent-shim run\` instead.`);
|
|
56127
56127
|
} else if (shadow.status === "shadowed") {
|
|
56128
56128
|
console.warn(
|
|
56129
56129
|
`warning: 'claude' on PATH currently resolves to ${shadow.by}, not ${result.targetPath}. Put ${import_node_path7.default.dirname(result.targetPath)} ahead of it on PATH.`
|
|
56130
56130
|
);
|
|
56131
56131
|
}
|
|
56132
56132
|
});
|
|
56133
|
-
withExamples(enable, ["
|
|
56134
|
-
const disable = shim.command("disable").description("Remove the `claude` command shim `shim enable` previously created. A no-op, not an error, if none is enabled.").option("--dir <path>", "Look in this directory instead of trusting the recorded location.").option("--force", "Remove the target even if it doesn't look like
|
|
56133
|
+
withExamples(enable, ["agent-shim shim enable", "agent-shim shim enable --dir ~/bin"]);
|
|
56134
|
+
const disable = shim.command("disable").description("Remove the `claude` command shim `shim enable` previously created. A no-op, not an error, if none is enabled.").option("--dir <path>", "Look in this directory instead of trusting the recorded location.").option("--force", "Remove the target even if it doesn't look like agent-shim's own doing.").action((options) => {
|
|
56135
56135
|
const ownExecutablePath = realOwnExecutablePath();
|
|
56136
56136
|
const contentSourcePath = realContentSourcePath();
|
|
56137
56137
|
const result = disableClaudeShim({
|
|
@@ -56145,11 +56145,37 @@ function registerShimCommand(program2, deps) {
|
|
|
56145
56145
|
result.action === "disabled" ? `Removed \`claude\` at ${result.targetPath}.` : `No \`claude\` command enabled at ${result.targetPath}; nothing to do.`
|
|
56146
56146
|
);
|
|
56147
56147
|
});
|
|
56148
|
-
withExamples(disable, ["
|
|
56148
|
+
withExamples(disable, ["agent-shim shim disable"]);
|
|
56149
|
+
}
|
|
56150
|
+
|
|
56151
|
+
// src/legacy.ts
|
|
56152
|
+
var ENV_PREFIX = "AGENT_SHIM_";
|
|
56153
|
+
var LEGACY_ENV_PREFIX = "CLAUDE_USE_";
|
|
56154
|
+
var HOME_DIRNAME = ".agent-shim";
|
|
56155
|
+
var LEGACY_HOME_DIRNAME = ".claude-use";
|
|
56156
|
+
var LEGACY_PORTABLE_CONFIG_FILENAME = ".claude-use.json";
|
|
56157
|
+
var LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME = ".claude-use.local.json";
|
|
56158
|
+
var LEGACY_FARM_MANIFEST_FILENAME = ".claude-use-farm.json";
|
|
56159
|
+
var LEGACY_COMMAND_NAME = "claude-use";
|
|
56160
|
+
function aliasLegacyEnv(env) {
|
|
56161
|
+
const aliased = [];
|
|
56162
|
+
for (const name of Object.keys(env).sort()) {
|
|
56163
|
+
if (!name.startsWith(LEGACY_ENV_PREFIX)) {
|
|
56164
|
+
continue;
|
|
56165
|
+
}
|
|
56166
|
+
const value = env[name];
|
|
56167
|
+
const current = `${ENV_PREFIX}${name.slice(LEGACY_ENV_PREFIX.length)}`;
|
|
56168
|
+
if (value === void 0 || env[current] !== void 0) {
|
|
56169
|
+
continue;
|
|
56170
|
+
}
|
|
56171
|
+
env[current] = value;
|
|
56172
|
+
aliased.push(name);
|
|
56173
|
+
}
|
|
56174
|
+
return aliased;
|
|
56149
56175
|
}
|
|
56150
56176
|
|
|
56151
56177
|
// src/configure.ts
|
|
56152
|
-
var
|
|
56178
|
+
var import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
56153
56179
|
var import_node_os4 = __toESM(require("node:os"), 1);
|
|
56154
56180
|
var import_node_path19 = __toESM(require("node:path"), 1);
|
|
56155
56181
|
|
|
@@ -57469,7 +57495,7 @@ function collectCredentialSource(value, previous = []) {
|
|
|
57469
57495
|
}
|
|
57470
57496
|
function addCredentialCacheOptions(command) {
|
|
57471
57497
|
return command.option("--credential-cache-ttl <ttl>", "Keep the resolved credential for this long (a whole number and s, m, h or d, for example 12h) so a launch need not re-run a source that needs a person. Enables caching.").addOption(
|
|
57472
|
-
new Option("--credential-cache-store <store>", "Where the cached credential is kept: keychain (macOS login Keychain, the default there) or file (mode 0600 under the
|
|
57498
|
+
new Option("--credential-cache-store <store>", "Where the cached credential is kept: keychain (macOS login Keychain, the default there) or file (mode 0600 under the agent-shim home, the default elsewhere). Enables caching.").choices(
|
|
57473
57499
|
CREDENTIAL_CACHE_STORES
|
|
57474
57500
|
)
|
|
57475
57501
|
).option("--credential-cache", "Cache this credential in the default store with no expiry (add --credential-cache-ttl for one).").option("--no-credential-cache", "Stop caching this credential. Run `credential forget` first to drop the stored copy.");
|
|
@@ -57646,7 +57672,7 @@ function trySource(source, params) {
|
|
|
57646
57672
|
}
|
|
57647
57673
|
function warmCommandFor(subject) {
|
|
57648
57674
|
const [kind, name] = subject.split(" ");
|
|
57649
|
-
return kind === "provider" ? `
|
|
57675
|
+
return kind === "provider" ? `agent-shim credential warm --provider ${name ?? ""}` : `agent-shim credential warm ${name ?? ""}`;
|
|
57650
57676
|
}
|
|
57651
57677
|
function resolveCredential(params) {
|
|
57652
57678
|
const target = params.credential.target ?? "bearer";
|
|
@@ -57672,11 +57698,11 @@ function resolveCredential(params) {
|
|
|
57672
57698
|
const line = `${describeSource(source)} ${outcome.reason}`;
|
|
57673
57699
|
attempts.push(line);
|
|
57674
57700
|
if (outcome.warn) {
|
|
57675
|
-
warnings.push(`
|
|
57701
|
+
warnings.push(`agent-shim: ${params.subject}: skipped ${line}`);
|
|
57676
57702
|
}
|
|
57677
57703
|
}
|
|
57678
57704
|
const hint = cacheBlock === void 0 ? "" : `; fill the cache from a terminal with \`${warmCommandFor(params.subject)}\``;
|
|
57679
|
-
return { ok: false, message: `
|
|
57705
|
+
return { ok: false, message: `agent-shim: ${params.subject} has no usable credential: ${attempts.join("; ")}${hint}` };
|
|
57680
57706
|
}
|
|
57681
57707
|
function credentialVariables(target, token) {
|
|
57682
57708
|
return {
|
|
@@ -58248,7 +58274,7 @@ function resolveEntry(relPath, params) {
|
|
|
58248
58274
|
diagnostics.push({
|
|
58249
58275
|
code: "UNCLASSIFIED_ENTRY",
|
|
58250
58276
|
severity: "warning",
|
|
58251
|
-
message: `"${head}" is not in the category map, so it is excluded. Run \`
|
|
58277
|
+
message: `"${head}" is not in the category map, so it is excluded. Run \`agent-shim configure\` to classify it, which records the answer in the local overlay without touching the shipped default map.`,
|
|
58252
58278
|
subject: head
|
|
58253
58279
|
});
|
|
58254
58280
|
return { decision: { relPath, shared: false, via: "unclassified", category }, diagnostics };
|
|
@@ -58664,7 +58690,7 @@ var DEFAULT_MAX_ATTEMPTS = 200;
|
|
|
58664
58690
|
var IdentityLockBusyError = class extends CliError {
|
|
58665
58691
|
constructor(identity, lockPath, holderPid) {
|
|
58666
58692
|
super(
|
|
58667
|
-
`Another
|
|
58693
|
+
`Another agent-shim resync is already running for identity "${identity}"` + (holderPid === void 0 ? "" : ` (pid ${String(holderPid)})`) + `. Its lock at ${lockPath} was still held after the full retry budget; nothing was changed.`
|
|
58668
58694
|
);
|
|
58669
58695
|
this.identity = identity;
|
|
58670
58696
|
this.lockPath = lockPath;
|
|
@@ -58743,7 +58769,7 @@ function acquireIdentityLock(params) {
|
|
|
58743
58769
|
}
|
|
58744
58770
|
|
|
58745
58771
|
// src/launcher/farm.ts
|
|
58746
|
-
var FARM_MANIFEST_FILENAME = ".
|
|
58772
|
+
var FARM_MANIFEST_FILENAME = ".agent-shim-farm.json";
|
|
58747
58773
|
var FarmManifestSchema = external_exports.strictObject({
|
|
58748
58774
|
version: external_exports.literal(1),
|
|
58749
58775
|
builtAtMs: external_exports.number(),
|
|
@@ -58754,8 +58780,8 @@ var FarmManifestSchema = external_exports.strictObject({
|
|
|
58754
58780
|
materialised: external_exports.array(external_exports.string()),
|
|
58755
58781
|
links: external_exports.array(external_exports.strictObject({ rel: external_exports.string(), target: external_exports.string() }))
|
|
58756
58782
|
});
|
|
58757
|
-
function readFarmManifest(
|
|
58758
|
-
const raw =
|
|
58783
|
+
function readFarmManifest(fs17, farmRoot) {
|
|
58784
|
+
const raw = fs17.readFileUtf8(import_node_path11.default.join(farmRoot, FARM_MANIFEST_FILENAME)) ?? fs17.readFileUtf8(import_node_path11.default.join(farmRoot, LEGACY_FARM_MANIFEST_FILENAME));
|
|
58759
58785
|
if (raw === void 0) {
|
|
58760
58786
|
return void 0;
|
|
58761
58787
|
}
|
|
@@ -58813,9 +58839,9 @@ function buildEntryFacts(params) {
|
|
|
58813
58839
|
entries
|
|
58814
58840
|
};
|
|
58815
58841
|
}
|
|
58816
|
-
function listSubtree(
|
|
58842
|
+
function listSubtree(fs17, root, rel) {
|
|
58817
58843
|
const absolute = import_node_path11.default.join(root, rel);
|
|
58818
|
-
const stat =
|
|
58844
|
+
const stat = fs17.lstat(absolute);
|
|
58819
58845
|
if (stat === void 0) {
|
|
58820
58846
|
return [];
|
|
58821
58847
|
}
|
|
@@ -58823,10 +58849,10 @@ function listSubtree(fs16, root, rel) {
|
|
|
58823
58849
|
return [{ rel, kind: "symlink" }];
|
|
58824
58850
|
}
|
|
58825
58851
|
if (stat.kind === "dir") {
|
|
58826
|
-
const children = [...
|
|
58852
|
+
const children = [...fs17.readdir(absolute)].sort().flatMap((name) => listSubtree(fs17, root, `${rel}/${name}`));
|
|
58827
58853
|
return [{ rel, kind: "dir" }, ...children];
|
|
58828
58854
|
}
|
|
58829
|
-
const contentHash =
|
|
58855
|
+
const contentHash = fs17.hashFile(absolute);
|
|
58830
58856
|
return [{ rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } }];
|
|
58831
58857
|
}
|
|
58832
58858
|
function topLevelScopeRoots(roots) {
|
|
@@ -58840,25 +58866,25 @@ function topLevelScopeRoots(roots) {
|
|
|
58840
58866
|
}
|
|
58841
58867
|
return kept;
|
|
58842
58868
|
}
|
|
58843
|
-
function reconciliationScope(
|
|
58869
|
+
function reconciliationScope(fs17, farmRoot, manifest) {
|
|
58844
58870
|
if (manifest !== void 0) {
|
|
58845
58871
|
return topLevelScopeRoots(manifest.materialised);
|
|
58846
58872
|
}
|
|
58847
|
-
return [...
|
|
58873
|
+
return [...fs17.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && name !== LEGACY_FARM_MANIFEST_FILENAME && fs17.lstat(import_node_path11.default.join(farmRoot, name))?.kind === "dir").sort();
|
|
58848
58874
|
}
|
|
58849
|
-
function collectFarmListing(
|
|
58850
|
-
return scopeRoots.flatMap((root) => listSubtree(
|
|
58875
|
+
function collectFarmListing(fs17, farmRoot, scopeRoots) {
|
|
58876
|
+
return scopeRoots.flatMap((root) => listSubtree(fs17, farmRoot, root));
|
|
58851
58877
|
}
|
|
58852
|
-
function collectCanonicalCounterparts(
|
|
58878
|
+
function collectCanonicalCounterparts(fs17, claudeHome, farmListing) {
|
|
58853
58879
|
const out = [];
|
|
58854
58880
|
for (const entry of farmListing) {
|
|
58855
58881
|
const absolute = import_node_path11.default.join(claudeHome, entry.rel);
|
|
58856
|
-
const stat =
|
|
58882
|
+
const stat = fs17.lstat(absolute);
|
|
58857
58883
|
if (stat === void 0) {
|
|
58858
58884
|
continue;
|
|
58859
58885
|
}
|
|
58860
58886
|
if (stat.kind === "file") {
|
|
58861
|
-
const contentHash =
|
|
58887
|
+
const contentHash = fs17.hashFile(absolute);
|
|
58862
58888
|
out.push({ rel: entry.rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } });
|
|
58863
58889
|
continue;
|
|
58864
58890
|
}
|
|
@@ -58868,7 +58894,7 @@ function collectCanonicalCounterparts(fs16, claudeHome, farmListing) {
|
|
|
58868
58894
|
}
|
|
58869
58895
|
function carryOver(params) {
|
|
58870
58896
|
const manifest = readFarmManifest(params.fs, params.previousRoot);
|
|
58871
|
-
const accounted = /* @__PURE__ */ new Set([FARM_MANIFEST_FILENAME]);
|
|
58897
|
+
const accounted = /* @__PURE__ */ new Set([FARM_MANIFEST_FILENAME, LEGACY_FARM_MANIFEST_FILENAME]);
|
|
58872
58898
|
for (const rel of manifest?.materialised ?? []) {
|
|
58873
58899
|
const head = rel.split("/")[0];
|
|
58874
58900
|
if (head !== void 0 && head !== "") {
|
|
@@ -59166,7 +59192,7 @@ function resyncFarm(params) {
|
|
|
59166
59192
|
diagnostics.push({
|
|
59167
59193
|
code: "FARM_PREVIOUS_RETAINED",
|
|
59168
59194
|
severity: "warning",
|
|
59169
|
-
message: `The superseded farm was left at ${swap.retainedPrevious} because it still holds ${swap.collided.join(", ")}, which the new farm has its own entry for. Nothing was overwritten in either direction; run \`
|
|
59195
|
+
message: `The superseded farm was left at ${swap.retainedPrevious} because it still holds ${swap.collided.join(", ")}, which the new farm has its own entry for. Nothing was overwritten in either direction; run \`agent-shim identity resolve-conflicts ${params.identity}\` to resolve it interactively.`,
|
|
59170
59196
|
subject: swap.retainedPrevious
|
|
59171
59197
|
});
|
|
59172
59198
|
}
|
|
@@ -59203,7 +59229,7 @@ function recoveryDiagnostics(recovery, identity) {
|
|
|
59203
59229
|
}
|
|
59204
59230
|
if (recovery.retained.length > 0) {
|
|
59205
59231
|
parts.push(
|
|
59206
|
-
`kept ${recovery.retained.join(", ")}, which still holds data the current farm also has an entry for \u2014 run \`
|
|
59232
|
+
`kept ${recovery.retained.join(", ")}, which still holds data the current farm also has an entry for \u2014 run \`agent-shim identity resolve-conflicts ${identity}\` to resolve it interactively`
|
|
59207
59233
|
);
|
|
59208
59234
|
}
|
|
59209
59235
|
return [
|
|
@@ -59348,7 +59374,7 @@ function parseDurationOption(value) {
|
|
|
59348
59374
|
// src/configProfiles.ts
|
|
59349
59375
|
var ProfileNotFoundError = class extends CliError {
|
|
59350
59376
|
constructor(profileName) {
|
|
59351
|
-
super(`No configuration profile named "${profileName}". Run \`
|
|
59377
|
+
super(`No configuration profile named "${profileName}". Run \`agent-shim profile add ${profileName}\` first.`);
|
|
59352
59378
|
this.profileName = profileName;
|
|
59353
59379
|
this.name = "ProfileNotFoundError";
|
|
59354
59380
|
}
|
|
@@ -59535,7 +59561,7 @@ function registerProfileCommand(program2, deps) {
|
|
|
59535
59561
|
const { paths } = deps;
|
|
59536
59562
|
const profile = withExamples(
|
|
59537
59563
|
program2.command("profile").description("Manage configuration profiles: named, reusable rules for what an identity shares with ~/.claude."),
|
|
59538
|
-
["
|
|
59564
|
+
["agent-shim profile add client-acme", "agent-shim profile list"]
|
|
59539
59565
|
);
|
|
59540
59566
|
withExamples(
|
|
59541
59567
|
profile.command("add [name]").description(
|
|
@@ -59556,7 +59582,7 @@ function registerProfileCommand(program2, deps) {
|
|
|
59556
59582
|
createProfile(paths, name, options.extends, options.description);
|
|
59557
59583
|
console.log(`Created configuration profile "${name}".`);
|
|
59558
59584
|
}),
|
|
59559
|
-
["
|
|
59585
|
+
["agent-shim profile add client-acme", "agent-shim profile add client-acme --extends work-default --extends strict"]
|
|
59560
59586
|
);
|
|
59561
59587
|
withExamples(
|
|
59562
59588
|
profile.command("set <name>").description(
|
|
@@ -59578,9 +59604,9 @@ function registerProfileCommand(program2, deps) {
|
|
|
59578
59604
|
console.log(`Updated configuration profile "${name}".`);
|
|
59579
59605
|
}),
|
|
59580
59606
|
[
|
|
59581
|
-
"
|
|
59582
|
-
'
|
|
59583
|
-
"
|
|
59607
|
+
"agent-shim profile set client-acme --category history=false --category knowledge=true",
|
|
59608
|
+
'agent-shim profile set client-acme --entry "knowledge/skills/commit=false"',
|
|
59609
|
+
"agent-shim profile set client-acme --launch-headroom --launch-provider z"
|
|
59584
59610
|
]
|
|
59585
59611
|
);
|
|
59586
59612
|
withExamples(
|
|
@@ -59592,7 +59618,7 @@ function registerProfileCommand(program2, deps) {
|
|
|
59592
59618
|
return;
|
|
59593
59619
|
}
|
|
59594
59620
|
if (entries.length === 0) {
|
|
59595
|
-
console.log("No configuration profiles yet. Run `
|
|
59621
|
+
console.log("No configuration profiles yet. Run `agent-shim profile add <name>` to create one.");
|
|
59596
59622
|
return;
|
|
59597
59623
|
}
|
|
59598
59624
|
for (const entry of entries) {
|
|
@@ -59601,7 +59627,7 @@ function registerProfileCommand(program2, deps) {
|
|
|
59601
59627
|
console.log(`${marker}${entry.name}${extendsSuffix}`);
|
|
59602
59628
|
}
|
|
59603
59629
|
}),
|
|
59604
|
-
["
|
|
59630
|
+
["agent-shim profile list", "agent-shim profile list --json"]
|
|
59605
59631
|
);
|
|
59606
59632
|
withExamples(
|
|
59607
59633
|
profile.command("show <name>").description("Show one configuration profile's contents.").option("--json", "Print the profile as JSON.").action((name, options) => {
|
|
@@ -59628,16 +59654,16 @@ function registerProfileCommand(program2, deps) {
|
|
|
59628
59654
|
console.log(`${label}: ${pairs.length === 0 ? "(none)" : pairs.map(([key, setting]) => `${key}=${JSON.stringify(setting)}`).join(", ")}`);
|
|
59629
59655
|
}
|
|
59630
59656
|
}),
|
|
59631
|
-
["
|
|
59657
|
+
["agent-shim profile show client-acme", "agent-shim profile show client-acme --json"]
|
|
59632
59658
|
);
|
|
59633
59659
|
withExamples(
|
|
59634
|
-
profile.command("remove <name>").description("Delete a configuration profile's file. References to it by name are left for `
|
|
59660
|
+
profile.command("remove <name>").description("Delete a configuration profile's file. References to it by name are left for `agent-shim doctor` to report.").option("--yes", "Remove without asking for confirmation (required when standard input is not a terminal).").action(async (name, options) => {
|
|
59635
59661
|
requireProfileExists(paths, name);
|
|
59636
59662
|
await confirmRemoval(deps, options.yes, `configuration profile "${name}"`);
|
|
59637
59663
|
removeProfile(paths, name);
|
|
59638
59664
|
console.log(`Removed configuration profile "${name}".`);
|
|
59639
59665
|
}),
|
|
59640
|
-
["
|
|
59666
|
+
["agent-shim profile remove client-acme --yes"]
|
|
59641
59667
|
);
|
|
59642
59668
|
withExamples(
|
|
59643
59669
|
profile.command("use <name>").description("Make a configuration profile the global default, used when no directory rule or identity selects one.").action(async (name) => {
|
|
@@ -59645,7 +59671,7 @@ function registerProfileCommand(program2, deps) {
|
|
|
59645
59671
|
setGlobalDefaultProfile(paths, name);
|
|
59646
59672
|
console.log(`Global default configuration profile is now "${name}".`);
|
|
59647
59673
|
}),
|
|
59648
|
-
["
|
|
59674
|
+
["agent-shim profile use work-default"]
|
|
59649
59675
|
);
|
|
59650
59676
|
}
|
|
59651
59677
|
|
|
@@ -59668,8 +59694,8 @@ function decideIdentity(params) {
|
|
|
59668
59694
|
if (isNonEmpty(params.argv0Identity)) {
|
|
59669
59695
|
return selected(params.argv0Identity, "argv");
|
|
59670
59696
|
}
|
|
59671
|
-
if (isNonEmpty(params.env.
|
|
59672
|
-
return selected(params.env.
|
|
59697
|
+
if (isNonEmpty(params.env.AGENT_SHIM_IDENTITY)) {
|
|
59698
|
+
return selected(params.env.AGENT_SHIM_IDENTITY, "env");
|
|
59673
59699
|
}
|
|
59674
59700
|
if (isNonEmpty(params.directoryPinnedIdentity)) {
|
|
59675
59701
|
return selected(params.directoryPinnedIdentity, "directory-pin");
|
|
@@ -59684,8 +59710,8 @@ function decideConfigProfile(params) {
|
|
|
59684
59710
|
if (isNonEmpty(params.cliFlagConfigProfile)) {
|
|
59685
59711
|
return { name: params.cliFlagConfigProfile, source: "cli-flag" };
|
|
59686
59712
|
}
|
|
59687
|
-
if (isNonEmpty(params.env.
|
|
59688
|
-
return { name: params.env.
|
|
59713
|
+
if (isNonEmpty(params.env.AGENT_SHIM_CONFIG_PROFILE)) {
|
|
59714
|
+
return { name: params.env.AGENT_SHIM_CONFIG_PROFILE, source: "env" };
|
|
59689
59715
|
}
|
|
59690
59716
|
if (isNonEmpty(params.directoryRuleConfigProfile)) {
|
|
59691
59717
|
return { name: params.directoryRuleConfigProfile, source: "directory-rule" };
|
|
@@ -59698,14 +59724,14 @@ function decideConfigProfile(params) {
|
|
|
59698
59724
|
}
|
|
59699
59725
|
return { source: "none" };
|
|
59700
59726
|
}
|
|
59701
|
-
function loadIdentity(identitiesDir, name,
|
|
59702
|
-
return loadConfigFile(import_node_path14.default.join(identitiesDir, name, "identity.json"), IdentitySchema,
|
|
59727
|
+
function loadIdentity(identitiesDir, name, fs17) {
|
|
59728
|
+
return loadConfigFile(import_node_path14.default.join(identitiesDir, name, "identity.json"), IdentitySchema, fs17.readConfigFile);
|
|
59703
59729
|
}
|
|
59704
59730
|
|
|
59705
59731
|
// src/poolStore.ts
|
|
59706
59732
|
var PoolNotFoundError = class extends CliError {
|
|
59707
59733
|
constructor(poolName) {
|
|
59708
|
-
super(`No pool named "${poolName}". Run \`
|
|
59734
|
+
super(`No pool named "${poolName}". Run \`agent-shim pool add ${poolName} --identity <name>...\` first.`);
|
|
59709
59735
|
this.poolName = poolName;
|
|
59710
59736
|
this.name = "PoolNotFoundError";
|
|
59711
59737
|
}
|
|
@@ -59713,7 +59739,7 @@ var PoolNotFoundError = class extends CliError {
|
|
|
59713
59739
|
};
|
|
59714
59740
|
var PoolAlreadyExistsError = class extends CliError {
|
|
59715
59741
|
constructor(poolName) {
|
|
59716
|
-
super(`A pool named "${poolName}" already exists. Use \`
|
|
59742
|
+
super(`A pool named "${poolName}" already exists. Use \`agent-shim pool set ${poolName}\` to change its members.`);
|
|
59717
59743
|
this.poolName = poolName;
|
|
59718
59744
|
this.name = "PoolAlreadyExistsError";
|
|
59719
59745
|
}
|
|
@@ -59767,7 +59793,7 @@ function removePool(paths, name) {
|
|
|
59767
59793
|
// src/identityManager.ts
|
|
59768
59794
|
var IdentityNotFoundError = class extends CliError {
|
|
59769
59795
|
constructor(name) {
|
|
59770
|
-
super(`No identity named "${name}". Run \`
|
|
59796
|
+
super(`No identity named "${name}". Run \`agent-shim identity add ${name}\` first.`);
|
|
59771
59797
|
this.name = name;
|
|
59772
59798
|
this.name = "IdentityNotFoundError";
|
|
59773
59799
|
}
|
|
@@ -59995,14 +60021,14 @@ function registerIdentityCommand(program2, deps) {
|
|
|
59995
60021
|
const { paths } = deps;
|
|
59996
60022
|
const identity = withExamples(
|
|
59997
60023
|
program2.command("identity").description("Manage identities: each one is a separate Claude Code login with its own credentials."),
|
|
59998
|
-
["
|
|
60024
|
+
["agent-shim identity add work", "agent-shim identity list"]
|
|
59999
60025
|
);
|
|
60000
60026
|
withExamples(
|
|
60001
60027
|
identity.command("add <name>").description("Create a new identity. Fails if one with this name already exists.").action((name) => {
|
|
60002
60028
|
addIdentity(paths, name);
|
|
60003
60029
|
console.log(`Created identity "${name}".`);
|
|
60004
60030
|
}),
|
|
60005
|
-
["
|
|
60031
|
+
["agent-shim identity add work"]
|
|
60006
60032
|
);
|
|
60007
60033
|
withExamples(
|
|
60008
60034
|
identity.command("list").description("List every identity, marking the active one with *.").option("--json", "Print the identities as JSON.").action((options) => {
|
|
@@ -60012,17 +60038,17 @@ function registerIdentityCommand(program2, deps) {
|
|
|
60012
60038
|
return;
|
|
60013
60039
|
}
|
|
60014
60040
|
if (entries.length === 0) {
|
|
60015
|
-
console.log("No identities yet. Run `
|
|
60041
|
+
console.log("No identities yet. Run `agent-shim identity add <name>` to create one.");
|
|
60016
60042
|
return;
|
|
60017
60043
|
}
|
|
60018
60044
|
for (const entry of entries) {
|
|
60019
60045
|
console.log(formatIdentityLine(entry));
|
|
60020
60046
|
}
|
|
60021
60047
|
if (entries.some((entry) => entry.problem !== void 0)) {
|
|
60022
|
-
console.log("\nRun `
|
|
60048
|
+
console.log("\nRun `agent-shim doctor` for the full detail on every unreadable entry.");
|
|
60023
60049
|
}
|
|
60024
60050
|
}),
|
|
60025
|
-
["
|
|
60051
|
+
["agent-shim identity list", "agent-shim identity list --json"]
|
|
60026
60052
|
);
|
|
60027
60053
|
withExamples(
|
|
60028
60054
|
identity.command("show <name>").description("Show one identity's settings and directory.").option("--json", "Print the identity as JSON.").action((name, options) => {
|
|
@@ -60045,7 +60071,7 @@ function registerIdentityCommand(program2, deps) {
|
|
|
60045
60071
|
console.log(`Allows ambient credential: ${view.allowAmbientCredential === true ? "yes" : "no"}`);
|
|
60046
60072
|
console.log(`Credential: ${entry.identity?.credential === void 0 ? "(none; uses its stored login)" : describeCredential(entry.identity.credential)}`);
|
|
60047
60073
|
}),
|
|
60048
|
-
["
|
|
60074
|
+
["agent-shim identity show work", "agent-shim identity show work --json"]
|
|
60049
60075
|
);
|
|
60050
60076
|
const identitySet = identity.command("set <name>").description("Update an identity's settings.").option("--default-profile <profile>", "Configuration profile this identity uses when nothing more specific selects one.").option("--no-default-profile", "Clear this identity's default configuration profile.").option("--allow-ambient-credential", "Allow this identity to launch even with an ambient credential env var set.").option("--no-allow-ambient-credential", "Disallow ambient credential env vars for this identity (the default).").option(
|
|
60051
60077
|
"--credential <source>",
|
|
@@ -60100,10 +60126,10 @@ function registerIdentityCommand(program2, deps) {
|
|
|
60100
60126
|
}
|
|
60101
60127
|
}),
|
|
60102
60128
|
[
|
|
60103
|
-
"
|
|
60104
|
-
"
|
|
60105
|
-
"
|
|
60106
|
-
"
|
|
60129
|
+
"agent-shim identity set work --default-profile client-acme",
|
|
60130
|
+
"agent-shim identity set work --allow-ambient-credential",
|
|
60131
|
+
"agent-shim identity set work --credential-target oauthToken --credential op:op://vault/claude-work/token",
|
|
60132
|
+
"agent-shim identity set work --no-credential"
|
|
60107
60133
|
]
|
|
60108
60134
|
);
|
|
60109
60135
|
withExamples(
|
|
@@ -60117,13 +60143,13 @@ function registerIdentityCommand(program2, deps) {
|
|
|
60117
60143
|
removeIdentity(paths, name);
|
|
60118
60144
|
console.log(`Removed identity "${name}".`);
|
|
60119
60145
|
}),
|
|
60120
|
-
["
|
|
60146
|
+
["agent-shim identity remove old-client --yes"]
|
|
60121
60147
|
);
|
|
60122
60148
|
withExamples(
|
|
60123
60149
|
identity.command("use <name>").description("Select the active identity, used by every launch that names none. Offers to create it on a terminal if it does not exist.").action(async (name) => {
|
|
60124
60150
|
await selectIdentity(deps, name);
|
|
60125
60151
|
}),
|
|
60126
|
-
["
|
|
60152
|
+
["agent-shim identity use work", "agent-shim @work"]
|
|
60127
60153
|
);
|
|
60128
60154
|
withExamples(
|
|
60129
60155
|
identity.command("resolve-conflicts <name>").description("Interactively resolve data a superseded farm left behind when it collides with the current farm's copy.").action(async (name) => {
|
|
@@ -60162,7 +60188,7 @@ function registerIdentityCommand(program2, deps) {
|
|
|
60162
60188
|
`Resolved ${String(result.resolved.length)} conflict(s): ${String(result.removed.length)} superseded director(ies) fully cleared, ${String(result.retained.length)} still retained pending a skipped conflict.`
|
|
60163
60189
|
);
|
|
60164
60190
|
}),
|
|
60165
|
-
["
|
|
60191
|
+
["agent-shim identity resolve-conflicts work"]
|
|
60166
60192
|
);
|
|
60167
60193
|
}
|
|
60168
60194
|
|
|
@@ -60183,7 +60209,7 @@ var DirectoryRuleMissingTargetError = class extends CliError {
|
|
|
60183
60209
|
};
|
|
60184
60210
|
var DirectoryRuleAlreadyExistsError = class extends CliError {
|
|
60185
60211
|
constructor(rulePath) {
|
|
60186
|
-
super(`A directory rule for path "${rulePath}" already exists. Use \`
|
|
60212
|
+
super(`A directory rule for path "${rulePath}" already exists. Use \`agent-shim rule set\` to change it.`);
|
|
60187
60213
|
this.rulePath = rulePath;
|
|
60188
60214
|
this.name = "DirectoryRuleAlreadyExistsError";
|
|
60189
60215
|
}
|
|
@@ -60271,7 +60297,7 @@ function registerRuleCommand(program2, deps) {
|
|
|
60271
60297
|
const { paths } = deps;
|
|
60272
60298
|
const rule = withExamples(
|
|
60273
60299
|
program2.command("rule").description("Manage directory rules: pin an identity or configuration profile to every launch under a path."),
|
|
60274
|
-
["
|
|
60300
|
+
["agent-shim rule add ~/work/acme --config-profile client-acme", "agent-shim rule list"]
|
|
60275
60301
|
);
|
|
60276
60302
|
withExamples(
|
|
60277
60303
|
rule.command("add <path>").description("Add a directory rule for a path. Fails if a rule for that exact path already exists.").option("--config-profile <profile>", "Configuration profile to select under this path.").option("--identity <identity>", "Identity to pin under this path.").action(async (rulePath, options) => {
|
|
@@ -60279,7 +60305,7 @@ function registerRuleCommand(program2, deps) {
|
|
|
60279
60305
|
addDirectoryRule(paths, rulePath, options);
|
|
60280
60306
|
console.log(`Added directory rule for "${rulePath}".`);
|
|
60281
60307
|
}),
|
|
60282
|
-
["
|
|
60308
|
+
["agent-shim rule add ~/work/acme --config-profile client-acme", "agent-shim rule add ~/personal --identity personal"]
|
|
60283
60309
|
);
|
|
60284
60310
|
withExamples(
|
|
60285
60311
|
rule.command("set <path>").description("Update the directory rule for a path.").option("--config-profile <profile>", "Configuration profile to select under this path.").option("--no-config-profile", "Stop selecting a configuration profile under this path.").option("--identity <identity>", "Identity to pin under this path.").option("--no-identity", "Stop pinning an identity under this path.").action(async (rulePath, options) => {
|
|
@@ -60290,7 +60316,7 @@ function registerRuleCommand(program2, deps) {
|
|
|
60290
60316
|
updateDirectoryRule(paths, rulePath, options);
|
|
60291
60317
|
console.log(`Updated directory rule for "${rulePath}".`);
|
|
60292
60318
|
}),
|
|
60293
|
-
["
|
|
60319
|
+
["agent-shim rule set ~/work/acme --identity work", "agent-shim rule set ~/work/acme --no-config-profile"]
|
|
60294
60320
|
);
|
|
60295
60321
|
withExamples(
|
|
60296
60322
|
rule.command("list").description("List every directory rule, in file order.").option("--json", "Print the rules as JSON.").action((options) => {
|
|
@@ -60300,14 +60326,14 @@ function registerRuleCommand(program2, deps) {
|
|
|
60300
60326
|
return;
|
|
60301
60327
|
}
|
|
60302
60328
|
if (entries.length === 0) {
|
|
60303
|
-
console.log("No directory rules yet. Run `
|
|
60329
|
+
console.log("No directory rules yet. Run `agent-shim rule add <path>` to create one.");
|
|
60304
60330
|
return;
|
|
60305
60331
|
}
|
|
60306
60332
|
for (const entry of entries) {
|
|
60307
60333
|
console.log(` ${entry.path} (${describeRule(entry)})`);
|
|
60308
60334
|
}
|
|
60309
60335
|
}),
|
|
60310
|
-
["
|
|
60336
|
+
["agent-shim rule list", "agent-shim rule list --json"]
|
|
60311
60337
|
);
|
|
60312
60338
|
withExamples(
|
|
60313
60339
|
rule.command("show <path>").description("Show the directory rule for a path, matched exactly as it was written.").option("--json", "Print the rule as JSON.").action((rulePath, options) => {
|
|
@@ -60322,7 +60348,7 @@ function registerRuleCommand(program2, deps) {
|
|
|
60322
60348
|
console.log(`Directory rule: ${found.path}`);
|
|
60323
60349
|
console.log(`Settings: ${describeRule(found)}`);
|
|
60324
60350
|
}),
|
|
60325
|
-
["
|
|
60351
|
+
["agent-shim rule show ~/work/acme"]
|
|
60326
60352
|
);
|
|
60327
60353
|
withExamples(
|
|
60328
60354
|
rule.command("remove <path>").description("Remove the directory rule for a path.").option("--yes", "Remove without asking for confirmation (required when standard input is not a terminal).").action(async (rulePath, options) => {
|
|
@@ -60333,7 +60359,7 @@ function registerRuleCommand(program2, deps) {
|
|
|
60333
60359
|
removeDirectoryRule(paths, rulePath);
|
|
60334
60360
|
console.log(`Removed directory rule for "${rulePath}".`);
|
|
60335
60361
|
}),
|
|
60336
|
-
["
|
|
60362
|
+
["agent-shim rule remove ~/work/acme --yes"]
|
|
60337
60363
|
);
|
|
60338
60364
|
}
|
|
60339
60365
|
|
|
@@ -60363,8 +60389,8 @@ function isAncestorOrSelf(ancestor, descendant) {
|
|
|
60363
60389
|
}
|
|
60364
60390
|
|
|
60365
60391
|
// src/launcher/cascade.ts
|
|
60366
|
-
var PORTABLE_CONFIG_FILENAME = ".
|
|
60367
|
-
var PORTABLE_LOCAL_CONFIG_FILENAME = ".
|
|
60392
|
+
var PORTABLE_CONFIG_FILENAME = ".agent-shim.json";
|
|
60393
|
+
var PORTABLE_LOCAL_CONFIG_FILENAME = ".agent-shim.local.json";
|
|
60368
60394
|
function loadCascadeInput(params) {
|
|
60369
60395
|
const globalConfig2 = loadConfigFile(params.paths.globalConfigFile, GlobalConfigSchema, params.read);
|
|
60370
60396
|
const directoryRules = loadConfigFile(params.paths.directoryRulesFile, DirectoryRulesSchema, params.read);
|
|
@@ -60384,8 +60410,8 @@ function loadCascadeInput(params) {
|
|
|
60384
60410
|
});
|
|
60385
60411
|
const levels = [];
|
|
60386
60412
|
for (const dir of dirs) {
|
|
60387
|
-
const portable = loadConfigFile(import_node_path17.default.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
60388
|
-
const portableLocal = loadConfigFile(import_node_path17.default.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
60413
|
+
const portable = loadConfigFile(import_node_path17.default.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path17.default.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
60414
|
+
const portableLocal = loadConfigFile(import_node_path17.default.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path17.default.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
|
|
60389
60415
|
const rules = (directoryRules?.config.rules ?? []).map((rule, index) => ({ rule, index })).filter(({ rule }) => normaliseRulePath(rule.path, params.home) === dir).map(({ rule, index }) => {
|
|
60390
60416
|
const entryOrder = directoryRules?.ruleEntryOrders[index];
|
|
60391
60417
|
return {
|
|
@@ -60434,17 +60460,23 @@ function readDirectorySelections(loaded) {
|
|
|
60434
60460
|
}
|
|
60435
60461
|
|
|
60436
60462
|
// src/paths.ts
|
|
60463
|
+
var import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
60437
60464
|
var import_node_os3 = __toESM(require("node:os"), 1);
|
|
60438
60465
|
var import_node_path18 = __toESM(require("node:path"), 1);
|
|
60439
|
-
function
|
|
60440
|
-
const fromEnv =
|
|
60466
|
+
function resolveAgentShimHome(env = process.env, home = import_node_os3.default.homedir(), isDirectory = isExistingDirectory) {
|
|
60467
|
+
const fromEnv = env.AGENT_SHIM_HOME;
|
|
60441
60468
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
60442
60469
|
return fromEnv;
|
|
60443
60470
|
}
|
|
60444
|
-
|
|
60471
|
+
const current = import_node_path18.default.join(home, HOME_DIRNAME);
|
|
60472
|
+
const legacy = import_node_path18.default.join(home, LEGACY_HOME_DIRNAME);
|
|
60473
|
+
return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
|
|
60474
|
+
}
|
|
60475
|
+
function isExistingDirectory(candidate) {
|
|
60476
|
+
return import_node_fs7.default.statSync(candidate, { throwIfNoEntry: false })?.isDirectory() ?? false;
|
|
60445
60477
|
}
|
|
60446
60478
|
function resolveClaudeHome() {
|
|
60447
|
-
const fromEnv = process.env.
|
|
60479
|
+
const fromEnv = process.env.AGENT_SHIM_CLAUDE_HOME;
|
|
60448
60480
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
60449
60481
|
return fromEnv;
|
|
60450
60482
|
}
|
|
@@ -60483,14 +60515,14 @@ function buildLayoutPaths(root) {
|
|
|
60483
60515
|
};
|
|
60484
60516
|
}
|
|
60485
60517
|
function resolveLayoutPaths() {
|
|
60486
|
-
return buildLayoutPaths(
|
|
60518
|
+
return buildLayoutPaths(resolveAgentShimHome());
|
|
60487
60519
|
}
|
|
60488
60520
|
|
|
60489
60521
|
// src/configure.ts
|
|
60490
60522
|
var NoConfigProfileResolvedError = class extends CliError {
|
|
60491
60523
|
constructor(identityName, cwd) {
|
|
60492
60524
|
super(
|
|
60493
|
-
`No configuration profile resolves for identity "${identityName}" at "${cwd}". Create one with \`
|
|
60525
|
+
`No configuration profile resolves for identity "${identityName}" at "${cwd}". Create one with \`agent-shim profile add <name>\` and make it this identity's default with \`agent-shim identity set ${identityName} --default-profile <name>\` before running \`configure\`.`
|
|
60494
60526
|
);
|
|
60495
60527
|
this.identityName = identityName;
|
|
60496
60528
|
this.cwd = cwd;
|
|
@@ -60501,13 +60533,13 @@ var NoConfigProfileResolvedError = class extends CliError {
|
|
|
60501
60533
|
};
|
|
60502
60534
|
var ConfigureNeedsTerminalError = class extends UsageError {
|
|
60503
60535
|
constructor() {
|
|
60504
|
-
super("`
|
|
60536
|
+
super("`agent-shim configure` is interactive and needs a terminal. From a script, use `agent-shim profile set` or edit the files it writes.");
|
|
60505
60537
|
this.name = "ConfigureNeedsTerminalError";
|
|
60506
60538
|
}
|
|
60507
60539
|
};
|
|
60508
60540
|
var NoIdentityResolvedError = class extends UsageError {
|
|
60509
60541
|
constructor(cwd) {
|
|
60510
|
-
super(`No identity resolves in "${cwd}": pass --identity <name>, or select one with \`
|
|
60542
|
+
super(`No identity resolves in "${cwd}": pass --identity <name>, or select one with \`agent-shim identity use <name>\`.`);
|
|
60511
60543
|
this.cwd = cwd;
|
|
60512
60544
|
this.name = "NoIdentityResolvedError";
|
|
60513
60545
|
}
|
|
@@ -60561,7 +60593,7 @@ function chooseWriteTarget(params) {
|
|
|
60561
60593
|
for (let index = params.levels.length - 1; index >= 0; index -= 1) {
|
|
60562
60594
|
const level = params.levels[index];
|
|
60563
60595
|
if (level !== void 0 && (level.hasPortable || level.hasPortableLocal)) {
|
|
60564
|
-
return { tier: "portable-local", localConfigPath: import_node_path19.default.join(level.dir,
|
|
60596
|
+
return { tier: "portable-local", localConfigPath: import_node_path19.default.join(level.dir, level.portableLocalFilename) };
|
|
60565
60597
|
}
|
|
60566
60598
|
}
|
|
60567
60599
|
const normalisedCwd = normaliseRulePath(params.cwd, params.home);
|
|
@@ -60653,11 +60685,16 @@ function parentOf3(relPath) {
|
|
|
60653
60685
|
function buildWriteTargetLevels(cwd, home, walkUpLimit) {
|
|
60654
60686
|
const limit = walkUpLimit === void 0 ? void 0 : expandTilde(walkUpLimit, home);
|
|
60655
60687
|
const dirs = walkDirectoryAncestors(cwd, { home, ...limit === void 0 ? {} : { limit } });
|
|
60656
|
-
return dirs.map((dir) =>
|
|
60657
|
-
dir,
|
|
60658
|
-
|
|
60659
|
-
|
|
60660
|
-
|
|
60688
|
+
return dirs.map((dir) => {
|
|
60689
|
+
const hasLocal = import_node_fs8.default.existsSync(import_node_path19.default.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME));
|
|
60690
|
+
const hasLegacyLocal = import_node_fs8.default.existsSync(import_node_path19.default.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME));
|
|
60691
|
+
return {
|
|
60692
|
+
dir,
|
|
60693
|
+
hasPortable: import_node_fs8.default.existsSync(import_node_path19.default.join(dir, PORTABLE_CONFIG_FILENAME)) || import_node_fs8.default.existsSync(import_node_path19.default.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME)),
|
|
60694
|
+
hasPortableLocal: hasLocal || hasLegacyLocal,
|
|
60695
|
+
portableLocalFilename: !hasLocal && hasLegacyLocal ? LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME : PORTABLE_LOCAL_CONFIG_FILENAME
|
|
60696
|
+
};
|
|
60697
|
+
});
|
|
60661
60698
|
}
|
|
60662
60699
|
function resolveWriteTarget(context) {
|
|
60663
60700
|
return chooseWriteTarget({
|
|
@@ -60821,7 +60858,7 @@ async function runProfileDirectMode(context) {
|
|
|
60821
60858
|
const { deps } = context;
|
|
60822
60859
|
const profiles = listProfiles(deps.paths);
|
|
60823
60860
|
if (profiles.length === 0) {
|
|
60824
|
-
deps.log.info("No configuration profiles exist yet. Run `
|
|
60861
|
+
deps.log.info("No configuration profiles exist yet. Run `agent-shim profile add <name>` first.");
|
|
60825
60862
|
return;
|
|
60826
60863
|
}
|
|
60827
60864
|
const chosen = await deps.prompts.select({
|
|
@@ -60979,7 +61016,7 @@ function registerConfigureCommand(program2, deps) {
|
|
|
60979
61016
|
}
|
|
60980
61017
|
);
|
|
60981
61018
|
});
|
|
60982
|
-
withExamples(command, ["
|
|
61019
|
+
withExamples(command, ["agent-shim configure", "agent-shim configure --identity work", "agent-shim configure projects --identity work"]);
|
|
60983
61020
|
}
|
|
60984
61021
|
function resolveLaunchIdentity(paths, cwd) {
|
|
60985
61022
|
const loaded = loadCascadeInput({ paths, home: import_node_os4.default.homedir(), cwd, read: cosmiconfigReader() });
|
|
@@ -60997,16 +61034,16 @@ function resolveLaunchIdentity(paths, cwd) {
|
|
|
60997
61034
|
// package.json
|
|
60998
61035
|
var package_default = {
|
|
60999
61036
|
name: "claude-use",
|
|
61000
|
-
version: "
|
|
61037
|
+
version: "7.1.1",
|
|
61001
61038
|
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.",
|
|
61002
|
-
license: "
|
|
61039
|
+
license: "MIT",
|
|
61003
61040
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
61004
61041
|
repository: {
|
|
61005
61042
|
type: "git",
|
|
61006
|
-
url: "git+https://github.com/ExaDev/
|
|
61043
|
+
url: "git+https://github.com/ExaDev/agent-shim.git"
|
|
61007
61044
|
},
|
|
61008
|
-
homepage: "https://github.com/ExaDev/
|
|
61009
|
-
bugs: "https://github.com/ExaDev/
|
|
61045
|
+
homepage: "https://github.com/ExaDev/agent-shim#readme",
|
|
61046
|
+
bugs: "https://github.com/ExaDev/agent-shim/issues",
|
|
61010
61047
|
keywords: [
|
|
61011
61048
|
"claude-code",
|
|
61012
61049
|
"claude",
|
|
@@ -61018,6 +61055,7 @@ var package_default = {
|
|
|
61018
61055
|
node: "^22.18 || >=24"
|
|
61019
61056
|
},
|
|
61020
61057
|
bin: {
|
|
61058
|
+
"agent-shim": "dist/cli.cjs",
|
|
61021
61059
|
"claude-use": "dist/cli.cjs"
|
|
61022
61060
|
},
|
|
61023
61061
|
files: [
|
|
@@ -61116,12 +61154,12 @@ function detectAmbientCredential(env, injected) {
|
|
|
61116
61154
|
return void 0;
|
|
61117
61155
|
}
|
|
61118
61156
|
function formatAmbientCredentialGuardMessage(variable, identityName) {
|
|
61119
|
-
const identitySetCommand = identityName === void 0 ? "
|
|
61157
|
+
const identitySetCommand = identityName === void 0 ? "agent-shim identity set <name> --allow-ambient-credential" : `agent-shim identity set ${identityName} --allow-ambient-credential`;
|
|
61120
61158
|
return [
|
|
61121
61159
|
`error: ${variable} is set in the environment. This identity's isolated`,
|
|
61122
61160
|
"credential would be bypassed \u2014 every identity authenticates as this same key",
|
|
61123
61161
|
"while it's set. Unset it, or if this is deliberate, opt in per-launch with",
|
|
61124
|
-
"
|
|
61162
|
+
"AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL=1, or persistently for this identity with",
|
|
61125
61163
|
`\`${identitySetCommand}\`.`
|
|
61126
61164
|
].join("\n");
|
|
61127
61165
|
}
|
|
@@ -61184,7 +61222,7 @@ function quotaWarnings(snapshot, provider, nowMs) {
|
|
|
61184
61222
|
}
|
|
61185
61223
|
const reset = window.resetsAt === void 0 ? "" : `, resets ${window.resetsAt}`;
|
|
61186
61224
|
const verdict = effective.status === "rejected" ? "exhausted" : "nearly used";
|
|
61187
|
-
return [`
|
|
61225
|
+
return [`agent-shim: identity ${snapshot.identity}: the ${name} quota is ${verdict}${reset} (last seen ${age} ago)`];
|
|
61188
61226
|
});
|
|
61189
61227
|
}
|
|
61190
61228
|
|
|
@@ -61363,12 +61401,12 @@ function isIdentityName(name) {
|
|
|
61363
61401
|
function claudeJsonPath(identitiesDir, identity) {
|
|
61364
61402
|
return import_node_path20.default.join(identitiesDir, identity, CLAUDE_JSON);
|
|
61365
61403
|
}
|
|
61366
|
-
function readAccountMetadata(
|
|
61404
|
+
function readAccountMetadata(fs17, identitiesDir, identity) {
|
|
61367
61405
|
if (!isIdentityName(identity)) {
|
|
61368
61406
|
throw new Error(`"${identity}" is not a valid identity name.`);
|
|
61369
61407
|
}
|
|
61370
61408
|
const file2 = claudeJsonPath(identitiesDir, identity);
|
|
61371
|
-
const raw =
|
|
61409
|
+
const raw = fs17.readFileUtf8(file2);
|
|
61372
61410
|
if (raw === void 0) {
|
|
61373
61411
|
return void 0;
|
|
61374
61412
|
}
|
|
@@ -61398,19 +61436,19 @@ function readAccountMetadata(fs16, identitiesDir, identity) {
|
|
|
61398
61436
|
}
|
|
61399
61437
|
return account.data;
|
|
61400
61438
|
}
|
|
61401
|
-
function createAccountReader(
|
|
61439
|
+
function createAccountReader(fs17, identitiesDir) {
|
|
61402
61440
|
const cache = /* @__PURE__ */ new Map();
|
|
61403
61441
|
return (identity) => {
|
|
61404
61442
|
if (!isIdentityName(identity)) {
|
|
61405
61443
|
throw new Error(`"${identity}" is not a valid identity name.`);
|
|
61406
61444
|
}
|
|
61407
|
-
const stat =
|
|
61445
|
+
const stat = fs17.lstat(claudeJsonPath(identitiesDir, identity));
|
|
61408
61446
|
const stamp = stat === void 0 ? "absent" : `${String(stat.mtimeMs)}:${String(stat.sizeBytes)}`;
|
|
61409
61447
|
const cached2 = cache.get(identity);
|
|
61410
61448
|
if (cached2?.stamp === stamp) {
|
|
61411
61449
|
return cached2.account;
|
|
61412
61450
|
}
|
|
61413
|
-
const account = readAccountMetadata(
|
|
61451
|
+
const account = readAccountMetadata(fs17, identitiesDir, identity);
|
|
61414
61452
|
cache.set(identity, { stamp, account });
|
|
61415
61453
|
return account;
|
|
61416
61454
|
};
|
|
@@ -61441,23 +61479,23 @@ var zlib = __toESM(require("node:zlib"), 1);
|
|
|
61441
61479
|
|
|
61442
61480
|
// src/frontdoor/route.ts
|
|
61443
61481
|
var INTERNAL_HEADER_NAMES = [
|
|
61444
|
-
"x-
|
|
61445
|
-
"x-
|
|
61446
|
-
"x-
|
|
61447
|
-
"x-
|
|
61448
|
-
"x-
|
|
61449
|
-
"x-
|
|
61482
|
+
"x-agent-shim-identity",
|
|
61483
|
+
"x-agent-shim-session",
|
|
61484
|
+
"x-agent-shim-headroom",
|
|
61485
|
+
"x-agent-shim-auth",
|
|
61486
|
+
"x-agent-shim-hop",
|
|
61487
|
+
"x-agent-shim-hop-id",
|
|
61450
61488
|
"x-headroom-project-id",
|
|
61451
61489
|
"x-headroom-base-url"
|
|
61452
61490
|
];
|
|
61453
|
-
var IDENTITY_HEADER = "x-
|
|
61454
|
-
var SESSION_HEADER = "x-
|
|
61455
|
-
var HEADROOM_FLAG_HEADER = "x-
|
|
61491
|
+
var IDENTITY_HEADER = "x-agent-shim-identity";
|
|
61492
|
+
var SESSION_HEADER = "x-agent-shim-session";
|
|
61493
|
+
var HEADROOM_FLAG_HEADER = "x-agent-shim-headroom";
|
|
61456
61494
|
var PROJECT_ID_HEADER = "x-headroom-project-id";
|
|
61457
61495
|
var HEADROOM_BASE_URL_HEADER = "x-headroom-base-url";
|
|
61458
|
-
var AUTH_HEADER = "x-
|
|
61459
|
-
var HOP_SECRET_HEADER = "x-
|
|
61460
|
-
var HOP_ID_HEADER = "x-
|
|
61496
|
+
var AUTH_HEADER = "x-agent-shim-auth";
|
|
61497
|
+
var HOP_SECRET_HEADER = "x-agent-shim-hop";
|
|
61498
|
+
var HOP_ID_HEADER = "x-agent-shim-hop-id";
|
|
61461
61499
|
function singleHeaderValue(value) {
|
|
61462
61500
|
if (typeof value === "string") {
|
|
61463
61501
|
return value;
|
|
@@ -62178,8 +62216,8 @@ function segmentDay(epochMs) {
|
|
|
62178
62216
|
function segmentName(day, pid) {
|
|
62179
62217
|
return `${day}.${String(pid)}.jsonl`;
|
|
62180
62218
|
}
|
|
62181
|
-
function listLogSegments(
|
|
62182
|
-
return
|
|
62219
|
+
function listLogSegments(fs17, logDir) {
|
|
62220
|
+
return fs17.readdir(logDir).flatMap((name) => {
|
|
62183
62221
|
const match = SEGMENT_RE.exec(name);
|
|
62184
62222
|
const day = match?.[1];
|
|
62185
62223
|
if (day === void 0) {
|
|
@@ -62188,15 +62226,15 @@ function listLogSegments(fs16, logDir) {
|
|
|
62188
62226
|
return [{ name, day, endsAt: Date.parse(`${day}T00:00:00.000Z`) + DAY_MS }];
|
|
62189
62227
|
}).sort((left, right) => left.day.localeCompare(right.day) || left.name.localeCompare(right.name));
|
|
62190
62228
|
}
|
|
62191
|
-
function readUsageLog(
|
|
62229
|
+
function readUsageLog(fs17, logDir, options = {}) {
|
|
62192
62230
|
const { sinceMs } = options;
|
|
62193
62231
|
const records = [];
|
|
62194
62232
|
let invalidLines = 0;
|
|
62195
|
-
for (const segment of listLogSegments(
|
|
62233
|
+
for (const segment of listLogSegments(fs17, logDir)) {
|
|
62196
62234
|
if (sinceMs !== void 0 && segment.endsAt <= sinceMs) {
|
|
62197
62235
|
continue;
|
|
62198
62236
|
}
|
|
62199
|
-
const contents =
|
|
62237
|
+
const contents = fs17.readFileUtf8(import_node_path21.default.join(logDir, segment.name));
|
|
62200
62238
|
if (contents === void 0) {
|
|
62201
62239
|
continue;
|
|
62202
62240
|
}
|
|
@@ -62228,7 +62266,7 @@ function readUsageLog(fs16, logDir, options = {}) {
|
|
|
62228
62266
|
}
|
|
62229
62267
|
var UsageSnapshotError = class extends Error {
|
|
62230
62268
|
constructor(file2, detail) {
|
|
62231
|
-
super(`${file2} is not a usage snapshot this
|
|
62269
|
+
super(`${file2} is not a usage snapshot this agent-shim can read (schema version ${String(USAGE_SCHEMA_VERSION)}): ${detail}`);
|
|
62232
62270
|
this.file = file2;
|
|
62233
62271
|
this.name = "UsageSnapshotError";
|
|
62234
62272
|
}
|
|
@@ -62240,9 +62278,9 @@ function snapshotPath(snapshotsDir, identity) {
|
|
|
62240
62278
|
}
|
|
62241
62279
|
return import_node_path21.default.join(snapshotsDir, `${identity}.json`);
|
|
62242
62280
|
}
|
|
62243
|
-
function readUsageSnapshot(
|
|
62281
|
+
function readUsageSnapshot(fs17, snapshotsDir, identity) {
|
|
62244
62282
|
const file2 = snapshotPath(snapshotsDir, identity);
|
|
62245
|
-
const raw =
|
|
62283
|
+
const raw = fs17.readFileUtf8(file2);
|
|
62246
62284
|
if (raw === void 0) {
|
|
62247
62285
|
return void 0;
|
|
62248
62286
|
}
|
|
@@ -62258,8 +62296,8 @@ function readUsageSnapshot(fs16, snapshotsDir, identity) {
|
|
|
62258
62296
|
}
|
|
62259
62297
|
return snapshot.data;
|
|
62260
62298
|
}
|
|
62261
|
-
function listUsageSnapshots(
|
|
62262
|
-
return
|
|
62299
|
+
function listUsageSnapshots(fs17, snapshotsDir) {
|
|
62300
|
+
return fs17.readdir(snapshotsDir).flatMap((name) => {
|
|
62263
62301
|
if (!name.endsWith(".json")) {
|
|
62264
62302
|
return [];
|
|
62265
62303
|
}
|
|
@@ -62267,7 +62305,7 @@ function listUsageSnapshots(fs16, snapshotsDir) {
|
|
|
62267
62305
|
if (!isIdentityName(identity)) {
|
|
62268
62306
|
return [];
|
|
62269
62307
|
}
|
|
62270
|
-
const snapshot = readUsageSnapshot(
|
|
62308
|
+
const snapshot = readUsageSnapshot(fs17, snapshotsDir, identity);
|
|
62271
62309
|
return snapshot === void 0 ? [] : [snapshot];
|
|
62272
62310
|
}).sort((left, right) => left.identity.localeCompare(right.identity));
|
|
62273
62311
|
}
|
|
@@ -62326,11 +62364,11 @@ var import_node_path22 = __toESM(require("node:path"), 1);
|
|
|
62326
62364
|
var DAY_MS2 = 864e5;
|
|
62327
62365
|
var DAYS_IN_WEEK = 7;
|
|
62328
62366
|
var USAGE_RETENTION_MS = DAYS_IN_WEEK * DAY_MS2;
|
|
62329
|
-
function pruneUsageLog(
|
|
62367
|
+
function pruneUsageLog(fs17, logDir, nowMs) {
|
|
62330
62368
|
const cutoff = nowMs - USAGE_RETENTION_MS;
|
|
62331
|
-
for (const segment of listLogSegments(
|
|
62369
|
+
for (const segment of listLogSegments(fs17, logDir)) {
|
|
62332
62370
|
if (segment.endsAt <= cutoff) {
|
|
62333
|
-
|
|
62371
|
+
fs17.removeRecursive(import_node_path22.default.join(logDir, segment.name));
|
|
62334
62372
|
}
|
|
62335
62373
|
}
|
|
62336
62374
|
}
|
|
@@ -62359,7 +62397,7 @@ function foldProviderState(current, record2) {
|
|
|
62359
62397
|
};
|
|
62360
62398
|
}
|
|
62361
62399
|
function createUsageStore(deps) {
|
|
62362
|
-
const { fs:
|
|
62400
|
+
const { fs: fs17, paths } = deps;
|
|
62363
62401
|
let prunedDay;
|
|
62364
62402
|
const rewriteSnapshot = (identity, fold) => {
|
|
62365
62403
|
if (!isIdentityName(identity)) {
|
|
@@ -62368,7 +62406,7 @@ function createUsageStore(deps) {
|
|
|
62368
62406
|
}
|
|
62369
62407
|
let current;
|
|
62370
62408
|
try {
|
|
62371
|
-
current = readUsageSnapshot(
|
|
62409
|
+
current = readUsageSnapshot(fs17, paths.usageSnapshotsDir, identity);
|
|
62372
62410
|
} catch (error62) {
|
|
62373
62411
|
if (!(error62 instanceof UsageSnapshotError)) {
|
|
62374
62412
|
throw error62;
|
|
@@ -62395,8 +62433,8 @@ function createUsageStore(deps) {
|
|
|
62395
62433
|
...account === void 0 ? {} : { account },
|
|
62396
62434
|
providers
|
|
62397
62435
|
});
|
|
62398
|
-
|
|
62399
|
-
|
|
62436
|
+
fs17.mkdirPrivate(paths.usageSnapshotsDir);
|
|
62437
|
+
fs17.writeFilePrivate(snapshotPath(paths.usageSnapshotsDir, identity), `${JSON.stringify(snapshot, null, 2)}
|
|
62400
62438
|
`);
|
|
62401
62439
|
return true;
|
|
62402
62440
|
};
|
|
@@ -62404,14 +62442,14 @@ function createUsageStore(deps) {
|
|
|
62404
62442
|
record: (input2) => {
|
|
62405
62443
|
const record2 = UsageRecordSchema.parse(input2);
|
|
62406
62444
|
const nowMs = deps.now();
|
|
62407
|
-
|
|
62408
|
-
|
|
62445
|
+
fs17.mkdirPrivate(paths.usageDir);
|
|
62446
|
+
fs17.mkdirPrivate(paths.usageLogDir);
|
|
62409
62447
|
const day = segmentDay(nowMs);
|
|
62410
62448
|
if (prunedDay !== day) {
|
|
62411
|
-
pruneUsageLog(
|
|
62449
|
+
pruneUsageLog(fs17, paths.usageLogDir, nowMs);
|
|
62412
62450
|
prunedDay = day;
|
|
62413
62451
|
}
|
|
62414
|
-
|
|
62452
|
+
fs17.appendFilePrivate(import_node_path22.default.join(paths.usageLogDir, segmentName(day, deps.pid)), `${JSON.stringify(record2)}
|
|
62415
62453
|
`);
|
|
62416
62454
|
if (record2.identity !== void 0) {
|
|
62417
62455
|
rewriteSnapshot(record2.identity, (current) => ({ ...current?.providers, [record2.provider]: foldProviderState(current?.providers[record2.provider], record2) }));
|
|
@@ -62438,14 +62476,14 @@ var PicksFileSchema = external_exports.strictObject({
|
|
|
62438
62476
|
function errorMessage(error62) {
|
|
62439
62477
|
return error62 instanceof Error ? error62.message : String(error62);
|
|
62440
62478
|
}
|
|
62441
|
-
function loadPoolMembers(
|
|
62479
|
+
function loadPoolMembers(fs17, paths, identities, nowMs) {
|
|
62442
62480
|
const windowStartMs = nowMs - FIVE_HOUR_WINDOW_MS;
|
|
62443
|
-
const log = readUsageLog(
|
|
62481
|
+
const log = readUsageLog(fs17, paths.usageLogDir, { sinceMs: windowStartMs });
|
|
62444
62482
|
return identities.map((identity) => {
|
|
62445
62483
|
const records = log.records.filter((record2) => record2.identity === identity && record2.provider === ANTHROPIC_PROVIDER && Date.parse(record2.at) >= windowStartMs);
|
|
62446
62484
|
try {
|
|
62447
|
-
const snapshot = readUsageSnapshot(
|
|
62448
|
-
const account = readAccountMetadata(
|
|
62485
|
+
const snapshot = readUsageSnapshot(fs17, paths.usageSnapshotsDir, identity);
|
|
62486
|
+
const account = readAccountMetadata(fs17, paths.identitiesDir, identity) ?? snapshot?.account;
|
|
62449
62487
|
return { identity, records, ...snapshot === void 0 ? {} : { snapshot }, ...account === void 0 ? {} : { account } };
|
|
62450
62488
|
} catch (error62) {
|
|
62451
62489
|
if (error62 instanceof UsageSnapshotError || error62 instanceof AccountMetadataError) {
|
|
@@ -62463,9 +62501,9 @@ function rankPoolFromStore(params) {
|
|
|
62463
62501
|
...params.sticky === void 0 ? {} : { sticky: params.sticky }
|
|
62464
62502
|
});
|
|
62465
62503
|
}
|
|
62466
|
-
function readPicksFile(
|
|
62504
|
+
function readPicksFile(fs17, file2) {
|
|
62467
62505
|
const empty = { schemaVersion: SCHEMA_VERSION, picks: {} };
|
|
62468
|
-
const raw =
|
|
62506
|
+
const raw = fs17.readFileUtf8(file2);
|
|
62469
62507
|
if (raw === void 0) {
|
|
62470
62508
|
return { file: empty };
|
|
62471
62509
|
}
|
|
@@ -62476,19 +62514,19 @@ function readPicksFile(fs16, file2) {
|
|
|
62476
62514
|
return { file: empty, problem: `${file2} is not valid JSON` };
|
|
62477
62515
|
}
|
|
62478
62516
|
const result = PicksFileSchema.safeParse(parsed);
|
|
62479
|
-
return result.success ? { file: result.data } : { file: empty, problem: `${file2} is not a picks file this
|
|
62517
|
+
return result.success ? { file: result.data } : { file: empty, problem: `${file2} is not a picks file this agent-shim can read` };
|
|
62480
62518
|
}
|
|
62481
|
-
function readStickyPick(
|
|
62482
|
-
const read = readPicksFile(
|
|
62519
|
+
function readStickyPick(fs17, picksFile, directory) {
|
|
62520
|
+
const read = readPicksFile(fs17, picksFile);
|
|
62483
62521
|
const entry = read.file.picks[directory];
|
|
62484
62522
|
return { ...entry === void 0 ? {} : { sticky: entry }, ...read.problem === void 0 ? {} : { problem: read.problem } };
|
|
62485
62523
|
}
|
|
62486
|
-
function recordStickyPick(
|
|
62487
|
-
const current = readPicksFile(
|
|
62524
|
+
function recordStickyPick(fs17, picksFile, directory, identity, nowMs) {
|
|
62525
|
+
const current = readPicksFile(fs17, picksFile).file.picks;
|
|
62488
62526
|
const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
|
|
62489
62527
|
const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
|
|
62490
|
-
|
|
62491
|
-
|
|
62528
|
+
fs17.mkdirPrivate(import_node_path23.default.dirname(picksFile));
|
|
62529
|
+
fs17.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
|
|
62492
62530
|
`);
|
|
62493
62531
|
}
|
|
62494
62532
|
|
|
@@ -62496,8 +62534,8 @@ function recordStickyPick(fs16, picksFile, directory, identity, nowMs) {
|
|
|
62496
62534
|
var RESUME_FLAGS = /* @__PURE__ */ new Set(["--continue", "-c", "--resume", "-r"]);
|
|
62497
62535
|
var TERMINATOR = "--";
|
|
62498
62536
|
var REASONS_LOGGED = 3;
|
|
62499
|
-
function splitMembers(pool, paths,
|
|
62500
|
-
const exists = (name) => loadIdentity(paths.identitiesDir, name,
|
|
62537
|
+
function splitMembers(pool, paths, fs17) {
|
|
62538
|
+
const exists = (name) => loadIdentity(paths.identitiesDir, name, fs17) !== void 0;
|
|
62501
62539
|
return { present: pool.identities.filter(exists), missing: pool.identities.filter((name) => !exists(name)) };
|
|
62502
62540
|
}
|
|
62503
62541
|
function isResuming(passthrough) {
|
|
@@ -62508,19 +62546,19 @@ function resolvePoolLaunch(params) {
|
|
|
62508
62546
|
const { poolName, log } = params;
|
|
62509
62547
|
const pool = params.pools?.[poolName];
|
|
62510
62548
|
if (pool === void 0) {
|
|
62511
|
-
return { ok: false, message: `
|
|
62549
|
+
return { ok: false, message: `agent-shim: no pool named "${poolName}" (selected via ${params.selectedVia}). Run \`agent-shim pool add ${poolName} --identity <name>...\` first.` };
|
|
62512
62550
|
}
|
|
62513
62551
|
const { present: identities, missing } = splitMembers(pool, params.paths, params.fs);
|
|
62514
62552
|
for (const name of missing) {
|
|
62515
|
-
log.warn(`
|
|
62553
|
+
log.warn(`agent-shim: pool "${poolName}" names identity "${name}", which does not exist; skipping it`);
|
|
62516
62554
|
}
|
|
62517
62555
|
if (identities.length === 0) {
|
|
62518
|
-
return { ok: false, message: `
|
|
62556
|
+
return { ok: false, message: `agent-shim: no member of pool "${poolName}" is an existing identity.` };
|
|
62519
62557
|
}
|
|
62520
62558
|
const resuming = isResuming(params.passthrough);
|
|
62521
62559
|
const stickyRead = readStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd);
|
|
62522
62560
|
if (stickyRead.problem !== void 0) {
|
|
62523
|
-
log.warn(`
|
|
62561
|
+
log.warn(`agent-shim: ${stickyRead.problem}; ignoring the last-pick record`);
|
|
62524
62562
|
}
|
|
62525
62563
|
for (; ; ) {
|
|
62526
62564
|
const nowMs = params.now();
|
|
@@ -62531,16 +62569,16 @@ function resolvePoolLaunch(params) {
|
|
|
62531
62569
|
return { ok: true, identity: pick2.identity, explanation: `pool ${poolName}: ${pick2.reasons.slice(0, REASONS_LOGGED).join("; ")}` };
|
|
62532
62570
|
}
|
|
62533
62571
|
if (earliestReturn === void 0) {
|
|
62534
|
-
return { ok: false, message: `
|
|
62572
|
+
return { ok: false, message: `agent-shim: no member of pool "${poolName}" can be picked.` };
|
|
62535
62573
|
}
|
|
62536
62574
|
const until = new Date(earliestReturn.atMs).toISOString();
|
|
62537
62575
|
if (!params.wait) {
|
|
62538
62576
|
return {
|
|
62539
62577
|
ok: false,
|
|
62540
|
-
message: `
|
|
62578
|
+
message: `agent-shim: every member of pool "${poolName}" is refused right now; the earliest, ${earliestReturn.identity}, returns at ${until} (in ${formatAge(earliestReturn.atMs - nowMs)}). Pass --wait to sleep until then.`
|
|
62541
62579
|
};
|
|
62542
62580
|
}
|
|
62543
|
-
log.info(`
|
|
62581
|
+
log.info(`agent-shim: every member of pool "${poolName}" is refused; waiting until ${until} for ${earliestReturn.identity}`);
|
|
62544
62582
|
params.sleep(Math.max(earliestReturn.atMs - nowMs, 0));
|
|
62545
62583
|
}
|
|
62546
62584
|
}
|
|
@@ -62606,7 +62644,7 @@ function registerPoolCommand(program2, deps) {
|
|
|
62606
62644
|
const { paths } = deps;
|
|
62607
62645
|
const pool = withExamples(
|
|
62608
62646
|
program2.command("pool").description("Manage pools: named sets of identities that a launch picks one member of, by remaining quota, with `claude @pool:<name>`."),
|
|
62609
|
-
["
|
|
62647
|
+
["agent-shim pool add subs --identity work --identity personal", "agent-shim pool pick subs"]
|
|
62610
62648
|
);
|
|
62611
62649
|
withExamples(
|
|
62612
62650
|
pool.command("add <name>").description("Define a pool. Fails if one with this name already exists.").option("--identity <name>", "A member identity (repeatable).", collectRepeated).action((name, options) => {
|
|
@@ -62615,7 +62653,7 @@ function registerPoolCommand(program2, deps) {
|
|
|
62615
62653
|
addPool(paths, name, members2);
|
|
62616
62654
|
console.log(`Created pool "${name}" with ${members2.join(", ")}.`);
|
|
62617
62655
|
}),
|
|
62618
|
-
["
|
|
62656
|
+
["agent-shim pool add subs --identity work --identity personal"]
|
|
62619
62657
|
);
|
|
62620
62658
|
withExamples(
|
|
62621
62659
|
pool.command("set <name>").description("Replace a pool's members.").option("--identity <name>", "A member identity (repeatable); the full new list.", collectRepeated).action((name, options) => {
|
|
@@ -62624,7 +62662,7 @@ function registerPoolCommand(program2, deps) {
|
|
|
62624
62662
|
setPool(paths, name, members2);
|
|
62625
62663
|
console.log(`Pool "${name}" now has ${members2.join(", ")}.`);
|
|
62626
62664
|
}),
|
|
62627
|
-
["
|
|
62665
|
+
["agent-shim pool set subs --identity work --identity personal --identity spare"]
|
|
62628
62666
|
);
|
|
62629
62667
|
withExamples(
|
|
62630
62668
|
pool.command("list").description("List every pool and its members, marking the active selection with *.").option("--json", "Print the pools as JSON.").action((options) => {
|
|
@@ -62636,14 +62674,14 @@ function registerPoolCommand(program2, deps) {
|
|
|
62636
62674
|
}
|
|
62637
62675
|
const names = Object.keys(pools).sort();
|
|
62638
62676
|
if (names.length === 0) {
|
|
62639
|
-
console.log("No pools yet. Run `
|
|
62677
|
+
console.log("No pools yet. Run `agent-shim pool add <name> --identity <name>...` to create one.");
|
|
62640
62678
|
return;
|
|
62641
62679
|
}
|
|
62642
62680
|
for (const name of names) {
|
|
62643
62681
|
console.log(`${active === `${POOL_SELECTOR_PREFIX}${name}` ? "*" : " "} ${name}: ${(pools[name]?.identities ?? []).join(", ")}`);
|
|
62644
62682
|
}
|
|
62645
62683
|
}),
|
|
62646
|
-
["
|
|
62684
|
+
["agent-shim pool list", "agent-shim pool list --json"]
|
|
62647
62685
|
);
|
|
62648
62686
|
withExamples(
|
|
62649
62687
|
pool.command("show <name>").description("Show one pool's members.").option("--json", "Print the pool as JSON.").action((name, options) => {
|
|
@@ -62655,7 +62693,7 @@ function registerPoolCommand(program2, deps) {
|
|
|
62655
62693
|
console.log(`Pool: ${name}`);
|
|
62656
62694
|
console.log(`Members: ${entry.identities.join(", ")}`);
|
|
62657
62695
|
}),
|
|
62658
|
-
["
|
|
62696
|
+
["agent-shim pool show subs"]
|
|
62659
62697
|
);
|
|
62660
62698
|
withExamples(
|
|
62661
62699
|
pool.command("remove <name>").description("Delete a pool. Its member identities are untouched.").option("--yes", "Skip the confirmation prompt.").action(async (name, options) => {
|
|
@@ -62664,14 +62702,14 @@ function registerPoolCommand(program2, deps) {
|
|
|
62664
62702
|
removePool(paths, name);
|
|
62665
62703
|
console.log(`Removed pool "${name}".`);
|
|
62666
62704
|
}),
|
|
62667
|
-
["
|
|
62705
|
+
["agent-shim pool remove subs --yes"]
|
|
62668
62706
|
);
|
|
62669
62707
|
withExamples(
|
|
62670
62708
|
pool.command("use <name>").description("Make launches with no other selection pick a member of this pool.").action((name) => {
|
|
62671
62709
|
useIdentity(paths, `${POOL_SELECTOR_PREFIX}${name}`);
|
|
62672
62710
|
console.log(`Active selection is now pool "${name}".`);
|
|
62673
62711
|
}),
|
|
62674
|
-
["
|
|
62712
|
+
["agent-shim pool use subs"]
|
|
62675
62713
|
);
|
|
62676
62714
|
withExamples(
|
|
62677
62715
|
pool.command("pick <name>").description("Show how a launch from this directory would rank the pool's members right now, and which it would run as. Read-only: it records nothing.").option("--json", "Print the ranking as JSON.").action((name, options) => {
|
|
@@ -62685,12 +62723,12 @@ function registerPoolCommand(program2, deps) {
|
|
|
62685
62723
|
console.log(line);
|
|
62686
62724
|
}
|
|
62687
62725
|
}),
|
|
62688
|
-
["
|
|
62726
|
+
["agent-shim pool pick subs", "agent-shim pool pick subs --json"]
|
|
62689
62727
|
);
|
|
62690
62728
|
}
|
|
62691
62729
|
|
|
62692
62730
|
// src/providers.ts
|
|
62693
|
-
var
|
|
62731
|
+
var import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
62694
62732
|
var import_node_path24 = __toESM(require("node:path"), 1);
|
|
62695
62733
|
|
|
62696
62734
|
// src/codex/translate.ts
|
|
@@ -62933,7 +62971,7 @@ function translateRequest(body, config2) {
|
|
|
62933
62971
|
// src/providers.ts
|
|
62934
62972
|
var ProviderNotFoundError = class extends CliError {
|
|
62935
62973
|
constructor(name) {
|
|
62936
|
-
super(`No provider named "${name}". Run \`
|
|
62974
|
+
super(`No provider named "${name}". Run \`agent-shim provider add ${name}\` first.`);
|
|
62937
62975
|
this.name = name;
|
|
62938
62976
|
this.name = "ProviderNotFoundError";
|
|
62939
62977
|
}
|
|
@@ -62962,7 +63000,7 @@ function providerJsonPath(paths, name) {
|
|
|
62962
63000
|
return import_node_path24.default.join(paths.providersDir, `${name}.json`);
|
|
62963
63001
|
}
|
|
62964
63002
|
function providerExists(paths, name) {
|
|
62965
|
-
return
|
|
63003
|
+
return import_node_fs9.default.existsSync(providerJsonPath(paths, name));
|
|
62966
63004
|
}
|
|
62967
63005
|
var LEGACY_PROVIDER_FIELDS = ["tokenEnv", "tokenCommand", "authScheme"];
|
|
62968
63006
|
var LEGACY_ENV_CREDENTIAL_KEYS = Object.values(CREDENTIAL_TARGET_VARS);
|
|
@@ -63028,10 +63066,10 @@ function parseProviderFile(filePath, raw) {
|
|
|
63028
63066
|
}
|
|
63029
63067
|
function readProvider(paths, name) {
|
|
63030
63068
|
const filePath = providerJsonPath(paths, name);
|
|
63031
|
-
if (!
|
|
63069
|
+
if (!import_node_fs9.default.existsSync(filePath)) {
|
|
63032
63070
|
return void 0;
|
|
63033
63071
|
}
|
|
63034
|
-
const raw = JSON.parse(
|
|
63072
|
+
const raw = JSON.parse(import_node_fs9.default.readFileSync(filePath, "utf8"));
|
|
63035
63073
|
return parseProviderFile(filePath, raw);
|
|
63036
63074
|
}
|
|
63037
63075
|
function loadProvider(providersDir, name, port) {
|
|
@@ -63041,7 +63079,7 @@ function loadProvider(providersDir, name, port) {
|
|
|
63041
63079
|
}
|
|
63042
63080
|
function listProviders(paths) {
|
|
63043
63081
|
const names = listProviderNames(
|
|
63044
|
-
(dir) =>
|
|
63082
|
+
(dir) => import_node_fs9.default.readdirSync(dir),
|
|
63045
63083
|
paths.providersDir
|
|
63046
63084
|
);
|
|
63047
63085
|
const result = [];
|
|
@@ -63053,7 +63091,7 @@ function listProviders(paths) {
|
|
|
63053
63091
|
if (!(error62 instanceof ConfigValidationError || error62 instanceof LegacyProviderFileError)) {
|
|
63054
63092
|
throw error62;
|
|
63055
63093
|
}
|
|
63056
|
-
console.error(`
|
|
63094
|
+
console.error(`agent-shim: providers/${name}.json is invalid and was skipped: ${error62.message}`);
|
|
63057
63095
|
continue;
|
|
63058
63096
|
}
|
|
63059
63097
|
if (provider !== void 0) {
|
|
@@ -63160,7 +63198,7 @@ function removeProvider(paths, name) {
|
|
|
63160
63198
|
if (!providerExists(paths, name)) {
|
|
63161
63199
|
throw new ProviderNotFoundError(name);
|
|
63162
63200
|
}
|
|
63163
|
-
|
|
63201
|
+
import_node_fs9.default.rmSync(providerJsonPath(paths, name));
|
|
63164
63202
|
}
|
|
63165
63203
|
function cascadeProviderName(cascade) {
|
|
63166
63204
|
let name;
|
|
@@ -63183,11 +63221,11 @@ function resolveProvider(params) {
|
|
|
63183
63221
|
return {
|
|
63184
63222
|
ok: false,
|
|
63185
63223
|
status: 1,
|
|
63186
|
-
message: `
|
|
63224
|
+
message: `agent-shim: no provider named "${name}". ` + (known.length > 0 ? `Known providers: ${known.join(", ")}.` : "No providers are defined yet; run `agent-shim provider add`.")
|
|
63187
63225
|
};
|
|
63188
63226
|
}
|
|
63189
63227
|
if (params.credentials === void 0) {
|
|
63190
|
-
return { ok: false, status: 1, message: `
|
|
63228
|
+
return { ok: false, status: 1, message: `agent-shim: provider ${name} needs its credential resolved, but this launcher has no credential port wired` };
|
|
63191
63229
|
}
|
|
63192
63230
|
const resolution = resolveCredential({ credential: definition.credential, env: params.env, port: params.credentials, subject: `provider ${name}` });
|
|
63193
63231
|
if (!resolution.ok) {
|
|
@@ -63224,10 +63262,10 @@ function registerProviderCommand(program2, deps) {
|
|
|
63224
63262
|
const { paths } = deps;
|
|
63225
63263
|
const provider = withExamples(
|
|
63226
63264
|
program2.command("provider").description("Manage API providers: Anthropic-compatible endpoints a launch can route through with --provider."),
|
|
63227
|
-
["
|
|
63265
|
+
["agent-shim provider add z --display-name z.ai --base-url https://api.z.ai/api/anthropic --credential env:Z_API_TOKEN", "agent-shim provider list"]
|
|
63228
63266
|
);
|
|
63229
63267
|
withExamples(
|
|
63230
|
-
provider.command("add <name>").description("Create a new API provider definition. Fails if one with this name already exists.").addOption(new Option("--kind <kind>", "http (default): an Anthropic-compatible endpoint at --base-url; codex: ChatGPT's Codex backend through the front-door daemon.").choices(PROVIDER_KINDS)).requiredOption("--display-name <name>", "Human-readable name, exported to the child as
|
|
63268
|
+
provider.command("add <name>").description("Create a new API provider definition. Fails if one with this name already exists.").addOption(new Option("--kind <kind>", "http (default): an Anthropic-compatible endpoint at --base-url; codex: ChatGPT's Codex backend through the front-door daemon.").choices(PROVIDER_KINDS)).requiredOption("--display-name <name>", "Human-readable name, exported to the child as AGENT_SHIM_PROVIDER.").option("--base-url <url>", "Anthropic-compatible base URL the child's requests are sent to (http providers only, and required for them).").requiredOption(
|
|
63231
63269
|
"--credential <source>",
|
|
63232
63270
|
`Where the provider's token comes from (repeatable; tried in the order given until one yields a token): ${CREDENTIAL_SOURCE_SYNTAX}. Never the token itself.`,
|
|
63233
63271
|
collectCredentialSource
|
|
@@ -63249,12 +63287,12 @@ function registerProviderCommand(program2, deps) {
|
|
|
63249
63287
|
console.log(`Created provider "${name}" (${describeProviderEndpoint(created)}, credential ${describeCredential(created.credential)}).`);
|
|
63250
63288
|
}),
|
|
63251
63289
|
[
|
|
63252
|
-
"
|
|
63253
|
-
"
|
|
63254
|
-
"
|
|
63255
|
-
"
|
|
63256
|
-
"
|
|
63257
|
-
"
|
|
63290
|
+
"agent-shim provider add z --display-name z.ai --base-url https://api.z.ai/api/anthropic --credential env:Z_API_TOKEN",
|
|
63291
|
+
"agent-shim provider add z --display-name z.ai --base-url https://api.z.ai/api/anthropic --credential env:Z_API_TOKEN --credential op:op://vault/z/credential",
|
|
63292
|
+
"agent-shim provider add anthropic-api --display-name Anthropic --base-url https://api.anthropic.com --credential-target apiKey --credential keychain:anthropic-api-key",
|
|
63293
|
+
"agent-shim provider add local --display-name Local --base-url http://127.0.0.1:4000 --credential literal:dummy",
|
|
63294
|
+
"agent-shim provider add codex --kind codex --display-name Codex --credential literal:codex",
|
|
63295
|
+
"agent-shim provider add codex --kind codex --display-name Codex --credential literal:codex --codex-model sonnet=gpt-5.6-sol --codex-effort medium"
|
|
63258
63296
|
]
|
|
63259
63297
|
);
|
|
63260
63298
|
const providerSet = provider.command("set <name>").description("Update an existing API provider definition.").option("--display-name <name>", "Replace the human-readable name.").option("--base-url <url>", "Replace the base URL (http providers only).").option(
|
|
@@ -63289,11 +63327,11 @@ function registerProviderCommand(program2, deps) {
|
|
|
63289
63327
|
console.log(`Updated provider "${name}" (${describeProviderEndpoint(updated)}, credential ${describeCredential(updated.credential)}).`);
|
|
63290
63328
|
}),
|
|
63291
63329
|
[
|
|
63292
|
-
"
|
|
63293
|
-
"
|
|
63294
|
-
"
|
|
63295
|
-
"
|
|
63296
|
-
"
|
|
63330
|
+
"agent-shim provider set z --base-url https://api.z.ai/api/anthropic",
|
|
63331
|
+
"agent-shim provider set z --env API_TIMEOUT_MS=600000",
|
|
63332
|
+
"agent-shim provider set z --credential op:op://vault/z/credential --credential-cache-ttl 12h",
|
|
63333
|
+
"agent-shim provider set anthropic-api --credential-target apiKey",
|
|
63334
|
+
"agent-shim provider set codex --codex-model haiku=gpt-5.6-terra"
|
|
63297
63335
|
]
|
|
63298
63336
|
);
|
|
63299
63337
|
withExamples(
|
|
@@ -63304,14 +63342,14 @@ function registerProviderCommand(program2, deps) {
|
|
|
63304
63342
|
return;
|
|
63305
63343
|
}
|
|
63306
63344
|
if (entries.length === 0) {
|
|
63307
|
-
console.log("No providers yet. Run `
|
|
63345
|
+
console.log("No providers yet. Run `agent-shim provider add <name>` to create one.");
|
|
63308
63346
|
return;
|
|
63309
63347
|
}
|
|
63310
63348
|
for (const entry of entries) {
|
|
63311
63349
|
console.log(` ${entry.name} (${entry.provider.displayName}, ${describeProviderEndpoint(entry.provider)})`);
|
|
63312
63350
|
}
|
|
63313
63351
|
}),
|
|
63314
|
-
["
|
|
63352
|
+
["agent-shim provider list", "agent-shim provider list --json"]
|
|
63315
63353
|
);
|
|
63316
63354
|
withExamples(
|
|
63317
63355
|
provider.command("show <name>").description("Show one provider's definition. Credentials are described by source, never printed.").option("--json", "Print the provider as JSON.").action((name, options) => {
|
|
@@ -63337,7 +63375,7 @@ function registerProviderCommand(program2, deps) {
|
|
|
63337
63375
|
const env = Object.entries(found.env ?? {});
|
|
63338
63376
|
console.log(`Environment: ${env.length === 0 ? "(none)" : env.map(([key, value]) => `${key}=${value}`).join(", ")}`);
|
|
63339
63377
|
}),
|
|
63340
|
-
["
|
|
63378
|
+
["agent-shim provider show z", "agent-shim provider show z --json"]
|
|
63341
63379
|
);
|
|
63342
63380
|
withExamples(
|
|
63343
63381
|
provider.command("remove <name>").description("Delete a provider definition.").option("--yes", "Remove without asking for confirmation (required when standard input is not a terminal).").action(async (name, options) => {
|
|
@@ -63348,7 +63386,7 @@ function registerProviderCommand(program2, deps) {
|
|
|
63348
63386
|
removeProvider(paths, name);
|
|
63349
63387
|
console.log(`Removed provider "${name}".`);
|
|
63350
63388
|
}),
|
|
63351
|
-
["
|
|
63389
|
+
["agent-shim provider remove z --yes"]
|
|
63352
63390
|
);
|
|
63353
63391
|
}
|
|
63354
63392
|
|
|
@@ -63510,7 +63548,7 @@ function runCheck(params) {
|
|
|
63510
63548
|
const ambientCredential = evaluateAmbientCredentialGuard({
|
|
63511
63549
|
env: params.env,
|
|
63512
63550
|
allowAmbientCredential: params.identity?.allowAmbientCredential ?? false,
|
|
63513
|
-
allowAmbientCredentialOverride: parseEnvBool("
|
|
63551
|
+
allowAmbientCredentialOverride: parseEnvBool("AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL", params.env.AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL) === true,
|
|
63514
63552
|
...params.identityName === void 0 ? {} : { identityName: params.identityName }
|
|
63515
63553
|
});
|
|
63516
63554
|
const settingsShared = resolved.flattened.categories.get("settings") ?? SHIPPED_CATEGORY_DEFAULTS.settings;
|
|
@@ -63723,12 +63761,12 @@ function registerCheckCommand(program2, deps) {
|
|
|
63723
63761
|
process.exitCode = 1;
|
|
63724
63762
|
}
|
|
63725
63763
|
});
|
|
63726
|
-
withExamples(command, ["
|
|
63764
|
+
withExamples(command, ["agent-shim check", "agent-shim check ~/work/acme --identity work --json", "agent-shim check --strict"]);
|
|
63727
63765
|
}
|
|
63728
63766
|
|
|
63729
63767
|
// src/codex/commands.ts
|
|
63730
63768
|
var import_node_crypto7 = require("node:crypto");
|
|
63731
|
-
var
|
|
63769
|
+
var import_node_fs10 = __toESM(require("node:fs"), 1);
|
|
63732
63770
|
var import_node_os6 = __toESM(require("node:os"), 1);
|
|
63733
63771
|
var import_node_path27 = __toESM(require("node:path"), 1);
|
|
63734
63772
|
|
|
@@ -63761,10 +63799,10 @@ var FrontDoorStateSchema = external_exports.strictObject({
|
|
|
63761
63799
|
/** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
|
|
63762
63800
|
lastError: external_exports.string().optional()
|
|
63763
63801
|
});
|
|
63764
|
-
function readFrontDoorState(
|
|
63802
|
+
function readFrontDoorState(fs17, stateFile) {
|
|
63765
63803
|
let raw;
|
|
63766
63804
|
try {
|
|
63767
|
-
raw =
|
|
63805
|
+
raw = fs17.readFileUtf8(stateFile);
|
|
63768
63806
|
} catch {
|
|
63769
63807
|
return void 0;
|
|
63770
63808
|
}
|
|
@@ -63778,28 +63816,28 @@ function readFrontDoorState(fs16, stateFile) {
|
|
|
63778
63816
|
return void 0;
|
|
63779
63817
|
}
|
|
63780
63818
|
}
|
|
63781
|
-
function writeFrontDoorState(
|
|
63782
|
-
|
|
63783
|
-
|
|
63819
|
+
function writeFrontDoorState(fs17, stateFile, state) {
|
|
63820
|
+
fs17.mkdirp(import_node_path26.default.dirname(stateFile));
|
|
63821
|
+
fs17.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
|
|
63784
63822
|
`);
|
|
63785
63823
|
}
|
|
63786
63824
|
function frontDoorOrigin(state) {
|
|
63787
63825
|
const port = state?.directPort ?? state?.lastDirectPort;
|
|
63788
63826
|
return port === void 0 ? void 0 : `http://127.0.0.1:${String(port)}`;
|
|
63789
63827
|
}
|
|
63790
|
-
function writeFrontDoorSession(
|
|
63791
|
-
|
|
63792
|
-
|
|
63828
|
+
function writeFrontDoorSession(fs17, sessionsDir, session) {
|
|
63829
|
+
fs17.mkdirPrivate(sessionsDir);
|
|
63830
|
+
fs17.writeFilePrivate(import_node_path26.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
|
|
63793
63831
|
`);
|
|
63794
63832
|
}
|
|
63795
|
-
function listFrontDoorSessions(
|
|
63833
|
+
function listFrontDoorSessions(fs17, sessionsDir) {
|
|
63796
63834
|
const sessions = [];
|
|
63797
|
-
for (const name of
|
|
63835
|
+
for (const name of fs17.readdir(sessionsDir)) {
|
|
63798
63836
|
if (!name.endsWith(".json")) {
|
|
63799
63837
|
continue;
|
|
63800
63838
|
}
|
|
63801
63839
|
try {
|
|
63802
|
-
const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(
|
|
63840
|
+
const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs17.readFileUtf8(import_node_path26.default.join(sessionsDir, name)) ?? ""));
|
|
63803
63841
|
if (parsed.success) {
|
|
63804
63842
|
sessions.push({ pid: parsed.data.pid, startedAt: parsed.data.startedAt });
|
|
63805
63843
|
}
|
|
@@ -63809,27 +63847,27 @@ function listFrontDoorSessions(fs16, sessionsDir) {
|
|
|
63809
63847
|
}
|
|
63810
63848
|
return sessions.sort((a2, b) => a2.pid - b.pid);
|
|
63811
63849
|
}
|
|
63812
|
-
function removeFrontDoorSession(
|
|
63813
|
-
|
|
63850
|
+
function removeFrontDoorSession(fs17, sessionsDir, pid) {
|
|
63851
|
+
fs17.removeRecursive(import_node_path26.default.join(sessionsDir, `${String(pid)}.json`));
|
|
63814
63852
|
}
|
|
63815
|
-
function pruneDeadFrontDoorSessions(
|
|
63853
|
+
function pruneDeadFrontDoorSessions(fs17, sessionsDir, isRunning) {
|
|
63816
63854
|
const removed = [];
|
|
63817
|
-
for (const session of listFrontDoorSessions(
|
|
63855
|
+
for (const session of listFrontDoorSessions(fs17, sessionsDir)) {
|
|
63818
63856
|
if (!isRunning(session.pid)) {
|
|
63819
|
-
removeFrontDoorSession(
|
|
63857
|
+
removeFrontDoorSession(fs17, sessionsDir, session.pid);
|
|
63820
63858
|
removed.push(session.pid);
|
|
63821
63859
|
}
|
|
63822
63860
|
}
|
|
63823
63861
|
return removed;
|
|
63824
63862
|
}
|
|
63825
|
-
function liveSessionTokens(
|
|
63863
|
+
function liveSessionTokens(fs17, sessionsDir) {
|
|
63826
63864
|
const tokens = /* @__PURE__ */ new Set();
|
|
63827
|
-
for (const name of
|
|
63865
|
+
for (const name of fs17.readdir(sessionsDir)) {
|
|
63828
63866
|
if (!name.endsWith(".json")) {
|
|
63829
63867
|
continue;
|
|
63830
63868
|
}
|
|
63831
63869
|
try {
|
|
63832
|
-
const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(
|
|
63870
|
+
const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs17.readFileUtf8(import_node_path26.default.join(sessionsDir, name)) ?? ""));
|
|
63833
63871
|
if (parsed.success) {
|
|
63834
63872
|
tokens.add(parsed.data.token);
|
|
63835
63873
|
}
|
|
@@ -64041,7 +64079,7 @@ function sessionIdFor(userId, randomId) {
|
|
|
64041
64079
|
if (userId === void 0 || userId === "") {
|
|
64042
64080
|
return randomId();
|
|
64043
64081
|
}
|
|
64044
|
-
const hex3 = (0, import_node_crypto6.createHash)("sha256").update(`
|
|
64082
|
+
const hex3 = (0, import_node_crypto6.createHash)("sha256").update(`agent-shim codex session
|
|
64045
64083
|
${userId}`).digest("hex");
|
|
64046
64084
|
let next = 0;
|
|
64047
64085
|
return UUID_TEMPLATE.replace(/x/g, () => hex3.charAt(next++));
|
|
@@ -64089,7 +64127,7 @@ var PRIVATE_FILE_MODE = 384;
|
|
|
64089
64127
|
var realCodexAuthFs = {
|
|
64090
64128
|
read: (filePath) => {
|
|
64091
64129
|
try {
|
|
64092
|
-
return
|
|
64130
|
+
return import_node_fs10.default.readFileSync(filePath, "utf8");
|
|
64093
64131
|
} catch (error62) {
|
|
64094
64132
|
if (isEnoent4(error62)) {
|
|
64095
64133
|
return void 0;
|
|
@@ -64098,21 +64136,21 @@ var realCodexAuthFs = {
|
|
|
64098
64136
|
}
|
|
64099
64137
|
},
|
|
64100
64138
|
writePrivate: (filePath, contents) => {
|
|
64101
|
-
|
|
64102
|
-
|
|
64139
|
+
import_node_fs10.default.writeFileSync(filePath, contents, { encoding: "utf8", mode: PRIVATE_FILE_MODE });
|
|
64140
|
+
import_node_fs10.default.chmodSync(filePath, PRIVATE_FILE_MODE);
|
|
64103
64141
|
},
|
|
64104
64142
|
rename: (from, to) => {
|
|
64105
|
-
|
|
64143
|
+
import_node_fs10.default.renameSync(from, to);
|
|
64106
64144
|
}
|
|
64107
64145
|
};
|
|
64108
64146
|
function writeUsageSnapshot(log, snapshot) {
|
|
64109
64147
|
const target = codexUsageSnapshotPath();
|
|
64110
64148
|
const temp = `${target}.${String(process.pid)}.tmp`;
|
|
64111
64149
|
try {
|
|
64112
|
-
|
|
64113
|
-
|
|
64150
|
+
import_node_fs10.default.mkdirSync(import_node_path27.default.dirname(target), { recursive: true });
|
|
64151
|
+
import_node_fs10.default.writeFileSync(temp, `${JSON.stringify(snapshot, null, 2)}
|
|
64114
64152
|
`);
|
|
64115
|
-
|
|
64153
|
+
import_node_fs10.default.renameSync(temp, target);
|
|
64116
64154
|
} catch (error62) {
|
|
64117
64155
|
log(`usage snapshot write failed: ${error62 instanceof Error ? error62.message : String(error62)}`);
|
|
64118
64156
|
}
|
|
@@ -64177,7 +64215,7 @@ function formatCodexStatus(status) {
|
|
|
64177
64215
|
}
|
|
64178
64216
|
function registerCodexCommand(program2, deps) {
|
|
64179
64217
|
const { paths } = deps;
|
|
64180
|
-
const codex = withExamples(program2.command("codex").description("Inspect the codex translation the front-door daemon serves for codex providers."), ["
|
|
64218
|
+
const codex = withExamples(program2.command("codex").description("Inspect the codex translation the front-door daemon serves for codex providers."), ["agent-shim codex status"]);
|
|
64181
64219
|
withExamples(
|
|
64182
64220
|
codex.command("status").description("Report the front door serving codex providers, its sessions, and the usage snapshot. Read-only.").option("--json", "Print the status as JSON.").action((options) => {
|
|
64183
64221
|
const status = collectCodexStatus(realFarmFs, paths, realIsProcessRunning);
|
|
@@ -64189,17 +64227,17 @@ function registerCodexCommand(program2, deps) {
|
|
|
64189
64227
|
console.log(line);
|
|
64190
64228
|
}
|
|
64191
64229
|
}),
|
|
64192
|
-
["
|
|
64230
|
+
["agent-shim codex status", "agent-shim codex status --json"]
|
|
64193
64231
|
);
|
|
64194
64232
|
}
|
|
64195
64233
|
|
|
64196
64234
|
// src/frontdoor/commands.ts
|
|
64197
64235
|
var import_node_crypto13 = require("node:crypto");
|
|
64198
|
-
var
|
|
64236
|
+
var import_node_fs11 = __toESM(require("node:fs"), 1);
|
|
64199
64237
|
|
|
64200
64238
|
// src/frontdoor/custody.ts
|
|
64201
64239
|
var CREDENTIAL_HEADERS = ["authorization", "x-api-key"];
|
|
64202
|
-
var SEQUESTERED_CREDENTIAL = "
|
|
64240
|
+
var SEQUESTERED_CREDENTIAL = "agent-shim-sequestered";
|
|
64203
64241
|
function placeholderFor(name, value) {
|
|
64204
64242
|
const first = typeof value === "string" ? value : value[0] ?? "";
|
|
64205
64243
|
if (name === "authorization") {
|
|
@@ -64259,19 +64297,19 @@ function singleValue(value) {
|
|
|
64259
64297
|
function admitLaunch(isLiveToken) {
|
|
64260
64298
|
return (request6) => {
|
|
64261
64299
|
const token = singleValue(request6.headers[AUTH_HEADER]);
|
|
64262
|
-
return token !== void 0 && isLiveToken(token) ? { ok: true, headers: { ...request6.forwardable } } : { ok: false, message: "
|
|
64300
|
+
return token !== void 0 && isLiveToken(token) ? { ok: true, headers: { ...request6.forwardable } } : { ok: false, message: "agent-shim front door: this request carries no capability from a live agent-shim launch" };
|
|
64263
64301
|
};
|
|
64264
64302
|
}
|
|
64265
64303
|
function admitHop(hopSecret, custody) {
|
|
64266
64304
|
return (request6) => {
|
|
64267
64305
|
if (singleValue(request6.headers[HOP_SECRET_HEADER]) !== hopSecret) {
|
|
64268
|
-
return { ok: false, message: "
|
|
64306
|
+
return { ok: false, message: "agent-shim front door: the direct listener serves only this door's own headroom hop" };
|
|
64269
64307
|
}
|
|
64270
64308
|
const hopId = singleValue(request6.headers[HOP_ID_HEADER]);
|
|
64271
64309
|
const provider = parseProviderPath(new URL(request6.url, "http://127.0.0.1").pathname)?.provider;
|
|
64272
64310
|
const credentials = hopId === void 0 || provider === void 0 ? void 0 : custody.redeem(hopId, provider);
|
|
64273
64311
|
if (credentials === void 0) {
|
|
64274
|
-
return { ok: false, message: "
|
|
64312
|
+
return { ok: false, message: "agent-shim front door: this request names no live headroom hop for its provider" };
|
|
64275
64313
|
}
|
|
64276
64314
|
return { ok: true, headers: restoreCredentials(request6.forwardable, credentials) };
|
|
64277
64315
|
};
|
|
@@ -64299,8 +64337,8 @@ function createDoorPipelines(deps) {
|
|
|
64299
64337
|
|
|
64300
64338
|
// src/frontdoor/capability.ts
|
|
64301
64339
|
var import_node_crypto8 = require("node:crypto");
|
|
64302
|
-
var CONNECT_PROXY_USER = "
|
|
64303
|
-
var CONNECT_PROXY_REALM = "
|
|
64340
|
+
var CONNECT_PROXY_USER = "agent-shim";
|
|
64341
|
+
var CONNECT_PROXY_REALM = "agent-shim front door";
|
|
64304
64342
|
var BASIC_SCHEME = "basic";
|
|
64305
64343
|
function connectProxyUrl(port, token) {
|
|
64306
64344
|
return `http://${encodeURIComponent(CONNECT_PROXY_USER)}:${encodeURIComponent(token)}@127.0.0.1:${String(port)}`;
|
|
@@ -64334,7 +64372,7 @@ function isLiveCapability(presented, live) {
|
|
|
64334
64372
|
|
|
64335
64373
|
// src/frontdoor/connect.ts
|
|
64336
64374
|
var import_node_crypto10 = require("node:crypto");
|
|
64337
|
-
var
|
|
64375
|
+
var fs11 = __toESM(require("node:fs"), 1);
|
|
64338
64376
|
var http = __toESM(require("node:http"), 1);
|
|
64339
64377
|
var https = __toESM(require("node:https"), 1);
|
|
64340
64378
|
var net3 = __toESM(require("node:net"), 1);
|
|
@@ -64616,8 +64654,8 @@ var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
|
|
|
64616
64654
|
var FRONTDOOR_POLL_MS = 1e3;
|
|
64617
64655
|
var MS_PER_MINUTE = 6e4;
|
|
64618
64656
|
async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
|
|
64619
|
-
const { fs:
|
|
64620
|
-
const previous = readFrontDoorState(
|
|
64657
|
+
const { fs: fs17, paths } = ports;
|
|
64658
|
+
const previous = readFrontDoorState(fs17, paths.frontdoorStateFile);
|
|
64621
64659
|
let lastPort = previous?.lastPort;
|
|
64622
64660
|
let lastConnectPort = previous?.lastConnectPort;
|
|
64623
64661
|
let lastDirectPort = previous?.lastDirectPort;
|
|
@@ -64627,12 +64665,12 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
64627
64665
|
...lastDirectPort === void 0 ? {} : { lastDirectPort }
|
|
64628
64666
|
});
|
|
64629
64667
|
const fail = (message) => {
|
|
64630
|
-
writeFrontDoorState(
|
|
64631
|
-
|
|
64632
|
-
ports.log(`
|
|
64668
|
+
writeFrontDoorState(fs17, paths.frontdoorStateFile, { lastError: message, ...sticky() });
|
|
64669
|
+
fs17.removeRecursive(paths.frontdoorLockFile);
|
|
64670
|
+
ports.log(`agent-shim frontdoor supervisor: ${message}`);
|
|
64633
64671
|
return 1;
|
|
64634
64672
|
};
|
|
64635
|
-
writeFrontDoorState(
|
|
64673
|
+
writeFrontDoorState(fs17, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
|
|
64636
64674
|
const previousSticky = lastPort;
|
|
64637
64675
|
let http5;
|
|
64638
64676
|
try {
|
|
@@ -64641,7 +64679,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
64641
64679
|
return fail(`could not start the provider listener: ${error62 instanceof Error ? error62.message : String(error62)}`);
|
|
64642
64680
|
}
|
|
64643
64681
|
if (previousSticky !== void 0 && http5.port !== previousSticky) {
|
|
64644
|
-
ports.log(`
|
|
64682
|
+
ports.log(`agent-shim frontdoor supervisor: sticky port ${String(previousSticky)} was occupied; moving to ${String(http5.port)} (sessions launched against the old port are stale until they relaunch)`);
|
|
64645
64683
|
}
|
|
64646
64684
|
lastPort = http5.port;
|
|
64647
64685
|
const previousStickyConnect = lastConnectPort;
|
|
@@ -64653,7 +64691,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
64653
64691
|
return fail(`could not start the CONNECT surface: ${error62 instanceof Error ? error62.message : String(error62)}`);
|
|
64654
64692
|
}
|
|
64655
64693
|
if (previousStickyConnect !== void 0 && connect2.port !== previousStickyConnect) {
|
|
64656
|
-
ports.log(`
|
|
64694
|
+
ports.log(`agent-shim frontdoor supervisor: sticky CONNECT port ${String(previousStickyConnect)} was occupied; moving to ${String(connect2.port)} (OAuth sessions launched against the old port are stale until they relaunch)`);
|
|
64657
64695
|
}
|
|
64658
64696
|
lastConnectPort = connect2.port;
|
|
64659
64697
|
const previousStickyDirect = lastDirectPort;
|
|
@@ -64666,12 +64704,12 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
64666
64704
|
return fail(`could not start the direct listener: ${error62 instanceof Error ? error62.message : String(error62)}`);
|
|
64667
64705
|
}
|
|
64668
64706
|
if (previousStickyDirect !== void 0 && direct.port !== previousStickyDirect) {
|
|
64669
|
-
ports.log(`
|
|
64707
|
+
ports.log(`agent-shim frontdoor supervisor: sticky direct port ${String(previousStickyDirect)} was occupied; moving to ${String(direct.port)} (headroom must be restarted to admit the new address)`);
|
|
64670
64708
|
}
|
|
64671
64709
|
lastDirectPort = direct.port;
|
|
64672
|
-
writeFrontDoorState(
|
|
64673
|
-
|
|
64674
|
-
ports.log(`
|
|
64710
|
+
writeFrontDoorState(fs17, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, port: http5.port, connectPort: connect2.port, directPort: direct.port, ...sticky() });
|
|
64711
|
+
fs17.removeRecursive(paths.frontdoorLockFile);
|
|
64712
|
+
ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http5.port)}, CONNECT surface on 127.0.0.1:${String(connect2.port)}`);
|
|
64675
64713
|
let idleSince;
|
|
64676
64714
|
let ticks = 0;
|
|
64677
64715
|
for (; ; ) {
|
|
@@ -64679,15 +64717,15 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
64679
64717
|
return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
|
|
64680
64718
|
}
|
|
64681
64719
|
ticks += 1;
|
|
64682
|
-
pruneDeadFrontDoorSessions(
|
|
64683
|
-
if (listFrontDoorSessions(
|
|
64720
|
+
pruneDeadFrontDoorSessions(fs17, paths.frontdoorSessionsDir, ports.isRunning);
|
|
64721
|
+
if (listFrontDoorSessions(fs17, paths.frontdoorSessionsDir).length === 0) {
|
|
64684
64722
|
idleSince ??= ports.now();
|
|
64685
64723
|
if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
|
|
64686
|
-
ports.log(`
|
|
64724
|
+
ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
|
|
64687
64725
|
await direct.close();
|
|
64688
64726
|
await connect2.close();
|
|
64689
64727
|
await http5.close();
|
|
64690
|
-
writeFrontDoorState(
|
|
64728
|
+
writeFrontDoorState(fs17, paths.frontdoorStateFile, sticky());
|
|
64691
64729
|
return 0;
|
|
64692
64730
|
}
|
|
64693
64731
|
} else {
|
|
@@ -64723,7 +64761,7 @@ var CONNECT_LIMITS = {
|
|
|
64723
64761
|
};
|
|
64724
64762
|
var CA_VALIDITY_DAYS = 3650;
|
|
64725
64763
|
var LEAF_VALIDITY_DAYS = 397;
|
|
64726
|
-
var CA_SUBJECT_COMMON_NAME = "
|
|
64764
|
+
var CA_SUBJECT_COMMON_NAME = "agent-shim front door CA";
|
|
64727
64765
|
var MS_PER_DAY = 864e5;
|
|
64728
64766
|
function parseConnectTarget(authority) {
|
|
64729
64767
|
const colon = authority.lastIndexOf(":");
|
|
@@ -65118,7 +65156,7 @@ function realConnectEffects() {
|
|
|
65118
65156
|
response.destroy(error62);
|
|
65119
65157
|
return;
|
|
65120
65158
|
}
|
|
65121
|
-
const body = `
|
|
65159
|
+
const body = `agent-shim headroom: upstream unreachable (${error62.message})`;
|
|
65122
65160
|
response.writeHead(HTTP_BAD_GATEWAY, { "content-type": "text/plain", "content-length": String(body.length) });
|
|
65123
65161
|
response.end(body);
|
|
65124
65162
|
});
|
|
@@ -65136,7 +65174,7 @@ function isEnoent5(error62) {
|
|
|
65136
65174
|
function realConnectCertStore(paths) {
|
|
65137
65175
|
const read = (file2) => {
|
|
65138
65176
|
try {
|
|
65139
|
-
return
|
|
65177
|
+
return fs11.readFileSync(file2, "utf8");
|
|
65140
65178
|
} catch (error62) {
|
|
65141
65179
|
if (isEnoent5(error62)) {
|
|
65142
65180
|
return void 0;
|
|
@@ -65151,10 +65189,10 @@ function realConnectCertStore(paths) {
|
|
|
65151
65189
|
return certPem === void 0 || keyPem2 === void 0 ? void 0 : { certPem, keyPem: keyPem2 };
|
|
65152
65190
|
},
|
|
65153
65191
|
writeCa: (ca) => {
|
|
65154
|
-
|
|
65155
|
-
|
|
65156
|
-
|
|
65157
|
-
|
|
65192
|
+
fs11.mkdirSync(paths.frontdoorCaDir, { recursive: true });
|
|
65193
|
+
fs11.writeFileSync(paths.frontdoorCaCertFile, ca.certPem, "utf8");
|
|
65194
|
+
fs11.writeFileSync(paths.frontdoorCaKeyFile, ca.keyPem, { encoding: "utf8", mode: CA_KEY_FILE_MODE });
|
|
65195
|
+
fs11.chmodSync(paths.frontdoorCaKeyFile, CA_KEY_FILE_MODE);
|
|
65158
65196
|
}
|
|
65159
65197
|
};
|
|
65160
65198
|
}
|
|
@@ -65188,13 +65226,13 @@ function ensureFrontDoor(params) {
|
|
|
65188
65226
|
}
|
|
65189
65227
|
lastRejection = `the listener on 127.0.0.1:${String(state.port)} (recorded for pid ${String(supervisorPid)}) failed authentication: ${verdict.reason}`;
|
|
65190
65228
|
if (spawned) {
|
|
65191
|
-
throw new FrontDoorStartError(`
|
|
65229
|
+
throw new FrontDoorStartError(`agent-shim: ${lastRejection}; refusing to send this session's credentials to it. Daemon log: ${paths.frontdoorLogPath}`);
|
|
65192
65230
|
}
|
|
65193
65231
|
distrusted.add(supervisorPid);
|
|
65194
65232
|
continue;
|
|
65195
65233
|
}
|
|
65196
65234
|
if (state?.lastError !== void 0) {
|
|
65197
|
-
throw new FrontDoorStartError(`
|
|
65235
|
+
throw new FrontDoorStartError(`agent-shim: the front door reported a fatal error and is not serving: ${state.lastError} (daemon log: ${paths.frontdoorLogPath})`);
|
|
65198
65236
|
}
|
|
65199
65237
|
} else if (!spawned) {
|
|
65200
65238
|
ports.fs.mkdirp(paths.frontdoorDir);
|
|
@@ -65214,7 +65252,7 @@ function ensureFrontDoor(params) {
|
|
|
65214
65252
|
if (ports.now() >= deadline) {
|
|
65215
65253
|
const lastError = state?.lastError;
|
|
65216
65254
|
throw new FrontDoorStartError(
|
|
65217
|
-
`
|
|
65255
|
+
`agent-shim: the front door did not become ready within ${String(FRONTDOOR_START_TIMEOUT_MS)}ms` + (lastError === void 0 ? "" : ` (last error: ${lastError})`) + (lastRejection === void 0 ? "" : ` (${lastRejection})`) + `. Daemon log: ${paths.frontdoorLogPath}`
|
|
65218
65256
|
);
|
|
65219
65257
|
}
|
|
65220
65258
|
ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
|
|
@@ -65253,7 +65291,7 @@ function createFrontDoorServer(pipeline, log, tls2) {
|
|
|
65253
65291
|
log(`request ${request6.method ?? "?"} ${request6.url ?? "?"} failed: ${error62 instanceof Error ? `${error62.name}: ${error62.message}` : String(error62)}`);
|
|
65254
65292
|
if (!response.headersSent) {
|
|
65255
65293
|
response.writeHead(HTTP_STATUS.internalServerError, { "Content-Type": "application/json" });
|
|
65256
|
-
response.end(JSON.stringify({ type: "error", error: { type: "api_error", message: "internal error in the
|
|
65294
|
+
response.end(JSON.stringify({ type: "error", error: { type: "api_error", message: "internal error in the agent-shim front door" } }));
|
|
65257
65295
|
} else {
|
|
65258
65296
|
response.destroy();
|
|
65259
65297
|
}
|
|
@@ -65368,7 +65406,7 @@ async function applyHeadroomHop(request6, response, upstream, deps) {
|
|
|
65368
65406
|
const port = deps.headroomPort();
|
|
65369
65407
|
if (port === void 0) {
|
|
65370
65408
|
response.start(HTTP_BAD_GATEWAY2, { "Content-Type": "application/json" });
|
|
65371
|
-
await response.write(JSON.stringify({ type: "error", error: { type: "api_error", message: "
|
|
65409
|
+
await response.write(JSON.stringify({ type: "error", error: { type: "api_error", message: "agent-shim front door: the headroom daemon is restarting" } }));
|
|
65372
65410
|
response.end();
|
|
65373
65411
|
return;
|
|
65374
65412
|
}
|
|
@@ -65426,7 +65464,7 @@ async function forwardThroughHeadroom(request6, response, target) {
|
|
|
65426
65464
|
target.log(`front door: headroom hop to 127.0.0.1:${String(port)} failed: ${error62.message}`);
|
|
65427
65465
|
if (!response.headersSent) {
|
|
65428
65466
|
response.start(HTTP_BAD_GATEWAY2, { "Content-Type": "application/json" });
|
|
65429
|
-
void response.write(JSON.stringify({ type: "error", error: { type: "api_error", message: `
|
|
65467
|
+
void response.write(JSON.stringify({ type: "error", error: { type: "api_error", message: `agent-shim front door: the headroom daemon is unreachable (${error62.message})` } })).then(() => {
|
|
65430
65468
|
response.end();
|
|
65431
65469
|
});
|
|
65432
65470
|
} else {
|
|
@@ -65599,7 +65637,7 @@ async function serveRouted(request6, deps) {
|
|
|
65599
65637
|
deps.log(`front door: route ${resolution.route.name} failed: ${error62 instanceof Error ? `${error62.name}: ${error62.message}` : String(error62)}`);
|
|
65600
65638
|
if (!response.headersSent) {
|
|
65601
65639
|
response.start(HTTP_STATUS.internalServerError, { "Content-Type": "application/json" });
|
|
65602
|
-
await response.write(errorBody(HTTP_STATUS.internalServerError, "internal error in the
|
|
65640
|
+
await response.write(errorBody(HTTP_STATUS.internalServerError, "internal error in the agent-shim front door"));
|
|
65603
65641
|
response.end();
|
|
65604
65642
|
return;
|
|
65605
65643
|
}
|
|
@@ -66268,6 +66306,7 @@ function responseHeaders2(headers) {
|
|
|
66268
66306
|
function createPassthroughRoute(name, target) {
|
|
66269
66307
|
const base = new URL(target.baseUrl);
|
|
66270
66308
|
const tls2 = base.protocol === "https:";
|
|
66309
|
+
const basePath = base.pathname.replace(/\/+$/, "");
|
|
66271
66310
|
const agent = tls2 ? new https3.Agent({ keepAlive: true }) : new http4.Agent({ keepAlive: true });
|
|
66272
66311
|
return {
|
|
66273
66312
|
name,
|
|
@@ -66283,7 +66322,7 @@ function createPassthroughRoute(name, target) {
|
|
|
66283
66322
|
host: base.hostname,
|
|
66284
66323
|
port: base.port === "" ? void 0 : Number(base.port),
|
|
66285
66324
|
method: request6.method,
|
|
66286
|
-
path: `${path36}${incoming.search}`,
|
|
66325
|
+
path: `${basePath}${path36}${incoming.search}`,
|
|
66287
66326
|
headers,
|
|
66288
66327
|
agent
|
|
66289
66328
|
};
|
|
@@ -66392,18 +66431,18 @@ var import_node_crypto12 = require("node:crypto");
|
|
|
66392
66431
|
var import_node_path28 = __toESM(require("node:path"), 1);
|
|
66393
66432
|
var BUNDLE_NAME_HEX_DIGITS = 16;
|
|
66394
66433
|
function resolveTrustBundle(params) {
|
|
66395
|
-
const { caCertFile, bundlesDir, inherited, fs:
|
|
66434
|
+
const { caCertFile, bundlesDir, inherited, fs: fs17 } = params;
|
|
66396
66435
|
if (inherited === void 0 || inherited === "" || import_node_path28.default.resolve(inherited) === import_node_path28.default.resolve(caCertFile)) {
|
|
66397
66436
|
return { path: caCertFile };
|
|
66398
66437
|
}
|
|
66399
|
-
const caPem =
|
|
66438
|
+
const caPem = fs17.readFileUtf8(caCertFile);
|
|
66400
66439
|
let inheritedPem;
|
|
66401
66440
|
try {
|
|
66402
|
-
inheritedPem =
|
|
66441
|
+
inheritedPem = fs17.readFileUtf8(inherited);
|
|
66403
66442
|
} catch (error62) {
|
|
66404
66443
|
return {
|
|
66405
66444
|
path: caCertFile,
|
|
66406
|
-
warning: `
|
|
66445
|
+
warning: `agent-shim: NODE_EXTRA_CA_CERTS names ${inherited}, which could not be read (${error62 instanceof Error ? error62.message : String(error62)}); the child trusts agent-shim's front-door CA on top of the system store, and nothing from that file`
|
|
66407
66446
|
};
|
|
66408
66447
|
}
|
|
66409
66448
|
if (inheritedPem.includes(caPem.trim())) {
|
|
@@ -66412,9 +66451,9 @@ function resolveTrustBundle(params) {
|
|
|
66412
66451
|
const combined = `${inheritedPem.trimEnd()}
|
|
66413
66452
|
${caPem}`;
|
|
66414
66453
|
const bundle = import_node_path28.default.join(bundlesDir, `${(0, import_node_crypto12.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
|
|
66415
|
-
if (!
|
|
66416
|
-
|
|
66417
|
-
|
|
66454
|
+
if (!fs17.exists(bundle)) {
|
|
66455
|
+
fs17.mkdirp(bundlesDir);
|
|
66456
|
+
fs17.writeFileAtomic(bundle, combined);
|
|
66418
66457
|
}
|
|
66419
66458
|
return { path: bundle };
|
|
66420
66459
|
}
|
|
@@ -66702,8 +66741,8 @@ function createRealQuotaRefresher(params) {
|
|
|
66702
66741
|
|
|
66703
66742
|
// src/frontdoor/commands.ts
|
|
66704
66743
|
function appendLog(paths, line) {
|
|
66705
|
-
|
|
66706
|
-
|
|
66744
|
+
import_node_fs11.default.mkdirSync(paths.logsDir, { recursive: true });
|
|
66745
|
+
import_node_fs11.default.appendFileSync(paths.frontdoorLogPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
66707
66746
|
`);
|
|
66708
66747
|
}
|
|
66709
66748
|
function liveHeadroomPort(paths) {
|
|
@@ -66794,7 +66833,7 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
66794
66833
|
log(`connect request ${request6.method ?? "?"} ${request6.url ?? "?"} failed: ${error62 instanceof Error ? `${error62.name}: ${error62.message}` : String(error62)}`);
|
|
66795
66834
|
if (!response.headersSent) {
|
|
66796
66835
|
response.writeHead(HTTP_STATUS.badGateway, { "Content-Type": "application/json" });
|
|
66797
|
-
response.end(JSON.stringify({ type: "error", error: { type: "api_error", message: "internal error in the
|
|
66836
|
+
response.end(JSON.stringify({ type: "error", error: { type: "api_error", message: "internal error in the agent-shim front door" } }));
|
|
66798
66837
|
return;
|
|
66799
66838
|
}
|
|
66800
66839
|
response.destroy();
|
|
@@ -66830,10 +66869,10 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
66830
66869
|
};
|
|
66831
66870
|
}
|
|
66832
66871
|
var realTrustBundleFs = {
|
|
66833
|
-
readFileUtf8: (file2) =>
|
|
66834
|
-
exists: (file2) =>
|
|
66872
|
+
readFileUtf8: (file2) => import_node_fs11.default.readFileSync(file2, "utf8"),
|
|
66873
|
+
exists: (file2) => import_node_fs11.default.existsSync(file2),
|
|
66835
66874
|
mkdirp: (dir) => {
|
|
66836
|
-
|
|
66875
|
+
import_node_fs11.default.mkdirSync(dir, { recursive: true });
|
|
66837
66876
|
},
|
|
66838
66877
|
writeFileAtomic: (file2, contents) => {
|
|
66839
66878
|
realFarmFs.writeFilePrivate(file2, contents);
|
|
@@ -66852,7 +66891,7 @@ function realFrontDoorPort(paths) {
|
|
|
66852
66891
|
sleep: realSleepSync,
|
|
66853
66892
|
spawnSupervisor: (layout) => spawnDetachedSupervisor(layout, "__frontdoor-supervisor", layout.frontdoorLogPath),
|
|
66854
66893
|
// Read fresh for each probe: a replacement supervisor may have regenerated an unparseable CA, and the probe must trust exactly what the serving door's leaf chains to.
|
|
66855
|
-
verifyListener: (port) => probeFrontDoorSync(port,
|
|
66894
|
+
verifyListener: (port) => probeFrontDoorSync(port, import_node_fs11.default.readFileSync(paths.frontdoorCaCertFile, "utf8"))
|
|
66856
66895
|
}
|
|
66857
66896
|
});
|
|
66858
66897
|
const trust = resolveTrustBundle({ caCertFile: paths.frontdoorCaCertFile, bundlesDir: paths.frontdoorCaBundlesDir, inherited: inheritedExtraCaCerts, fs: realTrustBundleFs });
|
|
@@ -66914,8 +66953,8 @@ function formatFrontDoorStatus(status, caCertPath) {
|
|
|
66914
66953
|
}
|
|
66915
66954
|
function registerFrontDoorCommand(program2, deps) {
|
|
66916
66955
|
const { paths } = deps;
|
|
66917
|
-
const frontdoor = withExamples(program2.command("frontdoor").description("Inspect the front-door daemon that routes every
|
|
66918
|
-
"
|
|
66956
|
+
const frontdoor = withExamples(program2.command("frontdoor").description("Inspect the front-door daemon that routes every agent-shim session."), [
|
|
66957
|
+
"agent-shim frontdoor status"
|
|
66919
66958
|
]);
|
|
66920
66959
|
withExamples(
|
|
66921
66960
|
frontdoor.command("status").description("Report the front door's supervisor, listeners, sessions, and last error. Read-only.").option("--json", "Print the status as JSON.").action((options) => {
|
|
@@ -66928,7 +66967,7 @@ function registerFrontDoorCommand(program2, deps) {
|
|
|
66928
66967
|
console.log(line);
|
|
66929
66968
|
}
|
|
66930
66969
|
}),
|
|
66931
|
-
["
|
|
66970
|
+
["agent-shim frontdoor status", "agent-shim frontdoor status --json"]
|
|
66932
66971
|
);
|
|
66933
66972
|
program2.command("__frontdoor-supervisor", { hidden: true }).description("Internal: serve the front-door routing listeners. Started by the launcher; never run by hand.").allowUnknownOption().action(async () => {
|
|
66934
66973
|
const idleShutdownMinutes = readGlobalConfig(paths)?.frontdoor?.idleShutdownMinutes ?? FRONTDOOR_DEFAULT_IDLE_SHUTDOWN_MINUTES;
|
|
@@ -67087,7 +67126,7 @@ function collectNodes(program2) {
|
|
|
67087
67126
|
const visit2 = (command, id) => {
|
|
67088
67127
|
const subcommands = help.visibleCommands(command).filter((sub) => sub.name() !== "help");
|
|
67089
67128
|
const children = new Map(subcommands.map((sub) => [sub.name(), `${id}/${sub.name()}`]));
|
|
67090
|
-
const optionWords = command.name() === "run" && id !== "root" ? LAUNCHER_FLAG_NAMES.map((flag) => ({ word: flag, description: "
|
|
67129
|
+
const optionWords = command.name() === "run" && id !== "root" ? LAUNCHER_FLAG_NAMES.map((flag) => ({ word: flag, description: "agent-shim launch flag" })) : help.visibleOptions(command).flatMap((option) => option.long === void 0 ? [] : [{ word: option.long, description: firstSentence(option.description) }]);
|
|
67091
67130
|
nodes.push({
|
|
67092
67131
|
id,
|
|
67093
67132
|
words: [...subcommands.map((sub) => ({ word: sub.name(), description: firstSentence(sub.description()) })), ...optionWords],
|
|
@@ -67111,8 +67150,8 @@ function transitionArms(nodes, indent) {
|
|
|
67111
67150
|
}
|
|
67112
67151
|
function bashScript(nodes) {
|
|
67113
67152
|
const arms = nodes.map((node2) => ` ${singleQuote(node2.id)}) candidates=${singleQuote(node2.words.map((word) => word.word).join(" "))} ;;`).join("\n");
|
|
67114
|
-
return `#
|
|
67115
|
-
|
|
67153
|
+
return `# agent-shim bash completion. Load with: source <(agent-shim completion bash)
|
|
67154
|
+
_agent_shim() {
|
|
67116
67155
|
local cur="\${COMP_WORDS[COMP_CWORD]}" node=root candidates="" i
|
|
67117
67156
|
for ((i = 1; i < COMP_CWORD; i++)); do
|
|
67118
67157
|
case "\${node}:\${COMP_WORDS[i]}" in
|
|
@@ -67124,7 +67163,7 @@ ${arms}
|
|
|
67124
67163
|
esac
|
|
67125
67164
|
COMPREPLY=($(compgen -W "\${candidates}" -- "\${cur}"))
|
|
67126
67165
|
}
|
|
67127
|
-
complete -o default -F
|
|
67166
|
+
complete -o default -F _agent_shim agent-shim ${LEGACY_COMMAND_NAME}
|
|
67128
67167
|
`;
|
|
67129
67168
|
}
|
|
67130
67169
|
function zshScript(nodes) {
|
|
@@ -67132,9 +67171,9 @@ function zshScript(nodes) {
|
|
|
67132
67171
|
const entries = node2.words.map((word) => singleQuote(`${word.word}:${word.description.replaceAll(":", "\\:")}`)).join(" ");
|
|
67133
67172
|
return ` ${singleQuote(node2.id)}) candidates=(${entries}) ;;`;
|
|
67134
67173
|
}).join("\n");
|
|
67135
|
-
return `#compdef
|
|
67136
|
-
#
|
|
67137
|
-
|
|
67174
|
+
return `#compdef agent-shim ${LEGACY_COMMAND_NAME}
|
|
67175
|
+
# agent-shim zsh completion. Load with: source <(agent-shim completion zsh), after compinit.
|
|
67176
|
+
_agent_shim() {
|
|
67138
67177
|
local node=root word
|
|
67139
67178
|
local -a candidates
|
|
67140
67179
|
for word in "\${(@)words[2,CURRENT-1]}"; do
|
|
@@ -67145,12 +67184,12 @@ ${transitionArms(nodes, " ")}
|
|
|
67145
67184
|
case "\${node}" in
|
|
67146
67185
|
${arms}
|
|
67147
67186
|
esac
|
|
67148
|
-
_describe -t commands '
|
|
67187
|
+
_describe -t commands 'agent-shim' candidates
|
|
67149
67188
|
}
|
|
67150
|
-
if [ "\${funcstack[1]}" = "
|
|
67151
|
-
|
|
67189
|
+
if [ "\${funcstack[1]}" = "_agent_shim" ]; then
|
|
67190
|
+
_agent_shim "$@"
|
|
67152
67191
|
else
|
|
67153
|
-
compdef
|
|
67192
|
+
compdef _agent_shim agent-shim ${LEGACY_COMMAND_NAME}
|
|
67154
67193
|
fi
|
|
67155
67194
|
`;
|
|
67156
67195
|
}
|
|
@@ -67161,13 +67200,13 @@ function fishScript(nodes) {
|
|
|
67161
67200
|
).join("\n");
|
|
67162
67201
|
const completions = nodes.flatMap(
|
|
67163
67202
|
(node2) => node2.words.map((word) => {
|
|
67164
|
-
const condition = fishQuote(`test (
|
|
67203
|
+
const condition = fishQuote(`test (__agent_shim_node) = ${node2.id}`);
|
|
67165
67204
|
const target = word.word.startsWith("--") ? `-l ${fishQuote(word.word.slice(2))}` : `-a ${fishQuote(word.word)}`;
|
|
67166
|
-
return `complete -c
|
|
67205
|
+
return ["agent-shim", LEGACY_COMMAND_NAME].map((command) => `complete -c ${command} -n ${condition} ${target} -d ${fishQuote(word.description)}`).join("\n");
|
|
67167
67206
|
})
|
|
67168
67207
|
).join("\n");
|
|
67169
|
-
return `#
|
|
67170
|
-
function
|
|
67208
|
+
return `# agent-shim fish completion. Load with: agent-shim completion fish | source
|
|
67209
|
+
function __agent_shim_node
|
|
67171
67210
|
set -l node root
|
|
67172
67211
|
for word in (commandline -opc)[2..-1]
|
|
67173
67212
|
switch "$node:$word"
|
|
@@ -67176,7 +67215,7 @@ ${transitions}
|
|
|
67176
67215
|
end
|
|
67177
67216
|
echo $node
|
|
67178
67217
|
end
|
|
67179
|
-
complete -c
|
|
67218
|
+
complete -c agent-shim -f
|
|
67180
67219
|
${completions}
|
|
67181
67220
|
`;
|
|
67182
67221
|
}
|
|
@@ -67212,7 +67251,7 @@ function registerCompletionCommand(program2) {
|
|
|
67212
67251
|
process.stdout.write(generateCompletion(program2, shell));
|
|
67213
67252
|
}).addHelpText(
|
|
67214
67253
|
"after",
|
|
67215
|
-
"\nExamples:\n $ source <(
|
|
67254
|
+
"\nExamples:\n $ source <(agent-shim completion bash) # in ~/.bashrc\n $ source <(agent-shim completion zsh) # in ~/.zshrc, after compinit\n $ agent-shim completion fish | source # in ~/.config/fish/config.fish"
|
|
67216
67255
|
);
|
|
67217
67256
|
}
|
|
67218
67257
|
|
|
@@ -67220,7 +67259,7 @@ function registerCompletionCommand(program2) {
|
|
|
67220
67259
|
var import_node_child_process4 = require("node:child_process");
|
|
67221
67260
|
|
|
67222
67261
|
// src/identityToken.ts
|
|
67223
|
-
var
|
|
67262
|
+
var import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
67224
67263
|
var import_node_path29 = __toESM(require("node:path"), 1);
|
|
67225
67264
|
var TOKEN_FILE_MODE = 384;
|
|
67226
67265
|
var TOKEN_DIR_MODE = 448;
|
|
@@ -67237,21 +67276,21 @@ function storeIdentityToken(paths, identityName, raw) {
|
|
|
67237
67276
|
throw new UsageError("That is not a claude setup-token token (expected it to start with sk-ant-oat). Run `claude setup-token` and pass its token on standard input.");
|
|
67238
67277
|
}
|
|
67239
67278
|
const dir = identityTokenDir(paths);
|
|
67240
|
-
|
|
67241
|
-
|
|
67279
|
+
import_node_fs12.default.mkdirSync(dir, { recursive: true, mode: TOKEN_DIR_MODE });
|
|
67280
|
+
import_node_fs12.default.chmodSync(dir, TOKEN_DIR_MODE);
|
|
67242
67281
|
const target = identityTokenPath(paths, identityName);
|
|
67243
67282
|
const temp = import_node_path29.default.join(dir, `.${identityName}.${String(process.pid)}.tmp`);
|
|
67244
|
-
|
|
67283
|
+
import_node_fs12.default.writeFileSync(temp, `${token}
|
|
67245
67284
|
`, { mode: TOKEN_FILE_MODE });
|
|
67246
|
-
|
|
67285
|
+
import_node_fs12.default.renameSync(temp, target);
|
|
67247
67286
|
return target;
|
|
67248
67287
|
}
|
|
67249
67288
|
|
|
67250
67289
|
// src/realCredentialCache.ts
|
|
67251
67290
|
var import_node_child_process3 = require("node:child_process");
|
|
67252
|
-
var
|
|
67291
|
+
var import_node_fs13 = __toESM(require("node:fs"), 1);
|
|
67253
67292
|
var import_node_path30 = __toESM(require("node:path"), 1);
|
|
67254
|
-
var KEYCHAIN_CACHE_SERVICE = "
|
|
67293
|
+
var KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
|
|
67255
67294
|
var CACHE_DIR_MODE = 448;
|
|
67256
67295
|
var CACHE_FILE_MODE = 384;
|
|
67257
67296
|
function cacheFileNameFor(owner) {
|
|
@@ -67283,7 +67322,7 @@ function createRealCredentialCache(root) {
|
|
|
67283
67322
|
read(store, owner) {
|
|
67284
67323
|
if (store === "file") {
|
|
67285
67324
|
try {
|
|
67286
|
-
return parseEntry(
|
|
67325
|
+
return parseEntry(import_node_fs13.default.readFileSync(filePath(owner), "utf8"));
|
|
67287
67326
|
} catch {
|
|
67288
67327
|
return void 0;
|
|
67289
67328
|
}
|
|
@@ -67295,12 +67334,12 @@ function createRealCredentialCache(root) {
|
|
|
67295
67334
|
write(store, owner, entry) {
|
|
67296
67335
|
const serialised = JSON.stringify(entry);
|
|
67297
67336
|
if (store === "file") {
|
|
67298
|
-
|
|
67299
|
-
|
|
67337
|
+
import_node_fs13.default.mkdirSync(dir, { recursive: true, mode: CACHE_DIR_MODE });
|
|
67338
|
+
import_node_fs13.default.chmodSync(dir, CACHE_DIR_MODE);
|
|
67300
67339
|
const target = filePath(owner);
|
|
67301
67340
|
const temp = `${target}.${String(process.pid)}.tmp`;
|
|
67302
|
-
|
|
67303
|
-
|
|
67341
|
+
import_node_fs13.default.writeFileSync(temp, serialised, { mode: CACHE_FILE_MODE });
|
|
67342
|
+
import_node_fs13.default.renameSync(temp, target);
|
|
67304
67343
|
return;
|
|
67305
67344
|
}
|
|
67306
67345
|
requireKeychain();
|
|
@@ -67313,7 +67352,7 @@ function createRealCredentialCache(root) {
|
|
|
67313
67352
|
},
|
|
67314
67353
|
remove(store, owner) {
|
|
67315
67354
|
if (store === "file") {
|
|
67316
|
-
|
|
67355
|
+
import_node_fs13.default.rmSync(filePath(owner), { force: true });
|
|
67317
67356
|
return;
|
|
67318
67357
|
}
|
|
67319
67358
|
requireKeychain();
|
|
@@ -67350,6 +67389,7 @@ function realCommandPorts(deps) {
|
|
|
67350
67389
|
ssh: (host, remoteCommand, input2) => (0, import_node_child_process4.spawnSync)("ssh", ["--", host, remoteCommand], { input: input2, stdio: ["pipe", "inherit", "inherit"] }).status
|
|
67351
67390
|
};
|
|
67352
67391
|
}
|
|
67392
|
+
var REMOTE_ROOT_SCRIPT = 'root="${AGENT_SHIM_HOME:-${CLAUDE_USE_HOME:-}}"; if [ -z "$root" ]; then if [ ! -d "$HOME/.agent-shim" ] && [ -d "$HOME/.claude-use" ]; then root="$HOME/.claude-use"; else root="$HOME/.agent-shim"; fi; fi';
|
|
67353
67393
|
var SSH_HOST_RE = /^[A-Za-z0-9._@:][A-Za-z0-9._@:-]*$/;
|
|
67354
67394
|
function credentialSubject(deps, name, asProvider) {
|
|
67355
67395
|
if (asProvider) {
|
|
@@ -67364,7 +67404,7 @@ function credentialSubject(deps, name, asProvider) {
|
|
|
67364
67404
|
throw new IdentityNotFoundError(name);
|
|
67365
67405
|
}
|
|
67366
67406
|
if (identity.credential === void 0) {
|
|
67367
|
-
throw new CredentialCommandError(`Identity "${name}" has no credential block to cache; it uses its stored login. Give it one with \`
|
|
67407
|
+
throw new CredentialCommandError(`Identity "${name}" has no credential block to cache; it uses its stored login. Give it one with \`agent-shim identity set ${name} --credential ...\`.`);
|
|
67368
67408
|
}
|
|
67369
67409
|
return { name, subject: `identity ${name}`, credential: identity.credential };
|
|
67370
67410
|
}
|
|
@@ -67372,14 +67412,14 @@ function requireCaching(subject) {
|
|
|
67372
67412
|
const cache = subject.credential.cache;
|
|
67373
67413
|
if (cache === void 0) {
|
|
67374
67414
|
const flag = subject.subject.startsWith("provider") ? `provider set ${subject.name}` : `identity set ${subject.name}`;
|
|
67375
|
-
throw new CredentialCommandError(`The credential for ${subject.subject} is not cached. Turn caching on with \`
|
|
67415
|
+
throw new CredentialCommandError(`The credential for ${subject.subject} is not cached. Turn caching on with \`agent-shim ${flag} --credential-cache-ttl 12h\` (or --credential-cache for no expiry).`);
|
|
67376
67416
|
}
|
|
67377
67417
|
return cache;
|
|
67378
67418
|
}
|
|
67379
67419
|
function registerCredentialCommand(program2, deps, ports = realCommandPorts(deps)) {
|
|
67380
67420
|
const credential = withExamples(program2.command("credential").description("Manage the credentials identities authenticate with."), [
|
|
67381
|
-
"
|
|
67382
|
-
"
|
|
67421
|
+
"agent-shim credential store work < token.txt",
|
|
67422
|
+
"agent-shim credential warm work"
|
|
67383
67423
|
]);
|
|
67384
67424
|
withExamples(
|
|
67385
67425
|
credential.command("store <identity>").description("Store a `claude setup-token` token for an identity and make it that identity's credential. The token is read from standard input and never printed.").action(async (name) => {
|
|
@@ -67395,7 +67435,7 @@ function registerCredentialCommand(program2, deps, ports = realCommandPorts(deps
|
|
|
67395
67435
|
console.log(`Identity "${name}" now authenticates with credential ${describeCredential(updated.credential)}.`);
|
|
67396
67436
|
}
|
|
67397
67437
|
}),
|
|
67398
|
-
["pbpaste |
|
|
67438
|
+
["pbpaste | agent-shim credential store work", "agent-shim credential store work < token.txt"]
|
|
67399
67439
|
);
|
|
67400
67440
|
withExamples(
|
|
67401
67441
|
credential.command("warm [identity]").description("Fetch an identity's or provider's credential from its sources now, prompting if a source needs a person, and fill its cache so later launches need no prompt. Never prints the token.").option("--provider <name>", "Warm a provider's credential instead of an identity's.").action((name, options) => {
|
|
@@ -67410,7 +67450,7 @@ function registerCredentialCommand(program2, deps, ports = realCommandPorts(deps
|
|
|
67410
67450
|
`Cached the credential for ${subject.subject} in the ${effectiveStore(block2, ports.platform)} store (${limit === void 0 ? "no expiry" : `expires after ${block2.ttl ?? ""}`}).`
|
|
67411
67451
|
);
|
|
67412
67452
|
}),
|
|
67413
|
-
["
|
|
67453
|
+
["agent-shim credential warm work", "agent-shim credential warm --provider z"]
|
|
67414
67454
|
);
|
|
67415
67455
|
withExamples(
|
|
67416
67456
|
credential.command("forget [identity]").description("Remove an identity's or provider's cached credential from every store. The next launch fetches from the sources again.").option("--provider <name>", "Forget a provider's credential instead of an identity's.").action((name, options) => {
|
|
@@ -67421,7 +67461,7 @@ function registerCredentialCommand(program2, deps, ports = realCommandPorts(deps
|
|
|
67421
67461
|
}
|
|
67422
67462
|
console.log(`Removed the cached credential for ${subject.subject}.`);
|
|
67423
67463
|
}),
|
|
67424
|
-
["
|
|
67464
|
+
["agent-shim credential forget work", "agent-shim credential forget --provider z"]
|
|
67425
67465
|
);
|
|
67426
67466
|
withExamples(
|
|
67427
67467
|
credential.command("push <identity> <host>").description("Read an identity's credential here and write it to the credential cache on another host over SSH (mode 0600, token on standard input), so that host needs no 1Password. The identity must cache with the file store on that host.").option("--provider <name>", "Push a provider's credential instead; <identity> is then ignored.").action((name, host, options) => {
|
|
@@ -67435,15 +67475,15 @@ function registerCredentialCommand(program2, deps, ports = realCommandPorts(deps
|
|
|
67435
67475
|
throw new CredentialCommandError(resolution.message, CREDENTIAL_UNAVAILABLE_EXIT);
|
|
67436
67476
|
}
|
|
67437
67477
|
const entry = JSON.stringify({ token: resolution.credential.token, fetchedAt: resolution.credential.cachedAt ?? ports.now(), source: resolution.credential.source });
|
|
67438
|
-
const remoteFile = `"
|
|
67439
|
-
const remoteDir =
|
|
67440
|
-
const status = ports.ssh(host,
|
|
67478
|
+
const remoteFile = `"$root/credential-cache/${cacheFileNameFor(subject.subject)}"`;
|
|
67479
|
+
const remoteDir = '"$root/credential-cache"';
|
|
67480
|
+
const status = ports.ssh(host, `${REMOTE_ROOT_SCRIPT} && umask 077 && mkdir -p ${remoteDir} && cat > ${remoteFile}`, entry);
|
|
67441
67481
|
if (status !== 0) {
|
|
67442
67482
|
throw new CredentialCommandError(`Could not write the credential cache for ${subject.subject} on ${host} (ssh exited ${status === null ? "without a status" : String(status)}).`);
|
|
67443
67483
|
}
|
|
67444
|
-
console.log(`Wrote the credential for ${subject.subject} to ${host}. There, set the credential's cache store to file: \`
|
|
67484
|
+
console.log(`Wrote the credential for ${subject.subject} to ${host}. There, set the credential's cache store to file: \`agent-shim ${subject.subject.startsWith("provider") ? "provider" : "identity"} set ${subject.name} --credential-cache-store file\`.`);
|
|
67445
67485
|
}),
|
|
67446
|
-
["
|
|
67486
|
+
["agent-shim credential push work build-host", "agent-shim credential push x build-host --provider z"]
|
|
67447
67487
|
);
|
|
67448
67488
|
}
|
|
67449
67489
|
function subjectName(positional, provider) {
|
|
@@ -67455,7 +67495,7 @@ function subjectName(positional, provider) {
|
|
|
67455
67495
|
}
|
|
67456
67496
|
|
|
67457
67497
|
// src/doctor.ts
|
|
67458
|
-
var
|
|
67498
|
+
var import_node_fs14 = __toESM(require("node:fs"), 1);
|
|
67459
67499
|
var import_node_path31 = __toESM(require("node:path"), 1);
|
|
67460
67500
|
|
|
67461
67501
|
// src/headroom/source.ts
|
|
@@ -67508,24 +67548,24 @@ function validateJson(schema, input2) {
|
|
|
67508
67548
|
}
|
|
67509
67549
|
function pushPathResolution(push, resolution) {
|
|
67510
67550
|
const ownDir = import_node_path31.default.dirname(resolution.ownExecutablePath);
|
|
67511
|
-
switch (resolution.
|
|
67551
|
+
switch (resolution.agentShim.status) {
|
|
67512
67552
|
case "ok":
|
|
67513
|
-
push("path-resolution", "pass", `\`
|
|
67553
|
+
push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
|
|
67514
67554
|
break;
|
|
67515
67555
|
case "not-on-path":
|
|
67516
67556
|
push(
|
|
67517
67557
|
"path-resolution",
|
|
67518
67558
|
"warn",
|
|
67519
|
-
`${ownDir} is not on PATH, so a bare \`
|
|
67520
|
-
"
|
|
67559
|
+
`${ownDir} is not on PATH, so a bare \`agent-shim\` does not reach ${resolution.ownExecutablePath}. Add it to PATH, or keep invoking this executable by its full path.`,
|
|
67560
|
+
"agent-shim"
|
|
67521
67561
|
);
|
|
67522
67562
|
break;
|
|
67523
67563
|
case "shadowed":
|
|
67524
67564
|
push(
|
|
67525
67565
|
"path-resolution",
|
|
67526
67566
|
"fail",
|
|
67527
|
-
`\`
|
|
67528
|
-
"
|
|
67567
|
+
`\`agent-shim\` on PATH resolves to ${resolution.agentShim.by}, not this running executable, ${resolution.ownExecutablePath}. Every command you type runs that one instead, at whatever version it happens to be \u2014 including the checks in this report, which describe this executable. Remove ${resolution.agentShim.by}, repoint it at ${resolution.ownExecutablePath}, or put ${ownDir} ahead of it on PATH.`,
|
|
67568
|
+
"agent-shim"
|
|
67529
67569
|
);
|
|
67530
67570
|
break;
|
|
67531
67571
|
}
|
|
@@ -67537,13 +67577,13 @@ function pushPathResolution(push, resolution) {
|
|
|
67537
67577
|
push("path-resolution", "pass", "`claude` on PATH resolves to the enabled shim.", "claude");
|
|
67538
67578
|
break;
|
|
67539
67579
|
case "not-on-path":
|
|
67540
|
-
push("path-resolution", "warn", "The enabled `claude` shim's directory is not on PATH \u2014 add it, or use `
|
|
67580
|
+
push("path-resolution", "warn", "The enabled `claude` shim's directory is not on PATH \u2014 add it, or use `agent-shim run` instead.", "claude");
|
|
67541
67581
|
break;
|
|
67542
67582
|
case "shadowed":
|
|
67543
67583
|
push(
|
|
67544
67584
|
"path-resolution",
|
|
67545
67585
|
"warn",
|
|
67546
|
-
`\`claude\` on PATH resolves to ${resolution.claude.by}, not the enabled shim. Put the shim's directory ahead of it on PATH, or run \`
|
|
67586
|
+
`\`claude\` on PATH resolves to ${resolution.claude.by}, not the enabled shim. Put the shim's directory ahead of it on PATH, or run \`agent-shim shim disable\` if you meant to launch that one directly.`,
|
|
67547
67587
|
"claude"
|
|
67548
67588
|
);
|
|
67549
67589
|
break;
|
|
@@ -67573,6 +67613,23 @@ function pushProvider(push, entry) {
|
|
|
67573
67613
|
}
|
|
67574
67614
|
push("provider", "pass", `${entry.name} is valid (${describeProviderEndpoint(validated.data)}, credential ${describeCredential(validated.data.credential)}).`, entry.name);
|
|
67575
67615
|
}
|
|
67616
|
+
function pushLegacyName(push, params) {
|
|
67617
|
+
const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
|
|
67618
|
+
if (legacyVariables.length === 0 && import_node_path31.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
|
|
67619
|
+
push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
|
|
67620
|
+
return;
|
|
67621
|
+
}
|
|
67622
|
+
for (const name of legacyVariables) {
|
|
67623
|
+
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);
|
|
67624
|
+
}
|
|
67625
|
+
if (import_node_path31.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
|
|
67626
|
+
push(
|
|
67627
|
+
"legacy-name",
|
|
67628
|
+
"warn",
|
|
67629
|
+
`The state root is the former ${params.rootPath}, used in place. Leave it where it is: macOS Claude Code keys each identity's Keychain login on its exact configuration directory path, so moving it signs every identity out.`
|
|
67630
|
+
);
|
|
67631
|
+
}
|
|
67632
|
+
}
|
|
67576
67633
|
function runDoctor(params) {
|
|
67577
67634
|
const findings = [];
|
|
67578
67635
|
const push = (section, severity, message, subject) => {
|
|
@@ -67592,21 +67649,22 @@ function runDoctor(params) {
|
|
|
67592
67649
|
push("binary-discovery", "fail", params.binaryDiscovery.message);
|
|
67593
67650
|
}
|
|
67594
67651
|
if (params.claudeShim.state === void 0) {
|
|
67595
|
-
push("claude-shim", "pass", "No `claude` command shim enabled (the default). Run `
|
|
67652
|
+
push("claude-shim", "pass", "No `claude` command shim enabled (the default). Run `agent-shim shim enable` to add one.");
|
|
67596
67653
|
} else if (!params.claudeShim.targetExists) {
|
|
67597
67654
|
push(
|
|
67598
67655
|
"claude-shim",
|
|
67599
67656
|
"warn",
|
|
67600
|
-
`claude-shim.json records a \`claude\` shim at ${params.claudeShim.state.targetPath}, but nothing is there. Run \`
|
|
67657
|
+
`claude-shim.json records a \`claude\` shim at ${params.claudeShim.state.targetPath}, but nothing is there. Run \`agent-shim shim enable\` again, or \`agent-shim shim disable\` to clear the stale record.`
|
|
67601
67658
|
);
|
|
67602
67659
|
} else {
|
|
67603
67660
|
push(
|
|
67604
67661
|
"claude-shim",
|
|
67605
67662
|
"pass",
|
|
67606
|
-
`\`claude\` is enabled at ${params.claudeShim.state.targetPath} (${params.claudeShim.state.method}). If you've upgraded
|
|
67663
|
+
`\`claude\` is enabled at ${params.claudeShim.state.targetPath} (${params.claudeShim.state.method}). If you've upgraded agent-shim since, re-run \`agent-shim shim enable\` to refresh it.`
|
|
67607
67664
|
);
|
|
67608
67665
|
}
|
|
67609
67666
|
pushPathResolution(push, params.pathResolution);
|
|
67667
|
+
pushLegacyName(push, params);
|
|
67610
67668
|
const profileSources = /* @__PURE__ */ new Map();
|
|
67611
67669
|
for (const entry of params.configProfiles) {
|
|
67612
67670
|
const validated = validateJson(ConfigProfileSchema, entry);
|
|
@@ -67804,6 +67862,7 @@ var SECTION_TITLES = {
|
|
|
67804
67862
|
"binary-discovery": "Claude Code binary discovery",
|
|
67805
67863
|
"claude-shim": "`claude` command shim",
|
|
67806
67864
|
"path-resolution": "PATH resolution",
|
|
67865
|
+
"legacy-name": "Former `claude-use` name",
|
|
67807
67866
|
"config-profile": "Configuration profiles",
|
|
67808
67867
|
identity: "Identities",
|
|
67809
67868
|
pool: "Pools",
|
|
@@ -67862,7 +67921,7 @@ function formatDoctorReport(report) {
|
|
|
67862
67921
|
}
|
|
67863
67922
|
function realpathOrSelf(target) {
|
|
67864
67923
|
try {
|
|
67865
|
-
return
|
|
67924
|
+
return import_node_fs14.default.realpathSync(target);
|
|
67866
67925
|
} catch {
|
|
67867
67926
|
return target;
|
|
67868
67927
|
}
|
|
@@ -67870,20 +67929,20 @@ function realpathOrSelf(target) {
|
|
|
67870
67929
|
function registerDoctorCommand(program2, deps) {
|
|
67871
67930
|
const { paths } = deps;
|
|
67872
67931
|
const command = program2.command("doctor").description(
|
|
67873
|
-
"Audit the whole ~/.
|
|
67932
|
+
"Audit the whole ~/.agent-shim config graph: every identity, every configuration profile's extends chain, every provider, directory-rules.json, config.json, categories.local.json, active-identity, and real Claude Code binary discoverability. Identity/directory-agnostic, unlike `check`. Exits 1 when any check fails."
|
|
67874
67933
|
).option("--json", "Print the report as JSON.").action((options) => {
|
|
67875
|
-
const identityNames =
|
|
67934
|
+
const identityNames = import_node_fs14.default.existsSync(paths.identitiesDir) ? import_node_fs14.default.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
|
|
67876
67935
|
const identities = identityNames.map((name) => {
|
|
67877
67936
|
const farmRoot = import_node_path31.default.join(paths.identitiesDir, name);
|
|
67878
67937
|
const identityPath = import_node_path31.default.join(farmRoot, "identity.json");
|
|
67879
67938
|
return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
|
|
67880
67939
|
});
|
|
67881
|
-
const profileNames =
|
|
67940
|
+
const profileNames = import_node_fs14.default.existsSync(paths.configProfilesDir) ? import_node_fs14.default.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
67882
67941
|
const configProfiles = profileNames.map((name) => {
|
|
67883
67942
|
const profilePath = import_node_path31.default.join(paths.configProfilesDir, `${name}.json`);
|
|
67884
67943
|
return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
|
|
67885
67944
|
});
|
|
67886
|
-
const providerNames =
|
|
67945
|
+
const providerNames = import_node_fs14.default.existsSync(paths.providersDir) ? import_node_fs14.default.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
67887
67946
|
const providers = providerNames.map((name) => {
|
|
67888
67947
|
const providerPath = import_node_path31.default.join(paths.providersDir, `${name}.json`);
|
|
67889
67948
|
return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
|
|
@@ -67918,14 +67977,15 @@ function registerDoctorCommand(program2, deps) {
|
|
|
67918
67977
|
categoriesLocal: { path: paths.categoriesLocalFile, raw: realFsPort.readFileUtf8(paths.categoriesLocalFile) },
|
|
67919
67978
|
activeIdentity: { path: paths.activeIdentityFile, raw: realFsPort.readFileUtf8(paths.activeIdentityFile) },
|
|
67920
67979
|
binaryDiscovery,
|
|
67921
|
-
claudeShim: { state: shimState, targetExists: shimState !== void 0 &&
|
|
67980
|
+
claudeShim: { state: shimState, targetExists: shimState !== void 0 && import_node_fs14.default.existsSync(shimState.targetPath) },
|
|
67981
|
+
rootPath: paths.root,
|
|
67922
67982
|
pathResolution: {
|
|
67923
67983
|
ownExecutablePath,
|
|
67924
|
-
|
|
67984
|
+
agentShim: refinePathShadow(
|
|
67925
67985
|
findPathShadow({
|
|
67926
67986
|
pathDirs,
|
|
67927
67987
|
targetDir: import_node_path31.default.dirname(ownExecutablePath),
|
|
67928
|
-
targetFilename: commandFilename(ownExecutablePath, "
|
|
67988
|
+
targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
|
|
67929
67989
|
findExecutableInDir
|
|
67930
67990
|
}),
|
|
67931
67991
|
ownExecutablePath,
|
|
@@ -67951,11 +68011,11 @@ function registerDoctorCommand(program2, deps) {
|
|
|
67951
68011
|
process.exitCode = 1;
|
|
67952
68012
|
}
|
|
67953
68013
|
});
|
|
67954
|
-
withExamples(command, ["
|
|
68014
|
+
withExamples(command, ["agent-shim doctor", "agent-shim doctor --json"]);
|
|
67955
68015
|
}
|
|
67956
68016
|
|
|
67957
68017
|
// src/headroom/commands.ts
|
|
67958
|
-
var
|
|
68018
|
+
var import_node_fs15 = __toESM(require("node:fs"), 1);
|
|
67959
68019
|
var import_node_net3 = __toESM(require("node:net"), 1);
|
|
67960
68020
|
var import_node_path32 = __toESM(require("node:path"), 1);
|
|
67961
68021
|
var import_node_child_process5 = require("node:child_process");
|
|
@@ -68088,32 +68148,32 @@ function compareVersions2(a2, b) {
|
|
|
68088
68148
|
}
|
|
68089
68149
|
var HEADROOM_SUPERVISOR_STILL_RUNNING = -1;
|
|
68090
68150
|
async function runSupervisor(initialConfig, ports, options = {}) {
|
|
68091
|
-
const { fs:
|
|
68151
|
+
const { fs: fs17, paths } = ports;
|
|
68092
68152
|
let config2 = initialConfig;
|
|
68093
|
-
const previousState = readHeadroomState(
|
|
68153
|
+
const previousState = readHeadroomState(fs17, paths.headroomStateFile);
|
|
68094
68154
|
if (previousState?.supervisorPid !== void 0 && previousState.supervisorPid !== ports.ownPid && ports.isRunning(previousState.supervisorPid)) {
|
|
68095
|
-
ports.log(`
|
|
68155
|
+
ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: supervisor ${String(previousState.supervisorPid)} already owns the daemon; exiting`);
|
|
68096
68156
|
return 0;
|
|
68097
68157
|
}
|
|
68098
68158
|
let installedSource = previousState?.installedSource;
|
|
68099
68159
|
let lastPort = previousState?.lastPort;
|
|
68100
68160
|
const sticky = () => lastPort === void 0 ? {} : { lastPort };
|
|
68101
68161
|
const ownsState = () => {
|
|
68102
|
-
const owner = readHeadroomState(
|
|
68162
|
+
const owner = readHeadroomState(fs17, paths.headroomStateFile)?.supervisorPid;
|
|
68103
68163
|
return owner === void 0 || owner === ports.ownPid || !ports.isRunning(owner);
|
|
68104
68164
|
};
|
|
68105
68165
|
const writeOwnState = (state) => {
|
|
68106
68166
|
if (!ownsState()) {
|
|
68107
68167
|
return false;
|
|
68108
68168
|
}
|
|
68109
|
-
writeHeadroomState(
|
|
68169
|
+
writeHeadroomState(fs17, paths.headroomStateFile, state);
|
|
68110
68170
|
return true;
|
|
68111
68171
|
};
|
|
68112
68172
|
const fail = (message) => {
|
|
68113
68173
|
if (writeOwnState({ lastError: message, ...sticky() })) {
|
|
68114
|
-
|
|
68174
|
+
fs17.removeRecursive(paths.headroomLockFile);
|
|
68115
68175
|
}
|
|
68116
|
-
ports.log(`
|
|
68176
|
+
ports.log(`agent-shim headroom supervisor: ${message}`);
|
|
68117
68177
|
return 1;
|
|
68118
68178
|
};
|
|
68119
68179
|
const ensureInstalled = () => {
|
|
@@ -68125,7 +68185,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
68125
68185
|
installedSource = config2.source;
|
|
68126
68186
|
return true;
|
|
68127
68187
|
}
|
|
68128
|
-
ports.log(`
|
|
68188
|
+
ports.log(`agent-shim headroom supervisor: installing headroom from ${config2.source}`);
|
|
68129
68189
|
const result = ports.install(config2.source);
|
|
68130
68190
|
if (!result.ok) {
|
|
68131
68191
|
return false;
|
|
@@ -68138,10 +68198,10 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
68138
68198
|
}
|
|
68139
68199
|
const version2 = ports.headroomVersion() ?? "unknown";
|
|
68140
68200
|
writeOwnState({ supervisorPid: ports.ownPid, version: version2, installedSource, ...sticky() });
|
|
68141
|
-
ports.log(`
|
|
68201
|
+
ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${allowlistOf(ports).join(", ")}]`);
|
|
68142
68202
|
const orphanPid = previousState?.headroomPid;
|
|
68143
68203
|
if (orphanPid !== void 0 && ports.isRunning(orphanPid)) {
|
|
68144
|
-
ports.log(`
|
|
68204
|
+
ports.log(`agent-shim headroom supervisor: stopping daemon pid ${String(orphanPid)} left behind by the previous supervisor`);
|
|
68145
68205
|
ports.stopProcess(orphanPid);
|
|
68146
68206
|
}
|
|
68147
68207
|
let headroomPid;
|
|
@@ -68160,16 +68220,16 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
68160
68220
|
const settingsHash = hashSettings(config2.settings);
|
|
68161
68221
|
const allowlist = allowlistOf(ports);
|
|
68162
68222
|
const allowlistHash = hashAllowlist(allowlist);
|
|
68163
|
-
pruneDeadSessions(
|
|
68223
|
+
pruneDeadSessions(fs17, paths.headroomSessionsDir, ports.isRunning);
|
|
68164
68224
|
const ownsNow = ownsState();
|
|
68165
68225
|
if (!ownsNow && !superseded) {
|
|
68166
|
-
ports.log("
|
|
68226
|
+
ports.log("agent-shim headroom supervisor: another supervisor now owns state.json; serving this daemon's own sessions until they end");
|
|
68167
68227
|
}
|
|
68168
68228
|
superseded = !ownsNow;
|
|
68169
68229
|
const crashed = headroomPid !== void 0 && !ports.isRunning(headroomPid);
|
|
68170
68230
|
if (headroomPid === void 0 || crashed) {
|
|
68171
68231
|
if (crashed) {
|
|
68172
|
-
ports.log(`
|
|
68232
|
+
ports.log(`agent-shim headroom supervisor: headroom pid ${String(headroomPid)} died`);
|
|
68173
68233
|
headroomPid = void 0;
|
|
68174
68234
|
runningHash = void 0;
|
|
68175
68235
|
runningSettingsHash = void 0;
|
|
@@ -68198,7 +68258,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
68198
68258
|
lastPort = port;
|
|
68199
68259
|
if (previousSticky !== void 0 && port !== previousSticky) {
|
|
68200
68260
|
ports.log(
|
|
68201
|
-
`
|
|
68261
|
+
`agent-shim headroom supervisor: sticky port ${String(previousSticky)} was occupied; moving to ${String(port)} (sessions launched against the old port are stale until they relaunch)`
|
|
68202
68262
|
);
|
|
68203
68263
|
}
|
|
68204
68264
|
const recorded = writeOwnState({
|
|
@@ -68212,23 +68272,23 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
68212
68272
|
...sticky()
|
|
68213
68273
|
});
|
|
68214
68274
|
if (recorded) {
|
|
68215
|
-
|
|
68275
|
+
fs17.removeRecursive(paths.headroomLockFile);
|
|
68216
68276
|
}
|
|
68217
68277
|
idleSince = void 0;
|
|
68218
|
-
ports.log(`
|
|
68278
|
+
ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on 127.0.0.1:${String(port)}`);
|
|
68219
68279
|
} else {
|
|
68220
68280
|
ports.stopProcess(pid);
|
|
68221
68281
|
consecutiveFailures += 1;
|
|
68222
68282
|
ports.log(
|
|
68223
|
-
`
|
|
68283
|
+
`agent-shim headroom supervisor: headroom did not become ready on port ${String(port)} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
|
|
68224
68284
|
);
|
|
68225
68285
|
await ports.sleep(backoffForAttempt(consecutiveFailures));
|
|
68226
68286
|
continue;
|
|
68227
68287
|
}
|
|
68228
68288
|
} else {
|
|
68229
68289
|
if (runningHash !== allowlistHash || runningSettingsHash !== settingsHash || installedSource !== config2.source) {
|
|
68230
|
-
if (sessionsForSupervisor(
|
|
68231
|
-
ports.log("
|
|
68290
|
+
if (sessionsForSupervisor(fs17, paths.headroomSessionsDir, ports.ownPid).length === 0) {
|
|
68291
|
+
ports.log("agent-shim headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
|
|
68232
68292
|
ports.stopProcess(headroomPid);
|
|
68233
68293
|
headroomPid = void 0;
|
|
68234
68294
|
runningHash = void 0;
|
|
@@ -68236,13 +68296,13 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
68236
68296
|
continue;
|
|
68237
68297
|
}
|
|
68238
68298
|
}
|
|
68239
|
-
const sessions = sessionsForSupervisor(
|
|
68299
|
+
const sessions = sessionsForSupervisor(fs17, paths.headroomSessionsDir, ports.ownPid);
|
|
68240
68300
|
if (sessions.length === 0) {
|
|
68241
68301
|
idleSince ??= ports.now();
|
|
68242
68302
|
const idleMs = ports.now() - idleSince;
|
|
68243
68303
|
if (idleMs >= config2.idleShutdownMinutes * MS_PER_MINUTE2) {
|
|
68244
68304
|
ports.log(
|
|
68245
|
-
`
|
|
68305
|
+
`agent-shim headroom supervisor: no sessions for ${String(config2.idleShutdownMinutes)} minute(s); stopping headroom and exiting`
|
|
68246
68306
|
);
|
|
68247
68307
|
ports.stopProcess(headroomPid);
|
|
68248
68308
|
writeOwnState({
|
|
@@ -68258,9 +68318,9 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
68258
68318
|
await ports.sleep(HEADROOM_POLL_MS);
|
|
68259
68319
|
}
|
|
68260
68320
|
}
|
|
68261
|
-
function currentHeadroomAllowlist(
|
|
68262
|
-
const providers = readAllProviders(
|
|
68263
|
-
return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(
|
|
68321
|
+
function currentHeadroomAllowlist(fs17, paths) {
|
|
68322
|
+
const providers = readAllProviders(fs17, paths.providersDir).map((entry) => entry.provider);
|
|
68323
|
+
return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(fs17, paths.frontdoorStateFile))));
|
|
68264
68324
|
}
|
|
68265
68325
|
function allowlistOf(ports) {
|
|
68266
68326
|
return currentHeadroomAllowlist(ports.fs, ports.paths);
|
|
@@ -68401,8 +68461,8 @@ function realSupervisorPorts(paths) {
|
|
|
68401
68461
|
isPortFree: realIsPortFree,
|
|
68402
68462
|
readConfig: () => resolveSupervisorConfig(readGlobalConfig(paths)?.headroom ?? {}),
|
|
68403
68463
|
spawnHeadroom: (port, allowlist, settings2) => {
|
|
68404
|
-
|
|
68405
|
-
const logFd =
|
|
68464
|
+
import_node_fs15.default.mkdirSync(paths.logsDir, { recursive: true });
|
|
68465
|
+
const logFd = import_node_fs15.default.openSync(paths.headroomLogPath, "a");
|
|
68406
68466
|
try {
|
|
68407
68467
|
const child = (0, import_node_child_process5.spawn)("headroom", ["proxy", "--host", "127.0.0.1", "--port", String(port), ...settingsArgs(settings2)], {
|
|
68408
68468
|
detached: true,
|
|
@@ -68417,12 +68477,12 @@ function realSupervisorPorts(paths) {
|
|
|
68417
68477
|
child.once("exit", (code, signal) => {
|
|
68418
68478
|
ownedHeadroom.delete(pid);
|
|
68419
68479
|
exitedHeadroom.add(pid);
|
|
68420
|
-
|
|
68480
|
+
import_node_fs15.default.appendFileSync(paths.headroomLogPath, `${(/* @__PURE__ */ new Date()).toISOString()} agent-shim headroom supervisor: headroom exited (${signal ?? `code ${String(code)}`})
|
|
68421
68481
|
`);
|
|
68422
68482
|
});
|
|
68423
68483
|
return pid;
|
|
68424
68484
|
} finally {
|
|
68425
|
-
|
|
68485
|
+
import_node_fs15.default.closeSync(logFd);
|
|
68426
68486
|
}
|
|
68427
68487
|
},
|
|
68428
68488
|
stopProcess: (pid) => {
|
|
@@ -68435,9 +68495,9 @@ function realSupervisorPorts(paths) {
|
|
|
68435
68495
|
now: () => Date.now()
|
|
68436
68496
|
});
|
|
68437
68497
|
if (outcome === "still-running") {
|
|
68438
|
-
|
|
68498
|
+
import_node_fs15.default.appendFileSync(
|
|
68439
68499
|
paths.headroomLogPath,
|
|
68440
|
-
`${(/* @__PURE__ */ new Date()).toISOString()}
|
|
68500
|
+
`${(/* @__PURE__ */ new Date()).toISOString()} agent-shim headroom supervisor: pid ${String(pid)} survived SIGKILL within its grace; it is stuck uninterruptibly
|
|
68441
68501
|
`
|
|
68442
68502
|
);
|
|
68443
68503
|
}
|
|
@@ -68456,10 +68516,10 @@ function realSupervisorPorts(paths) {
|
|
|
68456
68516
|
return { ok: false, error: `uv is not installed or not on PATH (${result.error.message})` };
|
|
68457
68517
|
}
|
|
68458
68518
|
if (result.stdout !== "") {
|
|
68459
|
-
|
|
68519
|
+
import_node_fs15.default.appendFileSync(paths.headroomLogPath, result.stdout);
|
|
68460
68520
|
}
|
|
68461
68521
|
if (result.stderr !== "") {
|
|
68462
|
-
|
|
68522
|
+
import_node_fs15.default.appendFileSync(paths.headroomLogPath, result.stderr);
|
|
68463
68523
|
}
|
|
68464
68524
|
return result.status === 0 ? { ok: true } : { ok: false, error: `uv tool install exited ${String(result.status)}` };
|
|
68465
68525
|
},
|
|
@@ -68469,8 +68529,8 @@ function realSupervisorPorts(paths) {
|
|
|
68469
68529
|
},
|
|
68470
68530
|
installedCommit: readInstalledHeadroomCommit,
|
|
68471
68531
|
log: (line) => {
|
|
68472
|
-
|
|
68473
|
-
|
|
68532
|
+
import_node_fs15.default.mkdirSync(paths.logsDir, { recursive: true });
|
|
68533
|
+
import_node_fs15.default.appendFileSync(paths.headroomLogPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
68474
68534
|
`);
|
|
68475
68535
|
}
|
|
68476
68536
|
};
|
|
@@ -68478,7 +68538,7 @@ function realSupervisorPorts(paths) {
|
|
|
68478
68538
|
function registerHeadroomCommand(program2, deps) {
|
|
68479
68539
|
const { paths } = deps;
|
|
68480
68540
|
const headroom = withExamples(program2.command("headroom").description("Inspect the headroom routing daemon."), [
|
|
68481
|
-
"
|
|
68541
|
+
"agent-shim headroom status"
|
|
68482
68542
|
]);
|
|
68483
68543
|
withExamples(
|
|
68484
68544
|
headroom.command("status").description("Report the headroom daemon's supervisor, process, port, sessions, and last error. Read-only.").option("--json", "Print the status as JSON.").action((options) => {
|
|
@@ -68491,7 +68551,7 @@ function registerHeadroomCommand(program2, deps) {
|
|
|
68491
68551
|
console.log(line);
|
|
68492
68552
|
}
|
|
68493
68553
|
}),
|
|
68494
|
-
["
|
|
68554
|
+
["agent-shim headroom status", "agent-shim headroom status --json"]
|
|
68495
68555
|
);
|
|
68496
68556
|
program2.command("__headroom-supervisor", { hidden: true }).description("Internal: supervise the headroom daemon. Started by the launcher; never run by hand.").allowUnknownOption().action(async () => {
|
|
68497
68557
|
const globalConfig2 = readGlobalConfig(paths);
|
|
@@ -68518,7 +68578,7 @@ function registerHeadroomCommand(program2, deps) {
|
|
|
68518
68578
|
// src/runCommand.ts
|
|
68519
68579
|
function registerRunCommand(program2, handler) {
|
|
68520
68580
|
program2.command("run").description(
|
|
68521
|
-
"Launch Claude Code under an identity, without needing a `claude`-named binary on PATH. Launch flags (see `
|
|
68581
|
+
"Launch Claude Code under an identity, without needing a `claude`-named binary on PATH. Launch flags (see `agent-shim --help`) are consumed first; every other argument is forwarded exactly as `claude` would receive it."
|
|
68522
68582
|
).allowUnknownOption().passThroughOptions().helpOption(false).argument("[args...]", "Arguments to forward, e.g. @<name>, --config-profile <name>, or any Claude Code flag.").action(async (args) => {
|
|
68523
68583
|
await handler(args);
|
|
68524
68584
|
});
|
|
@@ -68531,14 +68591,14 @@ function requireIdentity(paths, name) {
|
|
|
68531
68591
|
throw new IdentityNotFoundError(name);
|
|
68532
68592
|
}
|
|
68533
68593
|
}
|
|
68534
|
-
function collectUsageReport(
|
|
68594
|
+
function collectUsageReport(fs17, paths, filters) {
|
|
68535
68595
|
const { identity, provider, sinceMs } = filters;
|
|
68536
68596
|
if (identity !== void 0) {
|
|
68537
68597
|
requireIdentity(paths, identity);
|
|
68538
68598
|
}
|
|
68539
|
-
const log = readUsageLog(
|
|
68599
|
+
const log = readUsageLog(fs17, paths.usageLogDir, sinceMs === void 0 ? {} : { sinceMs });
|
|
68540
68600
|
const records = log.records.filter((record2) => (identity === void 0 || record2.identity === identity) && (provider === void 0 || record2.provider === provider));
|
|
68541
|
-
const snapshots = (identity === void 0 ? listUsageSnapshots(
|
|
68601
|
+
const snapshots = (identity === void 0 ? listUsageSnapshots(fs17, paths.usageSnapshotsDir) : [readUsageSnapshot(fs17, paths.usageSnapshotsDir, identity)].flatMap((snapshot) => snapshot === void 0 ? [] : [snapshot])).map((snapshot) => provider === void 0 ? snapshot : { ...snapshot, providers: Object.fromEntries(Object.entries(snapshot.providers).filter(([name]) => name === provider)) }).filter((snapshot) => Object.keys(snapshot.providers).length > 0);
|
|
68542
68602
|
return {
|
|
68543
68603
|
since: sinceMs === void 0 ? void 0 : new Date(sinceMs).toISOString(),
|
|
68544
68604
|
logDir: paths.usageLogDir,
|
|
@@ -68634,15 +68694,15 @@ function formatUsageReport(report) {
|
|
|
68634
68694
|
}
|
|
68635
68695
|
return lines;
|
|
68636
68696
|
}
|
|
68637
|
-
function collectAccounts(
|
|
68697
|
+
function collectAccounts(fs17, paths, identity) {
|
|
68638
68698
|
if (identity !== void 0) {
|
|
68639
68699
|
requireIdentity(paths, identity);
|
|
68640
68700
|
}
|
|
68641
68701
|
const names = identity === void 0 ? listIdentities(paths).map((entry) => entry.name) : [identity];
|
|
68642
68702
|
return names.map((name) => ({
|
|
68643
68703
|
identity: name,
|
|
68644
|
-
account: readAccountMetadata(
|
|
68645
|
-
usage: readUsageSnapshot(
|
|
68704
|
+
account: readAccountMetadata(fs17, paths.identitiesDir, name),
|
|
68705
|
+
usage: readUsageSnapshot(fs17, paths.usageSnapshotsDir, name)
|
|
68646
68706
|
}));
|
|
68647
68707
|
}
|
|
68648
68708
|
function formatAccounts(views) {
|
|
@@ -68722,10 +68782,10 @@ function registerUsageCommands(program2, deps) {
|
|
|
68722
68782
|
console.log(line);
|
|
68723
68783
|
}
|
|
68724
68784
|
}),
|
|
68725
|
-
["
|
|
68785
|
+
["agent-shim usage", "agent-shim usage --identity work --since 5h", "agent-shim usage --provider z --refresh --json"]
|
|
68726
68786
|
);
|
|
68727
68787
|
const account = withExamples(program2.command("account").description("Inspect the Claude account behind each identity: plan, tier and latest quota."), [
|
|
68728
|
-
"
|
|
68788
|
+
"agent-shim account show work"
|
|
68729
68789
|
]);
|
|
68730
68790
|
withExamples(
|
|
68731
68791
|
account.command("show [identity]").description("Show an identity's account metadata (read live from its stored login) and its latest recorded quota; every identity when none is named. Read-only.").option("--refresh", "First fetch the quota of providers that report it through their own usage endpoint (z.ai), regardless of how fresh the stored one is.").option("--json", "Print the accounts as JSON.").action(async (identity, options) => {
|
|
@@ -68743,21 +68803,21 @@ function registerUsageCommands(program2, deps) {
|
|
|
68743
68803
|
console.log(line);
|
|
68744
68804
|
}
|
|
68745
68805
|
}),
|
|
68746
|
-
["
|
|
68806
|
+
["agent-shim account show", "agent-shim account show work", "agent-shim account show work --json"]
|
|
68747
68807
|
);
|
|
68748
68808
|
}
|
|
68749
68809
|
|
|
68750
68810
|
// src/program.ts
|
|
68751
68811
|
var ROOT_HELP_AFTER = `
|
|
68752
68812
|
Grammar:
|
|
68753
|
-
|
|
68813
|
+
agent-shim <noun> <verb> [name] [options], where the nouns are identity, profile,
|
|
68754
68814
|
provider and rule, and the verbs are add, set, list, show, remove and use.
|
|
68755
68815
|
credential is the exception: it acts on the credentials identities use (store).
|
|
68756
68816
|
|
|
68757
68817
|
Launching:
|
|
68758
|
-
|
|
68759
|
-
Everything after run is forwarded to Claude Code, so \`
|
|
68760
|
-
claude's own help.
|
|
68818
|
+
agent-shim run [@<identity>] [launch flags] [claude arguments]
|
|
68819
|
+
Everything after run is forwarded to Claude Code, so \`agent-shim run --help\` shows
|
|
68820
|
+
claude's own help. agent-shim consumes these launch flags first, and only before a
|
|
68761
68821
|
\`--\` terminator (everything from \`--\` on is forwarded untouched):
|
|
68762
68822
|
--identity <name> the identity (same as a leading @<name>)
|
|
68763
68823
|
--config-profile <name> the configuration profile for this launch
|
|
@@ -68768,22 +68828,22 @@ Launching:
|
|
|
68768
68828
|
--[no-]wait with @pool:<name>, sleep until the earliest member returns when all are refused
|
|
68769
68829
|
|
|
68770
68830
|
Environment:
|
|
68771
|
-
|
|
68772
|
-
|
|
68773
|
-
|
|
68774
|
-
|
|
68831
|
+
AGENT_SHIM_IDENTITY, AGENT_SHIM_CONFIG_PROFILE, AGENT_SHIM_SKIP_PERMISSIONS,
|
|
68832
|
+
AGENT_SHIM_REMOTE_CONTROL, AGENT_SHIM_HEADROOM, AGENT_SHIM_TRACK_USAGE, AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL,
|
|
68833
|
+
AGENT_SHIM_CATEGORY_OVERRIDE, AGENT_SHIM_ENTRY_OVERRIDE, AGENT_SHIM_HOME,
|
|
68834
|
+
AGENT_SHIM_DEBUG (print stack traces), NO_COLOR. Booleans are true, false, 1 or 0.
|
|
68775
68835
|
|
|
68776
68836
|
Exit status:
|
|
68777
68837
|
0 success, 1 failure, 2 usage error, 64 a selected provider's or identity's credential
|
|
68778
68838
|
yields no token.
|
|
68779
68839
|
|
|
68780
68840
|
Examples:
|
|
68781
|
-
$
|
|
68782
|
-
$
|
|
68783
|
-
$
|
|
68841
|
+
$ agent-shim identity add work
|
|
68842
|
+
$ agent-shim run @work
|
|
68843
|
+
$ agent-shim run --identity work --provider z -p "hello"`;
|
|
68784
68844
|
function buildProgram(deps) {
|
|
68785
68845
|
const program2 = new Command();
|
|
68786
|
-
program2.name("
|
|
68846
|
+
program2.name("agent-shim").description("Run Claude Code under several logins from one machine, controlling what each one shares with ~/.claude.").version(package_default.version).exitOverride().enablePositionalOptions().addHelpText("after", ROOT_HELP_AFTER);
|
|
68787
68847
|
registerIdentityCommand(program2, deps);
|
|
68788
68848
|
registerProfileCommand(program2, deps);
|
|
68789
68849
|
registerPoolCommand(program2, deps);
|
|
@@ -68859,8 +68919,8 @@ function parseOverride(source, raw, parse3) {
|
|
|
68859
68919
|
}
|
|
68860
68920
|
function buildCliOverride(params) {
|
|
68861
68921
|
let categoryPairs = {};
|
|
68862
|
-
if (params.env.
|
|
68863
|
-
categoryPairs = parseOverride("
|
|
68922
|
+
if (params.env.AGENT_SHIM_CATEGORY_OVERRIDE !== void 0 && params.env.AGENT_SHIM_CATEGORY_OVERRIDE !== "") {
|
|
68923
|
+
categoryPairs = parseOverride("AGENT_SHIM_CATEGORY_OVERRIDE", params.env.AGENT_SHIM_CATEGORY_OVERRIDE, parseBoolPairList);
|
|
68864
68924
|
}
|
|
68865
68925
|
for (const flagValue of params.categoryFlags) {
|
|
68866
68926
|
const pair = parseOverride("--category", flagValue, (raw) => {
|
|
@@ -68870,8 +68930,8 @@ function buildCliOverride(params) {
|
|
|
68870
68930
|
categoryPairs[pair.key] = pair.value;
|
|
68871
68931
|
}
|
|
68872
68932
|
let entryPairs = {};
|
|
68873
|
-
if (params.env.
|
|
68874
|
-
entryPairs = parseOverride("
|
|
68933
|
+
if (params.env.AGENT_SHIM_ENTRY_OVERRIDE !== void 0 && params.env.AGENT_SHIM_ENTRY_OVERRIDE !== "") {
|
|
68934
|
+
entryPairs = parseOverride("AGENT_SHIM_ENTRY_OVERRIDE", params.env.AGENT_SHIM_ENTRY_OVERRIDE, parseBoolPairList);
|
|
68875
68935
|
}
|
|
68876
68936
|
for (const entryPath of params.shareFlags) {
|
|
68877
68937
|
entryPairs[entryPath] = true;
|
|
@@ -68930,10 +68990,10 @@ function parseCustomHeaderLine(line) {
|
|
|
68930
68990
|
// src/launcher/flags.ts
|
|
68931
68991
|
function resolveLaunchFlags(params) {
|
|
68932
68992
|
return {
|
|
68933
|
-
skipPermissions: params.flags?.skipPermissions ?? parseEnvBool("
|
|
68934
|
-
remoteControl: params.flags?.remoteControl ?? parseEnvBool("
|
|
68935
|
-
headroom: params.flags?.headroom ?? parseEnvBool("
|
|
68936
|
-
trackUsage: params.flags?.trackUsage ?? parseEnvBool("
|
|
68993
|
+
skipPermissions: params.flags?.skipPermissions ?? parseEnvBool("AGENT_SHIM_SKIP_PERMISSIONS", params.env.AGENT_SHIM_SKIP_PERMISSIONS) ?? params.cascade?.skipPermissions ?? false,
|
|
68994
|
+
remoteControl: params.flags?.remoteControl ?? parseEnvBool("AGENT_SHIM_REMOTE_CONTROL", params.env.AGENT_SHIM_REMOTE_CONTROL) ?? params.cascade?.remoteControl ?? false,
|
|
68995
|
+
headroom: params.flags?.headroom ?? parseEnvBool("AGENT_SHIM_HEADROOM", params.env.AGENT_SHIM_HEADROOM) ?? params.cascade?.headroom ?? false,
|
|
68996
|
+
trackUsage: params.flags?.trackUsage ?? parseEnvBool("AGENT_SHIM_TRACK_USAGE", params.env.AGENT_SHIM_TRACK_USAGE) ?? params.cascade?.trackUsage ?? params.trackUsageDefault ?? false
|
|
68937
68997
|
};
|
|
68938
68998
|
}
|
|
68939
68999
|
function buildFlagArgs(flags) {
|
|
@@ -68973,7 +69033,7 @@ function buildEnv(params) {
|
|
|
68973
69033
|
env.NO_PROXY = withLoopbackHosts(params.baseEnv.NO_PROXY);
|
|
68974
69034
|
env.no_proxy = withLoopbackHosts(params.baseEnv.no_proxy);
|
|
68975
69035
|
}
|
|
68976
|
-
env.
|
|
69036
|
+
env.AGENT_SHIM_PROVIDER = params.provider.definition.displayName;
|
|
68977
69037
|
for (const [key, value] of Object.entries(providerEnv)) {
|
|
68978
69038
|
env[key] = value;
|
|
68979
69039
|
}
|
|
@@ -69049,19 +69109,19 @@ function spawnClaude(params) {
|
|
|
69049
69109
|
// src/launcher.ts
|
|
69050
69110
|
function resolveIdentityCredential(identity, credential, env, port) {
|
|
69051
69111
|
if (port === void 0) {
|
|
69052
|
-
return { ok: false, status: 1, message: `
|
|
69112
|
+
return { ok: false, status: 1, message: `agent-shim: identity ${identity} needs its credential resolved, but this launcher has no credential port wired` };
|
|
69053
69113
|
}
|
|
69054
69114
|
const resolution = resolveCredential({ credential, env, port, subject: `identity ${identity}` });
|
|
69055
69115
|
return resolution.ok ? resolution : { ok: false, status: CREDENTIAL_UNAVAILABLE_EXIT, message: resolution.message };
|
|
69056
69116
|
}
|
|
69057
69117
|
function pickFromPool(decided, params, parsedArgv) {
|
|
69058
|
-
const { paths, fs:
|
|
69118
|
+
const { paths, fs: fs17, proc, log } = params;
|
|
69059
69119
|
if (decided.pool === void 0) {
|
|
69060
69120
|
return { identityDecision: decided };
|
|
69061
69121
|
}
|
|
69062
69122
|
const farmRuntime = params.farm;
|
|
69063
69123
|
if (farmRuntime === void 0) {
|
|
69064
|
-
log.error(`
|
|
69124
|
+
log.error(`agent-shim: pool "${decided.pool}" was selected, but this launcher has no farm wired to read usage and pick a member with.`);
|
|
69065
69125
|
return proc.exit(1);
|
|
69066
69126
|
}
|
|
69067
69127
|
const resolution = resolvePoolLaunch({
|
|
@@ -69069,7 +69129,7 @@ function pickFromPool(decided, params, parsedArgv) {
|
|
|
69069
69129
|
selectedVia: decided.source,
|
|
69070
69130
|
pools: params.pools,
|
|
69071
69131
|
paths,
|
|
69072
|
-
fs:
|
|
69132
|
+
fs: fs17,
|
|
69073
69133
|
usageFs: farmRuntime.fs,
|
|
69074
69134
|
cwd: farmRuntime.cwd,
|
|
69075
69135
|
now: farmRuntime.now,
|
|
@@ -69085,7 +69145,7 @@ function pickFromPool(decided, params, parsedArgv) {
|
|
|
69085
69145
|
return { identityDecision: { ...decided, name: resolution.identity }, poolExplanation: resolution.explanation };
|
|
69086
69146
|
}
|
|
69087
69147
|
function runLauncher(params) {
|
|
69088
|
-
const { paths, fs:
|
|
69148
|
+
const { paths, fs: fs17, spawn: spawn3, proc, log } = params;
|
|
69089
69149
|
const { env, argv } = proc;
|
|
69090
69150
|
const parsedArgv = parseLauncherArgv(argv);
|
|
69091
69151
|
const cliOverride = buildCliOverride({
|
|
@@ -69100,7 +69160,7 @@ function runLauncher(params) {
|
|
|
69100
69160
|
argv0Identity: parsedArgv.identity,
|
|
69101
69161
|
directoryPinnedIdentity: params.directoryPinnedIdentity,
|
|
69102
69162
|
readActiveIdentityFile: () => {
|
|
69103
|
-
const raw =
|
|
69163
|
+
const raw = fs17.readFileUtf8(paths.activeIdentityFile);
|
|
69104
69164
|
if (raw === void 0) {
|
|
69105
69165
|
return void 0;
|
|
69106
69166
|
}
|
|
@@ -69130,15 +69190,15 @@ function runLauncher(params) {
|
|
|
69130
69190
|
throw error62;
|
|
69131
69191
|
}
|
|
69132
69192
|
for (const diagnostic of recoveryDiagnostics(recovery, farmIdentity)) {
|
|
69133
|
-
log.warn(`
|
|
69193
|
+
log.warn(`agent-shim: ${diagnostic.code}: ${diagnostic.message}`);
|
|
69134
69194
|
}
|
|
69135
69195
|
}
|
|
69136
69196
|
let loadedIdentity;
|
|
69137
69197
|
if (identityDecision.name !== void 0) {
|
|
69138
|
-
loadedIdentity = loadIdentity(paths.identitiesDir, identityDecision.name,
|
|
69198
|
+
loadedIdentity = loadIdentity(paths.identitiesDir, identityDecision.name, fs17);
|
|
69139
69199
|
if (loadedIdentity === void 0) {
|
|
69140
69200
|
log.error(
|
|
69141
|
-
`
|
|
69201
|
+
`agent-shim: no identity named "${identityDecision.name}" (selected via ${identityDecision.source}). Run \`agent-shim identity add ${identityDecision.name}\` first.`
|
|
69142
69202
|
);
|
|
69143
69203
|
proc.exit(1);
|
|
69144
69204
|
}
|
|
@@ -69150,16 +69210,16 @@ function runLauncher(params) {
|
|
|
69150
69210
|
identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
|
|
69151
69211
|
globalDefaultConfigProfile: params.globalDefaultConfigProfile
|
|
69152
69212
|
});
|
|
69153
|
-
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true &&
|
|
69213
|
+
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs17.readConfigFile(import_node_path34.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
|
|
69154
69214
|
log.error(
|
|
69155
|
-
`
|
|
69215
|
+
`agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
|
|
69156
69216
|
);
|
|
69157
69217
|
proc.exit(1);
|
|
69158
69218
|
}
|
|
69159
69219
|
const farmContext = farm !== void 0 && farmIdentity !== void 0 ? { farm, identity: farmIdentity, cascade: farm.loadCascade(configProfileDecision.name, cliOverride) } : void 0;
|
|
69160
69220
|
const provider = parsedArgv.provider === false ? void 0 : resolveProvider({
|
|
69161
69221
|
paths,
|
|
69162
|
-
port:
|
|
69222
|
+
port: fs17,
|
|
69163
69223
|
env,
|
|
69164
69224
|
...params.credentials === void 0 ? {} : { credentials: params.credentials },
|
|
69165
69225
|
...parsedArgv.provider === void 0 ? {} : { cliProvider: parsedArgv.provider },
|
|
@@ -69183,7 +69243,7 @@ function runLauncher(params) {
|
|
|
69183
69243
|
if (!(error62 instanceof UsageSnapshotError)) {
|
|
69184
69244
|
throw error62;
|
|
69185
69245
|
}
|
|
69186
|
-
log.warn(`
|
|
69246
|
+
log.warn(`agent-shim: ${error62.message}`);
|
|
69187
69247
|
}
|
|
69188
69248
|
}
|
|
69189
69249
|
const identityCredentialBlock = loadedIdentity?.config.credential;
|
|
@@ -69199,7 +69259,7 @@ function runLauncher(params) {
|
|
|
69199
69259
|
const guardResult = evaluateAmbientCredentialGuard({
|
|
69200
69260
|
env,
|
|
69201
69261
|
allowAmbientCredential: loadedIdentity?.config.allowAmbientCredential ?? false,
|
|
69202
|
-
allowAmbientCredentialOverride: parseEnvBool("
|
|
69262
|
+
allowAmbientCredentialOverride: parseEnvBool("AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL", env.AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL) === true,
|
|
69203
69263
|
identityName: identityDecision.name,
|
|
69204
69264
|
providerSelected: resolvedProvider !== void 0,
|
|
69205
69265
|
...identityCredential === void 0 ? {} : { injectedCredential: { variable: CREDENTIAL_TARGET_VARS[identityCredential.target], token: identityCredential.token } }
|
|
@@ -69209,7 +69269,7 @@ function runLauncher(params) {
|
|
|
69209
69269
|
proc.exit(1);
|
|
69210
69270
|
}
|
|
69211
69271
|
log.info(
|
|
69212
|
-
`
|
|
69272
|
+
`agent-shim: identity ${identityDecision.name ?? "(none)"} (${identityDecision.source}${poolExplanation === void 0 ? "" : `, ${poolExplanation}`}), config profile ${configProfileDecision.name ?? "(none)"} (${configProfileDecision.source})` + (resolvedProvider === void 0 ? "" : `, provider ${resolvedProvider.name} (credential ${resolvedProvider.credential.target} from ${describeSource(resolvedProvider.credential.source)})`) + (identityCredential === void 0 ? "" : `, identity credential ${identityCredential.target} from ${describeSource(identityCredential.source)}`)
|
|
69213
69273
|
);
|
|
69214
69274
|
let cascadeLaunch;
|
|
69215
69275
|
if (farmContext !== void 0) {
|
|
@@ -69242,13 +69302,13 @@ function runLauncher(params) {
|
|
|
69242
69302
|
}
|
|
69243
69303
|
for (const diagnostic of result.diagnostics) {
|
|
69244
69304
|
if (diagnostic.severity === "error") {
|
|
69245
|
-
log.error(`
|
|
69305
|
+
log.error(`agent-shim: ${diagnostic.code}: ${diagnostic.message}`);
|
|
69246
69306
|
} else if (diagnostic.severity === "warning") {
|
|
69247
|
-
log.warn(`
|
|
69307
|
+
log.warn(`agent-shim: ${diagnostic.code}: ${diagnostic.message}`);
|
|
69248
69308
|
}
|
|
69249
69309
|
}
|
|
69250
69310
|
log.info(
|
|
69251
|
-
result.noOp ? `
|
|
69311
|
+
result.noOp ? `agent-shim: farm at ${result.farmRoot} already matches the resolved cascade` : `agent-shim: farm at ${result.farmRoot} resynced (${String(result.manifest.links.length)} link(s), ${String(result.manifest.materialised.length)} built director(ies)${result.adopted.length === 0 ? "" : `, ${String(result.adopted.length)} adopted into ${resyncFarmRuntime.claudeHome}`})`
|
|
69252
69312
|
);
|
|
69253
69313
|
cascadeLaunch = result.resolved.flattened.launch;
|
|
69254
69314
|
} else if (params.farm !== void 0) {
|
|
@@ -69270,7 +69330,7 @@ function runLauncher(params) {
|
|
|
69270
69330
|
const frontDoorPort = params.frontdoor;
|
|
69271
69331
|
const frontDoorEngaged = resolvedProvider !== void 0 || resolvedFlags.headroom || resolvedFlags.trackUsage;
|
|
69272
69332
|
if (frontDoorEngaged && frontDoorPort === void 0) {
|
|
69273
|
-
log.error("
|
|
69333
|
+
log.error("agent-shim: this launch routes through the front-door daemon, but this launcher has no front-door port wired; refusing to launch without it.");
|
|
69274
69334
|
proc.exit(1);
|
|
69275
69335
|
}
|
|
69276
69336
|
const frontDoor = frontDoorEngaged && frontDoorPort !== void 0 ? frontDoorPort.ensure(env.NODE_EXTRA_CA_CERTS) : void 0;
|
|
@@ -69286,12 +69346,12 @@ function runLauncher(params) {
|
|
|
69286
69346
|
if (resolvedFlags.headroom && headroomPort !== void 0) {
|
|
69287
69347
|
headroom = headroomPort.ensure();
|
|
69288
69348
|
const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
|
|
69289
|
-
log.info(`
|
|
69349
|
+
log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor?.port ?? 0)} with headroom on 127.0.0.1:${String(headroom.port)} (${via}, project ${headroom.projectId})`);
|
|
69290
69350
|
} else if (resolvedFlags.headroom) {
|
|
69291
|
-
log.error("
|
|
69351
|
+
log.error("agent-shim: headroom routing was requested but this launcher has no headroom port wired; refusing to launch without it.");
|
|
69292
69352
|
proc.exit(1);
|
|
69293
69353
|
} else if (frontDoor !== void 0) {
|
|
69294
|
-
log.info(`
|
|
69354
|
+
log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor.port)}${resolvedProvider === void 0 ? ` (OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor.connectPort)}, usage recorded)` : ` (provider ${resolvedProvider.name})`}`);
|
|
69295
69355
|
}
|
|
69296
69356
|
const frontDoorRelease = frontDoor === void 0 ? void 0 : frontDoorPort?.release;
|
|
69297
69357
|
const finalArgv = buildArgv({
|
|
@@ -69442,7 +69502,8 @@ async function runClaude(argvOverride) {
|
|
|
69442
69502
|
|
|
69443
69503
|
// src/cli.ts
|
|
69444
69504
|
async function main() {
|
|
69445
|
-
|
|
69505
|
+
aliasLegacyEnv(process.env);
|
|
69506
|
+
const invokedName = import_node_path35.default.basename(process.argv[1] ?? "agent-shim");
|
|
69446
69507
|
if (isInvokedAsClaude(invokedName)) {
|
|
69447
69508
|
await runClaude();
|
|
69448
69509
|
return;
|