@oxagen/cli 2.1.4-443 → 2.1.4-453
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/oxagen.mjs +719 -319
- package/package.json +1 -1
package/oxagen.mjs
CHANGED
|
@@ -7838,6 +7838,7 @@ function sessionScopeForEnrollment(next, previous) {
|
|
|
7838
7838
|
function harnessFilesRecord(paths) {
|
|
7839
7839
|
return {
|
|
7840
7840
|
claude_settings: paths.claudeSettings,
|
|
7841
|
+
claude_user_config: paths.claudeUserConfig,
|
|
7841
7842
|
codex_hooks: paths.codexHooks,
|
|
7842
7843
|
cursor_hooks: [...paths.cursorHooks],
|
|
7843
7844
|
stella_toml: paths.stellaToml,
|
|
@@ -7852,6 +7853,9 @@ function withRecordedHarnessFiles(paths, host) {
|
|
|
7852
7853
|
return {
|
|
7853
7854
|
...paths,
|
|
7854
7855
|
claudeSettings,
|
|
7856
|
+
// A record from before #5287 has no entry, and the host it describes
|
|
7857
|
+
// never had the Oxagen MCP server written, so this process's path stands.
|
|
7858
|
+
claudeUserConfig: record.claude_user_config ?? paths.claudeUserConfig,
|
|
7855
7859
|
claudeProjects: record.claude_settings !== void 0 ? join3(dirname3(claudeSettings), "projects") : paths.claudeProjects,
|
|
7856
7860
|
codexHooks: record.codex_hooks ?? paths.codexHooks,
|
|
7857
7861
|
cursorHooks: record.cursor_hooks ?? paths.cursorHooks,
|
|
@@ -8022,6 +8026,8 @@ var init_host_file = __esm({
|
|
|
8022
8026
|
HOST_FILE_SCHEMA = "tacho.host.v1";
|
|
8023
8027
|
harnessFilesRecordSchema = external_exports.object({
|
|
8024
8028
|
claude_settings: external_exports.string().min(1),
|
|
8029
|
+
/** Claude Code's user config, which holds the Oxagen MCP server entry. */
|
|
8030
|
+
claude_user_config: external_exports.string().min(1),
|
|
8025
8031
|
codex_hooks: external_exports.string().min(1),
|
|
8026
8032
|
cursor_hooks: external_exports.array(external_exports.string().min(1)),
|
|
8027
8033
|
stella_toml: external_exports.string().min(1),
|
|
@@ -8161,6 +8167,22 @@ var init_host_file = __esm({
|
|
|
8161
8167
|
* beside ours; this is the `displaced_env` of the connected tier.
|
|
8162
8168
|
*/
|
|
8163
8169
|
displaced_mcp_servers: external_exports.record(external_exports.string(), external_exports.record(external_exports.string(), external_exports.unknown())).default({}),
|
|
8170
|
+
/**
|
|
8171
|
+
* When this enrollment last wrote the `oxagen` server into a wrapped
|
|
8172
|
+
* harness's user MCP config, by harness (#5287). Today that is only
|
|
8173
|
+
* `claude-code`. Two readers use it:
|
|
8174
|
+
*
|
|
8175
|
+
* - `oxagen agent status` adds the server once to a live enrollment
|
|
8176
|
+
* made before enroll wrote it, and an entry here says it already
|
|
8177
|
+
* did. A person who later removes the server keeps it removed until
|
|
8178
|
+
* they enroll again.
|
|
8179
|
+
* - The Stop hook asks only a session that started after this time.
|
|
8180
|
+
* Claude Code loads MCP servers when a session starts, so a session
|
|
8181
|
+
* already running when the entry was written does not have the tool.
|
|
8182
|
+
*
|
|
8183
|
+
* Optional: a host enrolled before #5287 has none.
|
|
8184
|
+
*/
|
|
8185
|
+
mcp_registered_at: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
8164
8186
|
/**
|
|
8165
8187
|
* Where the harness files were when this host enrolled
|
|
8166
8188
|
* (`harnessFilesRecord`). Optional: a host enrolled before this field
|
|
@@ -9022,6 +9044,9 @@ import { join as join6 } from "node:path";
|
|
|
9022
9044
|
function claudeConfigDirFor(env, home) {
|
|
9023
9045
|
return env["CLAUDE_CONFIG_DIR"] ?? join6(home, ".claude");
|
|
9024
9046
|
}
|
|
9047
|
+
function claudeUserConfigFor(env, home) {
|
|
9048
|
+
return join6(env["CLAUDE_CONFIG_DIR"] ?? home, ".claude.json");
|
|
9049
|
+
}
|
|
9025
9050
|
function codexHomeFor(env, home) {
|
|
9026
9051
|
return env["CODEX_HOME"] ?? join6(home, ".codex");
|
|
9027
9052
|
}
|
|
@@ -9044,6 +9069,7 @@ function tachoHome(env = process.env, home = homedir(), platform = process.platf
|
|
|
9044
9069
|
log: join6(tachoDir, "tachod.log"),
|
|
9045
9070
|
daemonLauncher: join6(tachoDir, "tachod.cmd"),
|
|
9046
9071
|
claudeSettings: join6(claudeConfigDir, "settings.json"),
|
|
9072
|
+
claudeUserConfig: claudeUserConfigFor(env, home),
|
|
9047
9073
|
claudeProjects: join6(claudeConfigDir, "projects"),
|
|
9048
9074
|
codexHooks: join6(codexHome, "hooks.json"),
|
|
9049
9075
|
cursorHooks: cursorHooksPaths(home, platform, env),
|
|
@@ -9060,6 +9086,7 @@ function homeOf(paths) {
|
|
|
9060
9086
|
log: paths.log,
|
|
9061
9087
|
daemonLauncher: paths.daemonLauncher,
|
|
9062
9088
|
claudeSettings: paths.claudeSettings,
|
|
9089
|
+
claudeUserConfig: paths.claudeUserConfig,
|
|
9063
9090
|
claudeProjects: paths.claudeProjects,
|
|
9064
9091
|
codexHooks: paths.codexHooks,
|
|
9065
9092
|
cursorHooks: paths.cursorHooks,
|
|
@@ -10044,20 +10071,26 @@ function parsePsStarts(pids, result2) {
|
|
|
10044
10071
|
}
|
|
10045
10072
|
return out;
|
|
10046
10073
|
}
|
|
10074
|
+
function psStartCommand(pids) {
|
|
10075
|
+
return [
|
|
10076
|
+
"env",
|
|
10077
|
+
[...PS_ZONE, "ps", "-o", "pid=,lstart=", "-p", pids.join(",")]
|
|
10078
|
+
];
|
|
10079
|
+
}
|
|
10047
10080
|
function readProcessStarts(pids, exec4 = psExec, platform = process.platform, read2 = readText) {
|
|
10048
10081
|
if (platform === "win32" || pids.length === 0) return void 0;
|
|
10049
10082
|
if (platform === "linux") return readProcStarts(pids, read2);
|
|
10050
|
-
return parsePsStarts(pids, exec4(
|
|
10083
|
+
return parsePsStarts(pids, exec4(...psStartCommand(pids)));
|
|
10051
10084
|
}
|
|
10052
10085
|
async function readProcessStartsAsync(pids, exec4 = psExecAsync, platform = process.platform, read2 = readText) {
|
|
10053
10086
|
if (platform === "win32" || pids.length === 0) return void 0;
|
|
10054
10087
|
if (platform === "linux") return readProcStarts(pids, read2);
|
|
10055
|
-
return parsePsStarts(pids, await exec4(
|
|
10088
|
+
return parsePsStarts(pids, await exec4(...psStartCommand(pids)));
|
|
10056
10089
|
}
|
|
10057
10090
|
function readProcessStartsNoWait(pids, exec4 = psExecAsync, platform = process.platform, read2 = readText) {
|
|
10058
10091
|
if (platform === "win32" || pids.length === 0) return void 0;
|
|
10059
10092
|
if (platform === "linux") return readProcStarts(pids, read2);
|
|
10060
|
-
return exec4(
|
|
10093
|
+
return exec4(...psStartCommand(pids)).then(
|
|
10061
10094
|
(result2) => parsePsStarts(pids, result2),
|
|
10062
10095
|
() => void 0
|
|
10063
10096
|
);
|
|
@@ -10109,20 +10142,15 @@ function processExecutable(pid) {
|
|
|
10109
10142
|
return void 0;
|
|
10110
10143
|
}
|
|
10111
10144
|
}
|
|
10112
|
-
var CLAUDE_BINARY, CLAUDE_VERSIONS_DIR, PROCESS_START_TIMEOUT_MS,
|
|
10145
|
+
var CLAUDE_BINARY, CLAUDE_VERSIONS_DIR, PROCESS_START_TIMEOUT_MS, PS_ZONE, PS_ENV, DAEMON_IMAGES;
|
|
10113
10146
|
var init_process_scan = __esm({
|
|
10114
10147
|
"../../packages/tacho/src/host/process-scan.ts"() {
|
|
10115
10148
|
"use strict";
|
|
10116
10149
|
CLAUDE_BINARY = /(^|\/)claude(\s|$)/;
|
|
10117
10150
|
CLAUDE_VERSIONS_DIR = /\/claude\/versions\/\d+\.\d+\.\d+/;
|
|
10118
10151
|
PROCESS_START_TIMEOUT_MS = 2e3;
|
|
10152
|
+
PS_ZONE = ["TZ=UTC", "LC_ALL=C", "LANG=C"];
|
|
10119
10153
|
PS_ENV = { ...process.env, TZ: "UTC", LC_ALL: "C", LANG: "C" };
|
|
10120
|
-
PS_START_ARGS = (pids) => [
|
|
10121
|
-
"-o",
|
|
10122
|
-
"pid=,lstart=",
|
|
10123
|
-
"-p",
|
|
10124
|
-
pids.join(",")
|
|
10125
|
-
];
|
|
10126
10154
|
DAEMON_IMAGES = ["tacho", "node"];
|
|
10127
10155
|
}
|
|
10128
10156
|
});
|
|
@@ -20366,6 +20394,304 @@ var init_backfill3 = __esm({
|
|
|
20366
20394
|
}
|
|
20367
20395
|
});
|
|
20368
20396
|
|
|
20397
|
+
// ../../packages/tacho/src/host/claude-code-mcp-writer.ts
|
|
20398
|
+
function mergeClaudeCodeMcpConfig(existing, config) {
|
|
20399
|
+
return mergeOxagenMcpServer(existing, config, "stdio");
|
|
20400
|
+
}
|
|
20401
|
+
function stripClaudeCodeMcpConfig(existing, enrollmentId, restore = {}) {
|
|
20402
|
+
return stripOxagenMcpServer(existing, enrollmentId, restore);
|
|
20403
|
+
}
|
|
20404
|
+
function claudeCodeSessionHasOxagenTools(check2) {
|
|
20405
|
+
if (!check2.hasGatewayKey || check2.registeredAt === void 0) return false;
|
|
20406
|
+
const registered = Date.parse(check2.registeredAt);
|
|
20407
|
+
const started = Date.parse(check2.sessionStartedAt);
|
|
20408
|
+
if (!Number.isFinite(registered) || !Number.isFinite(started)) return false;
|
|
20409
|
+
if (started < registered) return false;
|
|
20410
|
+
return oxagenMcpPresence(check2.readUserConfig(), check2.enrollmentId).present;
|
|
20411
|
+
}
|
|
20412
|
+
function claudeUserConfigShapeProblem(document) {
|
|
20413
|
+
return mcpConfigShapeProblem(document);
|
|
20414
|
+
}
|
|
20415
|
+
var init_claude_code_mcp_writer = __esm({
|
|
20416
|
+
"../../packages/tacho/src/host/claude-code-mcp-writer.ts"() {
|
|
20417
|
+
"use strict";
|
|
20418
|
+
init_mcp_config_writer();
|
|
20419
|
+
}
|
|
20420
|
+
});
|
|
20421
|
+
|
|
20422
|
+
// ../../packages/tacho/src/host/install-lock.ts
|
|
20423
|
+
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
20424
|
+
import {
|
|
20425
|
+
closeSync as closeSync3,
|
|
20426
|
+
existsSync as existsSync4,
|
|
20427
|
+
linkSync,
|
|
20428
|
+
mkdirSync as mkdirSync4,
|
|
20429
|
+
openSync as openSync3,
|
|
20430
|
+
readdirSync as readdirSync5,
|
|
20431
|
+
readFileSync as readFileSync5,
|
|
20432
|
+
renameSync as renameSync3,
|
|
20433
|
+
rmdirSync as rmdirSync3,
|
|
20434
|
+
unlinkSync as unlinkSync3,
|
|
20435
|
+
writeSync as writeSync2
|
|
20436
|
+
} from "node:fs";
|
|
20437
|
+
import { dirname as dirname4, join as join12 } from "node:path";
|
|
20438
|
+
function readLock(path2) {
|
|
20439
|
+
try {
|
|
20440
|
+
return readFileSync5(path2, "utf8");
|
|
20441
|
+
} catch {
|
|
20442
|
+
return void 0;
|
|
20443
|
+
}
|
|
20444
|
+
}
|
|
20445
|
+
function holderOf(text4) {
|
|
20446
|
+
try {
|
|
20447
|
+
return JSON.parse(text4 ?? "");
|
|
20448
|
+
} catch {
|
|
20449
|
+
return {};
|
|
20450
|
+
}
|
|
20451
|
+
}
|
|
20452
|
+
function removeQuietly(path2) {
|
|
20453
|
+
try {
|
|
20454
|
+
unlinkSync3(path2);
|
|
20455
|
+
} catch {
|
|
20456
|
+
}
|
|
20457
|
+
}
|
|
20458
|
+
function pidAlive(pid) {
|
|
20459
|
+
try {
|
|
20460
|
+
process.kill(pid, 0);
|
|
20461
|
+
return true;
|
|
20462
|
+
} catch (error) {
|
|
20463
|
+
return error.code === "EPERM";
|
|
20464
|
+
}
|
|
20465
|
+
}
|
|
20466
|
+
function acquireInstallLock(root, now = Date.now, alive = pidAlive) {
|
|
20467
|
+
const path2 = join12(root, "install.lock");
|
|
20468
|
+
const created = [];
|
|
20469
|
+
let dir = root;
|
|
20470
|
+
while (!existsSync4(dir) && dirname4(dir) !== dir) {
|
|
20471
|
+
created.unshift(dir);
|
|
20472
|
+
dir = dirname4(dir);
|
|
20473
|
+
}
|
|
20474
|
+
mkdirSync4(root, { recursive: true, mode: 448 });
|
|
20475
|
+
const token = randomBytes3(12).toString("hex");
|
|
20476
|
+
const liveHolder = (holder) => typeof holder.pid === "number" && typeof holder.at === "number" && now() - holder.at < STALE_AFTER_MS && alive(holder.pid) ? holder.pid : void 0;
|
|
20477
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
20478
|
+
try {
|
|
20479
|
+
const fd2 = openSync3(path2, "wx", 384);
|
|
20480
|
+
writeSync2(fd2, JSON.stringify({ pid: process.pid, at: now(), token }));
|
|
20481
|
+
closeSync3(fd2);
|
|
20482
|
+
return {
|
|
20483
|
+
release: () => {
|
|
20484
|
+
if (holderOf(readLock(path2)).token === token) removeQuietly(path2);
|
|
20485
|
+
for (const made of [...created].reverse()) {
|
|
20486
|
+
try {
|
|
20487
|
+
if (readdirSync5(made).length === 0) rmdirSync3(made);
|
|
20488
|
+
} catch {
|
|
20489
|
+
}
|
|
20490
|
+
}
|
|
20491
|
+
}
|
|
20492
|
+
};
|
|
20493
|
+
} catch (error) {
|
|
20494
|
+
if (error.code !== "EEXIST") throw error;
|
|
20495
|
+
const live = liveHolder(holderOf(readLock(path2)));
|
|
20496
|
+
if (live !== void 0) return { heldBy: live };
|
|
20497
|
+
const aside = `${path2}.${process.pid}.${token}.stale`;
|
|
20498
|
+
try {
|
|
20499
|
+
renameSync3(path2, aside);
|
|
20500
|
+
} catch (renameError) {
|
|
20501
|
+
if (renameError.code === "ENOENT") continue;
|
|
20502
|
+
throw renameError;
|
|
20503
|
+
}
|
|
20504
|
+
const moved = liveHolder(holderOf(readLock(aside)));
|
|
20505
|
+
if (moved !== void 0) {
|
|
20506
|
+
try {
|
|
20507
|
+
linkSync(aside, path2);
|
|
20508
|
+
} catch {
|
|
20509
|
+
}
|
|
20510
|
+
removeQuietly(aside);
|
|
20511
|
+
return { heldBy: moved };
|
|
20512
|
+
}
|
|
20513
|
+
removeQuietly(aside);
|
|
20514
|
+
}
|
|
20515
|
+
}
|
|
20516
|
+
return { heldBy: -1 };
|
|
20517
|
+
}
|
|
20518
|
+
var STALE_AFTER_MS;
|
|
20519
|
+
var init_install_lock = __esm({
|
|
20520
|
+
"../../packages/tacho/src/host/install-lock.ts"() {
|
|
20521
|
+
"use strict";
|
|
20522
|
+
STALE_AFTER_MS = 10 * 6e4;
|
|
20523
|
+
}
|
|
20524
|
+
});
|
|
20525
|
+
|
|
20526
|
+
// ../../packages/tacho/src/cli/agent-deps.ts
|
|
20527
|
+
function agentDeps(deps, paths) {
|
|
20528
|
+
if (JSON.stringify(paths) === JSON.stringify(deps.paths)) return deps;
|
|
20529
|
+
const rebound = deps.atAgent?.(paths) ?? { ...deps, paths };
|
|
20530
|
+
return {
|
|
20531
|
+
...deps,
|
|
20532
|
+
...rebound,
|
|
20533
|
+
paths,
|
|
20534
|
+
serviceManager: deps.serviceManager,
|
|
20535
|
+
out: deps.out,
|
|
20536
|
+
err: deps.err
|
|
20537
|
+
};
|
|
20538
|
+
}
|
|
20539
|
+
function depsForHarness(deps, harness) {
|
|
20540
|
+
const agent = agentHolding(deps.paths, harness);
|
|
20541
|
+
return agent === void 0 ? deps : depsForAgent(deps, agent);
|
|
20542
|
+
}
|
|
20543
|
+
function depsForAgent(deps, agent) {
|
|
20544
|
+
const host = agent.host ?? readHostFileLenient(agent.paths.hostFile).salvaged;
|
|
20545
|
+
return agentDeps(deps, withRecordedHarnessFiles(agent.paths, host));
|
|
20546
|
+
}
|
|
20547
|
+
var init_agent_deps = __esm({
|
|
20548
|
+
"../../packages/tacho/src/cli/agent-deps.ts"() {
|
|
20549
|
+
"use strict";
|
|
20550
|
+
init_agents();
|
|
20551
|
+
init_host_file();
|
|
20552
|
+
}
|
|
20553
|
+
});
|
|
20554
|
+
|
|
20555
|
+
// ../../packages/tacho/src/cli/claude-code-mcp.ts
|
|
20556
|
+
function canServeOxagenTools(host) {
|
|
20557
|
+
return host.gateway_api_key !== void 0;
|
|
20558
|
+
}
|
|
20559
|
+
function registerClaudeCodeMcp(host, deps) {
|
|
20560
|
+
const edit = deps.editClaudeUserConfig;
|
|
20561
|
+
if (edit === void 0)
|
|
20562
|
+
return {
|
|
20563
|
+
host,
|
|
20564
|
+
result: "skipped",
|
|
20565
|
+
reason: "this build cannot edit Claude Code's user config",
|
|
20566
|
+
displaced: false
|
|
20567
|
+
};
|
|
20568
|
+
if (!canServeOxagenTools(host))
|
|
20569
|
+
return {
|
|
20570
|
+
host,
|
|
20571
|
+
result: "skipped",
|
|
20572
|
+
reason: "this enrollment has no gateway key, so the collector cannot serve Oxagen's tools. Run `oxagen agent enroll --force` to enroll this machine again with one",
|
|
20573
|
+
displaced: false
|
|
20574
|
+
};
|
|
20575
|
+
const path2 = deps.paths.claudeUserConfig;
|
|
20576
|
+
const shim = host.mcp_stdio_command ?? deps.runtime.mcpStdioCommand;
|
|
20577
|
+
let current = host;
|
|
20578
|
+
if (current.harness_files?.claude_user_config !== path2) {
|
|
20579
|
+
current = {
|
|
20580
|
+
...current,
|
|
20581
|
+
harness_files: { ...current.harness_files, claude_user_config: path2 }
|
|
20582
|
+
};
|
|
20583
|
+
writeHostFile(deps.paths.hostFile, current);
|
|
20584
|
+
}
|
|
20585
|
+
let result2 = "present";
|
|
20586
|
+
let displaced = false;
|
|
20587
|
+
let wroteEntry = false;
|
|
20588
|
+
edit((document) => {
|
|
20589
|
+
const problem = claudeUserConfigShapeProblem(document);
|
|
20590
|
+
if (problem !== void 0) throw new HarnessFileError(path2, problem);
|
|
20591
|
+
const merged = mergeClaudeCodeMcpConfig(document, {
|
|
20592
|
+
enrollmentId: current.host_enrollment_id,
|
|
20593
|
+
port: current.port,
|
|
20594
|
+
localToken: current.local_token,
|
|
20595
|
+
shimCommand: shim[0],
|
|
20596
|
+
shimArgs: shim.slice(1, -1),
|
|
20597
|
+
...deps.env["TACHO_HOME"] !== void 0 ? { tachoHome: deps.env["TACHO_HOME"] } : {}
|
|
20598
|
+
});
|
|
20599
|
+
if (!merged.changed) return void 0;
|
|
20600
|
+
if (Object.keys(merged.displaced).length > 0) {
|
|
20601
|
+
displaced = true;
|
|
20602
|
+
current = {
|
|
20603
|
+
...current,
|
|
20604
|
+
displaced_mcp_servers: {
|
|
20605
|
+
...current.displaced_mcp_servers,
|
|
20606
|
+
[HARNESS]: {
|
|
20607
|
+
...current.displaced_mcp_servers[HARNESS],
|
|
20608
|
+
// The server the person put under the name most recently wins:
|
|
20609
|
+
// one there now replaced whatever an earlier run moved aside.
|
|
20610
|
+
...merged.displaced
|
|
20611
|
+
}
|
|
20612
|
+
}
|
|
20613
|
+
};
|
|
20614
|
+
writeHostFile(deps.paths.hostFile, current);
|
|
20615
|
+
}
|
|
20616
|
+
result2 = "written";
|
|
20617
|
+
wroteEntry = true;
|
|
20618
|
+
return merged.config;
|
|
20619
|
+
});
|
|
20620
|
+
if (wroteEntry || current.mcp_registered_at?.[HARNESS] === void 0) {
|
|
20621
|
+
current = {
|
|
20622
|
+
...current,
|
|
20623
|
+
mcp_registered_at: {
|
|
20624
|
+
...current.mcp_registered_at,
|
|
20625
|
+
[HARNESS]: new Date(deps.now()).toISOString()
|
|
20626
|
+
}
|
|
20627
|
+
};
|
|
20628
|
+
writeHostFile(deps.paths.hostFile, current);
|
|
20629
|
+
}
|
|
20630
|
+
return { host: current, result: result2, displaced };
|
|
20631
|
+
}
|
|
20632
|
+
function needsClaudeCodeMcp(host) {
|
|
20633
|
+
return host.revoked_at === null && host.harnesses.includes(HARNESS) && canServeOxagenTools(host) && host.mcp_registered_at?.[HARNESS] === void 0;
|
|
20634
|
+
}
|
|
20635
|
+
function addMissingClaudeCodeMcp(deps) {
|
|
20636
|
+
if (deps.editClaudeUserConfig === void 0) return [];
|
|
20637
|
+
const pending = listAgents(deps.paths).filter(
|
|
20638
|
+
(agent) => agentIsLive(agent) && needsClaudeCodeMcp(agent.host)
|
|
20639
|
+
);
|
|
20640
|
+
if (pending.length === 0) return [];
|
|
20641
|
+
const lock = acquireInstallLock(deps.paths.tachoDir, deps.now);
|
|
20642
|
+
if ("heldBy" in lock) return [];
|
|
20643
|
+
const added = [];
|
|
20644
|
+
try {
|
|
20645
|
+
for (const agent of pending) {
|
|
20646
|
+
const own = depsForAgent(deps, agent);
|
|
20647
|
+
const host = readHostFile(own.paths.hostFile);
|
|
20648
|
+
if (host === void 0 || !needsClaudeCodeMcp(host)) continue;
|
|
20649
|
+
const recorded = host.harness_files;
|
|
20650
|
+
if (recorded?.claude_user_config === void 0 && recorded?.claude_settings !== void 0 && recorded.claude_settings !== agent.paths.claudeSettings) {
|
|
20651
|
+
added.push({
|
|
20652
|
+
agentKey: host.agent_key,
|
|
20653
|
+
path: own.paths.claudeUserConfig,
|
|
20654
|
+
ok: false,
|
|
20655
|
+
problem: `this agent was enrolled with Claude Code's settings at ${recorded.claude_settings}, and this command finds them at ${agent.paths.claudeSettings}, so it cannot tell which .claude.json Claude Code reads. Run \`oxagen agent enroll\` from a shell with the CLAUDE_CONFIG_DIR you enrolled with`
|
|
20656
|
+
});
|
|
20657
|
+
continue;
|
|
20658
|
+
}
|
|
20659
|
+
try {
|
|
20660
|
+
const outcome = registerClaudeCodeMcp(host, own);
|
|
20661
|
+
added.push({
|
|
20662
|
+
agentKey: host.agent_key,
|
|
20663
|
+
path: own.paths.claudeUserConfig,
|
|
20664
|
+
ok: outcome.result !== "skipped",
|
|
20665
|
+
...outcome.reason !== void 0 ? { problem: outcome.reason } : {}
|
|
20666
|
+
});
|
|
20667
|
+
} catch (error) {
|
|
20668
|
+
added.push({
|
|
20669
|
+
agentKey: host.agent_key,
|
|
20670
|
+
path: own.paths.claudeUserConfig,
|
|
20671
|
+
ok: false,
|
|
20672
|
+
problem: error instanceof Error ? error.message : String(error)
|
|
20673
|
+
});
|
|
20674
|
+
}
|
|
20675
|
+
}
|
|
20676
|
+
} finally {
|
|
20677
|
+
lock.release();
|
|
20678
|
+
}
|
|
20679
|
+
return added;
|
|
20680
|
+
}
|
|
20681
|
+
var HARNESS;
|
|
20682
|
+
var init_claude_code_mcp = __esm({
|
|
20683
|
+
"../../packages/tacho/src/cli/claude-code-mcp.ts"() {
|
|
20684
|
+
"use strict";
|
|
20685
|
+
init_agents();
|
|
20686
|
+
init_claude_code_mcp_writer();
|
|
20687
|
+
init_harness_file();
|
|
20688
|
+
init_host_file();
|
|
20689
|
+
init_install_lock();
|
|
20690
|
+
init_agent_deps();
|
|
20691
|
+
HARNESS = "claude-code";
|
|
20692
|
+
}
|
|
20693
|
+
});
|
|
20694
|
+
|
|
20369
20695
|
// ../../packages/tacho/src/host/model-base-url-toml.ts
|
|
20370
20696
|
function splitLines(text4) {
|
|
20371
20697
|
const lines = [];
|
|
@@ -20479,13 +20805,13 @@ var init_model_base_url_toml = __esm({
|
|
|
20479
20805
|
import { createHash as createHash5 } from "node:crypto";
|
|
20480
20806
|
import {
|
|
20481
20807
|
chmodSync as chmodSync3,
|
|
20482
|
-
existsSync as
|
|
20483
|
-
mkdirSync as
|
|
20484
|
-
readFileSync as
|
|
20808
|
+
existsSync as existsSync5,
|
|
20809
|
+
mkdirSync as mkdirSync5,
|
|
20810
|
+
readFileSync as readFileSync6,
|
|
20485
20811
|
statSync as statSync3,
|
|
20486
|
-
unlinkSync as
|
|
20812
|
+
unlinkSync as unlinkSync4
|
|
20487
20813
|
} from "node:fs";
|
|
20488
|
-
import { basename as basename3, dirname as
|
|
20814
|
+
import { basename as basename3, dirname as dirname5, join as join13 } from "node:path";
|
|
20489
20815
|
function claudeToolSearchEnabled(value) {
|
|
20490
20816
|
return typeof value === "string" && /^(true|auto(:\d+)?)$/i.test(value);
|
|
20491
20817
|
}
|
|
@@ -20499,19 +20825,19 @@ function isModelProxyBaseUrl(harness, value) {
|
|
|
20499
20825
|
}
|
|
20500
20826
|
function modelBaseUrlFile(harness, homes) {
|
|
20501
20827
|
if (harness === "claude-code")
|
|
20502
|
-
return
|
|
20828
|
+
return join13(
|
|
20503
20829
|
homes.claudeConfigDir ?? harnessConfigDirs(homes.home).claudeConfigDir,
|
|
20504
20830
|
"settings.json"
|
|
20505
20831
|
);
|
|
20506
20832
|
if (harness === "codex")
|
|
20507
|
-
return
|
|
20833
|
+
return join13(
|
|
20508
20834
|
homes.codexHome ?? harnessConfigDirs(homes.home).codexHome,
|
|
20509
20835
|
"config.toml"
|
|
20510
20836
|
);
|
|
20511
|
-
const stellaHome = homes.stellaHome ??
|
|
20512
|
-
const toml =
|
|
20513
|
-
const json2 =
|
|
20514
|
-
return !
|
|
20837
|
+
const stellaHome = homes.stellaHome ?? join13(homes.home, ".stella");
|
|
20838
|
+
const toml = join13(stellaHome, "stella.toml");
|
|
20839
|
+
const json2 = join13(stellaHome, "settings.json");
|
|
20840
|
+
return !existsSync5(toml) && existsSync5(json2) ? json2 : toml;
|
|
20515
20841
|
}
|
|
20516
20842
|
function keyLabel(harness) {
|
|
20517
20843
|
if (harness === "claude-code") return `env.${CLAUDE_KEY}`;
|
|
@@ -20521,7 +20847,7 @@ function isJsonFile(file) {
|
|
|
20521
20847
|
return file.endsWith(".json");
|
|
20522
20848
|
}
|
|
20523
20849
|
function sidecarFor(file) {
|
|
20524
|
-
return
|
|
20850
|
+
return join13(dirname5(file), `.${basename3(file)}.oxagen-model-base-url.json`);
|
|
20525
20851
|
}
|
|
20526
20852
|
function modelBaseUrlBackupPath(harness, home, stellaHome, dirs = {}) {
|
|
20527
20853
|
return sidecarFor(fileFor(harness, homesOf(home, stellaHome, dirs)));
|
|
@@ -20538,9 +20864,9 @@ function sha256(text4) {
|
|
|
20538
20864
|
return createHash5("sha256").update(text4, "utf8").digest("hex");
|
|
20539
20865
|
}
|
|
20540
20866
|
function readSidecar(path2) {
|
|
20541
|
-
if (!
|
|
20867
|
+
if (!existsSync5(path2)) return void 0;
|
|
20542
20868
|
try {
|
|
20543
|
-
const parsed = JSON.parse(
|
|
20869
|
+
const parsed = JSON.parse(readFileSync6(path2, "utf8"));
|
|
20544
20870
|
if (parsed.schema !== SIDECAR_SCHEMA) return void 0;
|
|
20545
20871
|
if (typeof parsed.written_sha256 !== "string") return void 0;
|
|
20546
20872
|
return {
|
|
@@ -20565,7 +20891,7 @@ function readSidecar(path2) {
|
|
|
20565
20891
|
}
|
|
20566
20892
|
}
|
|
20567
20893
|
function writeAtomicPreserving(path2, data) {
|
|
20568
|
-
|
|
20894
|
+
mkdirSync5(dirname5(path2), { recursive: true });
|
|
20569
20895
|
let mode = 384;
|
|
20570
20896
|
let owner;
|
|
20571
20897
|
try {
|
|
@@ -20581,7 +20907,7 @@ function writeAtomicPreserving(path2, data) {
|
|
|
20581
20907
|
}
|
|
20582
20908
|
function readTextIfExists(path2) {
|
|
20583
20909
|
try {
|
|
20584
|
-
return
|
|
20910
|
+
return readFileSync6(path2, "utf8");
|
|
20585
20911
|
} catch (error) {
|
|
20586
20912
|
if (error.code === "ENOENT") return void 0;
|
|
20587
20913
|
throw error;
|
|
@@ -20672,9 +20998,9 @@ function stellaManagedSettingsPath(platform = process.platform, env = process.en
|
|
|
20672
20998
|
const named = env["STELLA_MANAGED_SETTINGS"];
|
|
20673
20999
|
if (named !== void 0 && named.length > 0) return named;
|
|
20674
21000
|
const dir = platform === "darwin" ? "/Library/Application Support/stella" : "/etc/stella";
|
|
20675
|
-
const toml =
|
|
20676
|
-
const json2 =
|
|
20677
|
-
return !
|
|
21001
|
+
const toml = join13(dir, "stella.toml");
|
|
21002
|
+
const json2 = join13(dir, "settings.json");
|
|
21003
|
+
return !existsSync5(toml) && existsSync5(json2) ? json2 : toml;
|
|
20678
21004
|
}
|
|
20679
21005
|
function managedShadow(harness, managedFile, expected) {
|
|
20680
21006
|
try {
|
|
@@ -20933,7 +21259,7 @@ function applyOne(harness, options) {
|
|
|
20933
21259
|
original_base64: orphan ? "" : (
|
|
20934
21260
|
// The raw bytes, not the decoded text: restore is byte-exact even
|
|
20935
21261
|
// for a file that is not clean UTF-8.
|
|
20936
|
-
(text4 === void 0 ? Buffer.alloc(0) :
|
|
21262
|
+
(text4 === void 0 ? Buffer.alloc(0) : readFileSync6(file)).toString("base64")
|
|
20937
21263
|
),
|
|
20938
21264
|
written_sha256: orphan ? "" : sha256(next),
|
|
20939
21265
|
previous,
|
|
@@ -20954,7 +21280,7 @@ function restoreOne(harness, options) {
|
|
|
20954
21280
|
const sidecar = readSidecar(backup);
|
|
20955
21281
|
const text4 = readTextIfExists(file);
|
|
20956
21282
|
const dropSidecar = () => {
|
|
20957
|
-
if (
|
|
21283
|
+
if (existsSync5(backup)) unlinkSync4(backup);
|
|
20958
21284
|
};
|
|
20959
21285
|
if (text4 === void 0) {
|
|
20960
21286
|
dropSidecar();
|
|
@@ -20967,7 +21293,7 @@ function restoreOne(harness, options) {
|
|
|
20967
21293
|
Buffer.from(sidecar.original_base64, "base64")
|
|
20968
21294
|
);
|
|
20969
21295
|
} else {
|
|
20970
|
-
|
|
21296
|
+
unlinkSync4(file);
|
|
20971
21297
|
}
|
|
20972
21298
|
dropSidecar();
|
|
20973
21299
|
return true;
|
|
@@ -21069,8 +21395,8 @@ var init_model_base_url = __esm({
|
|
|
21069
21395
|
});
|
|
21070
21396
|
|
|
21071
21397
|
// ../../packages/tacho/src/host/run-token.ts
|
|
21072
|
-
import { createHmac, randomBytes as
|
|
21073
|
-
import { readFileSync as
|
|
21398
|
+
import { createHmac, randomBytes as randomBytes4, timingSafeEqual } from "node:crypto";
|
|
21399
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
21074
21400
|
function keyFromBytes(bytes) {
|
|
21075
21401
|
if (bytes.length !== KEY_BYTES)
|
|
21076
21402
|
throw new Error(
|
|
@@ -21080,7 +21406,7 @@ function keyFromBytes(bytes) {
|
|
|
21080
21406
|
return { bytes, id };
|
|
21081
21407
|
}
|
|
21082
21408
|
function generateRunTokenKey() {
|
|
21083
|
-
return keyFromBytes(
|
|
21409
|
+
return keyFromBytes(randomBytes4(KEY_BYTES));
|
|
21084
21410
|
}
|
|
21085
21411
|
function runTokenKeyFromHex(hex) {
|
|
21086
21412
|
const trimmed = hex.trim();
|
|
@@ -21091,7 +21417,7 @@ function runTokenKeyFromHex(hex) {
|
|
|
21091
21417
|
function loadOrCreateRunTokenKey(path2) {
|
|
21092
21418
|
try {
|
|
21093
21419
|
return {
|
|
21094
|
-
key: runTokenKeyFromHex(
|
|
21420
|
+
key: runTokenKeyFromHex(readFileSync7(path2, "utf8")),
|
|
21095
21421
|
created: false
|
|
21096
21422
|
};
|
|
21097
21423
|
} catch (error) {
|
|
@@ -21104,7 +21430,7 @@ function loadOrCreateRunTokenKey(path2) {
|
|
|
21104
21430
|
}
|
|
21105
21431
|
function readRunTokenKey(path2) {
|
|
21106
21432
|
try {
|
|
21107
|
-
return runTokenKeyFromHex(
|
|
21433
|
+
return runTokenKeyFromHex(readFileSync7(path2, "utf8"));
|
|
21108
21434
|
} catch (error) {
|
|
21109
21435
|
if (error.code === "ENOENT") return void 0;
|
|
21110
21436
|
throw error;
|
|
@@ -21127,7 +21453,7 @@ function mintRunToken(options) {
|
|
|
21127
21453
|
throw new Error("run token would already be expired when minted");
|
|
21128
21454
|
const claims = {
|
|
21129
21455
|
v: 1,
|
|
21130
|
-
tid: `rt_${
|
|
21456
|
+
tid: `rt_${randomBytes4(10).toString("hex")}`,
|
|
21131
21457
|
host: options.host,
|
|
21132
21458
|
harness: options.harness,
|
|
21133
21459
|
provider: options.provider,
|
|
@@ -21238,14 +21564,14 @@ var init_run_token = __esm({
|
|
|
21238
21564
|
import { createHash as createHash6 } from "node:crypto";
|
|
21239
21565
|
import {
|
|
21240
21566
|
chmodSync as chmodSync4,
|
|
21241
|
-
existsSync as
|
|
21567
|
+
existsSync as existsSync6,
|
|
21242
21568
|
lstatSync as lstatSync2,
|
|
21243
|
-
mkdirSync as
|
|
21244
|
-
readFileSync as
|
|
21569
|
+
mkdirSync as mkdirSync6,
|
|
21570
|
+
readFileSync as readFileSync8,
|
|
21245
21571
|
statSync as statSync4,
|
|
21246
|
-
unlinkSync as
|
|
21572
|
+
unlinkSync as unlinkSync5
|
|
21247
21573
|
} from "node:fs";
|
|
21248
|
-
import { basename as basename4, dirname as
|
|
21574
|
+
import { basename as basename4, dirname as dirname6, join as join14 } from "node:path";
|
|
21249
21575
|
function isTachoHelper(value) {
|
|
21250
21576
|
return typeof value === "string" && HELPER_MARK.test(value);
|
|
21251
21577
|
}
|
|
@@ -21253,16 +21579,16 @@ function helperCommandFor(tachoCommand) {
|
|
|
21253
21579
|
return `${tachoCommand} credential issue --harness claude-code`;
|
|
21254
21580
|
}
|
|
21255
21581
|
function fileFor2(harness, homes) {
|
|
21256
|
-
return harness === "claude-code" ?
|
|
21582
|
+
return harness === "claude-code" ? join14(
|
|
21257
21583
|
homes.claudeConfigDir ?? harnessConfigDirs(homes.home).claudeConfigDir,
|
|
21258
21584
|
"settings.json"
|
|
21259
|
-
) :
|
|
21585
|
+
) : join14(
|
|
21260
21586
|
homes.codexHome ?? harnessConfigDirs(homes.home).codexHome,
|
|
21261
21587
|
"auth.json"
|
|
21262
21588
|
);
|
|
21263
21589
|
}
|
|
21264
21590
|
function sidecarFor2(file) {
|
|
21265
|
-
return
|
|
21591
|
+
return join14(dirname6(file), `.${basename4(file)}.oxagen-model-credential.json`);
|
|
21266
21592
|
}
|
|
21267
21593
|
function modelCredentialBackupPath(harness, home, dirs = {}) {
|
|
21268
21594
|
return sidecarFor2(fileFor2(harness, { ...dirs, home }));
|
|
@@ -21271,9 +21597,9 @@ function sha2562(text4) {
|
|
|
21271
21597
|
return createHash6("sha256").update(text4, "utf8").digest("hex");
|
|
21272
21598
|
}
|
|
21273
21599
|
function readSidecar2(path2) {
|
|
21274
|
-
if (!
|
|
21600
|
+
if (!existsSync6(path2)) return void 0;
|
|
21275
21601
|
try {
|
|
21276
|
-
const parsed = JSON.parse(
|
|
21602
|
+
const parsed = JSON.parse(readFileSync8(path2, "utf8"));
|
|
21277
21603
|
if (parsed.schema !== SIDECAR_SCHEMA2) return void 0;
|
|
21278
21604
|
if (typeof parsed.written_sha256 !== "string") return void 0;
|
|
21279
21605
|
return {
|
|
@@ -21293,7 +21619,7 @@ function readSidecar2(path2) {
|
|
|
21293
21619
|
}
|
|
21294
21620
|
}
|
|
21295
21621
|
function writeAtomicPreserving2(path2, data) {
|
|
21296
|
-
|
|
21622
|
+
mkdirSync6(dirname6(path2), { recursive: true });
|
|
21297
21623
|
let mode = 384;
|
|
21298
21624
|
let owner;
|
|
21299
21625
|
try {
|
|
@@ -21309,7 +21635,7 @@ function writeAtomicPreserving2(path2, data) {
|
|
|
21309
21635
|
}
|
|
21310
21636
|
function readTextIfExists2(path2) {
|
|
21311
21637
|
try {
|
|
21312
|
-
return
|
|
21638
|
+
return readFileSync8(path2, "utf8");
|
|
21313
21639
|
} catch (error) {
|
|
21314
21640
|
if (error.code === "ENOENT") return void 0;
|
|
21315
21641
|
throw error;
|
|
@@ -21542,7 +21868,7 @@ function restoreClaude(options, released) {
|
|
|
21542
21868
|
const sidecar = readSidecar2(backup);
|
|
21543
21869
|
const text4 = readTextIfExists2(file);
|
|
21544
21870
|
const dropSidecar = () => {
|
|
21545
|
-
if (
|
|
21871
|
+
if (existsSync6(backup)) unlinkSync5(backup);
|
|
21546
21872
|
};
|
|
21547
21873
|
if (text4 === void 0) {
|
|
21548
21874
|
if (released !== void 0) {
|
|
@@ -21599,7 +21925,7 @@ function restoreCodex(options, released) {
|
|
|
21599
21925
|
const sidecar = readSidecar2(backup);
|
|
21600
21926
|
const text4 = readTextIfExists2(file);
|
|
21601
21927
|
const dropSidecar = () => {
|
|
21602
|
-
if (
|
|
21928
|
+
if (existsSync6(backup)) unlinkSync5(backup);
|
|
21603
21929
|
};
|
|
21604
21930
|
if (text4 === void 0) {
|
|
21605
21931
|
if (released !== void 0) {
|
|
@@ -21626,7 +21952,7 @@ function restoreCodex(options, released) {
|
|
|
21626
21952
|
if (released !== void 0) auth[CODEX_KEY2] = released.secret;
|
|
21627
21953
|
else delete auth[CODEX_KEY2];
|
|
21628
21954
|
if (sidecar !== void 0 && !sidecar.existed && Object.keys(auth).length === 0) {
|
|
21629
|
-
|
|
21955
|
+
unlinkSync5(file);
|
|
21630
21956
|
dropSidecar();
|
|
21631
21957
|
return { changed: true, secretRestored: released !== void 0 };
|
|
21632
21958
|
}
|
|
@@ -21771,42 +22097,13 @@ var init_model_credential = __esm({
|
|
|
21771
22097
|
}
|
|
21772
22098
|
});
|
|
21773
22099
|
|
|
21774
|
-
// ../../packages/tacho/src/cli/agent-deps.ts
|
|
21775
|
-
function agentDeps(deps, paths) {
|
|
21776
|
-
if (JSON.stringify(paths) === JSON.stringify(deps.paths)) return deps;
|
|
21777
|
-
const rebound = deps.atAgent?.(paths) ?? { ...deps, paths };
|
|
21778
|
-
return {
|
|
21779
|
-
...deps,
|
|
21780
|
-
...rebound,
|
|
21781
|
-
paths,
|
|
21782
|
-
serviceManager: deps.serviceManager,
|
|
21783
|
-
out: deps.out,
|
|
21784
|
-
err: deps.err
|
|
21785
|
-
};
|
|
21786
|
-
}
|
|
21787
|
-
function depsForHarness(deps, harness) {
|
|
21788
|
-
const agent = agentHolding(deps.paths, harness);
|
|
21789
|
-
return agent === void 0 ? deps : depsForAgent(deps, agent);
|
|
21790
|
-
}
|
|
21791
|
-
function depsForAgent(deps, agent) {
|
|
21792
|
-
const host = agent.host ?? readHostFileLenient(agent.paths.hostFile).salvaged;
|
|
21793
|
-
return agentDeps(deps, withRecordedHarnessFiles(agent.paths, host));
|
|
21794
|
-
}
|
|
21795
|
-
var init_agent_deps = __esm({
|
|
21796
|
-
"../../packages/tacho/src/cli/agent-deps.ts"() {
|
|
21797
|
-
"use strict";
|
|
21798
|
-
init_agents();
|
|
21799
|
-
init_host_file();
|
|
21800
|
-
}
|
|
21801
|
-
});
|
|
21802
|
-
|
|
21803
22100
|
// ../../packages/tacho/src/cli/credential.ts
|
|
21804
|
-
import { existsSync as
|
|
21805
|
-
import { dirname as
|
|
22101
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
22102
|
+
import { dirname as dirname7 } from "node:path";
|
|
21806
22103
|
function harnessDirsOf(deps) {
|
|
21807
22104
|
return {
|
|
21808
|
-
claudeConfigDir:
|
|
21809
|
-
codexHome:
|
|
22105
|
+
claudeConfigDir: dirname7(deps.paths.claudeSettings),
|
|
22106
|
+
codexHome: dirname7(deps.paths.codexHooks)
|
|
21810
22107
|
};
|
|
21811
22108
|
}
|
|
21812
22109
|
function parseCredentialMode(value) {
|
|
@@ -22057,7 +22354,7 @@ async function restoreCredentials(host, deps, mode = "unenroll", only) {
|
|
|
22057
22354
|
try {
|
|
22058
22355
|
if (host !== void 0 && !host.harnesses.includes(harness)) {
|
|
22059
22356
|
const dirs = harnessDirsOf(deps);
|
|
22060
|
-
const hasReceipt =
|
|
22357
|
+
const hasReceipt = existsSync7(
|
|
22061
22358
|
modelCredentialBackupPath(harness, deps.home, dirs)
|
|
22062
22359
|
);
|
|
22063
22360
|
if (!hasReceipt && !hasOrphanedModelCredential(harness, deps.home, dirs))
|
|
@@ -22288,20 +22585,20 @@ var init_codex_app_server = __esm({
|
|
|
22288
22585
|
});
|
|
22289
22586
|
|
|
22290
22587
|
// ../../packages/tacho/src/host/credential-store.ts
|
|
22291
|
-
import { createCipheriv, createDecipheriv, randomBytes as
|
|
22588
|
+
import { createCipheriv, createDecipheriv, randomBytes as randomBytes5 } from "node:crypto";
|
|
22292
22589
|
import {
|
|
22293
|
-
closeSync as
|
|
22294
|
-
existsSync as
|
|
22590
|
+
closeSync as closeSync4,
|
|
22591
|
+
existsSync as existsSync8,
|
|
22295
22592
|
fsyncSync as fsyncSync2,
|
|
22296
|
-
openSync as
|
|
22297
|
-
readFileSync as
|
|
22593
|
+
openSync as openSync4,
|
|
22594
|
+
readFileSync as readFileSync9,
|
|
22298
22595
|
statSync as statSync5,
|
|
22299
|
-
unlinkSync as
|
|
22300
|
-
writeSync as
|
|
22596
|
+
unlinkSync as unlinkSync6,
|
|
22597
|
+
writeSync as writeSync3
|
|
22301
22598
|
} from "node:fs";
|
|
22302
22599
|
function readKey(path2) {
|
|
22303
22600
|
try {
|
|
22304
|
-
const hex =
|
|
22601
|
+
const hex = readFileSync9(path2, "utf8").trim();
|
|
22305
22602
|
if (!/^[0-9a-f]{64}$/i.test(hex))
|
|
22306
22603
|
throw new Error(`${path2} does not hold a 32-byte key`);
|
|
22307
22604
|
return Buffer.from(hex, "hex");
|
|
@@ -22313,7 +22610,7 @@ function readKey(path2) {
|
|
|
22313
22610
|
function loadOrCreateKey(path2) {
|
|
22314
22611
|
const existing = readKey(path2);
|
|
22315
22612
|
if (existing !== void 0) return existing;
|
|
22316
|
-
const key =
|
|
22613
|
+
const key = randomBytes5(KEY_BYTES2);
|
|
22317
22614
|
writeSensitiveFileAtomic(path2, `${key.toString("hex")}
|
|
22318
22615
|
`);
|
|
22319
22616
|
return key;
|
|
@@ -22330,16 +22627,16 @@ function overwriteInPlace(path2) {
|
|
|
22330
22627
|
let fd2;
|
|
22331
22628
|
try {
|
|
22332
22629
|
const size = statSync5(path2).size;
|
|
22333
|
-
fd2 =
|
|
22334
|
-
|
|
22630
|
+
fd2 = openSync4(path2, "r+");
|
|
22631
|
+
writeSync3(fd2, randomBytes5(Math.max(size, KEY_BYTES2 * 2)), 0, void 0, 0);
|
|
22335
22632
|
fsyncSync2(fd2);
|
|
22336
22633
|
} catch {
|
|
22337
22634
|
} finally {
|
|
22338
|
-
if (fd2 !== void 0)
|
|
22635
|
+
if (fd2 !== void 0) closeSync4(fd2);
|
|
22339
22636
|
}
|
|
22340
22637
|
}
|
|
22341
22638
|
function seal(key, secret, aad) {
|
|
22342
|
-
const nonce =
|
|
22639
|
+
const nonce = randomBytes5(12);
|
|
22343
22640
|
const cipher = createCipheriv("aes-256-gcm", key, nonce);
|
|
22344
22641
|
cipher.setAAD(Buffer.from(aad, "utf8"));
|
|
22345
22642
|
const ciphertext = Buffer.concat([
|
|
@@ -22384,7 +22681,7 @@ function openCredentialStore(paths) {
|
|
|
22384
22681
|
function readAll() {
|
|
22385
22682
|
let text4;
|
|
22386
22683
|
try {
|
|
22387
|
-
text4 =
|
|
22684
|
+
text4 = readFileSync9(paths.file, "utf8");
|
|
22388
22685
|
} catch (error) {
|
|
22389
22686
|
if (error.code === "ENOENT") return [];
|
|
22390
22687
|
throw error;
|
|
@@ -22398,7 +22695,7 @@ function openCredentialStore(paths) {
|
|
|
22398
22695
|
}
|
|
22399
22696
|
function writeAll2(entries2) {
|
|
22400
22697
|
if (entries2.length === 0) {
|
|
22401
|
-
if (
|
|
22698
|
+
if (existsSync8(paths.file)) unlinkSync6(paths.file);
|
|
22402
22699
|
return;
|
|
22403
22700
|
}
|
|
22404
22701
|
writeSensitiveFileAtomic(
|
|
@@ -22453,9 +22750,9 @@ function openCredentialStore(paths) {
|
|
|
22453
22750
|
},
|
|
22454
22751
|
status: () => readAll().map(custodyOf),
|
|
22455
22752
|
shred: () => {
|
|
22456
|
-
if (
|
|
22753
|
+
if (existsSync8(paths.key)) overwriteInPlace(paths.key);
|
|
22457
22754
|
for (const path2 of [paths.file, paths.key])
|
|
22458
|
-
if (
|
|
22755
|
+
if (existsSync8(path2)) unlinkSync6(path2);
|
|
22459
22756
|
}
|
|
22460
22757
|
};
|
|
22461
22758
|
}
|
|
@@ -22499,16 +22796,87 @@ var init_credential_store = __esm({
|
|
|
22499
22796
|
}
|
|
22500
22797
|
});
|
|
22501
22798
|
|
|
22799
|
+
// ../../packages/tacho/src/host/claude-config-lock.ts
|
|
22800
|
+
import { mkdirSync as mkdirSync7, rmdirSync as rmdirSync4, statSync as statSync6 } from "node:fs";
|
|
22801
|
+
function sleepSync(ms) {
|
|
22802
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
22803
|
+
}
|
|
22804
|
+
function claudeConfigLockPath(file) {
|
|
22805
|
+
return `${file}.lock`;
|
|
22806
|
+
}
|
|
22807
|
+
function withClaudeConfigLock(file, edit, options = {}) {
|
|
22808
|
+
const lock = claudeConfigLockPath(file);
|
|
22809
|
+
const now = options.now ?? Date.now;
|
|
22810
|
+
const sleep3 = options.sleep ?? sleepSync;
|
|
22811
|
+
const staleMs = options.staleMs ?? CLAUDE_CONFIG_LOCK_STALE_MS;
|
|
22812
|
+
const waitMs = options.waitMs ?? CLAUDE_CONFIG_LOCK_WAIT_MS;
|
|
22813
|
+
const deadline = now() + waitMs;
|
|
22814
|
+
let held = false;
|
|
22815
|
+
for (; ; ) {
|
|
22816
|
+
try {
|
|
22817
|
+
mkdirSync7(lock);
|
|
22818
|
+
held = true;
|
|
22819
|
+
break;
|
|
22820
|
+
} catch (error) {
|
|
22821
|
+
const code = error.code;
|
|
22822
|
+
if (code === "ENOENT") break;
|
|
22823
|
+
if (code !== "EEXIST") throw error;
|
|
22824
|
+
}
|
|
22825
|
+
let modified;
|
|
22826
|
+
try {
|
|
22827
|
+
modified = statSync6(lock).mtimeMs;
|
|
22828
|
+
} catch {
|
|
22829
|
+
modified = void 0;
|
|
22830
|
+
}
|
|
22831
|
+
let retryNow = modified === void 0;
|
|
22832
|
+
if (modified !== void 0 && now() - modified > staleMs) {
|
|
22833
|
+
try {
|
|
22834
|
+
if (statSync6(lock).mtimeMs === modified) {
|
|
22835
|
+
rmdirSync4(lock);
|
|
22836
|
+
retryNow = true;
|
|
22837
|
+
}
|
|
22838
|
+
} catch {
|
|
22839
|
+
}
|
|
22840
|
+
}
|
|
22841
|
+
if (now() >= deadline)
|
|
22842
|
+
throw new HarnessFileError(
|
|
22843
|
+
file,
|
|
22844
|
+
`is being saved by Claude Code, which held its lock (${lock}) for more than ${Math.round(waitMs / 1e3)} seconds; nothing was written, so run the command again in a moment`
|
|
22845
|
+
);
|
|
22846
|
+
if (!retryNow) sleep3(RETRY_MS);
|
|
22847
|
+
}
|
|
22848
|
+
try {
|
|
22849
|
+
return edit();
|
|
22850
|
+
} finally {
|
|
22851
|
+
if (held) {
|
|
22852
|
+
try {
|
|
22853
|
+
rmdirSync4(lock);
|
|
22854
|
+
} catch {
|
|
22855
|
+
}
|
|
22856
|
+
}
|
|
22857
|
+
}
|
|
22858
|
+
}
|
|
22859
|
+
var CLAUDE_CONFIG_LOCK_STALE_MS, CLAUDE_CONFIG_LOCK_WAIT_MS, RETRY_MS;
|
|
22860
|
+
var init_claude_config_lock = __esm({
|
|
22861
|
+
"../../packages/tacho/src/host/claude-config-lock.ts"() {
|
|
22862
|
+
"use strict";
|
|
22863
|
+
init_harness_file();
|
|
22864
|
+
CLAUDE_CONFIG_LOCK_STALE_MS = 1e4;
|
|
22865
|
+
CLAUDE_CONFIG_LOCK_WAIT_MS = 3e3;
|
|
22866
|
+
RETRY_MS = 25;
|
|
22867
|
+
}
|
|
22868
|
+
});
|
|
22869
|
+
|
|
22502
22870
|
// ../../packages/tacho/src/host/service.ts
|
|
22503
|
-
import { join as
|
|
22871
|
+
import { join as join15 } from "node:path";
|
|
22504
22872
|
import {
|
|
22505
|
-
existsSync as
|
|
22506
|
-
readdirSync as
|
|
22507
|
-
readFileSync as
|
|
22508
|
-
rmdirSync as
|
|
22509
|
-
unlinkSync as
|
|
22873
|
+
existsSync as existsSync9,
|
|
22874
|
+
readdirSync as readdirSync6,
|
|
22875
|
+
readFileSync as readFileSync10,
|
|
22876
|
+
rmdirSync as rmdirSync5,
|
|
22877
|
+
unlinkSync as unlinkSync7
|
|
22510
22878
|
} from "node:fs";
|
|
22511
|
-
import { randomBytes as
|
|
22879
|
+
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
22512
22880
|
function xmlEscape(value) {
|
|
22513
22881
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
22514
22882
|
}
|
|
@@ -22580,8 +22948,8 @@ function blockingSleep(ms) {
|
|
|
22580
22948
|
}
|
|
22581
22949
|
function launchdManager(options) {
|
|
22582
22950
|
const sleep3 = options.sleep ?? blockingSleep;
|
|
22583
|
-
const dir =
|
|
22584
|
-
const unitPath =
|
|
22951
|
+
const dir = join15(options.home, "Library", "LaunchAgents");
|
|
22952
|
+
const unitPath = join15(dir, `${SERVICE_LABEL}.plist`);
|
|
22585
22953
|
const domain = `gui/${options.uid ?? process.getuid?.() ?? 501}`;
|
|
22586
22954
|
const target2 = `${domain}/${SERVICE_LABEL}`;
|
|
22587
22955
|
const loaded = () => options.exec("launchctl", ["print", target2]).status === 0;
|
|
@@ -22600,7 +22968,7 @@ function launchdManager(options) {
|
|
|
22600
22968
|
unitPath,
|
|
22601
22969
|
install: (spec) => {
|
|
22602
22970
|
const plist = renderLaunchdPlist(spec);
|
|
22603
|
-
const unchanged =
|
|
22971
|
+
const unchanged = existsSync9(unitPath) && readFileSync10(unitPath, "utf8") === plist;
|
|
22604
22972
|
if (unchanged && loaded()) {
|
|
22605
22973
|
const kicked = options.exec("launchctl", ["kickstart", "-k", target2]);
|
|
22606
22974
|
if (kicked.status === 0 && loaded()) return;
|
|
@@ -22629,10 +22997,10 @@ function launchdManager(options) {
|
|
|
22629
22997
|
uninstall: () => {
|
|
22630
22998
|
options.exec("launchctl", ["bootout", target2]);
|
|
22631
22999
|
if (!waitUntilGone()) throw stillLoaded("unenroll");
|
|
22632
|
-
if (
|
|
23000
|
+
if (existsSync9(unitPath)) unlinkSync7(unitPath);
|
|
22633
23001
|
},
|
|
22634
23002
|
status: () => {
|
|
22635
|
-
const installed =
|
|
23003
|
+
const installed = existsSync9(unitPath);
|
|
22636
23004
|
const result2 = options.exec("launchctl", [
|
|
22637
23005
|
"print",
|
|
22638
23006
|
`${domain}/${SERVICE_LABEL}`
|
|
@@ -22649,8 +23017,8 @@ function noUserManager(result2) {
|
|
|
22649
23017
|
}
|
|
22650
23018
|
function stopByPidFile(options) {
|
|
22651
23019
|
const { pidPath } = options;
|
|
22652
|
-
if (pidPath === void 0 || !
|
|
22653
|
-
const record = parseDaemonPid(
|
|
23020
|
+
if (pidPath === void 0 || !existsSync9(pidPath)) return;
|
|
23021
|
+
const record = parseDaemonPid(readFileSync10(pidPath, "utf8"));
|
|
22654
23022
|
if (record === void 0) return;
|
|
22655
23023
|
const sleep3 = options.sleep ?? blockingSleep;
|
|
22656
23024
|
const processes = options.processes ?? {
|
|
@@ -22682,9 +23050,9 @@ function stopByPidFile(options) {
|
|
|
22682
23050
|
);
|
|
22683
23051
|
}
|
|
22684
23052
|
function systemdManager(options) {
|
|
22685
|
-
const dir =
|
|
22686
|
-
const unitPath =
|
|
22687
|
-
const wants =
|
|
23053
|
+
const dir = join15(options.home, ".config", "systemd", "user");
|
|
23054
|
+
const unitPath = join15(dir, "tachod.service");
|
|
23055
|
+
const wants = join15(dir, "default.target.wants");
|
|
22688
23056
|
return {
|
|
22689
23057
|
kind: "systemd",
|
|
22690
23058
|
unitPath,
|
|
@@ -22694,8 +23062,8 @@ function systemdManager(options) {
|
|
|
22694
23062
|
throw new Error(
|
|
22695
23063
|
`no systemd user manager is available (${probe.stderr.trim().split("\n")[0] ?? ""})`
|
|
22696
23064
|
);
|
|
22697
|
-
const previous =
|
|
22698
|
-
const createsWants = previous === void 0 ? !
|
|
23065
|
+
const previous = existsSync9(unitPath) ? readFileSync10(unitPath, "utf8") : void 0;
|
|
23066
|
+
const createsWants = previous === void 0 ? !existsSync9(wants) : previous.includes(CREATED_WANTS_MARK);
|
|
22699
23067
|
ensureDir(dir, 493);
|
|
22700
23068
|
writeSensitiveFileAtomic(
|
|
22701
23069
|
unitPath,
|
|
@@ -22735,7 +23103,7 @@ function systemdManager(options) {
|
|
|
22735
23103
|
]);
|
|
22736
23104
|
if (noUserManager(disabled)) {
|
|
22737
23105
|
stopByPidFile(options);
|
|
22738
|
-
if (
|
|
23106
|
+
if (existsSync9(unitPath)) unlinkSync7(unitPath);
|
|
22739
23107
|
return;
|
|
22740
23108
|
}
|
|
22741
23109
|
const active2 = options.exec("systemctl", [
|
|
@@ -22744,13 +23112,13 @@ function systemdManager(options) {
|
|
|
22744
23112
|
"tachod.service"
|
|
22745
23113
|
]);
|
|
22746
23114
|
const stopped2 = active2.status === 3 && ["inactive", "failed"].includes(active2.stdout.trim()) || active2.status === 4 && active2.stdout.trim() === "unknown";
|
|
22747
|
-
if (!stopped2 || disabled.status !== 0 &&
|
|
23115
|
+
if (!stopped2 || disabled.status !== 0 && existsSync9(unitPath)) {
|
|
22748
23116
|
throw new Error(
|
|
22749
23117
|
`systemctl could not remove tachod.service: ${disabled.stderr.trim() || active2.stderr.trim() || active2.stdout.trim() || "service state is unknown"}`
|
|
22750
23118
|
);
|
|
22751
23119
|
}
|
|
22752
|
-
const unit =
|
|
22753
|
-
if (unit !== void 0)
|
|
23120
|
+
const unit = existsSync9(unitPath) ? readFileSync10(unitPath, "utf8") : void 0;
|
|
23121
|
+
if (unit !== void 0) unlinkSync7(unitPath);
|
|
22754
23122
|
try {
|
|
22755
23123
|
const reload = options.exec("systemctl", ["--user", "daemon-reload"]);
|
|
22756
23124
|
if (reload.status !== 0)
|
|
@@ -22763,13 +23131,13 @@ function systemdManager(options) {
|
|
|
22763
23131
|
}
|
|
22764
23132
|
if (unit?.includes(CREATED_WANTS_MARK) === true) {
|
|
22765
23133
|
try {
|
|
22766
|
-
if (
|
|
23134
|
+
if (readdirSync6(wants).length === 0) rmdirSync5(wants);
|
|
22767
23135
|
} catch {
|
|
22768
23136
|
}
|
|
22769
23137
|
}
|
|
22770
23138
|
},
|
|
22771
23139
|
status: () => {
|
|
22772
|
-
const installed =
|
|
23140
|
+
const installed = existsSync9(unitPath);
|
|
22773
23141
|
const result2 = options.exec("systemctl", [
|
|
22774
23142
|
"--user",
|
|
22775
23143
|
"is-active",
|
|
@@ -22821,11 +23189,11 @@ function tasklistImage(listing, pid) {
|
|
|
22821
23189
|
return void 0;
|
|
22822
23190
|
}
|
|
22823
23191
|
function schtasksManager(options) {
|
|
22824
|
-
const launcher = options.launcherPath ??
|
|
22825
|
-
const pidPath = options.pidPath ??
|
|
23192
|
+
const launcher = options.launcherPath ?? join15(options.home, "tachod.cmd");
|
|
23193
|
+
const pidPath = options.pidPath ?? join15(launcher, "..", "tachod.pid");
|
|
22826
23194
|
const livePid = () => {
|
|
22827
|
-
if (!
|
|
22828
|
-
const record = parseDaemonPid(
|
|
23195
|
+
if (!existsSync9(pidPath)) return void 0;
|
|
23196
|
+
const record = parseDaemonPid(readFileSync10(pidPath, "utf8"));
|
|
22829
23197
|
if (record === void 0) return void 0;
|
|
22830
23198
|
const { pid } = record;
|
|
22831
23199
|
const query = options.exec("tasklist", [
|
|
@@ -22864,7 +23232,7 @@ function schtasksManager(options) {
|
|
|
22864
23232
|
unitPath: launcher,
|
|
22865
23233
|
install: (spec) => {
|
|
22866
23234
|
stopDaemon();
|
|
22867
|
-
ensureDir(
|
|
23235
|
+
ensureDir(join15(launcher, ".."), 493);
|
|
22868
23236
|
writeSensitiveFileAtomic(
|
|
22869
23237
|
launcher,
|
|
22870
23238
|
renderWindowsLauncher(
|
|
@@ -22876,7 +23244,7 @@ function schtasksManager(options) {
|
|
|
22876
23244
|
// an empty directory stayed behind (#4317). The daemon uses
|
|
22877
23245
|
// absolute paths only.
|
|
22878
23246
|
{ ...spec, workingDirectory: options.home },
|
|
22879
|
-
|
|
23247
|
+
randomBytes6(8).toString("hex")
|
|
22880
23248
|
),
|
|
22881
23249
|
384
|
|
22882
23250
|
);
|
|
@@ -22918,7 +23286,7 @@ function schtasksManager(options) {
|
|
|
22918
23286
|
`schtasks /Delete failed: ${deleted.stderr.trim() || "task removal was not confirmed"}`
|
|
22919
23287
|
);
|
|
22920
23288
|
}
|
|
22921
|
-
if (
|
|
23289
|
+
if (existsSync9(launcher)) unlinkSync7(launcher);
|
|
22922
23290
|
},
|
|
22923
23291
|
status: () => {
|
|
22924
23292
|
const result2 = options.exec("schtasks", [
|
|
@@ -22991,15 +23359,15 @@ var init_service = __esm({
|
|
|
22991
23359
|
});
|
|
22992
23360
|
|
|
22993
23361
|
// ../../packages/tacho/src/version.ts
|
|
22994
|
-
import { readFileSync as
|
|
22995
|
-
import { dirname as
|
|
23362
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
23363
|
+
import { dirname as dirname8, resolve as resolve2 } from "node:path";
|
|
22996
23364
|
import { fileURLToPath } from "node:url";
|
|
22997
23365
|
function readVersion() {
|
|
22998
|
-
if (true) return "2.1.4-
|
|
23366
|
+
if (true) return "2.1.4-453";
|
|
22999
23367
|
try {
|
|
23000
|
-
const here =
|
|
23368
|
+
const here = dirname8(fileURLToPath(import.meta.url));
|
|
23001
23369
|
const pkg = JSON.parse(
|
|
23002
|
-
|
|
23370
|
+
readFileSync11(resolve2(here, "..", "package.json"), "utf8")
|
|
23003
23371
|
);
|
|
23004
23372
|
return pkg.version ?? "0.0.0";
|
|
23005
23373
|
} catch {
|
|
@@ -23016,8 +23384,8 @@ var init_version = __esm({
|
|
|
23016
23384
|
|
|
23017
23385
|
// ../../packages/tacho/src/cli/deps.ts
|
|
23018
23386
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
23019
|
-
import { randomBytes as
|
|
23020
|
-
import { existsSync as
|
|
23387
|
+
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
23388
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
23021
23389
|
import { get as httpGet, request as httpRequest } from "node:http";
|
|
23022
23390
|
import { createServer } from "node:net";
|
|
23023
23391
|
import {
|
|
@@ -23028,7 +23396,7 @@ import {
|
|
|
23028
23396
|
userInfo
|
|
23029
23397
|
} from "node:os";
|
|
23030
23398
|
import { createRequire } from "node:module";
|
|
23031
|
-
import { dirname as
|
|
23399
|
+
import { dirname as dirname9, posix as posix2, resolve as resolve3, win32 as win323 } from "node:path";
|
|
23032
23400
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
23033
23401
|
function configPicker(env, home) {
|
|
23034
23402
|
let config = {};
|
|
@@ -23094,7 +23462,7 @@ function isNativeBuild() {
|
|
|
23094
23462
|
function exeName(name, platform) {
|
|
23095
23463
|
return platform === "win32" ? `${name}.exe` : name;
|
|
23096
23464
|
}
|
|
23097
|
-
function stableExecutablePath(executable, platform, exists =
|
|
23465
|
+
function stableExecutablePath(executable, platform, exists = existsSync10) {
|
|
23098
23466
|
const stable = platform === "win32" ? executable.replace(
|
|
23099
23467
|
/^(.*\\apps\\[^\\]+\\)(?!current\\)[^\\]+(\\.*)$/i,
|
|
23100
23468
|
"$1current$2"
|
|
@@ -23104,7 +23472,7 @@ function stableExecutablePath(executable, platform, exists = existsSync9) {
|
|
|
23104
23472
|
);
|
|
23105
23473
|
return stable !== executable && exists(stable) ? stable : executable;
|
|
23106
23474
|
}
|
|
23107
|
-
function runtimeCommands(entry2 = process.argv[1], env = process.env, nodePath = process.execPath, platform = process.platform, native = isNativeBuild(), exists =
|
|
23475
|
+
function runtimeCommands(entry2 = process.argv[1], env = process.env, nodePath = process.execPath, platform = process.platform, native = isNativeBuild(), exists = existsSync10) {
|
|
23108
23476
|
const P = platform === "win32" ? win323 : posix2;
|
|
23109
23477
|
const named = env["TACHO_BIN_DIR"];
|
|
23110
23478
|
let binDir = named;
|
|
@@ -23112,7 +23480,7 @@ function runtimeCommands(entry2 = process.argv[1], env = process.env, nodePath =
|
|
|
23112
23480
|
if (native) {
|
|
23113
23481
|
binDir = P.dirname(nodePath);
|
|
23114
23482
|
} else {
|
|
23115
|
-
const here =
|
|
23483
|
+
const here = dirname9(fileURLToPath2(import.meta.url));
|
|
23116
23484
|
const entryDir = entry2 !== void 0 ? P.dirname(P.resolve(entry2)) : void 0;
|
|
23117
23485
|
if (entryDir !== void 0 && exists(P.join(entryDir, "tachod.mjs")))
|
|
23118
23486
|
binDir = entryDir;
|
|
@@ -23153,7 +23521,7 @@ function runtimeCommands(entry2 = process.argv[1], env = process.env, nodePath =
|
|
|
23153
23521
|
...flagged
|
|
23154
23522
|
};
|
|
23155
23523
|
}
|
|
23156
|
-
function oxagenRuntimeCommands(entry2 = process.argv[1], env = process.env, nodePath = process.execPath, platform = process.platform, native = isNativeBuild(), exists =
|
|
23524
|
+
function oxagenRuntimeCommands(entry2 = process.argv[1], env = process.env, nodePath = process.execPath, platform = process.platform, native = isNativeBuild(), exists = existsSync10) {
|
|
23157
23525
|
const P = platform === "win32" ? win323 : posix2;
|
|
23158
23526
|
const named = env["TACHO_BIN_DIR"];
|
|
23159
23527
|
let prefix;
|
|
@@ -23240,7 +23608,7 @@ function whereExecutable(result2) {
|
|
|
23240
23608
|
function shellExecutable(result2) {
|
|
23241
23609
|
return outputLines(result2).reverse().find((line) => line.startsWith("/"));
|
|
23242
23610
|
}
|
|
23243
|
-
function harnessFacts(exec4, name, platform = process.platform, env = process.env, home = env["HOME"] ?? env["USERPROFILE"] ?? "", exists =
|
|
23611
|
+
function harnessFacts(exec4, name, platform = process.platform, env = process.env, home = env["HOME"] ?? env["USERPROFILE"] ?? "", exists = existsSync10) {
|
|
23244
23612
|
let path2;
|
|
23245
23613
|
if (platform === "win32") {
|
|
23246
23614
|
path2 = whereExecutable(exec4("where", [name]));
|
|
@@ -23268,7 +23636,7 @@ function harnessFacts(exec4, name, platform = process.platform, env = process.en
|
|
|
23268
23636
|
const match = /(\d+\.\d+\.\d+)/.exec(version2.stdout);
|
|
23269
23637
|
return { path: path2, ...match?.[1] !== void 0 ? { version: match[1] } : {} };
|
|
23270
23638
|
}
|
|
23271
|
-
function claudeDesktopFacts(platform = process.platform, home = homedir3(), env = process.env, exists =
|
|
23639
|
+
function claudeDesktopFacts(platform = process.platform, home = homedir3(), env = process.env, exists = existsSync10) {
|
|
23272
23640
|
const candidates = platform === "darwin" ? ["/Applications/Claude.app", `${home}/Applications/Claude.app`] : platform === "win32" ? [
|
|
23273
23641
|
`${env["LOCALAPPDATA"] ?? `${home}\\AppData\\Local`}\\AnthropicClaude`,
|
|
23274
23642
|
`${env["LOCALAPPDATA"] ?? `${home}\\AppData\\Local`}\\Programs\\Claude`
|
|
@@ -23278,7 +23646,7 @@ function claudeDesktopFacts(platform = process.platform, home = homedir3(), env
|
|
|
23278
23646
|
}
|
|
23279
23647
|
return { installed: false };
|
|
23280
23648
|
}
|
|
23281
|
-
function cursorAppFacts(platform = process.platform, home = homedir3(), env = process.env, exists =
|
|
23649
|
+
function cursorAppFacts(platform = process.platform, home = homedir3(), env = process.env, exists = existsSync10) {
|
|
23282
23650
|
const local = env["LOCALAPPDATA"] ?? `${home}\\AppData\\Local`;
|
|
23283
23651
|
const programs = env["PROGRAMFILES"] ?? "C:\\Program Files";
|
|
23284
23652
|
const candidates = platform === "darwin" ? ["/Applications/Cursor.app", `${home}/Applications/Cursor.app`] : platform === "win32" ? [`${local}\\Programs\\cursor`, `${programs}\\Cursor`] : [];
|
|
@@ -23322,8 +23690,8 @@ function defaultCliDeps(overrides = {}, managed = {}) {
|
|
|
23322
23690
|
const paths = overrides.paths ?? defaultAgentPaths(tachoHome(env, home, platform));
|
|
23323
23691
|
const harnessFiles = new HarnessFiles(paths.dir);
|
|
23324
23692
|
const harnessDirs = {
|
|
23325
|
-
claudeConfigDir:
|
|
23326
|
-
codexHome:
|
|
23693
|
+
claudeConfigDir: dirname9(paths.claudeSettings),
|
|
23694
|
+
codexHome: dirname9(paths.codexHooks)
|
|
23327
23695
|
};
|
|
23328
23696
|
const daemonGet = async (path2) => {
|
|
23329
23697
|
const host = readHostFile(paths.hostFile);
|
|
@@ -23431,6 +23799,21 @@ function defaultCliDeps(overrides = {}, managed = {}) {
|
|
|
23431
23799
|
`
|
|
23432
23800
|
);
|
|
23433
23801
|
},
|
|
23802
|
+
// Claude Code rewrites this file all the time, so the read is taken
|
|
23803
|
+
// inside its lock, not before it. proper-lockfile resolves a file's real
|
|
23804
|
+
// path before it locks it, so Claude Code holds no lock on a file that
|
|
23805
|
+
// does not exist yet, and neither does this.
|
|
23806
|
+
editClaudeUserConfig: (edit) => {
|
|
23807
|
+
const file = paths.claudeUserConfig;
|
|
23808
|
+
const apply = () => {
|
|
23809
|
+
const next = edit(harnessFiles.readJson(file));
|
|
23810
|
+
if (next !== void 0)
|
|
23811
|
+
harnessFiles.write(file, `${JSON.stringify(next, null, 2)}
|
|
23812
|
+
`);
|
|
23813
|
+
};
|
|
23814
|
+
if (existsSync10(file)) withClaudeConfigLock(file, apply);
|
|
23815
|
+
else apply();
|
|
23816
|
+
},
|
|
23434
23817
|
harnessWriteProblem: (path2) => harnessFiles.writeProblem(path2),
|
|
23435
23818
|
settleHarnessFiles: () => settleOrThrow(harnessFiles),
|
|
23436
23819
|
// The base URL and the vendor key live in the files the hooks went into,
|
|
@@ -23541,7 +23924,7 @@ function defaultCliDeps(overrides = {}, managed = {}) {
|
|
|
23541
23924
|
server.close(() => resolvePromise(port));
|
|
23542
23925
|
});
|
|
23543
23926
|
}),
|
|
23544
|
-
randomToken: () =>
|
|
23927
|
+
randomToken: () => randomBytes7(24).toString("hex"),
|
|
23545
23928
|
sleep: (ms) => new Promise((resolvePromise) => setTimeout(resolvePromise, ms)),
|
|
23546
23929
|
wrapperVersion: TACHO_VERSION,
|
|
23547
23930
|
atAgent: (agentPaths2) => defaultCliDeps({ ...overrides, paths: agentPaths2 }, managed),
|
|
@@ -23555,6 +23938,7 @@ var init_deps = __esm({
|
|
|
23555
23938
|
init_hook_client();
|
|
23556
23939
|
init_codex_app_server();
|
|
23557
23940
|
init_credential_store();
|
|
23941
|
+
init_claude_config_lock();
|
|
23558
23942
|
init_fs();
|
|
23559
23943
|
init_harness_file();
|
|
23560
23944
|
init_host_file();
|
|
@@ -24073,7 +24457,7 @@ import {
|
|
|
24073
24457
|
sign as sign2,
|
|
24074
24458
|
verify as verify2
|
|
24075
24459
|
} from "node:crypto";
|
|
24076
|
-
import { readFileSync as
|
|
24460
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
24077
24461
|
function encodePublicKey(privateKey) {
|
|
24078
24462
|
const spki = createPublicKey2(privateKey).export({
|
|
24079
24463
|
type: "spki",
|
|
@@ -24111,7 +24495,7 @@ function deviceKeyPem(key) {
|
|
|
24111
24495
|
function loadOrCreateDeviceKey(path2) {
|
|
24112
24496
|
try {
|
|
24113
24497
|
return {
|
|
24114
|
-
key: deviceKeyFromPem(
|
|
24498
|
+
key: deviceKeyFromPem(readFileSync12(path2, "utf8")),
|
|
24115
24499
|
created: false
|
|
24116
24500
|
};
|
|
24117
24501
|
} catch (error) {
|
|
@@ -24149,110 +24533,6 @@ var init_device_key = __esm({
|
|
|
24149
24533
|
}
|
|
24150
24534
|
});
|
|
24151
24535
|
|
|
24152
|
-
// ../../packages/tacho/src/host/install-lock.ts
|
|
24153
|
-
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
24154
|
-
import {
|
|
24155
|
-
closeSync as closeSync4,
|
|
24156
|
-
existsSync as existsSync10,
|
|
24157
|
-
linkSync,
|
|
24158
|
-
mkdirSync as mkdirSync6,
|
|
24159
|
-
openSync as openSync4,
|
|
24160
|
-
readdirSync as readdirSync6,
|
|
24161
|
-
readFileSync as readFileSync12,
|
|
24162
|
-
renameSync as renameSync3,
|
|
24163
|
-
rmdirSync as rmdirSync4,
|
|
24164
|
-
unlinkSync as unlinkSync7,
|
|
24165
|
-
writeSync as writeSync3
|
|
24166
|
-
} from "node:fs";
|
|
24167
|
-
import { dirname as dirname9, join as join15 } from "node:path";
|
|
24168
|
-
function readLock(path2) {
|
|
24169
|
-
try {
|
|
24170
|
-
return readFileSync12(path2, "utf8");
|
|
24171
|
-
} catch {
|
|
24172
|
-
return void 0;
|
|
24173
|
-
}
|
|
24174
|
-
}
|
|
24175
|
-
function holderOf(text4) {
|
|
24176
|
-
try {
|
|
24177
|
-
return JSON.parse(text4 ?? "");
|
|
24178
|
-
} catch {
|
|
24179
|
-
return {};
|
|
24180
|
-
}
|
|
24181
|
-
}
|
|
24182
|
-
function removeQuietly(path2) {
|
|
24183
|
-
try {
|
|
24184
|
-
unlinkSync7(path2);
|
|
24185
|
-
} catch {
|
|
24186
|
-
}
|
|
24187
|
-
}
|
|
24188
|
-
function pidAlive(pid) {
|
|
24189
|
-
try {
|
|
24190
|
-
process.kill(pid, 0);
|
|
24191
|
-
return true;
|
|
24192
|
-
} catch (error) {
|
|
24193
|
-
return error.code === "EPERM";
|
|
24194
|
-
}
|
|
24195
|
-
}
|
|
24196
|
-
function acquireInstallLock(root, now = Date.now, alive = pidAlive) {
|
|
24197
|
-
const path2 = join15(root, "install.lock");
|
|
24198
|
-
const created = [];
|
|
24199
|
-
let dir = root;
|
|
24200
|
-
while (!existsSync10(dir) && dirname9(dir) !== dir) {
|
|
24201
|
-
created.unshift(dir);
|
|
24202
|
-
dir = dirname9(dir);
|
|
24203
|
-
}
|
|
24204
|
-
mkdirSync6(root, { recursive: true, mode: 448 });
|
|
24205
|
-
const token = randomBytes7(12).toString("hex");
|
|
24206
|
-
const liveHolder = (holder) => typeof holder.pid === "number" && typeof holder.at === "number" && now() - holder.at < STALE_AFTER_MS && alive(holder.pid) ? holder.pid : void 0;
|
|
24207
|
-
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
24208
|
-
try {
|
|
24209
|
-
const fd2 = openSync4(path2, "wx", 384);
|
|
24210
|
-
writeSync3(fd2, JSON.stringify({ pid: process.pid, at: now(), token }));
|
|
24211
|
-
closeSync4(fd2);
|
|
24212
|
-
return {
|
|
24213
|
-
release: () => {
|
|
24214
|
-
if (holderOf(readLock(path2)).token === token) removeQuietly(path2);
|
|
24215
|
-
for (const made of [...created].reverse()) {
|
|
24216
|
-
try {
|
|
24217
|
-
if (readdirSync6(made).length === 0) rmdirSync4(made);
|
|
24218
|
-
} catch {
|
|
24219
|
-
}
|
|
24220
|
-
}
|
|
24221
|
-
}
|
|
24222
|
-
};
|
|
24223
|
-
} catch (error) {
|
|
24224
|
-
if (error.code !== "EEXIST") throw error;
|
|
24225
|
-
const live = liveHolder(holderOf(readLock(path2)));
|
|
24226
|
-
if (live !== void 0) return { heldBy: live };
|
|
24227
|
-
const aside = `${path2}.${process.pid}.${token}.stale`;
|
|
24228
|
-
try {
|
|
24229
|
-
renameSync3(path2, aside);
|
|
24230
|
-
} catch (renameError) {
|
|
24231
|
-
if (renameError.code === "ENOENT") continue;
|
|
24232
|
-
throw renameError;
|
|
24233
|
-
}
|
|
24234
|
-
const moved = liveHolder(holderOf(readLock(aside)));
|
|
24235
|
-
if (moved !== void 0) {
|
|
24236
|
-
try {
|
|
24237
|
-
linkSync(aside, path2);
|
|
24238
|
-
} catch {
|
|
24239
|
-
}
|
|
24240
|
-
removeQuietly(aside);
|
|
24241
|
-
return { heldBy: moved };
|
|
24242
|
-
}
|
|
24243
|
-
removeQuietly(aside);
|
|
24244
|
-
}
|
|
24245
|
-
}
|
|
24246
|
-
return { heldBy: -1 };
|
|
24247
|
-
}
|
|
24248
|
-
var STALE_AFTER_MS;
|
|
24249
|
-
var init_install_lock = __esm({
|
|
24250
|
-
"../../packages/tacho/src/host/install-lock.ts"() {
|
|
24251
|
-
"use strict";
|
|
24252
|
-
STALE_AFTER_MS = 10 * 6e4;
|
|
24253
|
-
}
|
|
24254
|
-
});
|
|
24255
|
-
|
|
24256
24536
|
// ../../packages/tacho/src/host/wal-index.ts
|
|
24257
24537
|
import {
|
|
24258
24538
|
appendFileSync,
|
|
@@ -24260,7 +24540,7 @@ import {
|
|
|
24260
24540
|
existsSync as existsSync11,
|
|
24261
24541
|
openSync as openSync5,
|
|
24262
24542
|
readSync as readSync2,
|
|
24263
|
-
statSync as
|
|
24543
|
+
statSync as statSync7,
|
|
24264
24544
|
unlinkSync as unlinkSync8
|
|
24265
24545
|
} from "node:fs";
|
|
24266
24546
|
import { open as open2 } from "node:fs/promises";
|
|
@@ -24278,7 +24558,7 @@ function parseStoredBody(text4) {
|
|
|
24278
24558
|
return void 0;
|
|
24279
24559
|
return stored;
|
|
24280
24560
|
}
|
|
24281
|
-
function readTailLine(path2, size =
|
|
24561
|
+
function readTailLine(path2, size = statSync7(path2).size, window2 = SCAN_CHUNK_BYTES) {
|
|
24282
24562
|
if (size === 0) return void 0;
|
|
24283
24563
|
const fd2 = openSync5(path2, "r");
|
|
24284
24564
|
try {
|
|
@@ -24495,7 +24775,7 @@ var init_wal_index = __esm({
|
|
|
24495
24775
|
}
|
|
24496
24776
|
/** The index to extend, and the byte the scan starts from. */
|
|
24497
24777
|
base(sessionUuid2, bodiesPath) {
|
|
24498
|
-
const size =
|
|
24778
|
+
const size = statSync7(bodiesPath).size;
|
|
24499
24779
|
const held = this.cached.get(sessionUuid2) ?? this.load(sessionUuid2);
|
|
24500
24780
|
if (held !== void 0 && held.covered <= size) return held;
|
|
24501
24781
|
this.discard(sessionUuid2);
|
|
@@ -24569,7 +24849,7 @@ ${lines.join("\n")}
|
|
|
24569
24849
|
* answers undefined.
|
|
24570
24850
|
*/
|
|
24571
24851
|
covering(sessionUuid2, bodiesPath) {
|
|
24572
|
-
const size =
|
|
24852
|
+
const size = statSync7(bodiesPath).size;
|
|
24573
24853
|
const held = this.cached.get(sessionUuid2) ?? this.load(sessionUuid2);
|
|
24574
24854
|
if (held === void 0 || held.covered !== size) return void 0;
|
|
24575
24855
|
this.remember(sessionUuid2, held);
|
|
@@ -24583,7 +24863,7 @@ ${lines.join("\n")}
|
|
|
24583
24863
|
* file.
|
|
24584
24864
|
*/
|
|
24585
24865
|
held(sessionUuid2, bodiesPath) {
|
|
24586
|
-
const size =
|
|
24866
|
+
const size = statSync7(bodiesPath).size;
|
|
24587
24867
|
const held = this.cached.get(sessionUuid2) ?? this.load(sessionUuid2);
|
|
24588
24868
|
if (held === void 0 || held.covered > size) return void 0;
|
|
24589
24869
|
this.remember(sessionUuid2, held);
|
|
@@ -24592,7 +24872,7 @@ ${lines.join("\n")}
|
|
|
24592
24872
|
/** The index of a body file, built or extended to cover the whole file. */
|
|
24593
24873
|
ensure(sessionUuid2, bodiesPath, onInvalidRecord, onWriteFailure) {
|
|
24594
24874
|
const index = this.base(sessionUuid2, bodiesPath);
|
|
24595
|
-
const size =
|
|
24875
|
+
const size = statSync7(bodiesPath).size;
|
|
24596
24876
|
if (index.covered < size) {
|
|
24597
24877
|
const result2 = {
|
|
24598
24878
|
added: [],
|
|
@@ -24646,7 +24926,7 @@ ${lines.join("\n")}
|
|
|
24646
24926
|
for (let attempt = 0; ; attempt += 1) {
|
|
24647
24927
|
const generation = this.generationOf(sessionUuid2);
|
|
24648
24928
|
const index = this.base(sessionUuid2, bodiesPath);
|
|
24649
|
-
const size =
|
|
24929
|
+
const size = statSync7(bodiesPath).size;
|
|
24650
24930
|
if (index.covered >= size) {
|
|
24651
24931
|
this.remember(sessionUuid2, index);
|
|
24652
24932
|
return index;
|
|
@@ -24686,7 +24966,7 @@ import {
|
|
|
24686
24966
|
readSync as readSync3,
|
|
24687
24967
|
truncateSync,
|
|
24688
24968
|
renameSync as renameSync4,
|
|
24689
|
-
statSync as
|
|
24969
|
+
statSync as statSync8,
|
|
24690
24970
|
unlinkSync as unlinkSync9,
|
|
24691
24971
|
writeSync as writeSync4
|
|
24692
24972
|
} from "node:fs";
|
|
@@ -24697,7 +24977,7 @@ function activityAt(event) {
|
|
|
24697
24977
|
return Number.isFinite(at) ? at : Number.NEGATIVE_INFINITY;
|
|
24698
24978
|
}
|
|
24699
24979
|
function sizeOf(path2) {
|
|
24700
|
-
return
|
|
24980
|
+
return statSync8(path2, { throwIfNoEntry: false })?.size ?? 0;
|
|
24701
24981
|
}
|
|
24702
24982
|
var BODY_READ_SLICE, BODY_DROP_SLICE_BYTES, BODY_DROP_SCANS, NEWLINE, EVENT_TAIL_WINDOW, WalRecoveryConflict, Wal;
|
|
24703
24983
|
var init_wal = __esm({
|
|
@@ -25057,7 +25337,7 @@ ${lines.join("\n")}
|
|
|
25057
25337
|
for (const session of sessions) {
|
|
25058
25338
|
if (sizes.has(session)) continue;
|
|
25059
25339
|
const path2 = pathOf2(session);
|
|
25060
|
-
sizes.set(session, existsSync12(path2) ?
|
|
25340
|
+
sizes.set(session, existsSync12(path2) ? statSync8(path2).size : void 0);
|
|
25061
25341
|
}
|
|
25062
25342
|
return sizes;
|
|
25063
25343
|
}
|
|
@@ -25073,7 +25353,7 @@ ${lines.join("\n")}
|
|
|
25073
25353
|
try {
|
|
25074
25354
|
if (!existsSync12(path2)) continue;
|
|
25075
25355
|
if (size === void 0) unlinkSync9(path2);
|
|
25076
|
-
else if (
|
|
25356
|
+
else if (statSync8(path2).size !== size) truncateSync(path2, size);
|
|
25077
25357
|
} catch (error) {
|
|
25078
25358
|
onFailure(session, error);
|
|
25079
25359
|
}
|
|
@@ -25736,7 +26016,7 @@ ${lines.join("\n")}
|
|
|
25736
26016
|
const lastSeq = this.lastWrittenSeq(sessionUuid2);
|
|
25737
26017
|
if (lastSeq === void 0) return 0;
|
|
25738
26018
|
const path2 = this.bodyFileFor(sessionUuid2);
|
|
25739
|
-
const size =
|
|
26019
|
+
const size = statSync8(path2).size;
|
|
25740
26020
|
let keep = size;
|
|
25741
26021
|
let cut2 = 0;
|
|
25742
26022
|
while (keep > 0) {
|
|
@@ -25769,7 +26049,7 @@ ${lines.join("\n")}
|
|
|
25769
26049
|
*/
|
|
25770
26050
|
lastWrittenSeq(sessionUuid2) {
|
|
25771
26051
|
const path2 = this.fileFor(sessionUuid2);
|
|
25772
|
-
if (!existsSync12(path2) ||
|
|
26052
|
+
if (!existsSync12(path2) || statSync8(path2).size === 0) return -1;
|
|
25773
26053
|
return this.lastEvent(sessionUuid2)?.seq;
|
|
25774
26054
|
}
|
|
25775
26055
|
/**
|
|
@@ -25800,7 +26080,7 @@ ${lines.join("\n")}
|
|
|
25800
26080
|
*eventsBackward(sessionUuid2) {
|
|
25801
26081
|
const path2 = this.fileFor(sessionUuid2);
|
|
25802
26082
|
if (!existsSync12(path2)) return;
|
|
25803
|
-
let end =
|
|
26083
|
+
let end = statSync8(path2).size;
|
|
25804
26084
|
while (end > 0) {
|
|
25805
26085
|
const line = readTailLine(path2, end, EVENT_TAIL_WINDOW);
|
|
25806
26086
|
if (line === void 0) return;
|
|
@@ -25831,7 +26111,7 @@ ${lines.join("\n")}
|
|
|
25831
26111
|
this.unverifiedResume.delete(sessionUuid2);
|
|
25832
26112
|
let holds2 = false;
|
|
25833
26113
|
try {
|
|
25834
|
-
if (mark.offset <=
|
|
26114
|
+
if (mark.offset <= statSync8(path2).size) {
|
|
25835
26115
|
const line = readTailLine(path2, mark.offset, EVENT_TAIL_WINDOW);
|
|
25836
26116
|
holds2 = line !== void 0 && line.terminated && line.end === mark.offset && JSON.parse(line.text).seq === mark.afterSeq;
|
|
25837
26117
|
}
|
|
@@ -26227,7 +26507,7 @@ ${lines.join("\n")}
|
|
|
26227
26507
|
if (sealedAt === void 0) continue;
|
|
26228
26508
|
const path2 = this.fileFor(session);
|
|
26229
26509
|
try {
|
|
26230
|
-
const age = now - Math.max(Date.parse(sealedAt),
|
|
26510
|
+
const age = now - Math.max(Date.parse(sealedAt), statSync8(path2).mtimeMs);
|
|
26231
26511
|
if (age < retainMs) continue;
|
|
26232
26512
|
const last = this.lastSeqOf(session);
|
|
26233
26513
|
if (last < 0 || last > this.shippedThrough(session)) continue;
|
|
@@ -26249,7 +26529,7 @@ ${lines.join("\n")}
|
|
|
26249
26529
|
if (removed.includes(session) || existsSync12(this.fileFor(session)))
|
|
26250
26530
|
continue;
|
|
26251
26531
|
try {
|
|
26252
|
-
if (now -
|
|
26532
|
+
if (now - statSync8(this.bodyFileFor(session)).mtimeMs < retainMs)
|
|
26253
26533
|
continue;
|
|
26254
26534
|
} catch (error) {
|
|
26255
26535
|
this.bodyFailure(session, "cleanup", error);
|
|
@@ -27303,7 +27583,7 @@ import {
|
|
|
27303
27583
|
existsSync as existsSync15,
|
|
27304
27584
|
lstatSync as lstatSync3,
|
|
27305
27585
|
readdirSync as readdirSync8,
|
|
27306
|
-
rmdirSync as
|
|
27586
|
+
rmdirSync as rmdirSync6,
|
|
27307
27587
|
rmSync as rmSync2,
|
|
27308
27588
|
unlinkSync as unlinkSync10
|
|
27309
27589
|
} from "node:fs";
|
|
@@ -27540,6 +27820,24 @@ async function stripEnrollmentHooks(host, deps, settle3 = false) {
|
|
|
27540
27820
|
}
|
|
27541
27821
|
});
|
|
27542
27822
|
}
|
|
27823
|
+
let claudeCodeMcpChanged;
|
|
27824
|
+
const editUserConfig = deps.editClaudeUserConfig;
|
|
27825
|
+
if (editUserConfig !== void 0 && (host?.harnesses === void 0 || host.harnesses.includes("claude-code"))) {
|
|
27826
|
+
const userConfig = deps.paths.claudeUserConfig;
|
|
27827
|
+
attempt(userConfig, () => {
|
|
27828
|
+
editUserConfig((current) => {
|
|
27829
|
+
if (current === void 0) return void 0;
|
|
27830
|
+
const stripped = stripClaudeCodeMcpConfig(
|
|
27831
|
+
current,
|
|
27832
|
+
host?.host_enrollment_id,
|
|
27833
|
+
host?.displaced_mcp_servers?.["claude-code"] ?? {}
|
|
27834
|
+
);
|
|
27835
|
+
if (!stripped.changed) return void 0;
|
|
27836
|
+
claudeCodeMcpChanged = userConfig;
|
|
27837
|
+
return stripped.config;
|
|
27838
|
+
});
|
|
27839
|
+
});
|
|
27840
|
+
}
|
|
27543
27841
|
if (settle3 && failed3.length === 0) {
|
|
27544
27842
|
try {
|
|
27545
27843
|
deps.settleHarnessFiles?.();
|
|
@@ -27557,6 +27855,7 @@ async function stripEnrollmentHooks(host, deps, settle3 = false) {
|
|
|
27557
27855
|
cursorChanged,
|
|
27558
27856
|
stellaChanged,
|
|
27559
27857
|
claudeDesktopChanged,
|
|
27858
|
+
...claudeCodeMcpChanged !== void 0 ? { claudeCodeMcpChanged } : {},
|
|
27560
27859
|
failed: failed3
|
|
27561
27860
|
};
|
|
27562
27861
|
}
|
|
@@ -27669,7 +27968,7 @@ function restartForRemaining(installed, deps) {
|
|
|
27669
27968
|
}
|
|
27670
27969
|
function removeIfEmpty(dir) {
|
|
27671
27970
|
try {
|
|
27672
|
-
if (readdirSync8(dir).length === 0)
|
|
27971
|
+
if (readdirSync8(dir).length === 0) rmdirSync6(dir);
|
|
27673
27972
|
} catch {
|
|
27674
27973
|
}
|
|
27675
27974
|
}
|
|
@@ -27759,6 +28058,11 @@ async function unenrollLocked(options, deps) {
|
|
|
27759
28058
|
" Quit Claude Desktop and open it again for the change to take effect"
|
|
27760
28059
|
);
|
|
27761
28060
|
}
|
|
28061
|
+
if (stripped.claudeCodeMcpChanged !== void 0) {
|
|
28062
|
+
deps.out(
|
|
28063
|
+
` Oxagen's MCP server removed from ${stripped.claudeCodeMcpChanged}`
|
|
28064
|
+
);
|
|
28065
|
+
}
|
|
27762
28066
|
for (const failure2 of stripped.failed) {
|
|
27763
28067
|
incomplete = true;
|
|
27764
28068
|
warnings.push(
|
|
@@ -27890,6 +28194,7 @@ var init_unenroll = __esm({
|
|
|
27890
28194
|
"../../packages/tacho/src/cli/unenroll.ts"() {
|
|
27891
28195
|
"use strict";
|
|
27892
28196
|
init_install_lock();
|
|
28197
|
+
init_claude_code_mcp_writer();
|
|
27893
28198
|
init_claude_desktop_writer();
|
|
27894
28199
|
init_codex_hook_trust();
|
|
27895
28200
|
init_codex_writer();
|
|
@@ -28638,6 +28943,32 @@ ${problems.map((problem) => ` ${problem}`).join("\n")}`
|
|
|
28638
28943
|
deps.out(" already present; nothing to change");
|
|
28639
28944
|
}
|
|
28640
28945
|
});
|
|
28946
|
+
if (harnesses.includes("claude-code") && !unhooked.includes("claude-code") && deps.editClaudeUserConfig !== void 0) {
|
|
28947
|
+
deps.out(` Claude Code MCP server: ${deps.paths.claudeUserConfig}`);
|
|
28948
|
+
try {
|
|
28949
|
+
const registered = registerClaudeCodeMcp(host, deps);
|
|
28950
|
+
host = registered.host;
|
|
28951
|
+
if (registered.result === "skipped")
|
|
28952
|
+
warnings.push(
|
|
28953
|
+
`Claude Code was not given Oxagen's tools: ${registered.reason ?? "unknown reason"}. Until it has them, the Stop hook asks Claude Code for no reflection.`
|
|
28954
|
+
);
|
|
28955
|
+
else if (registered.result === "written")
|
|
28956
|
+
deps.out(
|
|
28957
|
+
" `oxagen` server written; a new Claude Code session lists Oxagen's tools"
|
|
28958
|
+
);
|
|
28959
|
+
else deps.out(" already present; nothing to change");
|
|
28960
|
+
if (registered.displaced)
|
|
28961
|
+
warnings.push(
|
|
28962
|
+
"an MCP server already used the name `oxagen` in Claude Code; it was moved aside and unenroll restores it"
|
|
28963
|
+
);
|
|
28964
|
+
} catch (error) {
|
|
28965
|
+
host = readHostFile(deps.paths.hostFile) ?? host;
|
|
28966
|
+
warnings.push(
|
|
28967
|
+
`Claude Code was not given Oxagen's tools: ${error instanceof Error ? error.message : String(error)}. The hooks are written. Run \`oxagen agent enroll\` again to add the tools; until then the Stop hook asks Claude Code for no reflection.`
|
|
28968
|
+
);
|
|
28969
|
+
deps.out(" not written (see the warning below)");
|
|
28970
|
+
}
|
|
28971
|
+
}
|
|
28641
28972
|
hook("codex", () => {
|
|
28642
28973
|
deps.out(` Codex: ${deps.paths.codexHooks}`);
|
|
28643
28974
|
const merged = mergeCodexHooks(deps.readCodexHooks(), hookConfig);
|
|
@@ -29012,6 +29343,7 @@ var init_enroll = __esm({
|
|
|
29012
29343
|
init_credential();
|
|
29013
29344
|
init_github();
|
|
29014
29345
|
init_agent_deps();
|
|
29346
|
+
init_claude_code_mcp();
|
|
29015
29347
|
init_daemon_service();
|
|
29016
29348
|
init_policy_mode();
|
|
29017
29349
|
init_status();
|
|
@@ -29914,9 +30246,9 @@ import {
|
|
|
29914
30246
|
readFileSync as readFileSync14,
|
|
29915
30247
|
readlinkSync as readlinkSync3,
|
|
29916
30248
|
realpathSync as realpathSync2,
|
|
29917
|
-
rmdirSync as
|
|
30249
|
+
rmdirSync as rmdirSync7,
|
|
29918
30250
|
rmSync as rmSync4,
|
|
29919
|
-
statSync as
|
|
30251
|
+
statSync as statSync9,
|
|
29920
30252
|
unlinkSync as unlinkSync11
|
|
29921
30253
|
} from "node:fs";
|
|
29922
30254
|
import { dirname as dirname13, isAbsolute, join as join19, relative, resolve as resolve6, sep } from "node:path";
|
|
@@ -30072,7 +30404,7 @@ function removeFile(path2, tally2, note = "") {
|
|
|
30072
30404
|
function removeDirIfEmpty(dir) {
|
|
30073
30405
|
try {
|
|
30074
30406
|
if (readdirSync9(dir).length > 0) return false;
|
|
30075
|
-
|
|
30407
|
+
rmdirSync7(dir);
|
|
30076
30408
|
return true;
|
|
30077
30409
|
} catch {
|
|
30078
30410
|
return false;
|
|
@@ -30091,7 +30423,7 @@ function removeProfileBlock(path2, tally2) {
|
|
|
30091
30423
|
if (updated === text4) return;
|
|
30092
30424
|
try {
|
|
30093
30425
|
const real = realpathSync2(path2);
|
|
30094
|
-
writeFileAtomic(real, updated, { mode:
|
|
30426
|
+
writeFileAtomic(real, updated, { mode: statSync9(real).mode & 4095 });
|
|
30095
30427
|
tally2.removed.push(`the Oxagen PATH lines in ${path2}`);
|
|
30096
30428
|
} catch (error) {
|
|
30097
30429
|
tally2.left.push(`cannot rewrite ${path2}: ${reasonOf3(error)}`);
|
|
@@ -31162,10 +31494,12 @@ __export(cli_exports, {
|
|
|
31162
31494
|
MODEL_CREDENTIAL_HARNESSES: () => MODEL_CREDENTIAL_HARNESSES,
|
|
31163
31495
|
SHIPPING_STALL_MS: () => SHIPPING_STALL_MS,
|
|
31164
31496
|
STATIC_TOKEN_RENEW_WINDOW_MS: () => STATIC_TOKEN_RENEW_WINDOW_MS,
|
|
31497
|
+
addMissingClaudeCodeMcp: () => addMissingClaudeCodeMcp,
|
|
31165
31498
|
agentNameFromCommand: () => agentNameFromCommand,
|
|
31166
31499
|
backfillCommand: () => backfillCommand,
|
|
31167
31500
|
brokerCredentials: () => brokerCredentials,
|
|
31168
31501
|
brokerEnvVar: () => brokerEnvVar,
|
|
31502
|
+
canServeOxagenTools: () => canServeOxagenTools,
|
|
31169
31503
|
claudeDesktopFacts: () => claudeDesktopFacts,
|
|
31170
31504
|
claudeFacts: () => claudeFacts,
|
|
31171
31505
|
credentialIssue: () => credentialIssue,
|
|
@@ -31191,6 +31525,7 @@ __export(cli_exports, {
|
|
|
31191
31525
|
isNativeBuild: () => isNativeBuild,
|
|
31192
31526
|
moveOffTachoNames: () => moveOffTachoNames,
|
|
31193
31527
|
namesTachoExecutable: () => namesTachoExecutable,
|
|
31528
|
+
needsClaudeCodeMcp: () => needsClaudeCodeMcp,
|
|
31194
31529
|
observedTiers: () => observedTiers,
|
|
31195
31530
|
oxagenRuntimeCommands: () => oxagenRuntimeCommands,
|
|
31196
31531
|
parseCredentialMode: () => parseCredentialMode,
|
|
@@ -31199,6 +31534,7 @@ __export(cli_exports, {
|
|
|
31199
31534
|
readDesktopRecord: () => readDesktopRecord,
|
|
31200
31535
|
reassign: () => reassign,
|
|
31201
31536
|
reassignTarget: () => reassignTarget,
|
|
31537
|
+
registerClaudeCodeMcp: () => registerClaudeCodeMcp,
|
|
31202
31538
|
removePathBlocks: () => removePathBlocks,
|
|
31203
31539
|
repointCommands: () => repointCommands,
|
|
31204
31540
|
resolveApiUrl: () => resolveApiUrl,
|
|
@@ -31241,6 +31577,7 @@ var init_cli = __esm({
|
|
|
31241
31577
|
"../../packages/tacho/src/cli/index.ts"() {
|
|
31242
31578
|
"use strict";
|
|
31243
31579
|
init_backfill3();
|
|
31580
|
+
init_claude_code_mcp();
|
|
31244
31581
|
init_credential();
|
|
31245
31582
|
init_deps();
|
|
31246
31583
|
init_detect();
|
|
@@ -37377,6 +37714,7 @@ function reflectionAsk(record, options) {
|
|
|
37377
37714
|
const state = states.get(record);
|
|
37378
37715
|
if (state === void 0 || state.asked || state.reflected || state.signals.size === 0)
|
|
37379
37716
|
return void 0;
|
|
37717
|
+
if (!options.toolRegistered()) return void 0;
|
|
37380
37718
|
state.asked = true;
|
|
37381
37719
|
const full = askText(state, true);
|
|
37382
37720
|
return full.length <= REFLECTION_ASK_MAX_CHARS ? full : askText(state, false);
|
|
@@ -38682,7 +39020,10 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
38682
39020
|
const ask = input.agent_id !== void 0 ? void 0 : reflectionAsk(record, {
|
|
38683
39021
|
harness: record.customAgent !== void 0 ? void 0 : record.harness ?? "claude-code",
|
|
38684
39022
|
stopHookActive: input["stop_hook_active"] === true,
|
|
38685
|
-
replayed: replay !== void 0
|
|
39023
|
+
replayed: replay !== void 0,
|
|
39024
|
+
toolRegistered: () => deps.reflectionToolRegistered?.({
|
|
39025
|
+
startedAt: record.startedAt
|
|
39026
|
+
}) ?? false
|
|
38686
39027
|
});
|
|
38687
39028
|
const texts = [
|
|
38688
39029
|
...drainMidTurn(input, record, deps, events, replay, ask?.length ?? 0),
|
|
@@ -45687,7 +46028,7 @@ var init_model_proxy_listener = __esm({
|
|
|
45687
46028
|
import {
|
|
45688
46029
|
createServer as createServer4
|
|
45689
46030
|
} from "node:http";
|
|
45690
|
-
import { chmodSync as chmodSync7, existsSync as existsSync18, statSync as
|
|
46031
|
+
import { chmodSync as chmodSync7, existsSync as existsSync18, statSync as statSync10, unlinkSync as unlinkSync12 } from "node:fs";
|
|
45691
46032
|
import { randomBytes as randomBytes10 } from "node:crypto";
|
|
45692
46033
|
import { createConnection } from "node:net";
|
|
45693
46034
|
function readBody(req) {
|
|
@@ -45959,7 +46300,7 @@ function createRequestHandler(api, log, options = {}) {
|
|
|
45959
46300
|
}
|
|
45960
46301
|
async function removeStaleSocket(socketPath) {
|
|
45961
46302
|
if (!existsSync18(socketPath)) return;
|
|
45962
|
-
if (!
|
|
46303
|
+
if (!statSync10(socketPath).isSocket()) {
|
|
45963
46304
|
throw new Error(`collector socket path is not a socket: ${socketPath}`);
|
|
45964
46305
|
}
|
|
45965
46306
|
const stale = await new Promise((resolve20, reject) => {
|
|
@@ -46747,7 +47088,7 @@ import {
|
|
|
46747
47088
|
readdirSync as readdirSync12,
|
|
46748
47089
|
readFileSync as readFileSync18,
|
|
46749
47090
|
renameSync as renameSync5,
|
|
46750
|
-
statSync as
|
|
47091
|
+
statSync as statSync11,
|
|
46751
47092
|
unlinkSync as unlinkSync13,
|
|
46752
47093
|
writeFileSync as writeFileSync3
|
|
46753
47094
|
} from "node:fs";
|
|
@@ -46922,6 +47263,22 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
46922
47263
|
))
|
|
46923
47264
|
memoryUses.note({ ...file, ...run });
|
|
46924
47265
|
};
|
|
47266
|
+
const reflectionToolRegistered = (session) => {
|
|
47267
|
+
try {
|
|
47268
|
+
const current = readHostFile(paths.hostFile) ?? host;
|
|
47269
|
+
return claudeCodeSessionHasOxagenTools({
|
|
47270
|
+
enrollmentId: current.host_enrollment_id,
|
|
47271
|
+
hasGatewayKey: current.gateway_api_key !== void 0,
|
|
47272
|
+
registeredAt: current.mcp_registered_at?.["claude-code"],
|
|
47273
|
+
sessionStartedAt: session.startedAt,
|
|
47274
|
+
readUserConfig: () => readJsonFileIfExists(
|
|
47275
|
+
withRecordedHarnessFiles(paths, current).claudeUserConfig
|
|
47276
|
+
)
|
|
47277
|
+
});
|
|
47278
|
+
} catch {
|
|
47279
|
+
return false;
|
|
47280
|
+
}
|
|
47281
|
+
};
|
|
46925
47282
|
const localServers = options.localServers === true ? createMachineLoop({
|
|
46926
47283
|
host: () => host,
|
|
46927
47284
|
fetch: options.fetch ?? globalThis.fetch,
|
|
@@ -46987,7 +47344,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
46987
47344
|
processStarts: hookProcessStarts,
|
|
46988
47345
|
adoptedChain: (sessionUuid2) => backfillLedger.chainHead(sessionUuid2)
|
|
46989
47346
|
});
|
|
46990
|
-
const priorStateWrittenAt = existsSync20(paths.daemonState) ?
|
|
47347
|
+
const priorStateWrittenAt = existsSync20(paths.daemonState) ? statSync11(paths.daemonState).mtimeMs : void 0;
|
|
46991
47348
|
const sealedState = parseSealedState(
|
|
46992
47349
|
readJsonStateFile(
|
|
46993
47350
|
paths.daemonSealedState,
|
|
@@ -48063,7 +48420,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
48063
48420
|
cedar: loadCedarRuntime,
|
|
48064
48421
|
skills,
|
|
48065
48422
|
...recallMemories !== void 0 ? { recallMemories } : {},
|
|
48066
|
-
...noteMemoryReads !== void 0 ? { noteMemoryReads } : {}
|
|
48423
|
+
...noteMemoryReads !== void 0 ? { noteMemoryReads } : {},
|
|
48424
|
+
reflectionToolRegistered
|
|
48067
48425
|
},
|
|
48068
48426
|
envelope2.replay,
|
|
48069
48427
|
envelope2.harness,
|
|
@@ -49012,7 +49370,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
49012
49370
|
if (!name.endsWith(".json")) continue;
|
|
49013
49371
|
const file = join34(paths.quarantine, name);
|
|
49014
49372
|
try {
|
|
49015
|
-
if (at -
|
|
49373
|
+
if (at - statSync11(file).mtimeMs < retainMs) continue;
|
|
49016
49374
|
unlinkSync13(file);
|
|
49017
49375
|
removed += 1;
|
|
49018
49376
|
} catch {
|
|
@@ -49442,6 +49800,7 @@ var init_daemon = __esm({
|
|
|
49442
49800
|
init_device_key();
|
|
49443
49801
|
init_fs();
|
|
49444
49802
|
init_host_file();
|
|
49803
|
+
init_claude_code_mcp_writer();
|
|
49445
49804
|
init_model_base_url();
|
|
49446
49805
|
init_model_credential();
|
|
49447
49806
|
init_run_token();
|
|
@@ -49877,7 +50236,7 @@ import {
|
|
|
49877
50236
|
constants as constants3,
|
|
49878
50237
|
fstatSync as fstatSync2,
|
|
49879
50238
|
lstatSync as lstatSync7,
|
|
49880
|
-
mkdirSync as
|
|
50239
|
+
mkdirSync as mkdirSync8,
|
|
49881
50240
|
openSync as openSync7,
|
|
49882
50241
|
readSync as readSync4,
|
|
49883
50242
|
realpathSync as realpathSync5,
|
|
@@ -49886,7 +50245,7 @@ import {
|
|
|
49886
50245
|
import { dirname as dirname20, join as join35, resolve as resolve13 } from "node:path";
|
|
49887
50246
|
function bundlePath(root, relative10, create2 = false) {
|
|
49888
50247
|
const absolute = resolve13(root);
|
|
49889
|
-
if (create2)
|
|
50248
|
+
if (create2) mkdirSync8(absolute, { recursive: true, mode: 448 });
|
|
49890
50249
|
if (lstatSync7(absolute).isSymbolicLink() || !lstatSync7(absolute).isDirectory()) {
|
|
49891
50250
|
throw new Error("ARP bundle root must be a directory, not a symlink");
|
|
49892
50251
|
}
|
|
@@ -49902,7 +50261,7 @@ function bundlePath(root, relative10, create2 = false) {
|
|
|
49902
50261
|
}
|
|
49903
50262
|
} catch (error) {
|
|
49904
50263
|
if (error.code !== "ENOENT") throw error;
|
|
49905
|
-
if (create2 && i2 < parts.length - 1)
|
|
50264
|
+
if (create2 && i2 < parts.length - 1) mkdirSync8(current, { mode: 448 });
|
|
49906
50265
|
else if (i2 < parts.length - 1) throw error;
|
|
49907
50266
|
}
|
|
49908
50267
|
}
|
|
@@ -50766,7 +51125,7 @@ import {
|
|
|
50766
51125
|
constants as constants4,
|
|
50767
51126
|
fstatSync as fstatSync3,
|
|
50768
51127
|
lstatSync as lstatSync8,
|
|
50769
|
-
mkdirSync as
|
|
51128
|
+
mkdirSync as mkdirSync9,
|
|
50770
51129
|
openSync as openSync8,
|
|
50771
51130
|
readSync as readSync5,
|
|
50772
51131
|
realpathSync as realpathSync6,
|
|
@@ -50896,7 +51255,7 @@ function captureCheckpoint(options) {
|
|
|
50896
51255
|
executable: (file.mode & 73) !== 0
|
|
50897
51256
|
});
|
|
50898
51257
|
}
|
|
50899
|
-
|
|
51258
|
+
mkdirSync9(out, { mode: 448 });
|
|
50900
51259
|
try {
|
|
50901
51260
|
const blob = (value) => storeBlob(out, Buffer.from(jcs(value)), "application/json");
|
|
50902
51261
|
const entries2 = [];
|
|
@@ -51083,16 +51442,16 @@ function prepareCheckpoint(options) {
|
|
|
51083
51442
|
}
|
|
51084
51443
|
return { entry: entry2, bytes: null };
|
|
51085
51444
|
});
|
|
51086
|
-
|
|
51445
|
+
mkdirSync9(destination, { mode: 448 });
|
|
51087
51446
|
try {
|
|
51088
51447
|
const restored = join36(destination, "workspace");
|
|
51089
|
-
|
|
51448
|
+
mkdirSync9(restored, { mode: 448 });
|
|
51090
51449
|
for (const { entry: entry2, bytes } of files2) {
|
|
51091
51450
|
const path2 = join36(restored, entry2.path);
|
|
51092
51451
|
if (entry2.kind === "directory")
|
|
51093
|
-
|
|
51452
|
+
mkdirSync9(path2, { recursive: true, mode: 448 });
|
|
51094
51453
|
else {
|
|
51095
|
-
|
|
51454
|
+
mkdirSync9(dirname21(path2), { recursive: true, mode: 448 });
|
|
51096
51455
|
if (bytes === null) fail2("Workspace file has no bytes.");
|
|
51097
51456
|
writeFileSync6(path2, bytes, {
|
|
51098
51457
|
flag: "wx",
|
|
@@ -51101,7 +51460,7 @@ function prepareCheckpoint(options) {
|
|
|
51101
51460
|
}
|
|
51102
51461
|
}
|
|
51103
51462
|
const promptDir = join36(restored, ".arp");
|
|
51104
|
-
|
|
51463
|
+
mkdirSync9(promptDir, { mode: 448 });
|
|
51105
51464
|
const promptFile = join36(promptDir, "handoff.json");
|
|
51106
51465
|
const prompt = {
|
|
51107
51466
|
checkpoint_digest: checkpointDigest,
|
|
@@ -51676,7 +52035,7 @@ var init_package = __esm({
|
|
|
51676
52035
|
"package.json"() {
|
|
51677
52036
|
package_default = {
|
|
51678
52037
|
name: "@oxagen/cli",
|
|
51679
|
-
version: "2.1.4-
|
|
52038
|
+
version: "2.1.4-453",
|
|
51680
52039
|
description: "Oxagen governance CLI \u2014 spend, lineage, grounding, credentials, and audit (agentic coding lives in the stella CLI)",
|
|
51681
52040
|
type: "module",
|
|
51682
52041
|
main: "./dist/index.js",
|
|
@@ -51787,7 +52146,7 @@ var init_atomic_write = __esm({
|
|
|
51787
52146
|
// src/lib/config.ts
|
|
51788
52147
|
import { homedir as homedir8 } from "os";
|
|
51789
52148
|
import { join as join38 } from "path";
|
|
51790
|
-
import { readFileSync as readFileSync21, mkdirSync as
|
|
52149
|
+
import { readFileSync as readFileSync21, mkdirSync as mkdirSync10, existsSync as existsSync22 } from "fs";
|
|
51791
52150
|
function getConfigDir() {
|
|
51792
52151
|
return CONFIG_DIR;
|
|
51793
52152
|
}
|
|
@@ -51808,7 +52167,7 @@ Run \`oxagen login\` to re-authenticate.
|
|
|
51808
52167
|
function writeConfig(patch) {
|
|
51809
52168
|
const current = readConfig();
|
|
51810
52169
|
const next = { ...current, ...patch };
|
|
51811
|
-
if (!existsSync22(CONFIG_DIR))
|
|
52170
|
+
if (!existsSync22(CONFIG_DIR)) mkdirSync10(CONFIG_DIR, { recursive: true });
|
|
51812
52171
|
atomicWriteFileSync(CONFIG_FILE, JSON.stringify(next, null, 2));
|
|
51813
52172
|
}
|
|
51814
52173
|
function clearConfig() {
|
|
@@ -52363,6 +52722,34 @@ var init_api = __esm({
|
|
|
52363
52722
|
}
|
|
52364
52723
|
});
|
|
52365
52724
|
|
|
52725
|
+
// src/commands/add-claude-code-mcp.ts
|
|
52726
|
+
async function addClaudeCodeMcp(writer) {
|
|
52727
|
+
const { addMissingClaudeCodeMcp: addMissingClaudeCodeMcp2, defaultCliDeps: defaultCliDeps2, oxagenRuntimeCommands: oxagenRuntimeCommands2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
|
|
52728
|
+
let added;
|
|
52729
|
+
try {
|
|
52730
|
+
added = addMissingClaudeCodeMcp2(
|
|
52731
|
+
defaultCliDeps2({
|
|
52732
|
+
out: () => void 0,
|
|
52733
|
+
err: (line) => writer.writeErr(line),
|
|
52734
|
+
runtime: oxagenRuntimeCommands2()
|
|
52735
|
+
})
|
|
52736
|
+
);
|
|
52737
|
+
} catch (error) {
|
|
52738
|
+
writer.writeErr(
|
|
52739
|
+
`Could not check Claude Code for Oxagen's MCP server: ${error instanceof Error ? error.message : String(error)}. Run \`oxagen agent enroll\` to add it.`
|
|
52740
|
+
);
|
|
52741
|
+
return;
|
|
52742
|
+
}
|
|
52743
|
+
for (const agent of added)
|
|
52744
|
+
writer.writeErr(
|
|
52745
|
+
agent.ok ? `Added Oxagen's MCP server to Claude Code for ${agent.agentKey} in ${agent.path}. New Claude Code sessions list Oxagen's tools.` : `Could not add Oxagen's MCP server to Claude Code for ${agent.agentKey}: ${agent.problem ?? "unknown reason"}. The hooks keep working. Run \`oxagen agent enroll\` to try again.`
|
|
52746
|
+
);
|
|
52747
|
+
}
|
|
52748
|
+
var init_add_claude_code_mcp = __esm({
|
|
52749
|
+
"src/commands/add-claude-code-mcp.ts"() {
|
|
52750
|
+
}
|
|
52751
|
+
});
|
|
52752
|
+
|
|
52366
52753
|
// src/commands/move-off-tacho.ts
|
|
52367
52754
|
async function moveOffTacho(writer) {
|
|
52368
52755
|
const { defaultCliDeps: defaultCliDeps2, moveOffTachoNames: moveOffTachoNames2, oxagenRuntimeCommands: oxagenRuntimeCommands2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
|
|
@@ -52462,6 +52849,7 @@ async function handleTachoEnroll(opts, writer = stdoutWriter) {
|
|
|
52462
52849
|
async function handleTachoStatus(opts, writer = stdoutWriter) {
|
|
52463
52850
|
const { status: status2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
|
|
52464
52851
|
await moveOffTacho(writer);
|
|
52852
|
+
await addClaudeCodeMcp(writer);
|
|
52465
52853
|
const report = await status2(opts, await tachoDeps(writer));
|
|
52466
52854
|
const reports = [report, ...report.enrollments ?? []];
|
|
52467
52855
|
return report.enrolled && !reports.some((entry2) => entry2.shipping?.healthy === false);
|
|
@@ -52678,6 +53066,7 @@ var init_tacho = __esm({
|
|
|
52678
53066
|
init_config();
|
|
52679
53067
|
init_capture_writer();
|
|
52680
53068
|
init_api();
|
|
53069
|
+
init_add_claude_code_mcp();
|
|
52681
53070
|
init_move_off_tacho();
|
|
52682
53071
|
}
|
|
52683
53072
|
});
|
|
@@ -54094,6 +54483,12 @@ async function findingsList(opts, writer = stdoutWriter) {
|
|
|
54094
54483
|
]),
|
|
54095
54484
|
writer
|
|
54096
54485
|
);
|
|
54486
|
+
if (result2.truncated === true) {
|
|
54487
|
+
writer.write("");
|
|
54488
|
+
writer.write(
|
|
54489
|
+
`The list shows the first ${result2.findings.length} of ${result2.counts.findings} ${status2} findings.`
|
|
54490
|
+
);
|
|
54491
|
+
}
|
|
54097
54492
|
}
|
|
54098
54493
|
var STATUSES, FRAMES_SHOWN;
|
|
54099
54494
|
var init_findings = __esm({
|
|
@@ -56802,7 +57197,7 @@ var init_src2 = __esm({
|
|
|
56802
57197
|
// src/commands/workspace-link.ts
|
|
56803
57198
|
import {
|
|
56804
57199
|
existsSync as existsSync23,
|
|
56805
|
-
mkdirSync as
|
|
57200
|
+
mkdirSync as mkdirSync11,
|
|
56806
57201
|
readFileSync as readFileSync22,
|
|
56807
57202
|
rmSync as rmSync9,
|
|
56808
57203
|
writeFileSync as writeFileSync8
|
|
@@ -56827,7 +57222,7 @@ function readWorkspaceLink(cwd) {
|
|
|
56827
57222
|
}
|
|
56828
57223
|
function writeWorkspaceLink(cwd, link) {
|
|
56829
57224
|
const dir = join44(cwd, ".oxagen");
|
|
56830
|
-
|
|
57225
|
+
mkdirSync11(dir, { recursive: true });
|
|
56831
57226
|
writeFileSync8(workspaceLinkPath(cwd), JSON.stringify(link, null, 2), "utf8");
|
|
56832
57227
|
}
|
|
56833
57228
|
var init_workspace_link = __esm({
|
|
@@ -58277,7 +58672,7 @@ var init_runtime_shared = __esm({
|
|
|
58277
58672
|
function spanDays(from, to) {
|
|
58278
58673
|
return (Date.parse(`${to}T00:00:00Z`) - Date.parse(`${from}T00:00:00Z`)) / DAY_MS + 1;
|
|
58279
58674
|
}
|
|
58280
|
-
var costBasisSchema, microsSchema, moneySchema, costSchema, daySchema, monthSchema, SPEND_RANGE_DAYS_MAX, DAY_MS, dayRangeSchema, principalPublicIdSchema, tokenCountsSchema, spendGroupKindSchema, ratioSchema, spendFigureSchema, spendDaySchema, unmeteredRunsSchema;
|
|
58675
|
+
var costBasisSchema, microsSchema, moneySchema, costSchema, daySchema, monthSchema, SPEND_RANGE_DAYS_MAX, DAY_MS, dayRangeSchema, principalPublicIdSchema, tokenCountsSchema, standingTokensSchema, spendGroupKindSchema, ratioSchema, spendFigureSchema, spendDaySchema, unmeteredRunsSchema;
|
|
58281
58676
|
var init_spend_shared = __esm({
|
|
58282
58677
|
"../../packages/oxagen/src/contracts/spend.shared.ts"() {
|
|
58283
58678
|
"use strict";
|
|
@@ -58326,6 +58721,11 @@ var init_spend_shared = __esm({
|
|
|
58326
58721
|
*/
|
|
58327
58722
|
server_tool_request: external_exports.number().int().nonnegative()
|
|
58328
58723
|
}).strict();
|
|
58724
|
+
standingTokensSchema = external_exports.object({
|
|
58725
|
+
toolDefinitionTokens: external_exports.number().int().nonnegative().nullable(),
|
|
58726
|
+
contextFrameTokens: external_exports.number().int().nonnegative().nullable(),
|
|
58727
|
+
steeringTokens: external_exports.number().int().nonnegative().nullable()
|
|
58728
|
+
}).strict();
|
|
58329
58729
|
spendGroupKindSchema = external_exports.enum([
|
|
58330
58730
|
"operator",
|
|
58331
58731
|
"agent",
|
|
@@ -74214,7 +74614,7 @@ __export(verify_exports, {
|
|
|
74214
74614
|
readBundle: () => readBundle,
|
|
74215
74615
|
verifyBundle: () => verifyBundle3
|
|
74216
74616
|
});
|
|
74217
|
-
import { existsSync as existsSync25, readFileSync as readFileSync23, statSync as
|
|
74617
|
+
import { existsSync as existsSync25, readFileSync as readFileSync23, statSync as statSync12 } from "node:fs";
|
|
74218
74618
|
import { join as join47 } from "node:path";
|
|
74219
74619
|
function readDirectory(dir) {
|
|
74220
74620
|
const read2 = (name) => {
|
|
@@ -74260,7 +74660,7 @@ function readBundle(path2) {
|
|
|
74260
74660
|
if (!existsSync25(path2)) {
|
|
74261
74661
|
throw new BundleReadError(`${path2} does not exist.`);
|
|
74262
74662
|
}
|
|
74263
|
-
return
|
|
74663
|
+
return statSync12(path2).isDirectory() ? readDirectory(path2) : readZip(path2);
|
|
74264
74664
|
}
|
|
74265
74665
|
function digestLabel(state) {
|
|
74266
74666
|
return state === "not_carried" ? "not carried" : state;
|
|
@@ -75154,7 +75554,7 @@ import {
|
|
|
75154
75554
|
appendFileSync as appendFileSync4,
|
|
75155
75555
|
existsSync as existsSync26,
|
|
75156
75556
|
lstatSync as lstatSync9,
|
|
75157
|
-
mkdirSync as
|
|
75557
|
+
mkdirSync as mkdirSync12,
|
|
75158
75558
|
readFileSync as readFileSync24,
|
|
75159
75559
|
readdirSync as readdirSync13,
|
|
75160
75560
|
realpathSync as realpathSync8,
|
|
@@ -75251,7 +75651,7 @@ function machineId(configDir = getConfigDir()) {
|
|
|
75251
75651
|
}
|
|
75252
75652
|
if (secret === null) {
|
|
75253
75653
|
secret = randomBytes11(32).toString("hex");
|
|
75254
|
-
|
|
75654
|
+
mkdirSync12(configDir, { recursive: true });
|
|
75255
75655
|
writeFileSync10(file, `${secret}
|
|
75256
75656
|
`, { encoding: "utf8", mode: 384 });
|
|
75257
75657
|
}
|
|
@@ -75803,12 +76203,12 @@ __export(pull_exports, {
|
|
|
75803
76203
|
import { createHash as createHash19 } from "node:crypto";
|
|
75804
76204
|
import {
|
|
75805
76205
|
lstatSync as lstatSync10,
|
|
75806
|
-
mkdirSync as
|
|
76206
|
+
mkdirSync as mkdirSync13,
|
|
75807
76207
|
readFileSync as readFileSync25,
|
|
75808
76208
|
readdirSync as readdirSync14,
|
|
75809
76209
|
realpathSync as realpathSync9,
|
|
75810
76210
|
rmSync as rmSync10,
|
|
75811
|
-
rmdirSync as
|
|
76211
|
+
rmdirSync as rmdirSync8
|
|
75812
76212
|
} from "node:fs";
|
|
75813
76213
|
import {
|
|
75814
76214
|
dirname as dirname27,
|
|
@@ -75979,7 +76379,7 @@ function pruneEmptyDirs(root, path2) {
|
|
|
75979
76379
|
while (dir.startsWith(stop + sep7)) {
|
|
75980
76380
|
try {
|
|
75981
76381
|
if (readdirSync14(dir).length > 0) return;
|
|
75982
|
-
|
|
76382
|
+
rmdirSync8(dir);
|
|
75983
76383
|
} catch {
|
|
75984
76384
|
return;
|
|
75985
76385
|
}
|
|
@@ -75991,7 +76391,7 @@ function applyPlan(root, plan) {
|
|
|
75991
76391
|
for (const d of plan.deletes) assertInsideOxagen(root, d);
|
|
75992
76392
|
for (const w of plan.writes) {
|
|
75993
76393
|
const abs = join49(root, ...w.path.split("/"));
|
|
75994
|
-
|
|
76394
|
+
mkdirSync13(dirname27(abs), { recursive: true });
|
|
75995
76395
|
atomicWriteFileSync(abs, w.content);
|
|
75996
76396
|
}
|
|
75997
76397
|
for (const d of plan.deletes) {
|
|
@@ -113377,10 +113777,10 @@ import { execFileSync as execFileSync2 } from "node:child_process";
|
|
|
113377
113777
|
import { createHash as createHash20 } from "node:crypto";
|
|
113378
113778
|
import {
|
|
113379
113779
|
lstatSync as lstatSync11,
|
|
113380
|
-
mkdirSync as
|
|
113780
|
+
mkdirSync as mkdirSync14,
|
|
113381
113781
|
readFileSync as readFileSync26,
|
|
113382
113782
|
readlinkSync as readlinkSync4,
|
|
113383
|
-
statSync as
|
|
113783
|
+
statSync as statSync13
|
|
113384
113784
|
} from "node:fs";
|
|
113385
113785
|
import { dirname as dirname28, isAbsolute as isAbsolute14, join as join50, relative as relative9, resolve as resolve19, sep as sep8 } from "node:path";
|
|
113386
113786
|
function git5(cwd, args, input) {
|
|
@@ -113488,14 +113888,14 @@ function chooseBase(root, ref2) {
|
|
|
113488
113888
|
}
|
|
113489
113889
|
function isFile(path2) {
|
|
113490
113890
|
try {
|
|
113491
|
-
return
|
|
113891
|
+
return statSync13(path2).isFile();
|
|
113492
113892
|
} catch {
|
|
113493
113893
|
return false;
|
|
113494
113894
|
}
|
|
113495
113895
|
}
|
|
113496
113896
|
function isDir(path2) {
|
|
113497
113897
|
try {
|
|
113498
|
-
return
|
|
113898
|
+
return statSync13(path2).isDirectory();
|
|
113499
113899
|
} catch {
|
|
113500
113900
|
return false;
|
|
113501
113901
|
}
|
|
@@ -113611,7 +114011,7 @@ async function publishedInputs(root, deps, refresh, out) {
|
|
|
113611
114011
|
}
|
|
113612
114012
|
if (file !== null) {
|
|
113613
114013
|
try {
|
|
113614
|
-
|
|
114014
|
+
mkdirSync14(dirname28(file), { recursive: true });
|
|
113615
114015
|
atomicWriteFileSync(
|
|
113616
114016
|
file,
|
|
113617
114017
|
JSON.stringify({
|