@pleri/olam-cli 0.1.199 → 0.1.201
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ask/knowledge-pack.generated.d.ts.map +1 -1
- package/dist/ask/knowledge-pack.generated.js +3 -1
- package/dist/ask/knowledge-pack.generated.js.map +1 -1
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +23 -8
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +3 -0
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/flywheel/diversity-check.d.ts +1 -1
- package/dist/commands/flywheel/diversity-check.js +1 -1
- package/dist/commands/flywheel/k5-score.d.ts +1 -1
- package/dist/commands/flywheel/k5-score.js +1 -1
- package/dist/commands/flywheel/k5-validate.d.ts +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/kg-mirror.d.ts +16 -0
- package/dist/commands/kg-mirror.d.ts.map +1 -1
- package/dist/commands/kg-mirror.js +94 -0
- package/dist/commands/kg-mirror.js.map +1 -1
- package/dist/commands/ps.d.ts.map +1 -1
- package/dist/commands/ps.js +7 -3
- package/dist/commands/ps.js.map +1 -1
- package/dist/commands/refresh.js +1 -1
- package/dist/commands/refresh.js.map +1 -1
- package/dist/commands/skills-100x.d.ts +34 -0
- package/dist/commands/skills-100x.d.ts.map +1 -0
- package/dist/commands/{skills-10x.js → skills-100x.js} +138 -41
- package/dist/commands/skills-100x.js.map +1 -0
- package/dist/commands/skills-install-model-router.d.ts +20 -0
- package/dist/commands/skills-install-model-router.d.ts.map +1 -0
- package/dist/commands/skills-install-model-router.js +55 -0
- package/dist/commands/skills-install-model-router.js.map +1 -0
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +2 -0
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +0 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/workspace.d.ts.map +1 -1
- package/dist/commands/workspace.js +1 -2
- package/dist/commands/workspace.js.map +1 -1
- package/dist/image-digests.json +8 -8
- package/dist/index.js +1127 -716
- package/dist/index.js.map +1 -1
- package/dist/lib/help-groups.js +1 -1
- package/dist/lib/help-groups.js.map +1 -1
- package/dist/mcp-server.js +547 -346
- package/hermes-bundle/version.json +1 -1
- package/hooks/model-router.py +445 -0
- package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
- package/package.json +2 -1
- package/dist/commands/skills-10x.d.ts +0 -23
- package/dist/commands/skills-10x.d.ts.map +0 -1
- package/dist/commands/skills-10x.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -5568,7 +5568,7 @@ async function safeText(res) {
|
|
|
5568
5568
|
}
|
|
5569
5569
|
}
|
|
5570
5570
|
function sleep(ms) {
|
|
5571
|
-
return new Promise((
|
|
5571
|
+
return new Promise((resolve31) => setTimeout(resolve31, ms));
|
|
5572
5572
|
}
|
|
5573
5573
|
var DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, RETRY_COUNT, RETRY_BACKOFF_MS, AuthClient;
|
|
5574
5574
|
var init_client = __esm({
|
|
@@ -5721,7 +5721,7 @@ function resolveAuthServicePath() {
|
|
|
5721
5721
|
return path10.join(pkgsDir, "auth-service");
|
|
5722
5722
|
}
|
|
5723
5723
|
function sleep2(ms) {
|
|
5724
|
-
return new Promise((
|
|
5724
|
+
return new Promise((resolve31) => setTimeout(resolve31, ms));
|
|
5725
5725
|
}
|
|
5726
5726
|
var DEFAULT_PORT, DEFAULT_VOLUME, DEFAULT_CONTAINER, DEFAULT_IMAGE, AuthContainerController;
|
|
5727
5727
|
var init_container = __esm({
|
|
@@ -6032,7 +6032,7 @@ var init_network = __esm({
|
|
|
6032
6032
|
// ../adapters/dist/docker/pull.js
|
|
6033
6033
|
import { spawn } from "node:child_process";
|
|
6034
6034
|
function spawnAsync(cmd, args, opts = {}) {
|
|
6035
|
-
return new Promise((
|
|
6035
|
+
return new Promise((resolve31) => {
|
|
6036
6036
|
const child = spawn(cmd, [...args], {
|
|
6037
6037
|
stdio: ["ignore", "pipe", "pipe"],
|
|
6038
6038
|
signal: opts.signal
|
|
@@ -6046,10 +6046,10 @@ function spawnAsync(cmd, args, opts = {}) {
|
|
|
6046
6046
|
stderr += chunk.toString();
|
|
6047
6047
|
});
|
|
6048
6048
|
child.on("error", (err) => {
|
|
6049
|
-
|
|
6049
|
+
resolve31({ exitCode: -1, stdout, stderr: stderr + err.message });
|
|
6050
6050
|
});
|
|
6051
6051
|
child.on("close", (code) => {
|
|
6052
|
-
|
|
6052
|
+
resolve31({ exitCode: code ?? -1, stdout, stderr });
|
|
6053
6053
|
});
|
|
6054
6054
|
});
|
|
6055
6055
|
}
|
|
@@ -6614,7 +6614,7 @@ var demuxStream, execInContainer;
|
|
|
6614
6614
|
var init_exec = __esm({
|
|
6615
6615
|
"../adapters/dist/docker/exec.js"() {
|
|
6616
6616
|
"use strict";
|
|
6617
|
-
demuxStream = (stream) => new Promise((
|
|
6617
|
+
demuxStream = (stream) => new Promise((resolve31, reject) => {
|
|
6618
6618
|
const stdoutChunks = [];
|
|
6619
6619
|
const stderrChunks = [];
|
|
6620
6620
|
const stdout = new PassThrough();
|
|
@@ -6628,7 +6628,7 @@ var init_exec = __esm({
|
|
|
6628
6628
|
stream.pipe(stdout);
|
|
6629
6629
|
}
|
|
6630
6630
|
stream.on("end", () => {
|
|
6631
|
-
|
|
6631
|
+
resolve31({
|
|
6632
6632
|
stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
|
|
6633
6633
|
stderr: Buffer.concat(stderrChunks).toString("utf-8")
|
|
6634
6634
|
});
|
|
@@ -7088,7 +7088,7 @@ var init_connection = __esm({
|
|
|
7088
7088
|
// -----------------------------------------------------------------------
|
|
7089
7089
|
async exec(host, command) {
|
|
7090
7090
|
const client = await this.getConnection(host);
|
|
7091
|
-
return new Promise((
|
|
7091
|
+
return new Promise((resolve31, reject) => {
|
|
7092
7092
|
client.exec(command, (err, stream) => {
|
|
7093
7093
|
if (err) {
|
|
7094
7094
|
reject(new Error(`SSH exec failed on ${host}: ${err.message}`));
|
|
@@ -7103,7 +7103,7 @@ var init_connection = __esm({
|
|
|
7103
7103
|
stderr += data.toString();
|
|
7104
7104
|
});
|
|
7105
7105
|
stream.on("close", (code) => {
|
|
7106
|
-
|
|
7106
|
+
resolve31({
|
|
7107
7107
|
exitCode: code ?? 0,
|
|
7108
7108
|
stdout: stdout.trimEnd(),
|
|
7109
7109
|
stderr: stderr.trimEnd()
|
|
@@ -7134,10 +7134,10 @@ var init_connection = __esm({
|
|
|
7134
7134
|
throw new Error(`No SSH configuration found for host: ${host}`);
|
|
7135
7135
|
}
|
|
7136
7136
|
const client = new SSHClient();
|
|
7137
|
-
return new Promise((
|
|
7137
|
+
return new Promise((resolve31, reject) => {
|
|
7138
7138
|
client.on("ready", () => {
|
|
7139
7139
|
this.connections.set(host, client);
|
|
7140
|
-
|
|
7140
|
+
resolve31(client);
|
|
7141
7141
|
}).on("error", (err) => {
|
|
7142
7142
|
this.connections.delete(host);
|
|
7143
7143
|
reject(new Error(`SSH connection to ${host} failed: ${err.message}`));
|
|
@@ -9539,8 +9539,8 @@ import { execFileSync as execFileSync4 } from "node:child_process";
|
|
|
9539
9539
|
import * as fs17 from "node:fs";
|
|
9540
9540
|
import * as os11 from "node:os";
|
|
9541
9541
|
import * as path19 from "node:path";
|
|
9542
|
-
function expandHome2(p,
|
|
9543
|
-
return p.replace(/^~(?=$|\/|\\)/,
|
|
9542
|
+
function expandHome2(p, homedir77) {
|
|
9543
|
+
return p.replace(/^~(?=$|\/|\\)/, homedir77());
|
|
9544
9544
|
}
|
|
9545
9545
|
function sanitizeRepoFilename(name) {
|
|
9546
9546
|
const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -9563,7 +9563,7 @@ ${stderr}`;
|
|
|
9563
9563
|
}
|
|
9564
9564
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
9565
9565
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync4(cmd, args, opts));
|
|
9566
|
-
const
|
|
9566
|
+
const homedir77 = deps.homedir ?? (() => os11.homedir());
|
|
9567
9567
|
const baselineDir = path19.join(workspacePath, ".olam", "baseline");
|
|
9568
9568
|
try {
|
|
9569
9569
|
fs17.mkdirSync(baselineDir, { recursive: true });
|
|
@@ -9579,7 +9579,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
9579
9579
|
continue;
|
|
9580
9580
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
9581
9581
|
const outPath = path19.join(baselineDir, filename);
|
|
9582
|
-
const repoPath = expandHome2(repo.path,
|
|
9582
|
+
const repoPath = expandHome2(repo.path, homedir77);
|
|
9583
9583
|
if (!fs17.existsSync(repoPath)) {
|
|
9584
9584
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
9585
9585
|
# (skipped: path ${repoPath} does not exist)
|
|
@@ -9699,21 +9699,21 @@ function extractStderr(err) {
|
|
|
9699
9699
|
}
|
|
9700
9700
|
function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
9701
9701
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync4(cmd, args, opts));
|
|
9702
|
-
const
|
|
9703
|
-
const
|
|
9702
|
+
const homedir77 = deps.homedir ?? (() => os11.homedir());
|
|
9703
|
+
const existsSync122 = deps.existsSync ?? ((p) => fs17.existsSync(p));
|
|
9704
9704
|
const copyFileSync17 = deps.copyFileSync ?? ((src, dest) => fs17.copyFileSync(src, dest));
|
|
9705
|
-
const
|
|
9705
|
+
const mkdirSync73 = deps.mkdirSync ?? ((dirPath, opts) => {
|
|
9706
9706
|
fs17.mkdirSync(dirPath, opts);
|
|
9707
9707
|
});
|
|
9708
9708
|
const plans = [];
|
|
9709
9709
|
for (const repo of repos) {
|
|
9710
9710
|
if (!repo.path)
|
|
9711
9711
|
continue;
|
|
9712
|
-
const repoPath = expandHome2(repo.path,
|
|
9712
|
+
const repoPath = expandHome2(repo.path, homedir77);
|
|
9713
9713
|
const worktreePath = path19.join(workspacePath, repo.name);
|
|
9714
|
-
if (!
|
|
9714
|
+
if (!existsSync122(repoPath))
|
|
9715
9715
|
continue;
|
|
9716
|
-
if (!
|
|
9716
|
+
if (!existsSync122(worktreePath)) {
|
|
9717
9717
|
console.warn(`[carry] ${repo.name}: world worktree ${worktreePath} missing; skipping carry for this repo`);
|
|
9718
9718
|
continue;
|
|
9719
9719
|
}
|
|
@@ -9773,10 +9773,10 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
|
9773
9773
|
for (const rel of plan.diff.untracked) {
|
|
9774
9774
|
const src = path19.join(plan.repoPath, rel);
|
|
9775
9775
|
const dest = path19.join(plan.worktreePath, rel);
|
|
9776
|
-
if (!
|
|
9776
|
+
if (!existsSync122(src))
|
|
9777
9777
|
continue;
|
|
9778
9778
|
try {
|
|
9779
|
-
|
|
9779
|
+
mkdirSync73(path19.dirname(dest), { recursive: true });
|
|
9780
9780
|
copyFileSync17(src, dest);
|
|
9781
9781
|
} catch (err) {
|
|
9782
9782
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -11425,7 +11425,7 @@ var init_auto_dispatch_task = __esm({
|
|
|
11425
11425
|
this.name = "TaskDispatchError";
|
|
11426
11426
|
}
|
|
11427
11427
|
};
|
|
11428
|
-
DEFAULT_SLEEP = (ms) => new Promise((
|
|
11428
|
+
DEFAULT_SLEEP = (ms) => new Promise((resolve31) => setTimeout(resolve31, ms));
|
|
11429
11429
|
}
|
|
11430
11430
|
});
|
|
11431
11431
|
|
|
@@ -11660,7 +11660,7 @@ var init_schema4 = __esm({
|
|
|
11660
11660
|
env: external_exports.record(external_exports.string().min(1), external_exports.record(external_exports.string().min(1), external_exports.string())).optional(),
|
|
11661
11661
|
updatedAt: external_exports.number().int().nonnegative()
|
|
11662
11662
|
});
|
|
11663
|
-
MetaHookBlockKindSchema = external_exports.enum(["memory-recall", "memory-classify"]);
|
|
11663
|
+
MetaHookBlockKindSchema = external_exports.enum(["memory-recall", "memory-classify", "model-router"]);
|
|
11664
11664
|
GlobalConfigSchema = external_exports.object({
|
|
11665
11665
|
schemaVersion: external_exports.literal(1),
|
|
11666
11666
|
repos: external_exports.array(RepoEntrySchema).optional().default([]),
|
|
@@ -15417,7 +15417,7 @@ function isCloudflaredAvailable() {
|
|
|
15417
15417
|
}
|
|
15418
15418
|
}
|
|
15419
15419
|
function startTunnel(port2) {
|
|
15420
|
-
return new Promise((
|
|
15420
|
+
return new Promise((resolve31, reject) => {
|
|
15421
15421
|
const child = spawn3("cloudflared", ["tunnel", "--url", `http://localhost:${port2}`], {
|
|
15422
15422
|
stdio: ["ignore", "pipe", "pipe"],
|
|
15423
15423
|
detached: false
|
|
@@ -15439,7 +15439,7 @@ function startTunnel(port2) {
|
|
|
15439
15439
|
if (match2) {
|
|
15440
15440
|
resolved = true;
|
|
15441
15441
|
clearTimeout(timeout);
|
|
15442
|
-
|
|
15442
|
+
resolve31(match2[0]);
|
|
15443
15443
|
}
|
|
15444
15444
|
}
|
|
15445
15445
|
child.stdout?.on("data", scan);
|
|
@@ -15526,8 +15526,8 @@ var init_dashboard = __esm({
|
|
|
15526
15526
|
}
|
|
15527
15527
|
throw err;
|
|
15528
15528
|
}
|
|
15529
|
-
await new Promise((
|
|
15530
|
-
this.server.on("listening",
|
|
15529
|
+
await new Promise((resolve31, reject) => {
|
|
15530
|
+
this.server.on("listening", resolve31);
|
|
15531
15531
|
this.server.on("error", reject);
|
|
15532
15532
|
});
|
|
15533
15533
|
this.info = { localUrl: `http://localhost:${port2}` };
|
|
@@ -15573,8 +15573,8 @@ var init_dashboard = __esm({
|
|
|
15573
15573
|
async stop() {
|
|
15574
15574
|
stopTunnel();
|
|
15575
15575
|
if (this.server) {
|
|
15576
|
-
await new Promise((
|
|
15577
|
-
this.server.close(() =>
|
|
15576
|
+
await new Promise((resolve31) => {
|
|
15577
|
+
this.server.close(() => resolve31());
|
|
15578
15578
|
});
|
|
15579
15579
|
this.server = null;
|
|
15580
15580
|
}
|
|
@@ -15903,8 +15903,8 @@ async function findHostCpContainer() {
|
|
|
15903
15903
|
const docker3 = new Dockerode2(resolveDockerHostOptions());
|
|
15904
15904
|
let timer = null;
|
|
15905
15905
|
const listing = docker3.listContainers({ all: true }).then((cs) => cs);
|
|
15906
|
-
const timeout = new Promise((
|
|
15907
|
-
timer = setTimeout(() =>
|
|
15906
|
+
const timeout = new Promise((resolve31) => {
|
|
15907
|
+
timer = setTimeout(() => resolve31(null), DOCKER_PROBE_TIMEOUT_MS);
|
|
15908
15908
|
});
|
|
15909
15909
|
let containers;
|
|
15910
15910
|
try {
|
|
@@ -16688,7 +16688,7 @@ async function ensureOlamPostgresSingleton(options = {}) {
|
|
|
16688
16688
|
};
|
|
16689
16689
|
}
|
|
16690
16690
|
function sleep3(ms) {
|
|
16691
|
-
return new Promise((
|
|
16691
|
+
return new Promise((resolve31) => setTimeout(resolve31, ms));
|
|
16692
16692
|
}
|
|
16693
16693
|
var DEFAULT_POSTGRES_NETWORK, DEFAULT_POSTGRES_CONTAINER, DEFAULT_POSTGRES_HOST_PORT, DEFAULT_POSTGRES_IMAGE, DEFAULT_POSTGRES_USER, DEFAULT_POSTGRES_PASSWORD, DEFAULT_POSTGRES_DB, DEFAULT_POSTGRES_READY_TIMEOUT_MS;
|
|
16694
16694
|
var init_postgres_init_helpers = __esm({
|
|
@@ -18399,17 +18399,143 @@ var init_memory_classify = __esm({
|
|
|
18399
18399
|
}
|
|
18400
18400
|
});
|
|
18401
18401
|
|
|
18402
|
+
// ../core/dist/meta-hooks/model-router.js
|
|
18403
|
+
import * as fs69 from "node:fs";
|
|
18404
|
+
function buildModelRouterHookEntry() {
|
|
18405
|
+
return {
|
|
18406
|
+
hooks: [
|
|
18407
|
+
{
|
|
18408
|
+
type: "command",
|
|
18409
|
+
command: `OLAM_META_SENTINEL=${OLAM_META_MODEL_ROUTER_SENTINEL}; ${OLAM_META_NOOP_GUARD3} python3 "${OLAM_META_MODEL_ROUTER_SCRIPT_PATH}"`,
|
|
18410
|
+
timeout: OLAM_META_MODEL_ROUTER_TIMEOUT_MS
|
|
18411
|
+
}
|
|
18412
|
+
]
|
|
18413
|
+
};
|
|
18414
|
+
}
|
|
18415
|
+
function computeModelRouterUninstall(settings) {
|
|
18416
|
+
const matchers = settings.hooks?.UserPromptSubmit;
|
|
18417
|
+
if (!Array.isArray(matchers) || matchers.length === 0) {
|
|
18418
|
+
return { status: "not-found" };
|
|
18419
|
+
}
|
|
18420
|
+
let changed = false;
|
|
18421
|
+
const filteredMatchers = [];
|
|
18422
|
+
for (const matcher of matchers) {
|
|
18423
|
+
const innerHooks = matcher.hooks ?? [];
|
|
18424
|
+
const keptInner = innerHooks.filter((h) => {
|
|
18425
|
+
if (typeof h.command === "string" && h.command.includes(OLAM_META_MODEL_ROUTER_SENTINEL)) {
|
|
18426
|
+
changed = true;
|
|
18427
|
+
return false;
|
|
18428
|
+
}
|
|
18429
|
+
return true;
|
|
18430
|
+
});
|
|
18431
|
+
if (keptInner.length === 0 && innerHooks.length > 0) {
|
|
18432
|
+
changed = true;
|
|
18433
|
+
continue;
|
|
18434
|
+
}
|
|
18435
|
+
if (keptInner.length === innerHooks.length) {
|
|
18436
|
+
filteredMatchers.push(matcher);
|
|
18437
|
+
} else {
|
|
18438
|
+
filteredMatchers.push({ ...matcher, hooks: keptInner });
|
|
18439
|
+
}
|
|
18440
|
+
}
|
|
18441
|
+
if (!changed)
|
|
18442
|
+
return { status: "not-found" };
|
|
18443
|
+
const next = {
|
|
18444
|
+
...settings,
|
|
18445
|
+
hooks: {
|
|
18446
|
+
...settings.hooks,
|
|
18447
|
+
UserPromptSubmit: filteredMatchers
|
|
18448
|
+
}
|
|
18449
|
+
};
|
|
18450
|
+
if (filteredMatchers.length === 0) {
|
|
18451
|
+
const otherStages = Object.keys(next.hooks ?? {}).filter((k) => k !== "UserPromptSubmit");
|
|
18452
|
+
if (otherStages.length === 0) {
|
|
18453
|
+
delete next.hooks;
|
|
18454
|
+
} else {
|
|
18455
|
+
delete next.hooks.UserPromptSubmit;
|
|
18456
|
+
}
|
|
18457
|
+
}
|
|
18458
|
+
return { status: "removed", settingsAfter: next };
|
|
18459
|
+
}
|
|
18460
|
+
function matchModelRouterSentinel(commandLine) {
|
|
18461
|
+
return commandLine.includes(OLAM_META_MODEL_ROUTER_SENTINEL);
|
|
18462
|
+
}
|
|
18463
|
+
var OLAM_META_MODEL_ROUTER_SENTINEL, OLAM_META_MODEL_ROUTER_STAGE, OLAM_META_MODEL_ROUTER_TIMEOUT_MS, OLAM_META_MODEL_ROUTER_SCRIPT_PATH, OLAM_META_MODEL_ROUTER_SCRIPT_BASENAME, OLAM_META_NOOP_GUARD3;
|
|
18464
|
+
var init_model_router = __esm({
|
|
18465
|
+
"../core/dist/meta-hooks/model-router.js"() {
|
|
18466
|
+
"use strict";
|
|
18467
|
+
OLAM_META_MODEL_ROUTER_SENTINEL = "olam-meta-model-router-v1";
|
|
18468
|
+
OLAM_META_MODEL_ROUTER_STAGE = "UserPromptSubmit";
|
|
18469
|
+
OLAM_META_MODEL_ROUTER_TIMEOUT_MS = 5e3;
|
|
18470
|
+
OLAM_META_MODEL_ROUTER_SCRIPT_PATH = "$HOME/.claude/hooks/model-router.py";
|
|
18471
|
+
OLAM_META_MODEL_ROUTER_SCRIPT_BASENAME = "model-router.py";
|
|
18472
|
+
OLAM_META_NOOP_GUARD3 = "command -v olam >/dev/null 2>&1 || exit 0;";
|
|
18473
|
+
}
|
|
18474
|
+
});
|
|
18475
|
+
|
|
18476
|
+
// ../core/dist/meta-hooks/model-router-deploy.js
|
|
18477
|
+
import { existsSync as existsSync77, mkdirSync as mkdirSync45, readFileSync as readFileSync66, writeFileSync as writeFileSync41 } from "node:fs";
|
|
18478
|
+
import { homedir as homedir43 } from "node:os";
|
|
18479
|
+
import { dirname as dirname39, join as join75, resolve as resolve20 } from "node:path";
|
|
18480
|
+
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
18481
|
+
function resolveModelRouterSourcePath() {
|
|
18482
|
+
const here3 = dirname39(fileURLToPath8(import.meta.url));
|
|
18483
|
+
const candidates2 = [
|
|
18484
|
+
// (1) in-repo tsc dist: core/dist/meta-hooks → ../../../cli/hooks
|
|
18485
|
+
resolve20(here3, "..", "..", "..", "cli", "hooks", MODEL_ROUTER_SCRIPT_BASENAME),
|
|
18486
|
+
// (1b) in-repo src (tsx / vitest): core/src/meta-hooks → ../../../cli/hooks
|
|
18487
|
+
resolve20(here3, "..", "..", "..", "cli", "hooks", MODEL_ROUTER_SCRIPT_BASENAME),
|
|
18488
|
+
// (2) bundled CLI: dist/<bundle> → ../hooks (hooks is sibling of dist)
|
|
18489
|
+
resolve20(here3, "..", "hooks", MODEL_ROUTER_SCRIPT_BASENAME),
|
|
18490
|
+
resolve20(here3, "..", "..", "hooks", MODEL_ROUTER_SCRIPT_BASENAME)
|
|
18491
|
+
];
|
|
18492
|
+
for (const candidate of candidates2) {
|
|
18493
|
+
if (existsSync77(candidate))
|
|
18494
|
+
return candidate;
|
|
18495
|
+
}
|
|
18496
|
+
return candidates2[0];
|
|
18497
|
+
}
|
|
18498
|
+
function deployModelRouterScript(opts = {}) {
|
|
18499
|
+
const targetDir = opts.targetDir ?? join75(homedir43(), ".claude", "hooks");
|
|
18500
|
+
const targetPath = join75(targetDir, MODEL_ROUTER_SCRIPT_BASENAME);
|
|
18501
|
+
const sourcePath = opts.sourcePath ?? resolveModelRouterSourcePath();
|
|
18502
|
+
if (!existsSync77(sourcePath)) {
|
|
18503
|
+
return { basename: MODEL_ROUTER_SCRIPT_BASENAME, action: "source-missing", targetPath };
|
|
18504
|
+
}
|
|
18505
|
+
const newContent = readFileSync66(sourcePath, "utf8");
|
|
18506
|
+
if (existsSync77(targetPath)) {
|
|
18507
|
+
const existing = readFileSync66(targetPath, "utf8");
|
|
18508
|
+
if (existing === newContent) {
|
|
18509
|
+
return { basename: MODEL_ROUTER_SCRIPT_BASENAME, action: "unchanged", targetPath };
|
|
18510
|
+
}
|
|
18511
|
+
}
|
|
18512
|
+
if (opts.dryRun !== true) {
|
|
18513
|
+
mkdirSync45(dirname39(targetPath), { recursive: true });
|
|
18514
|
+
writeFileSync41(targetPath, newContent, { mode: 493 });
|
|
18515
|
+
}
|
|
18516
|
+
return { basename: MODEL_ROUTER_SCRIPT_BASENAME, action: "written", targetPath };
|
|
18517
|
+
}
|
|
18518
|
+
var MODEL_ROUTER_SCRIPT_BASENAME;
|
|
18519
|
+
var init_model_router_deploy = __esm({
|
|
18520
|
+
"../core/dist/meta-hooks/model-router-deploy.js"() {
|
|
18521
|
+
"use strict";
|
|
18522
|
+
MODEL_ROUTER_SCRIPT_BASENAME = "model-router.py";
|
|
18523
|
+
}
|
|
18524
|
+
});
|
|
18525
|
+
|
|
18402
18526
|
// ../core/dist/meta-hooks/index.js
|
|
18403
18527
|
var init_meta_hooks = __esm({
|
|
18404
18528
|
"../core/dist/meta-hooks/index.js"() {
|
|
18405
18529
|
"use strict";
|
|
18406
18530
|
init_memory_recall();
|
|
18407
18531
|
init_memory_classify();
|
|
18532
|
+
init_model_router();
|
|
18533
|
+
init_model_router_deploy();
|
|
18408
18534
|
}
|
|
18409
18535
|
});
|
|
18410
18536
|
|
|
18411
18537
|
// ../core/dist/skill-sync/settings-merger.js
|
|
18412
|
-
import * as
|
|
18538
|
+
import * as fs70 from "node:fs";
|
|
18413
18539
|
import * as os39 from "node:os";
|
|
18414
18540
|
import * as path68 from "node:path";
|
|
18415
18541
|
function claudeSettingsPath() {
|
|
@@ -18478,28 +18604,28 @@ function tagOlam(entry) {
|
|
|
18478
18604
|
return { ...entry, [OLAM_SKILLS_MARKER]: true };
|
|
18479
18605
|
}
|
|
18480
18606
|
function readJson(file) {
|
|
18481
|
-
return JSON.parse(
|
|
18607
|
+
return JSON.parse(fs70.readFileSync(file, "utf-8"));
|
|
18482
18608
|
}
|
|
18483
18609
|
function rotateBackups(backupDir) {
|
|
18484
|
-
if (!
|
|
18610
|
+
if (!fs70.existsSync(backupDir))
|
|
18485
18611
|
return;
|
|
18486
|
-
const files =
|
|
18612
|
+
const files = fs70.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full: path68.join(backupDir, f), mtime: fs70.statSync(path68.join(backupDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
18487
18613
|
for (const f of files.slice(BACKUP_RETENTION)) {
|
|
18488
18614
|
try {
|
|
18489
|
-
|
|
18615
|
+
fs70.unlinkSync(f.full);
|
|
18490
18616
|
} catch {
|
|
18491
18617
|
}
|
|
18492
18618
|
}
|
|
18493
18619
|
}
|
|
18494
18620
|
function backupSettings() {
|
|
18495
18621
|
const src = claudeSettingsPath();
|
|
18496
|
-
if (!
|
|
18622
|
+
if (!fs70.existsSync(src))
|
|
18497
18623
|
return void 0;
|
|
18498
18624
|
const dir = settingsBackupDir();
|
|
18499
|
-
|
|
18625
|
+
fs70.mkdirSync(dir, { recursive: true });
|
|
18500
18626
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
18501
18627
|
const dest = path68.join(dir, `settings-${stamp}.json`);
|
|
18502
|
-
|
|
18628
|
+
fs70.copyFileSync(src, dest);
|
|
18503
18629
|
rotateBackups(dir);
|
|
18504
18630
|
return dest;
|
|
18505
18631
|
}
|
|
@@ -18507,7 +18633,7 @@ function mergeSettings(input2) {
|
|
|
18507
18633
|
const settingsPath = claudeSettingsPath();
|
|
18508
18634
|
const backupPath = backupSettings();
|
|
18509
18635
|
let base = {};
|
|
18510
|
-
if (
|
|
18636
|
+
if (fs70.existsSync(settingsPath)) {
|
|
18511
18637
|
try {
|
|
18512
18638
|
base = readJson(settingsPath);
|
|
18513
18639
|
} catch {
|
|
@@ -18575,10 +18701,10 @@ function mergeSettings(input2) {
|
|
|
18575
18701
|
...input2.permissionFiles.length > 0 ? { allow: [...permSet] } : {}
|
|
18576
18702
|
}
|
|
18577
18703
|
};
|
|
18578
|
-
|
|
18704
|
+
fs70.mkdirSync(path68.dirname(settingsPath), { recursive: true });
|
|
18579
18705
|
const tmp = `${settingsPath}.tmp-${process.pid}`;
|
|
18580
|
-
|
|
18581
|
-
|
|
18706
|
+
fs70.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
|
|
18707
|
+
fs70.renameSync(tmp, settingsPath);
|
|
18582
18708
|
return { backupPath, hooksAdded, permissionsCount: permSet.size, dualWriteDeduped, dualWriteDroppedCommands };
|
|
18583
18709
|
}
|
|
18584
18710
|
var OLAM_SKILLS_MARKER, BACKUP_RETENTION, DUAL_WRITE_DEDUP_RULES;
|
|
@@ -18635,7 +18761,7 @@ var init_schema5 = __esm({
|
|
|
18635
18761
|
|
|
18636
18762
|
// ../core/dist/skill-sync/per-project-override.js
|
|
18637
18763
|
import { execFileSync as execFileSync16 } from "node:child_process";
|
|
18638
|
-
import * as
|
|
18764
|
+
import * as fs71 from "node:fs";
|
|
18639
18765
|
import * as path69 from "node:path";
|
|
18640
18766
|
import { parse as parseYaml6 } from "yaml";
|
|
18641
18767
|
function findProjectOverride(startDir) {
|
|
@@ -18643,8 +18769,8 @@ function findProjectOverride(startDir) {
|
|
|
18643
18769
|
const root = path69.parse(dir).root;
|
|
18644
18770
|
while (true) {
|
|
18645
18771
|
const candidate = path69.join(dir, PROJECT_OVERRIDE_RELATIVE_PATH);
|
|
18646
|
-
if (
|
|
18647
|
-
const raw =
|
|
18772
|
+
if (fs71.existsSync(candidate) && fs71.statSync(candidate).isFile()) {
|
|
18773
|
+
const raw = fs71.readFileSync(candidate, "utf-8");
|
|
18648
18774
|
let parsed;
|
|
18649
18775
|
try {
|
|
18650
18776
|
parsed = parseYaml6(raw);
|
|
@@ -18703,7 +18829,7 @@ var init_per_project_override = __esm({
|
|
|
18703
18829
|
});
|
|
18704
18830
|
|
|
18705
18831
|
// ../core/dist/lib/file-lock.js
|
|
18706
|
-
import * as
|
|
18832
|
+
import * as fs72 from "node:fs";
|
|
18707
18833
|
import * as os40 from "node:os";
|
|
18708
18834
|
import * as path70 from "node:path";
|
|
18709
18835
|
function defaultIsPidAlive(pid) {
|
|
@@ -18716,11 +18842,11 @@ function defaultIsPidAlive(pid) {
|
|
|
18716
18842
|
}
|
|
18717
18843
|
}
|
|
18718
18844
|
function sleep7(ms) {
|
|
18719
|
-
return new Promise((
|
|
18845
|
+
return new Promise((resolve31) => setTimeout(resolve31, ms));
|
|
18720
18846
|
}
|
|
18721
18847
|
function readLockMeta(lockPath) {
|
|
18722
18848
|
try {
|
|
18723
|
-
const raw =
|
|
18849
|
+
const raw = fs72.readFileSync(lockPath, "utf-8");
|
|
18724
18850
|
const parsed = JSON.parse(raw);
|
|
18725
18851
|
if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
|
|
18726
18852
|
return parsed;
|
|
@@ -18739,12 +18865,12 @@ function isLockStale(meta, opts) {
|
|
|
18739
18865
|
}
|
|
18740
18866
|
function tryAcquireOnce(lockPath, meta, opts) {
|
|
18741
18867
|
try {
|
|
18742
|
-
|
|
18743
|
-
const fd =
|
|
18868
|
+
fs72.mkdirSync(path70.dirname(lockPath), { recursive: true });
|
|
18869
|
+
const fd = fs72.openSync(lockPath, "wx", 384);
|
|
18744
18870
|
try {
|
|
18745
|
-
|
|
18871
|
+
fs72.writeSync(fd, JSON.stringify(meta));
|
|
18746
18872
|
} finally {
|
|
18747
|
-
|
|
18873
|
+
fs72.closeSync(fd);
|
|
18748
18874
|
}
|
|
18749
18875
|
return true;
|
|
18750
18876
|
} catch (err) {
|
|
@@ -18754,14 +18880,14 @@ function tryAcquireOnce(lockPath, meta, opts) {
|
|
|
18754
18880
|
const existing = readLockMeta(lockPath);
|
|
18755
18881
|
if (existing === void 0) {
|
|
18756
18882
|
try {
|
|
18757
|
-
|
|
18883
|
+
fs72.unlinkSync(lockPath);
|
|
18758
18884
|
} catch {
|
|
18759
18885
|
}
|
|
18760
18886
|
return tryAcquireOnce(lockPath, meta, opts);
|
|
18761
18887
|
}
|
|
18762
18888
|
if (isLockStale(existing, opts)) {
|
|
18763
18889
|
try {
|
|
18764
|
-
|
|
18890
|
+
fs72.unlinkSync(lockPath);
|
|
18765
18891
|
} catch {
|
|
18766
18892
|
}
|
|
18767
18893
|
return tryAcquireOnce(lockPath, meta, opts);
|
|
@@ -18791,7 +18917,7 @@ async function acquireFileLock(lockDir, options = {}) {
|
|
|
18791
18917
|
lockPath,
|
|
18792
18918
|
release: () => {
|
|
18793
18919
|
try {
|
|
18794
|
-
|
|
18920
|
+
fs72.unlinkSync(lockPath);
|
|
18795
18921
|
} catch {
|
|
18796
18922
|
}
|
|
18797
18923
|
}
|
|
@@ -18831,13 +18957,13 @@ var init_file_lock = __esm({
|
|
|
18831
18957
|
});
|
|
18832
18958
|
|
|
18833
18959
|
// ../core/dist/lib/min-version-filter.js
|
|
18834
|
-
import { existsSync as
|
|
18960
|
+
import { existsSync as existsSync80, readFileSync as readFileSync70 } from "node:fs";
|
|
18835
18961
|
function readOlamMinVersion(filepath) {
|
|
18836
|
-
if (!
|
|
18962
|
+
if (!existsSync80(filepath))
|
|
18837
18963
|
return void 0;
|
|
18838
18964
|
let text;
|
|
18839
18965
|
try {
|
|
18840
|
-
text =
|
|
18966
|
+
text = readFileSync70(filepath, "utf8");
|
|
18841
18967
|
} catch {
|
|
18842
18968
|
return void 0;
|
|
18843
18969
|
}
|
|
@@ -18895,11 +19021,11 @@ var init_min_version_filter = __esm({
|
|
|
18895
19021
|
});
|
|
18896
19022
|
|
|
18897
19023
|
// ../core/dist/skill-sync/overlay-scan.js
|
|
18898
|
-
import * as
|
|
19024
|
+
import * as fs73 from "node:fs";
|
|
18899
19025
|
import * as path71 from "node:path";
|
|
18900
19026
|
function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
18901
19027
|
const result = /* @__PURE__ */ new Map();
|
|
18902
|
-
if (!
|
|
19028
|
+
if (!fs73.existsSync(overlayRoot)) {
|
|
18903
19029
|
return result;
|
|
18904
19030
|
}
|
|
18905
19031
|
if (basenames.length === 0) {
|
|
@@ -18908,13 +19034,13 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
|
18908
19034
|
const mdFiles = [];
|
|
18909
19035
|
let overlayRootReal;
|
|
18910
19036
|
try {
|
|
18911
|
-
overlayRootReal =
|
|
19037
|
+
overlayRootReal = fs73.realpathSync(overlayRoot);
|
|
18912
19038
|
} catch {
|
|
18913
19039
|
return result;
|
|
18914
19040
|
}
|
|
18915
19041
|
for (const subdir of OVERRIDE_SUBDIRS) {
|
|
18916
19042
|
const dir = path71.join(overlayRoot, subdir);
|
|
18917
|
-
if (!
|
|
19043
|
+
if (!fs73.existsSync(dir))
|
|
18918
19044
|
continue;
|
|
18919
19045
|
walkMarkdown(dir, mdFiles, caps.maxFiles);
|
|
18920
19046
|
}
|
|
@@ -18922,7 +19048,7 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
|
18922
19048
|
for (const filepath of mdFiles) {
|
|
18923
19049
|
let realFile;
|
|
18924
19050
|
try {
|
|
18925
|
-
realFile =
|
|
19051
|
+
realFile = fs73.realpathSync(filepath);
|
|
18926
19052
|
} catch (err) {
|
|
18927
19053
|
const code = err.code;
|
|
18928
19054
|
if (code === "ENOENT" || code === "EACCES")
|
|
@@ -18935,12 +19061,12 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
|
18935
19061
|
}
|
|
18936
19062
|
let content;
|
|
18937
19063
|
try {
|
|
18938
|
-
const stat =
|
|
19064
|
+
const stat = fs73.statSync(filepath);
|
|
18939
19065
|
totalBytes += stat.size;
|
|
18940
19066
|
if (totalBytes > caps.maxTotalBytes) {
|
|
18941
19067
|
throw new Error(`[overlay-scan] aborted: overlay tree exceeds ${caps.maxTotalBytes} total bytes. Check OLAM_CLAUDE_DIR / overlay paths are correctly scoped.`);
|
|
18942
19068
|
}
|
|
18943
|
-
content =
|
|
19069
|
+
content = fs73.readFileSync(filepath, "utf8");
|
|
18944
19070
|
} catch (err) {
|
|
18945
19071
|
const code = err.code;
|
|
18946
19072
|
if (code === "ENOENT" || code === "EACCES") {
|
|
@@ -18962,7 +19088,7 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
|
18962
19088
|
function walkMarkdown(dir, out, cap) {
|
|
18963
19089
|
let entries;
|
|
18964
19090
|
try {
|
|
18965
|
-
entries =
|
|
19091
|
+
entries = fs73.readdirSync(dir, { withFileTypes: true });
|
|
18966
19092
|
} catch (err) {
|
|
18967
19093
|
if (err.code === "ENOENT")
|
|
18968
19094
|
return;
|
|
@@ -18997,7 +19123,7 @@ var init_overlay_scan = __esm({
|
|
|
18997
19123
|
});
|
|
18998
19124
|
|
|
18999
19125
|
// ../core/dist/skill-sync/settings-json-lock.js
|
|
19000
|
-
import * as
|
|
19126
|
+
import * as fs74 from "node:fs";
|
|
19001
19127
|
import * as os41 from "node:os";
|
|
19002
19128
|
import * as path72 from "node:path";
|
|
19003
19129
|
function defaultSettingsJsonLockPath() {
|
|
@@ -19014,11 +19140,11 @@ function defaultIsPidAlive2(pid) {
|
|
|
19014
19140
|
}
|
|
19015
19141
|
}
|
|
19016
19142
|
function sleep8(ms) {
|
|
19017
|
-
return new Promise((
|
|
19143
|
+
return new Promise((resolve31) => setTimeout(resolve31, ms));
|
|
19018
19144
|
}
|
|
19019
19145
|
function readLockMeta2(lockPath) {
|
|
19020
19146
|
try {
|
|
19021
|
-
const raw =
|
|
19147
|
+
const raw = fs74.readFileSync(lockPath, "utf-8");
|
|
19022
19148
|
const parsed = JSON.parse(raw);
|
|
19023
19149
|
if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
|
|
19024
19150
|
return parsed;
|
|
@@ -19041,12 +19167,12 @@ function isLockStale2(meta, opts) {
|
|
|
19041
19167
|
function tryAcquireOnce2(lockPath, meta, opts) {
|
|
19042
19168
|
for (let attempt = 0; attempt <= MAX_STEAL_ATTEMPTS; attempt += 1) {
|
|
19043
19169
|
try {
|
|
19044
|
-
|
|
19045
|
-
const fd =
|
|
19170
|
+
fs74.mkdirSync(path72.dirname(lockPath), { recursive: true });
|
|
19171
|
+
const fd = fs74.openSync(lockPath, "wx", 384);
|
|
19046
19172
|
try {
|
|
19047
|
-
|
|
19173
|
+
fs74.writeSync(fd, JSON.stringify(meta));
|
|
19048
19174
|
} finally {
|
|
19049
|
-
|
|
19175
|
+
fs74.closeSync(fd);
|
|
19050
19176
|
}
|
|
19051
19177
|
return true;
|
|
19052
19178
|
} catch (err) {
|
|
@@ -19064,9 +19190,9 @@ function tryAcquireOnce2(lockPath, meta, opts) {
|
|
|
19064
19190
|
}
|
|
19065
19191
|
const victimPath = `${lockPath}.victim-${process.pid}-${attempt}-${Date.now()}`;
|
|
19066
19192
|
try {
|
|
19067
|
-
|
|
19193
|
+
fs74.renameSync(lockPath, victimPath);
|
|
19068
19194
|
try {
|
|
19069
|
-
|
|
19195
|
+
fs74.unlinkSync(victimPath);
|
|
19070
19196
|
} catch {
|
|
19071
19197
|
}
|
|
19072
19198
|
} catch (err) {
|
|
@@ -19098,7 +19224,7 @@ async function acquireSettingsJsonLock(options = {}) {
|
|
|
19098
19224
|
lockPath,
|
|
19099
19225
|
release: () => {
|
|
19100
19226
|
try {
|
|
19101
|
-
|
|
19227
|
+
fs74.unlinkSync(lockPath);
|
|
19102
19228
|
} catch {
|
|
19103
19229
|
}
|
|
19104
19230
|
}
|
|
@@ -19201,7 +19327,7 @@ var init_services_status = __esm({
|
|
|
19201
19327
|
|
|
19202
19328
|
// ../core/dist/skill-sources/meta-hooks-migration-snapshot.js
|
|
19203
19329
|
import * as crypto10 from "node:crypto";
|
|
19204
|
-
import * as
|
|
19330
|
+
import * as fs75 from "node:fs";
|
|
19205
19331
|
import * as os42 from "node:os";
|
|
19206
19332
|
import * as path73 from "node:path";
|
|
19207
19333
|
function migrationSnapshotsDir2() {
|
|
@@ -19219,41 +19345,41 @@ function writeMetaHooksSnapshot(originalSettings) {
|
|
|
19219
19345
|
};
|
|
19220
19346
|
const validated = MetaHooksMigrationSnapshotSchema.parse(snapshot);
|
|
19221
19347
|
const dir = migrationSnapshotsDir2();
|
|
19222
|
-
|
|
19348
|
+
fs75.mkdirSync(dir, { recursive: true });
|
|
19223
19349
|
const stamp = validated.takenAt.replace(/[:.]/g, "-");
|
|
19224
19350
|
const rand = crypto10.randomBytes(3).toString("hex");
|
|
19225
19351
|
const file = path73.join(dir, `${META_HOOKS_SNAPSHOT_PREFIX}${stamp}-${process.pid}-${rand}.json`);
|
|
19226
|
-
|
|
19352
|
+
fs75.writeFileSync(file, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
|
|
19227
19353
|
return file;
|
|
19228
19354
|
}
|
|
19229
19355
|
function readMetaHooksSnapshot(filePath) {
|
|
19230
|
-
if (!
|
|
19356
|
+
if (!fs75.existsSync(filePath)) {
|
|
19231
19357
|
throw new Error(`snapshot file not found: ${filePath}`);
|
|
19232
19358
|
}
|
|
19233
|
-
const raw =
|
|
19359
|
+
const raw = fs75.readFileSync(filePath, "utf-8");
|
|
19234
19360
|
const parsed = JSON.parse(raw);
|
|
19235
19361
|
return MetaHooksMigrationSnapshotSchema.parse(parsed);
|
|
19236
19362
|
}
|
|
19237
19363
|
function findLatestMetaHooksSnapshot() {
|
|
19238
19364
|
const dir = migrationSnapshotsDir2();
|
|
19239
|
-
if (!
|
|
19365
|
+
if (!fs75.existsSync(dir))
|
|
19240
19366
|
return void 0;
|
|
19241
|
-
const candidates2 =
|
|
19367
|
+
const candidates2 = fs75.readdirSync(dir).filter((n) => n.startsWith(META_HOOKS_SNAPSHOT_PREFIX) && n.endsWith(".json")).sort().reverse();
|
|
19242
19368
|
if (candidates2.length === 0)
|
|
19243
19369
|
return void 0;
|
|
19244
19370
|
return path73.join(dir, candidates2[0]);
|
|
19245
19371
|
}
|
|
19246
19372
|
function restoreSettingsFromSnapshot(snapshot, settingsPath) {
|
|
19247
19373
|
if (snapshot.originalSettings === null) {
|
|
19248
|
-
if (
|
|
19249
|
-
|
|
19374
|
+
if (fs75.existsSync(settingsPath)) {
|
|
19375
|
+
fs75.unlinkSync(settingsPath);
|
|
19250
19376
|
}
|
|
19251
19377
|
return;
|
|
19252
19378
|
}
|
|
19253
|
-
|
|
19379
|
+
fs75.mkdirSync(path73.dirname(settingsPath), { recursive: true });
|
|
19254
19380
|
const tmp = `${settingsPath}.tmp-restore-${process.pid}-${Date.now()}`;
|
|
19255
|
-
|
|
19256
|
-
|
|
19381
|
+
fs75.writeFileSync(tmp, JSON.stringify(snapshot.originalSettings, null, 2) + "\n");
|
|
19382
|
+
fs75.renameSync(tmp, settingsPath);
|
|
19257
19383
|
}
|
|
19258
19384
|
var META_HOOKS_SNAPSHOT_SCHEMA_VERSION, META_HOOKS_SNAPSHOT_PREFIX, SettingsLooseSchema, MetaHooksMigrationSnapshotSchema;
|
|
19259
19385
|
var init_meta_hooks_migration_snapshot = __esm({
|
|
@@ -19393,6 +19519,8 @@ function decideTargetBlocks(opts) {
|
|
|
19393
19519
|
target.add("memory-recall");
|
|
19394
19520
|
if (wantMemory && !disabled.has("memory-classify"))
|
|
19395
19521
|
target.add("memory-classify");
|
|
19522
|
+
if (!disabled.has("model-router"))
|
|
19523
|
+
target.add("model-router");
|
|
19396
19524
|
return target;
|
|
19397
19525
|
}
|
|
19398
19526
|
function injectMetaHooks(opts) {
|
|
@@ -19400,6 +19528,7 @@ function injectMetaHooks(opts) {
|
|
|
19400
19528
|
let working = JSON.parse(JSON.stringify(opts.currentSettings ?? {}));
|
|
19401
19529
|
const blocksAdded = [];
|
|
19402
19530
|
const blocksRemoved = [];
|
|
19531
|
+
const blocksSkippedForeign = [];
|
|
19403
19532
|
const memoryRecallPresent = hasMemoryRecallBlock(working);
|
|
19404
19533
|
if (target.has("memory-recall")) {
|
|
19405
19534
|
if (!memoryRecallPresent) {
|
|
@@ -19430,10 +19559,30 @@ function injectMetaHooks(opts) {
|
|
|
19430
19559
|
}
|
|
19431
19560
|
}
|
|
19432
19561
|
}
|
|
19562
|
+
const modelRouterPresent = hasModelRouterBlock(working);
|
|
19563
|
+
if (target.has("model-router")) {
|
|
19564
|
+
if (!modelRouterPresent) {
|
|
19565
|
+
if (hasForeignModelRouterEntry(working)) {
|
|
19566
|
+
blocksSkippedForeign.push("model-router");
|
|
19567
|
+
} else {
|
|
19568
|
+
working = appendBlock(working, OLAM_META_MODEL_ROUTER_STAGE, buildModelRouterHookEntry());
|
|
19569
|
+
blocksAdded.push("model-router");
|
|
19570
|
+
}
|
|
19571
|
+
}
|
|
19572
|
+
} else {
|
|
19573
|
+
if (modelRouterPresent) {
|
|
19574
|
+
const r = computeModelRouterUninstall(working);
|
|
19575
|
+
if (r.status === "removed" && r.settingsAfter) {
|
|
19576
|
+
working = r.settingsAfter;
|
|
19577
|
+
blocksRemoved.push("model-router");
|
|
19578
|
+
}
|
|
19579
|
+
}
|
|
19580
|
+
}
|
|
19433
19581
|
return {
|
|
19434
19582
|
nextSettings: working,
|
|
19435
19583
|
blocksAdded,
|
|
19436
19584
|
blocksRemoved,
|
|
19585
|
+
blocksSkippedForeign,
|
|
19437
19586
|
mode: opts.mode ?? "auto"
|
|
19438
19587
|
};
|
|
19439
19588
|
}
|
|
@@ -19467,6 +19616,40 @@ function hasMemoryClassifyBlock(settings) {
|
|
|
19467
19616
|
}
|
|
19468
19617
|
return false;
|
|
19469
19618
|
}
|
|
19619
|
+
function hasModelRouterBlock(settings) {
|
|
19620
|
+
const entries = settings.hooks?.UserPromptSubmit;
|
|
19621
|
+
if (!Array.isArray(entries))
|
|
19622
|
+
return false;
|
|
19623
|
+
for (const matcher of entries) {
|
|
19624
|
+
const inner = matcher?.hooks ?? [];
|
|
19625
|
+
if (!Array.isArray(inner))
|
|
19626
|
+
continue;
|
|
19627
|
+
for (const h of inner) {
|
|
19628
|
+
if (typeof h?.command === "string" && matchModelRouterSentinel(h.command))
|
|
19629
|
+
return true;
|
|
19630
|
+
}
|
|
19631
|
+
}
|
|
19632
|
+
return false;
|
|
19633
|
+
}
|
|
19634
|
+
function hasForeignModelRouterEntry(settings) {
|
|
19635
|
+
const entries = settings.hooks?.UserPromptSubmit;
|
|
19636
|
+
if (!Array.isArray(entries))
|
|
19637
|
+
return false;
|
|
19638
|
+
for (const matcher of entries) {
|
|
19639
|
+
const inner = matcher?.hooks ?? [];
|
|
19640
|
+
if (!Array.isArray(inner))
|
|
19641
|
+
continue;
|
|
19642
|
+
for (const h of inner) {
|
|
19643
|
+
if (typeof h?.command !== "string")
|
|
19644
|
+
continue;
|
|
19645
|
+
if (matchModelRouterSentinel(h.command))
|
|
19646
|
+
continue;
|
|
19647
|
+
if (h.command.includes(OLAM_META_MODEL_ROUTER_SCRIPT_BASENAME))
|
|
19648
|
+
return true;
|
|
19649
|
+
}
|
|
19650
|
+
}
|
|
19651
|
+
return false;
|
|
19652
|
+
}
|
|
19470
19653
|
function appendBlock(settings, stage, entry) {
|
|
19471
19654
|
const next = { ...settings };
|
|
19472
19655
|
const hooks = { ...settings.hooks ?? {} };
|
|
@@ -19485,7 +19668,7 @@ var init_meta_hook_injector = __esm({
|
|
|
19485
19668
|
|
|
19486
19669
|
// ../core/dist/lib/markdown-merger.js
|
|
19487
19670
|
import { createHash as createHash9 } from "node:crypto";
|
|
19488
|
-
import { readFileSync as
|
|
19671
|
+
import { readFileSync as readFileSync74, existsSync as existsSync83, statSync as statSync23 } from "node:fs";
|
|
19489
19672
|
function parseFrontmatter3(text) {
|
|
19490
19673
|
const match2 = FM_RE2.exec(text);
|
|
19491
19674
|
if (match2 === null)
|
|
@@ -19614,9 +19797,9 @@ function mergeMarkdown(upstreamText, overlayText, labelForError, upstreamPath, o
|
|
|
19614
19797
|
return { merged: fmBlock !== "" ? fmBlock + mergedBody : mergedBody };
|
|
19615
19798
|
}
|
|
19616
19799
|
function sha256OfPath(p) {
|
|
19617
|
-
if (!
|
|
19800
|
+
if (!existsSync83(p) || !statSync23(p).isFile())
|
|
19618
19801
|
return "MISSING";
|
|
19619
|
-
return createHash9("sha256").update(
|
|
19802
|
+
return createHash9("sha256").update(readFileSync74(p)).digest("hex");
|
|
19620
19803
|
}
|
|
19621
19804
|
var FM_RE2, H2_RE;
|
|
19622
19805
|
var init_markdown_merger = __esm({
|
|
@@ -19628,7 +19811,7 @@ var init_markdown_merger = __esm({
|
|
|
19628
19811
|
});
|
|
19629
19812
|
|
|
19630
19813
|
// ../core/dist/skill-sync/managed-merge.js
|
|
19631
|
-
import * as
|
|
19814
|
+
import * as fs76 from "node:fs";
|
|
19632
19815
|
import * as path74 from "node:path";
|
|
19633
19816
|
function materializeMergedSkill(opts) {
|
|
19634
19817
|
const { sourceId, sourcePath, deployBasename, mergedContent, claudeDir: claudeDir2 } = opts;
|
|
@@ -19638,12 +19821,12 @@ function materializeMergedSkill(opts) {
|
|
|
19638
19821
|
if (!(managedResolved === sourceRoot || managedResolved.startsWith(sourceRoot + path74.sep))) {
|
|
19639
19822
|
throw new Error(`[managed-merge] refusing to materialize: deployBasename "${deployBasename}" escapes managed root "${sourceRoot}" (resolved to "${managedResolved}")`);
|
|
19640
19823
|
}
|
|
19641
|
-
|
|
19824
|
+
fs76.mkdirSync(managedDir, { recursive: true });
|
|
19642
19825
|
const skillMdPath = path74.join(managedDir, "SKILL.md");
|
|
19643
19826
|
const tmpPath = `${skillMdPath}.tmp-${process.pid}-${Date.now()}`;
|
|
19644
|
-
|
|
19645
|
-
|
|
19646
|
-
const baseEntries =
|
|
19827
|
+
fs76.writeFileSync(tmpPath, mergedContent);
|
|
19828
|
+
fs76.renameSync(tmpPath, skillMdPath);
|
|
19829
|
+
const baseEntries = fs76.readdirSync(sourcePath);
|
|
19647
19830
|
for (const entry of baseEntries) {
|
|
19648
19831
|
if (entry === "SKILL.md")
|
|
19649
19832
|
continue;
|
|
@@ -19651,13 +19834,13 @@ function materializeMergedSkill(opts) {
|
|
|
19651
19834
|
const targetAbsolute = path74.join(sourcePath, entry);
|
|
19652
19835
|
const targetRelative = path74.relative(managedDir, targetAbsolute);
|
|
19653
19836
|
try {
|
|
19654
|
-
|
|
19655
|
-
|
|
19837
|
+
fs76.lstatSync(linkPath);
|
|
19838
|
+
fs76.rmSync(linkPath, { recursive: true, force: true });
|
|
19656
19839
|
} catch {
|
|
19657
19840
|
}
|
|
19658
|
-
|
|
19841
|
+
fs76.symlinkSync(targetRelative, linkPath);
|
|
19659
19842
|
}
|
|
19660
|
-
const managedEntries =
|
|
19843
|
+
const managedEntries = fs76.readdirSync(managedDir);
|
|
19661
19844
|
const baseEntrySet = new Set(baseEntries);
|
|
19662
19845
|
for (const entry of managedEntries) {
|
|
19663
19846
|
if (entry === "SKILL.md")
|
|
@@ -19665,7 +19848,7 @@ function materializeMergedSkill(opts) {
|
|
|
19665
19848
|
if (!baseEntrySet.has(entry)) {
|
|
19666
19849
|
const stalePath = path74.join(managedDir, entry);
|
|
19667
19850
|
try {
|
|
19668
|
-
|
|
19851
|
+
fs76.rmSync(stalePath, { recursive: true, force: true });
|
|
19669
19852
|
} catch {
|
|
19670
19853
|
}
|
|
19671
19854
|
}
|
|
@@ -19673,7 +19856,7 @@ function materializeMergedSkill(opts) {
|
|
|
19673
19856
|
return managedDir;
|
|
19674
19857
|
}
|
|
19675
19858
|
function cleanMergedDir(claudeDir2) {
|
|
19676
|
-
|
|
19859
|
+
fs76.rmSync(path74.join(claudeDir2, ".olam-merged"), { recursive: true, force: true });
|
|
19677
19860
|
}
|
|
19678
19861
|
var init_managed_merge = __esm({
|
|
19679
19862
|
"../core/dist/skill-sync/managed-merge.js"() {
|
|
@@ -19812,7 +19995,7 @@ var init_prefix_rules = __esm({
|
|
|
19812
19995
|
});
|
|
19813
19996
|
|
|
19814
19997
|
// ../core/dist/skill-sync/prefix-deploy.js
|
|
19815
|
-
import * as
|
|
19998
|
+
import * as fs77 from "node:fs";
|
|
19816
19999
|
import * as path75 from "node:path";
|
|
19817
20000
|
function buildSourcePrefixMap(sources) {
|
|
19818
20001
|
const byId = /* @__PURE__ */ new Map();
|
|
@@ -19868,7 +20051,7 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
|
|
|
19868
20051
|
}
|
|
19869
20052
|
if (artifact.kind === "skill") {
|
|
19870
20053
|
const skillMdPath = path75.join(artifact.sourcePath, "SKILL.md");
|
|
19871
|
-
const content =
|
|
20054
|
+
const content = fs77.readFileSync(skillMdPath);
|
|
19872
20055
|
const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
|
|
19873
20056
|
const managedDir = materializeMergedSkill({
|
|
19874
20057
|
sourceId: artifact.sourceId,
|
|
@@ -19880,7 +20063,7 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
|
|
|
19880
20063
|
artifact.sourcePath = managedDir;
|
|
19881
20064
|
artifact.deployBasename = renamed;
|
|
19882
20065
|
} else {
|
|
19883
|
-
const content = artifact.resolvedContent !== void 0 ? artifact.resolvedContent :
|
|
20066
|
+
const content = artifact.resolvedContent !== void 0 ? artifact.resolvedContent : fs77.readFileSync(artifact.sourcePath);
|
|
19884
20067
|
const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
|
|
19885
20068
|
artifact.resolvedContent = rewritten;
|
|
19886
20069
|
artifact.deployBasename = renamed;
|
|
@@ -19925,19 +20108,19 @@ var init_prefix_deploy = __esm({
|
|
|
19925
20108
|
});
|
|
19926
20109
|
|
|
19927
20110
|
// ../core/dist/skill-sync/resolve-source-config.js
|
|
19928
|
-
import { readFileSync as
|
|
19929
|
-
import { join as
|
|
20111
|
+
import { readFileSync as readFileSync76, existsSync as existsSync84 } from "node:fs";
|
|
20112
|
+
import { join as join84 } from "node:path";
|
|
19930
20113
|
import { parse as parseYaml7 } from "yaml";
|
|
19931
20114
|
function sourceConfigPath(clonePath) {
|
|
19932
|
-
return
|
|
20115
|
+
return join84(clonePath, "shared", "source-config.yaml");
|
|
19933
20116
|
}
|
|
19934
20117
|
function readSourceConfig(clonePath, sourceId) {
|
|
19935
20118
|
const path106 = sourceConfigPath(clonePath);
|
|
19936
|
-
if (!
|
|
20119
|
+
if (!existsSync84(path106))
|
|
19937
20120
|
return void 0;
|
|
19938
20121
|
let raw;
|
|
19939
20122
|
try {
|
|
19940
|
-
raw =
|
|
20123
|
+
raw = readFileSync76(path106, "utf-8");
|
|
19941
20124
|
} catch (err) {
|
|
19942
20125
|
emitMalformedWarning(sourceId, `read failed: ${errToMsg(err)}`);
|
|
19943
20126
|
return void 0;
|
|
@@ -20032,7 +20215,7 @@ var init_resolve_source_config = __esm({
|
|
|
20032
20215
|
});
|
|
20033
20216
|
|
|
20034
20217
|
// ../core/dist/skill-sync/engine.js
|
|
20035
|
-
import * as
|
|
20218
|
+
import * as fs78 from "node:fs";
|
|
20036
20219
|
import * as os43 from "node:os";
|
|
20037
20220
|
import * as path76 from "node:path";
|
|
20038
20221
|
function resolveAtlasUser(override) {
|
|
@@ -20040,8 +20223,8 @@ function resolveAtlasUser(override) {
|
|
|
20040
20223
|
return override;
|
|
20041
20224
|
const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path76.join(os43.homedir(), ".claude");
|
|
20042
20225
|
const f = path76.join(claudeDir2, ".atlas-user");
|
|
20043
|
-
if (
|
|
20044
|
-
return
|
|
20226
|
+
if (fs78.existsSync(f)) {
|
|
20227
|
+
return fs78.readFileSync(f, "utf-8").trim() || void 0;
|
|
20045
20228
|
}
|
|
20046
20229
|
return void 0;
|
|
20047
20230
|
}
|
|
@@ -20053,7 +20236,7 @@ async function syncSkills(opts = {}) {
|
|
|
20053
20236
|
const perSource = [];
|
|
20054
20237
|
for (const source of sources) {
|
|
20055
20238
|
const clonePath = skillSourceClonePath(source.id);
|
|
20056
|
-
if (!
|
|
20239
|
+
if (!fs78.existsSync(clonePath))
|
|
20057
20240
|
continue;
|
|
20058
20241
|
const { artifacts, subscription } = await withFileLock(clonePath, () => {
|
|
20059
20242
|
const pinRef = projectOverride?.override.pin?.[source.id];
|
|
@@ -20093,7 +20276,7 @@ async function syncSkills(opts = {}) {
|
|
|
20093
20276
|
const overlayArtifacts = memberOverlaysEnabled ? projectFilteredArtifacts.filter((a) => a.kind === "overlay") : [];
|
|
20094
20277
|
const effectiveSources = sources.map((s) => {
|
|
20095
20278
|
const clonePath = skillSourceClonePath(s.id);
|
|
20096
|
-
const sourceConfig =
|
|
20279
|
+
const sourceConfig = fs78.existsSync(clonePath) ? readSourceConfig(clonePath, s.id) : void 0;
|
|
20097
20280
|
const eff = resolveEffectivePrefix(s, sourceConfig);
|
|
20098
20281
|
const entry = {
|
|
20099
20282
|
id: s.id,
|
|
@@ -20200,12 +20383,12 @@ async function syncSkills(opts = {}) {
|
|
|
20200
20383
|
let basePath;
|
|
20201
20384
|
if (overlay.targetKind === "skill") {
|
|
20202
20385
|
basePath = path76.join(base.sourcePath, "SKILL.md");
|
|
20203
|
-
baseContent =
|
|
20386
|
+
baseContent = fs78.readFileSync(basePath, "utf-8");
|
|
20204
20387
|
} else {
|
|
20205
20388
|
basePath = base.sourcePath;
|
|
20206
|
-
baseContent =
|
|
20389
|
+
baseContent = fs78.readFileSync(basePath, "utf-8");
|
|
20207
20390
|
}
|
|
20208
|
-
const overlayContent =
|
|
20391
|
+
const overlayContent = fs78.readFileSync(overlay.sourcePath, "utf-8");
|
|
20209
20392
|
const label = `${overlay.sourceId}/${overlay.deployBasename}`;
|
|
20210
20393
|
const mergeResult = mergeMarkdown(baseContent, overlayContent, label, basePath, overlay.sourcePath);
|
|
20211
20394
|
if ("error" in mergeResult) {
|
|
@@ -20287,24 +20470,34 @@ async function injectMetaHooksIntoSettings(opts) {
|
|
|
20287
20470
|
...memoryProbe.detail !== void 0 ? { memoryDetail: memoryProbe.detail } : {}
|
|
20288
20471
|
};
|
|
20289
20472
|
const settingsFile = claudeSettingsPath();
|
|
20473
|
+
let configDisabled = [];
|
|
20474
|
+
try {
|
|
20475
|
+
const cfg = readGlobalConfig();
|
|
20476
|
+
configDisabled = cfg.metaHooksDisabled ?? [];
|
|
20477
|
+
} catch {
|
|
20478
|
+
}
|
|
20479
|
+
const disabledBlocks = Array.from(/* @__PURE__ */ new Set([
|
|
20480
|
+
...configDisabled,
|
|
20481
|
+
...opts.metaHooksDisabled ?? []
|
|
20482
|
+
]));
|
|
20290
20483
|
let snapshotError;
|
|
20291
20484
|
let stripCandidates = [];
|
|
20292
20485
|
const result = await withSettingsJsonLock(() => {
|
|
20293
20486
|
let currentSettings = {};
|
|
20294
20487
|
let settingsExisted = false;
|
|
20295
|
-
if (
|
|
20488
|
+
if (fs78.existsSync(settingsFile)) {
|
|
20296
20489
|
settingsExisted = true;
|
|
20297
20490
|
try {
|
|
20298
|
-
const raw =
|
|
20491
|
+
const raw = fs78.readFileSync(settingsFile, "utf-8");
|
|
20299
20492
|
currentSettings = raw.trim() ? JSON.parse(raw) : {};
|
|
20300
20493
|
} catch {
|
|
20301
20494
|
try {
|
|
20302
|
-
const raw =
|
|
20495
|
+
const raw = fs78.readFileSync(settingsFile);
|
|
20303
20496
|
const bakDir = path76.join(path76.dirname(settingsFile), ".malformed-backups");
|
|
20304
|
-
|
|
20497
|
+
fs78.mkdirSync(bakDir, { recursive: true });
|
|
20305
20498
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
20306
20499
|
const bakFile = path76.join(bakDir, `settings.json.malformed.${stamp}.bak`);
|
|
20307
|
-
|
|
20500
|
+
fs78.writeFileSync(bakFile, raw, { mode: 384 });
|
|
20308
20501
|
snapshotError = `settings.json was malformed; original bytes preserved at ${bakFile}`;
|
|
20309
20502
|
} catch (bakErr) {
|
|
20310
20503
|
snapshotError = `settings.json malformed AND .bak write failed: ${bakErr instanceof Error ? bakErr.message : String(bakErr)}`;
|
|
@@ -20315,16 +20508,6 @@ async function injectMetaHooksIntoSettings(opts) {
|
|
|
20315
20508
|
}
|
|
20316
20509
|
stripCandidates = findStripCandidates(currentSettings);
|
|
20317
20510
|
const settingsForInject = stripCandidates.length > 0 ? applyStrip(currentSettings, stripCandidates).nextSettings : currentSettings;
|
|
20318
|
-
let configDisabled = [];
|
|
20319
|
-
try {
|
|
20320
|
-
const cfg = readGlobalConfig();
|
|
20321
|
-
configDisabled = cfg.metaHooksDisabled ?? [];
|
|
20322
|
-
} catch {
|
|
20323
|
-
}
|
|
20324
|
-
const disabledBlocks = Array.from(/* @__PURE__ */ new Set([
|
|
20325
|
-
...configDisabled,
|
|
20326
|
-
...opts.metaHooksDisabled ?? []
|
|
20327
|
-
]));
|
|
20328
20511
|
const inject = injectMetaHooks({
|
|
20329
20512
|
servicesStatus: servicesStatus2,
|
|
20330
20513
|
currentSettings: settingsForInject,
|
|
@@ -20354,17 +20537,34 @@ async function injectMetaHooksIntoSettings(opts) {
|
|
|
20354
20537
|
} catch {
|
|
20355
20538
|
}
|
|
20356
20539
|
}
|
|
20357
|
-
|
|
20540
|
+
fs78.mkdirSync(path76.dirname(settingsFile), { recursive: true });
|
|
20358
20541
|
const tmpPath = `${settingsFile}.tmp-${process.pid}-${Date.now()}`;
|
|
20359
|
-
|
|
20360
|
-
|
|
20542
|
+
fs78.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
|
|
20543
|
+
fs78.renameSync(tmpPath, settingsFile);
|
|
20361
20544
|
return inject;
|
|
20362
20545
|
}, { reason: `syncSkills meta-hook injection (mode=${mode})` });
|
|
20546
|
+
let scriptDeploy;
|
|
20547
|
+
const modelRouterTargeted = mode !== "never" && !disabledBlocks.includes("model-router");
|
|
20548
|
+
if (modelRouterTargeted) {
|
|
20549
|
+
try {
|
|
20550
|
+
scriptDeploy = deployModelRouterScript({
|
|
20551
|
+
targetDir: path76.join(claudeDir(), "hooks")
|
|
20552
|
+
});
|
|
20553
|
+
} catch (err) {
|
|
20554
|
+
scriptDeploy = {
|
|
20555
|
+
basename: "model-router.py",
|
|
20556
|
+
action: "source-missing",
|
|
20557
|
+
targetPath: `${err instanceof Error ? err.message : String(err)}`
|
|
20558
|
+
};
|
|
20559
|
+
}
|
|
20560
|
+
}
|
|
20363
20561
|
return {
|
|
20364
20562
|
mode: result.mode,
|
|
20365
20563
|
servicesStatus: servicesStatus2,
|
|
20366
20564
|
blocksAdded: result.blocksAdded,
|
|
20367
20565
|
blocksRemoved: result.blocksRemoved,
|
|
20566
|
+
...result.blocksSkippedForeign.length > 0 ? { blocksSkippedForeign: result.blocksSkippedForeign } : {},
|
|
20567
|
+
...scriptDeploy !== void 0 ? { scriptDeploy } : {},
|
|
20368
20568
|
...snapshotError !== void 0 ? { snapshotError } : {},
|
|
20369
20569
|
...stripCandidates.length > 0 ? { autoMigrated: { strippedCount: stripCandidates.length, stripCandidates } } : {}
|
|
20370
20570
|
};
|
|
@@ -20389,6 +20589,7 @@ var init_engine = __esm({
|
|
|
20389
20589
|
init_trust_audit_log();
|
|
20390
20590
|
init_atlas_hook_strip();
|
|
20391
20591
|
init_meta_hook_injector();
|
|
20592
|
+
init_model_router_deploy();
|
|
20392
20593
|
init_markdown_merger();
|
|
20393
20594
|
init_managed_merge();
|
|
20394
20595
|
init_prefix_deploy();
|
|
@@ -20398,7 +20599,7 @@ var init_engine = __esm({
|
|
|
20398
20599
|
});
|
|
20399
20600
|
|
|
20400
20601
|
// ../core/dist/skill-sync/shadow-backup-manager.js
|
|
20401
|
-
import * as
|
|
20602
|
+
import * as fs79 from "node:fs";
|
|
20402
20603
|
import * as path77 from "node:path";
|
|
20403
20604
|
function listShadowBackups(opts = {}) {
|
|
20404
20605
|
const claude = opts.claudeDirOverride ?? claudeDir();
|
|
@@ -20406,11 +20607,11 @@ function listShadowBackups(opts = {}) {
|
|
|
20406
20607
|
const out = [];
|
|
20407
20608
|
for (const bucket of SHADOW_BACKUP_BUCKETS) {
|
|
20408
20609
|
const bucketDir = path77.join(claude, bucket);
|
|
20409
|
-
if (!
|
|
20610
|
+
if (!fs79.existsSync(bucketDir))
|
|
20410
20611
|
continue;
|
|
20411
20612
|
let entries;
|
|
20412
20613
|
try {
|
|
20413
|
-
entries =
|
|
20614
|
+
entries = fs79.readdirSync(bucketDir);
|
|
20414
20615
|
} catch {
|
|
20415
20616
|
continue;
|
|
20416
20617
|
}
|
|
@@ -20424,7 +20625,7 @@ function listShadowBackups(opts = {}) {
|
|
|
20424
20625
|
const full = path77.join(bucketDir, name);
|
|
20425
20626
|
let sizeBytes = 0;
|
|
20426
20627
|
try {
|
|
20427
|
-
const st =
|
|
20628
|
+
const st = fs79.statSync(full);
|
|
20428
20629
|
if (st.isDirectory())
|
|
20429
20630
|
continue;
|
|
20430
20631
|
sizeBytes = st.size;
|
|
@@ -20480,7 +20681,7 @@ function pruneShadowBackups(opts) {
|
|
|
20480
20681
|
}
|
|
20481
20682
|
if (!opts.dryRun) {
|
|
20482
20683
|
try {
|
|
20483
|
-
|
|
20684
|
+
fs79.unlinkSync(b.path);
|
|
20484
20685
|
} catch {
|
|
20485
20686
|
skipped.push(b);
|
|
20486
20687
|
continue;
|
|
@@ -20492,7 +20693,7 @@ function pruneShadowBackups(opts) {
|
|
|
20492
20693
|
}
|
|
20493
20694
|
function restoreShadowBackup(opts) {
|
|
20494
20695
|
const abs = path77.resolve(opts.backupPath);
|
|
20495
|
-
if (!
|
|
20696
|
+
if (!fs79.existsSync(abs)) {
|
|
20496
20697
|
throw new Error(`backup file not found: ${abs}`);
|
|
20497
20698
|
}
|
|
20498
20699
|
const basename17 = path77.basename(abs);
|
|
@@ -20502,13 +20703,13 @@ function restoreShadowBackup(opts) {
|
|
|
20502
20703
|
}
|
|
20503
20704
|
const originalBasename = basename17.slice(0, basename17.length - match2[0].length);
|
|
20504
20705
|
const originalPath = path77.join(path77.dirname(abs), originalBasename);
|
|
20505
|
-
if (
|
|
20706
|
+
if (fs79.existsSync(originalPath) && !opts.force) {
|
|
20506
20707
|
throw new Error(`original path already occupied: ${originalPath}. Move/rename it first OR re-run with --force.`);
|
|
20507
20708
|
}
|
|
20508
|
-
if (opts.force &&
|
|
20509
|
-
|
|
20709
|
+
if (opts.force && fs79.existsSync(originalPath)) {
|
|
20710
|
+
fs79.unlinkSync(originalPath);
|
|
20510
20711
|
}
|
|
20511
|
-
|
|
20712
|
+
fs79.renameSync(abs, originalPath);
|
|
20512
20713
|
return { restoredTo: originalPath };
|
|
20513
20714
|
}
|
|
20514
20715
|
var SHADOW_BACKUP_BUCKETS, SHADOW_BACKUP_SUFFIX_RE;
|
|
@@ -20522,7 +20723,7 @@ var init_shadow_backup_manager = __esm({
|
|
|
20522
20723
|
});
|
|
20523
20724
|
|
|
20524
20725
|
// ../core/dist/global-config/repos.js
|
|
20525
|
-
import * as
|
|
20726
|
+
import * as fs80 from "node:fs";
|
|
20526
20727
|
import * as os44 from "node:os";
|
|
20527
20728
|
import * as path78 from "node:path";
|
|
20528
20729
|
function expandPath(p) {
|
|
@@ -20540,7 +20741,7 @@ function addRepo(entry) {
|
|
|
20540
20741
|
throw new Error(`repo "${entry.name}" already registered. Use "olam repos update" to change its path.`);
|
|
20541
20742
|
}
|
|
20542
20743
|
const resolvedPath = expandPath(entry.path);
|
|
20543
|
-
if (!
|
|
20744
|
+
if (!fs80.existsSync(resolvedPath)) {
|
|
20544
20745
|
throw new Error(`path "${entry.path}" does not exist. Verify the path is correct.`);
|
|
20545
20746
|
}
|
|
20546
20747
|
const now = Date.now();
|
|
@@ -20569,7 +20770,7 @@ function updateRepo(name, updates) {
|
|
|
20569
20770
|
throw new Error(`repo "${name}" is not registered. Run "olam repos list" to see registered repos.`);
|
|
20570
20771
|
}
|
|
20571
20772
|
const resolvedUpdatePath = updates.path !== void 0 ? expandPath(updates.path) : void 0;
|
|
20572
|
-
if (resolvedUpdatePath !== void 0 && !
|
|
20773
|
+
if (resolvedUpdatePath !== void 0 && !fs80.existsSync(resolvedUpdatePath)) {
|
|
20573
20774
|
throw new Error(`path "${updates.path}" does not exist. Verify the path is correct.`);
|
|
20574
20775
|
}
|
|
20575
20776
|
const existing = config.repos[idx];
|
|
@@ -20638,7 +20839,7 @@ var init_global_config = __esm({
|
|
|
20638
20839
|
});
|
|
20639
20840
|
|
|
20640
20841
|
// ../core/dist/skill-sources/doctor-checks.js
|
|
20641
|
-
import * as
|
|
20842
|
+
import * as fs81 from "node:fs";
|
|
20642
20843
|
import * as path79 from "node:path";
|
|
20643
20844
|
import * as os45 from "node:os";
|
|
20644
20845
|
function claudeDirInternal3() {
|
|
@@ -20654,11 +20855,11 @@ function checkStateFileParse() {
|
|
|
20654
20855
|
healthy: true,
|
|
20655
20856
|
description: `~/.olam state file (${filePath})`
|
|
20656
20857
|
};
|
|
20657
|
-
if (!
|
|
20858
|
+
if (!fs81.existsSync(filePath)) {
|
|
20658
20859
|
result.details = ["(file does not yet exist \u2014 will be created on first write)"];
|
|
20659
20860
|
return result;
|
|
20660
20861
|
}
|
|
20661
|
-
const raw =
|
|
20862
|
+
const raw = fs81.readFileSync(filePath, "utf-8");
|
|
20662
20863
|
let parsed;
|
|
20663
20864
|
try {
|
|
20664
20865
|
parsed = JSON.parse(raw);
|
|
@@ -20668,8 +20869,8 @@ function checkStateFileParse() {
|
|
|
20668
20869
|
result.details = [err instanceof Error ? err.message : String(err)];
|
|
20669
20870
|
result.repair = () => {
|
|
20670
20871
|
const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
|
|
20671
|
-
|
|
20672
|
-
|
|
20872
|
+
fs81.renameSync(filePath, aside);
|
|
20873
|
+
fs81.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
|
|
20673
20874
|
};
|
|
20674
20875
|
return result;
|
|
20675
20876
|
}
|
|
@@ -20680,7 +20881,7 @@ function checkStateFileParse() {
|
|
|
20680
20881
|
result.details = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`);
|
|
20681
20882
|
result.repair = () => {
|
|
20682
20883
|
const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
|
|
20683
|
-
|
|
20884
|
+
fs81.copyFileSync(filePath, aside);
|
|
20684
20885
|
const base = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
20685
20886
|
const next = {
|
|
20686
20887
|
...base,
|
|
@@ -20689,7 +20890,7 @@ function checkStateFileParse() {
|
|
|
20689
20890
|
runbooks: [],
|
|
20690
20891
|
skillSources: []
|
|
20691
20892
|
};
|
|
20692
|
-
|
|
20893
|
+
fs81.writeFileSync(filePath, JSON.stringify(next, null, 2));
|
|
20693
20894
|
};
|
|
20694
20895
|
return result;
|
|
20695
20896
|
}
|
|
@@ -20701,15 +20902,15 @@ function checkDanglingSymlinks() {
|
|
|
20701
20902
|
const dangling = [];
|
|
20702
20903
|
for (const bucket of buckets) {
|
|
20703
20904
|
const dir = path79.join(claude, bucket);
|
|
20704
|
-
if (!
|
|
20905
|
+
if (!fs81.existsSync(dir))
|
|
20705
20906
|
continue;
|
|
20706
|
-
for (const name of
|
|
20907
|
+
for (const name of fs81.readdirSync(dir)) {
|
|
20707
20908
|
const linkPath = path79.join(dir, name);
|
|
20708
20909
|
try {
|
|
20709
|
-
const lst =
|
|
20910
|
+
const lst = fs81.lstatSync(linkPath);
|
|
20710
20911
|
if (!lst.isSymbolicLink())
|
|
20711
20912
|
continue;
|
|
20712
|
-
if (!
|
|
20913
|
+
if (!fs81.existsSync(linkPath)) {
|
|
20713
20914
|
dangling.push(linkPath);
|
|
20714
20915
|
}
|
|
20715
20916
|
} catch {
|
|
@@ -20727,7 +20928,7 @@ function checkDanglingSymlinks() {
|
|
|
20727
20928
|
result.repair = () => {
|
|
20728
20929
|
for (const p of dangling) {
|
|
20729
20930
|
try {
|
|
20730
|
-
|
|
20931
|
+
fs81.unlinkSync(p);
|
|
20731
20932
|
} catch {
|
|
20732
20933
|
}
|
|
20733
20934
|
}
|
|
@@ -20742,19 +20943,19 @@ function checkOrphanedSnapshots() {
|
|
|
20742
20943
|
healthy: true,
|
|
20743
20944
|
description: `orphaned migration snapshots under ${dir}`
|
|
20744
20945
|
};
|
|
20745
|
-
if (!
|
|
20946
|
+
if (!fs81.existsSync(dir)) {
|
|
20746
20947
|
return result;
|
|
20747
20948
|
}
|
|
20748
20949
|
const orphans = [];
|
|
20749
|
-
for (const name of
|
|
20950
|
+
for (const name of fs81.readdirSync(dir)) {
|
|
20750
20951
|
if (!name.endsWith(".json"))
|
|
20751
20952
|
continue;
|
|
20752
20953
|
const full = path79.join(dir, name);
|
|
20753
20954
|
try {
|
|
20754
|
-
const stat =
|
|
20955
|
+
const stat = fs81.statSync(full);
|
|
20755
20956
|
if (!stat.isFile())
|
|
20756
20957
|
continue;
|
|
20757
|
-
const raw =
|
|
20958
|
+
const raw = fs81.readFileSync(full, "utf-8");
|
|
20758
20959
|
let parsed;
|
|
20759
20960
|
try {
|
|
20760
20961
|
parsed = JSON.parse(raw);
|
|
@@ -20779,7 +20980,7 @@ function checkOrphanedSnapshots() {
|
|
|
20779
20980
|
result.repair = () => {
|
|
20780
20981
|
for (const o of orphans) {
|
|
20781
20982
|
try {
|
|
20782
|
-
|
|
20983
|
+
fs81.unlinkSync(o.path);
|
|
20783
20984
|
} catch {
|
|
20784
20985
|
}
|
|
20785
20986
|
}
|
|
@@ -20794,12 +20995,12 @@ function checkSentinelDrift() {
|
|
|
20794
20995
|
healthy: true,
|
|
20795
20996
|
description: `olam-skills sentinel block in ${filePath}`
|
|
20796
20997
|
};
|
|
20797
|
-
if (!
|
|
20998
|
+
if (!fs81.existsSync(filePath)) {
|
|
20798
20999
|
return result;
|
|
20799
21000
|
}
|
|
20800
21001
|
let parsed;
|
|
20801
21002
|
try {
|
|
20802
|
-
parsed = JSON.parse(
|
|
21003
|
+
parsed = JSON.parse(fs81.readFileSync(filePath, "utf-8"));
|
|
20803
21004
|
} catch {
|
|
20804
21005
|
return result;
|
|
20805
21006
|
}
|
|
@@ -20840,7 +21041,7 @@ function checkSentinelDrift() {
|
|
|
20840
21041
|
backupSettings();
|
|
20841
21042
|
} catch {
|
|
20842
21043
|
}
|
|
20843
|
-
const next = JSON.parse(
|
|
21044
|
+
const next = JSON.parse(fs81.readFileSync(filePath, "utf-8"));
|
|
20844
21045
|
if (!next.hooks)
|
|
20845
21046
|
return;
|
|
20846
21047
|
for (const stage of Object.keys(next.hooks)) {
|
|
@@ -20863,7 +21064,7 @@ function checkSentinelDrift() {
|
|
|
20863
21064
|
return bad === void 0;
|
|
20864
21065
|
});
|
|
20865
21066
|
}
|
|
20866
|
-
|
|
21067
|
+
fs81.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
20867
21068
|
};
|
|
20868
21069
|
}
|
|
20869
21070
|
return result;
|
|
@@ -20888,7 +21089,7 @@ function checkMemberNameMissing() {
|
|
|
20888
21089
|
}
|
|
20889
21090
|
const claudeDir2 = claudeDirInternal3();
|
|
20890
21091
|
const atlasUserPath = path79.join(claudeDir2, ".atlas-user");
|
|
20891
|
-
const value =
|
|
21092
|
+
const value = fs81.existsSync(atlasUserPath) ? fs81.readFileSync(atlasUserPath, "utf-8").trim() : "";
|
|
20892
21093
|
if (value.length > 0) {
|
|
20893
21094
|
result.details = [`atlas-user: ${value}`];
|
|
20894
21095
|
return result;
|
|
@@ -20897,9 +21098,9 @@ function checkMemberNameMissing() {
|
|
|
20897
21098
|
result.issue = "atlas-toolbox source registered but ~/.claude/.atlas-user not set";
|
|
20898
21099
|
const clonePath = skillSourceClonePath(atlasSource.id);
|
|
20899
21100
|
const membersDir = path79.join(clonePath, "members");
|
|
20900
|
-
const existing =
|
|
21101
|
+
const existing = fs81.existsSync(membersDir) ? fs81.readdirSync(membersDir).filter((e) => {
|
|
20901
21102
|
try {
|
|
20902
|
-
return
|
|
21103
|
+
return fs81.statSync(path79.join(membersDir, e)).isDirectory();
|
|
20903
21104
|
} catch {
|
|
20904
21105
|
return false;
|
|
20905
21106
|
}
|
|
@@ -20914,7 +21115,7 @@ function checkMemberNameMissing() {
|
|
|
20914
21115
|
function checkMemberOverlayDrift() {
|
|
20915
21116
|
const claudeDir2 = claudeDirInternal3();
|
|
20916
21117
|
const atlasUserPath = path79.join(claudeDir2, ".atlas-user");
|
|
20917
|
-
const atlasUser =
|
|
21118
|
+
const atlasUser = fs81.existsSync(atlasUserPath) ? fs81.readFileSync(atlasUserPath, "utf-8").trim() : "";
|
|
20918
21119
|
if (atlasUser.length === 0) {
|
|
20919
21120
|
return [];
|
|
20920
21121
|
}
|
|
@@ -20931,11 +21132,11 @@ function checkMemberOverlayDrift() {
|
|
|
20931
21132
|
const results = [];
|
|
20932
21133
|
for (const kind of ["skills", "agents"]) {
|
|
20933
21134
|
const localRoot = path79.join(claudeDir2, `${kind}.overrides`);
|
|
20934
|
-
if (!
|
|
21135
|
+
if (!fs81.existsSync(localRoot))
|
|
20935
21136
|
continue;
|
|
20936
21137
|
let entries;
|
|
20937
21138
|
try {
|
|
20938
|
-
entries =
|
|
21139
|
+
entries = fs81.readdirSync(localRoot);
|
|
20939
21140
|
} catch {
|
|
20940
21141
|
continue;
|
|
20941
21142
|
}
|
|
@@ -20943,7 +21144,7 @@ function checkMemberOverlayDrift() {
|
|
|
20943
21144
|
const localFile = path79.join(localRoot, entry);
|
|
20944
21145
|
let stat;
|
|
20945
21146
|
try {
|
|
20946
|
-
stat =
|
|
21147
|
+
stat = fs81.statSync(localFile);
|
|
20947
21148
|
} catch {
|
|
20948
21149
|
continue;
|
|
20949
21150
|
}
|
|
@@ -21119,7 +21320,7 @@ __export(project_sweep_exports, {
|
|
|
21119
21320
|
walkProjectRoot: () => walkProjectRoot
|
|
21120
21321
|
});
|
|
21121
21322
|
import * as path80 from "node:path";
|
|
21122
|
-
import { readdirSync as readdirSync26, lstatSync as lstatSync6, statSync as statSync26, existsSync as
|
|
21323
|
+
import { readdirSync as readdirSync26, lstatSync as lstatSync6, statSync as statSync26, existsSync as existsSync89 } from "node:fs";
|
|
21123
21324
|
function isSkipped(basename17, extra) {
|
|
21124
21325
|
if (DEFAULT_SKIP.has(basename17))
|
|
21125
21326
|
return true;
|
|
@@ -21198,7 +21399,7 @@ function makeRealFsAdapter() {
|
|
|
21198
21399
|
const s = statSync26(p, { throwIfNoEntry: true });
|
|
21199
21400
|
return { isDirectory: () => s.isDirectory(), mtimeMs: s.mtimeMs };
|
|
21200
21401
|
},
|
|
21201
|
-
existsSync: (p) =>
|
|
21402
|
+
existsSync: (p) => existsSync89(p)
|
|
21202
21403
|
};
|
|
21203
21404
|
}
|
|
21204
21405
|
function walkProjectRoot(rootPath, opts = {}) {
|
|
@@ -21224,7 +21425,7 @@ __export(kg_eager_exports, {
|
|
|
21224
21425
|
runEagerKgBuild: () => runEagerKgBuild,
|
|
21225
21426
|
writeQueue: () => writeQueue
|
|
21226
21427
|
});
|
|
21227
|
-
import * as
|
|
21428
|
+
import * as fs82 from "node:fs";
|
|
21228
21429
|
import * as path81 from "node:path";
|
|
21229
21430
|
import * as os46 from "node:os";
|
|
21230
21431
|
function defaultQueuePath() {
|
|
@@ -21232,9 +21433,9 @@ function defaultQueuePath() {
|
|
|
21232
21433
|
return path81.join(stateDir, "kg-pending.jsonl");
|
|
21233
21434
|
}
|
|
21234
21435
|
function readQueue(queuePath) {
|
|
21235
|
-
if (!
|
|
21436
|
+
if (!fs82.existsSync(queuePath))
|
|
21236
21437
|
return [];
|
|
21237
|
-
const raw =
|
|
21438
|
+
const raw = fs82.readFileSync(queuePath, "utf-8");
|
|
21238
21439
|
const entries = [];
|
|
21239
21440
|
for (const line of raw.split("\n")) {
|
|
21240
21441
|
const trimmed = line.trim();
|
|
@@ -21248,16 +21449,16 @@ function readQueue(queuePath) {
|
|
|
21248
21449
|
return entries;
|
|
21249
21450
|
}
|
|
21250
21451
|
function writeQueue(queuePath, entries) {
|
|
21251
|
-
|
|
21452
|
+
fs82.mkdirSync(path81.dirname(queuePath), { recursive: true });
|
|
21252
21453
|
const content = entries.map((e) => JSON.stringify(e)).join("\n") + (entries.length > 0 ? "\n" : "");
|
|
21253
|
-
|
|
21454
|
+
fs82.writeFileSync(queuePath, content, "utf-8");
|
|
21254
21455
|
}
|
|
21255
21456
|
function appendQueue(queuePath, repos, nowMs) {
|
|
21256
21457
|
if (repos.length === 0)
|
|
21257
21458
|
return;
|
|
21258
|
-
|
|
21459
|
+
fs82.mkdirSync(path81.dirname(queuePath), { recursive: true });
|
|
21259
21460
|
const lines = repos.map((r) => JSON.stringify({ path: r.path, addedAt: nowMs })).join("\n") + "\n";
|
|
21260
|
-
|
|
21461
|
+
fs82.appendFileSync(queuePath, lines, "utf-8");
|
|
21261
21462
|
}
|
|
21262
21463
|
async function defaultBuildOne(_repo) {
|
|
21263
21464
|
return { ok: true, ms: 0 };
|
|
@@ -21397,27 +21598,27 @@ var init_install_shared = __esm({
|
|
|
21397
21598
|
});
|
|
21398
21599
|
|
|
21399
21600
|
// src/commands/memory/_paths.ts
|
|
21400
|
-
import { homedir as
|
|
21401
|
-
import { join as
|
|
21402
|
-
import { fileURLToPath as
|
|
21601
|
+
import { homedir as homedir53 } from "node:os";
|
|
21602
|
+
import { join as join93, dirname as dirname50 } from "node:path";
|
|
21603
|
+
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
21403
21604
|
var OLAM_HOME5, MEMORY_PID_PATH, MEMORY_LOG_PATH, MEMORY_DATA_DIR, MEMORY_REST_PORT, MEMORY_LIVEZ_URL, here, candidates, MEMORY_SERVICE_CANDIDATES;
|
|
21404
21605
|
var init_paths2 = __esm({
|
|
21405
21606
|
"src/commands/memory/_paths.ts"() {
|
|
21406
21607
|
"use strict";
|
|
21407
|
-
OLAM_HOME5 =
|
|
21408
|
-
MEMORY_PID_PATH =
|
|
21409
|
-
MEMORY_LOG_PATH =
|
|
21410
|
-
MEMORY_DATA_DIR =
|
|
21608
|
+
OLAM_HOME5 = join93(homedir53(), ".olam");
|
|
21609
|
+
MEMORY_PID_PATH = join93(OLAM_HOME5, "memory.pid");
|
|
21610
|
+
MEMORY_LOG_PATH = join93(OLAM_HOME5, "memory-service.log");
|
|
21611
|
+
MEMORY_DATA_DIR = join93(OLAM_HOME5, "memory-data");
|
|
21411
21612
|
MEMORY_REST_PORT = 3111;
|
|
21412
21613
|
MEMORY_LIVEZ_URL = `http://localhost:${MEMORY_REST_PORT}/agentmemory/livez`;
|
|
21413
|
-
here =
|
|
21614
|
+
here = dirname50(fileURLToPath9(import.meta.url));
|
|
21414
21615
|
candidates = [
|
|
21415
21616
|
// 1. Workspace dev (built): packages/cli/dist/commands/memory/_paths.js → packages/cli → packages/memory-service
|
|
21416
|
-
|
|
21617
|
+
join93(here, "..", "..", "..", "..", "memory-service"),
|
|
21417
21618
|
// 2. Workspace bundled: packages/cli/dist/index.js → packages/cli → packages/memory-service
|
|
21418
|
-
|
|
21619
|
+
join93(here, "..", "..", "memory-service"),
|
|
21419
21620
|
// 3. CWD fallback
|
|
21420
|
-
|
|
21621
|
+
join93(process.cwd(), "packages", "memory-service")
|
|
21421
21622
|
];
|
|
21422
21623
|
MEMORY_SERVICE_CANDIDATES = candidates;
|
|
21423
21624
|
}
|
|
@@ -21526,16 +21727,16 @@ __export(machine_schema_exports, {
|
|
|
21526
21727
|
readMachineConfig: () => readMachineConfig,
|
|
21527
21728
|
writeMachineConfig: () => writeMachineConfig
|
|
21528
21729
|
});
|
|
21529
|
-
import * as
|
|
21730
|
+
import * as fs86 from "node:fs";
|
|
21530
21731
|
import * as path86 from "node:path";
|
|
21531
21732
|
import * as os48 from "node:os";
|
|
21532
21733
|
import { parse as parseYaml8, stringify as stringifyYaml6 } from "yaml";
|
|
21533
21734
|
function readMachineConfig(configPath) {
|
|
21534
21735
|
const p = configPath ?? DEFAULT_CONFIG_PATH;
|
|
21535
|
-
if (!
|
|
21736
|
+
if (!fs86.existsSync(p))
|
|
21536
21737
|
return null;
|
|
21537
21738
|
try {
|
|
21538
|
-
const raw =
|
|
21739
|
+
const raw = fs86.readFileSync(p, "utf-8");
|
|
21539
21740
|
const parsed = parseYaml8(raw);
|
|
21540
21741
|
return MachineConfigSchema.parse(parsed);
|
|
21541
21742
|
} catch {
|
|
@@ -21544,8 +21745,8 @@ function readMachineConfig(configPath) {
|
|
|
21544
21745
|
}
|
|
21545
21746
|
function writeMachineConfig(config, configPath) {
|
|
21546
21747
|
const p = configPath ?? DEFAULT_CONFIG_PATH;
|
|
21547
|
-
|
|
21548
|
-
|
|
21748
|
+
fs86.mkdirSync(path86.dirname(p), { recursive: true });
|
|
21749
|
+
fs86.writeFileSync(p, stringifyYaml6({ ...config }), { mode: 420 });
|
|
21549
21750
|
}
|
|
21550
21751
|
function initMachineConfig(opts = {}) {
|
|
21551
21752
|
const configPath = opts.configPath ?? DEFAULT_CONFIG_PATH;
|
|
@@ -21671,7 +21872,7 @@ function registerWorkspace(program2) {
|
|
|
21671
21872
|
process.exitCode = 1;
|
|
21672
21873
|
}
|
|
21673
21874
|
});
|
|
21674
|
-
workspace.command("remove").description("Delete a workspace (does NOT touch worlds that already referenced it)").argument("<name>", "Workspace name").
|
|
21875
|
+
workspace.command("remove").description("Delete a workspace (does NOT touch worlds that already referenced it)").argument("<name>", "Workspace name").action((name) => {
|
|
21675
21876
|
try {
|
|
21676
21877
|
if (removeWorkspace(name)) {
|
|
21677
21878
|
printSuccess(`Removed workspace "${name}"`);
|
|
@@ -22040,7 +22241,7 @@ function runGlobalInit(opts) {
|
|
|
22040
22241
|
}
|
|
22041
22242
|
}
|
|
22042
22243
|
function registerInit(program2) {
|
|
22043
|
-
program2.command("init").description("Initialize olam in the current project or globally").option("--path <path>", "Project root path", process.cwd()).option("--skip-pleri", "
|
|
22244
|
+
program2.command("init").description("Initialize olam in the current project or globally").option("--path <path>", "Project root path", process.cwd()).option("--skip-pleri", "No-op (deprecated \u2014 PLERI is always optional; accepted for backward compat but has no effect)").option("--global", "Write only ~/.olam/config.json (global scope); skip per-repo .olam/config.yaml").option("--project", "Write .olam/config.yaml in the nearest git repo (per-repo scope; default when --global is absent)").option("--yes / -y", "Auto-affirm prompts (non-interactive)").action(async (opts) => {
|
|
22044
22245
|
if (opts.global) {
|
|
22045
22246
|
try {
|
|
22046
22247
|
const result = runGlobalInit({});
|
|
@@ -22594,7 +22795,7 @@ async function kubectlWrap(args, opts = {}) {
|
|
|
22594
22795
|
const spawnImpl = opts.spawnImpl ?? spawn4;
|
|
22595
22796
|
const stdout = [];
|
|
22596
22797
|
const stderr = [];
|
|
22597
|
-
return new Promise((
|
|
22798
|
+
return new Promise((resolve31) => {
|
|
22598
22799
|
let resolved = false;
|
|
22599
22800
|
let killTimer = null;
|
|
22600
22801
|
let sigkillTimer = null;
|
|
@@ -22609,7 +22810,7 @@ async function kubectlWrap(args, opts = {}) {
|
|
|
22609
22810
|
clearTimeout(sigkillTimer);
|
|
22610
22811
|
sigkillTimer = null;
|
|
22611
22812
|
}
|
|
22612
|
-
|
|
22813
|
+
resolve31(r);
|
|
22613
22814
|
}
|
|
22614
22815
|
let child;
|
|
22615
22816
|
try {
|
|
@@ -22618,7 +22819,7 @@ async function kubectlWrap(args, opts = {}) {
|
|
|
22618
22819
|
env: { ...process.env, ...opts.env ?? {} }
|
|
22619
22820
|
});
|
|
22620
22821
|
} catch (err) {
|
|
22621
|
-
|
|
22822
|
+
resolve31({
|
|
22622
22823
|
ok: false,
|
|
22623
22824
|
stdout: "",
|
|
22624
22825
|
stderr: err instanceof Error ? err.message : String(err),
|
|
@@ -23134,7 +23335,7 @@ function runLiveTask(label, cmd, args, opts) {
|
|
|
23134
23335
|
const startMs = Date.now();
|
|
23135
23336
|
const settle = opts.settle ?? "auto";
|
|
23136
23337
|
const useSpinner = !opts.verbose && Boolean(process.stdout.isTTY);
|
|
23137
|
-
return new Promise((
|
|
23338
|
+
return new Promise((resolve31) => {
|
|
23138
23339
|
const child = spawn5(cmd, [...args], {
|
|
23139
23340
|
env: opts.env ?? process.env,
|
|
23140
23341
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -23198,7 +23399,7 @@ function runLiveTask(label, cmd, args, opts) {
|
|
|
23198
23399
|
);
|
|
23199
23400
|
}
|
|
23200
23401
|
}
|
|
23201
|
-
|
|
23402
|
+
resolve31({ ok, exitCode: code, durationMs, logPath });
|
|
23202
23403
|
};
|
|
23203
23404
|
child.on("error", (err) => {
|
|
23204
23405
|
chunks.push(`
|
|
@@ -24388,10 +24589,10 @@ async function confirm(message) {
|
|
|
24388
24589
|
if (!process.stdin.isTTY) return true;
|
|
24389
24590
|
const { createInterface: createInterface12 } = await import("node:readline");
|
|
24390
24591
|
const rl = createInterface12({ input: process.stdin, output: process.stdout });
|
|
24391
|
-
return new Promise((
|
|
24592
|
+
return new Promise((resolve31) => {
|
|
24392
24593
|
rl.question(`${message} [y/N] `, (answer) => {
|
|
24393
24594
|
rl.close();
|
|
24394
|
-
|
|
24595
|
+
resolve31(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
24395
24596
|
});
|
|
24396
24597
|
});
|
|
24397
24598
|
}
|
|
@@ -24863,7 +25064,7 @@ var KgServiceContainerController = class {
|
|
|
24863
25064
|
}
|
|
24864
25065
|
};
|
|
24865
25066
|
function sleep4(ms) {
|
|
24866
|
-
return new Promise((
|
|
25067
|
+
return new Promise((resolve31) => setTimeout(resolve31, ms));
|
|
24867
25068
|
}
|
|
24868
25069
|
|
|
24869
25070
|
// src/commands/memory-service-container.ts
|
|
@@ -25086,7 +25287,7 @@ var MemoryServiceContainerController = class {
|
|
|
25086
25287
|
}
|
|
25087
25288
|
};
|
|
25088
25289
|
function sleep5(ms) {
|
|
25089
|
-
return new Promise((
|
|
25290
|
+
return new Promise((resolve31) => setTimeout(resolve31, ms));
|
|
25090
25291
|
}
|
|
25091
25292
|
|
|
25092
25293
|
// src/lib/peripheral-registry.ts
|
|
@@ -25681,7 +25882,7 @@ var McpAuthContainerController = class {
|
|
|
25681
25882
|
}
|
|
25682
25883
|
};
|
|
25683
25884
|
function sleep6(ms) {
|
|
25684
|
-
return new Promise((
|
|
25885
|
+
return new Promise((resolve31) => setTimeout(resolve31, ms));
|
|
25685
25886
|
}
|
|
25686
25887
|
var K8S_NAMESPACE2 = "olam";
|
|
25687
25888
|
function assertK8sContext(configPath) {
|
|
@@ -26287,14 +26488,14 @@ async function probePortForwardLiveness(deps = {}) {
|
|
|
26287
26488
|
return probe2("127.0.0.1", PORT_FORWARD_PORT, TCP_PROBE_TIMEOUT_MS);
|
|
26288
26489
|
}
|
|
26289
26490
|
function realTcpProbe(host, port2, timeoutMs) {
|
|
26290
|
-
return new Promise((
|
|
26491
|
+
return new Promise((resolve31) => {
|
|
26291
26492
|
const socket = new net3.Socket();
|
|
26292
26493
|
let done = false;
|
|
26293
26494
|
function finish(result) {
|
|
26294
26495
|
if (done) return;
|
|
26295
26496
|
done = true;
|
|
26296
26497
|
socket.destroy();
|
|
26297
|
-
|
|
26498
|
+
resolve31(result);
|
|
26298
26499
|
}
|
|
26299
26500
|
const timer = setTimeout(() => finish(false), timeoutMs);
|
|
26300
26501
|
socket.once("connect", () => {
|
|
@@ -26632,12 +26833,12 @@ function appendAuditEntry(entry, auditLogPath, writeFileSyncImpl) {
|
|
|
26632
26833
|
async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, peripheral) {
|
|
26633
26834
|
const auditLogPath = deps.auditLogPath ?? MANIFEST_REFRESH_AUDIT_LOG;
|
|
26634
26835
|
const readdirSync34 = deps.readdirSync ?? fs35.readdirSync;
|
|
26635
|
-
const
|
|
26836
|
+
const readFileSync110 = deps.readFileSync ?? fs35.readFileSync;
|
|
26636
26837
|
const writeFileSyncImpl = deps.writeFileSync ?? fs35.writeFileSync;
|
|
26637
|
-
const
|
|
26838
|
+
const existsSync122 = deps.existsSync ?? fs35.existsSync;
|
|
26638
26839
|
const now = deps.now ? deps.now() : /* @__PURE__ */ new Date();
|
|
26639
26840
|
const targetDir = peripheral ? path36.join(manifestsDir, peripheral) : manifestsDir;
|
|
26640
|
-
if (!
|
|
26841
|
+
if (!existsSync122(targetDir)) {
|
|
26641
26842
|
return {
|
|
26642
26843
|
ok: false,
|
|
26643
26844
|
message: peripheral ? `peripheral manifests directory not found: ${targetDir}` : `manifests directory not found: ${targetDir}`
|
|
@@ -26658,7 +26859,7 @@ async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, per
|
|
|
26658
26859
|
const filePath = path36.join(targetDir, file);
|
|
26659
26860
|
let content;
|
|
26660
26861
|
try {
|
|
26661
|
-
content =
|
|
26862
|
+
content = readFileSync110(filePath, "utf8");
|
|
26662
26863
|
} catch {
|
|
26663
26864
|
continue;
|
|
26664
26865
|
}
|
|
@@ -26914,11 +27115,11 @@ async function checkSecretPreCondition(context, deps) {
|
|
|
26914
27115
|
}
|
|
26915
27116
|
async function applyConfigMapSubstitution(context, manifestsDir, deps) {
|
|
26916
27117
|
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
26917
|
-
const
|
|
27118
|
+
const readFileSync110 = deps.readFileSyncImpl ?? fs36.readFileSync;
|
|
26918
27119
|
const configMapPath = path37.join(manifestsDir, "30-configmap.yaml");
|
|
26919
27120
|
let rawYaml;
|
|
26920
27121
|
try {
|
|
26921
|
-
rawYaml =
|
|
27122
|
+
rawYaml = readFileSync110(configMapPath, "utf8");
|
|
26922
27123
|
} catch (err) {
|
|
26923
27124
|
return `Failed to read ConfigMap at ${configMapPath}: ${err instanceof Error ? err.message : String(err)}`;
|
|
26924
27125
|
}
|
|
@@ -28193,10 +28394,10 @@ function emptyMigrationState() {
|
|
|
28193
28394
|
return { version: 1, migrated: {} };
|
|
28194
28395
|
}
|
|
28195
28396
|
function readMigrationState(statePath, deps) {
|
|
28196
|
-
const
|
|
28197
|
-
const
|
|
28198
|
-
if (!
|
|
28199
|
-
const raw =
|
|
28397
|
+
const existsSync122 = deps.existsSync ?? fs40.existsSync;
|
|
28398
|
+
const readFileSync110 = deps.readFileSync ?? ((p) => fs40.readFileSync(p, "utf-8"));
|
|
28399
|
+
if (!existsSync122(statePath)) return emptyMigrationState();
|
|
28400
|
+
const raw = readFileSync110(statePath);
|
|
28200
28401
|
let parsed;
|
|
28201
28402
|
try {
|
|
28202
28403
|
parsed = JSON.parse(raw);
|
|
@@ -28213,17 +28414,17 @@ function readMigrationState(statePath, deps) {
|
|
|
28213
28414
|
return parsed;
|
|
28214
28415
|
}
|
|
28215
28416
|
function writeMigrationStateAtomic(statePath, state, deps) {
|
|
28216
|
-
const
|
|
28417
|
+
const writeFileSync67 = deps.writeFileSync ?? ((p, d) => fs40.writeFileSync(p, d, "utf-8"));
|
|
28217
28418
|
const renameSync21 = deps.renameSync ?? fs40.renameSync;
|
|
28218
28419
|
const tmpPath = `${statePath}.tmp`;
|
|
28219
|
-
|
|
28420
|
+
writeFileSync67(tmpPath, JSON.stringify(state, null, 2) + "\n");
|
|
28220
28421
|
renameSync21(tmpPath, statePath);
|
|
28221
28422
|
}
|
|
28222
28423
|
function readLocalAccounts(accountsPath, deps) {
|
|
28223
|
-
const
|
|
28224
|
-
const
|
|
28225
|
-
if (!
|
|
28226
|
-
const raw =
|
|
28424
|
+
const existsSync122 = deps.existsSync ?? fs40.existsSync;
|
|
28425
|
+
const readFileSync110 = deps.readFileSync ?? ((p) => fs40.readFileSync(p, "utf-8"));
|
|
28426
|
+
if (!existsSync122(accountsPath)) return null;
|
|
28427
|
+
const raw = readFileSync110(accountsPath);
|
|
28227
28428
|
let parsed;
|
|
28228
28429
|
try {
|
|
28229
28430
|
parsed = JSON.parse(raw);
|
|
@@ -29108,18 +29309,31 @@ ${pc13.dim("Tip: set ANTHROPIC_BASE_URL=" + baseUrl.replace(/\/+$/, "") + "/v1/p
|
|
|
29108
29309
|
auth.command("revoke-anthropic-token").description("Revoke an Anthropic proxy token on the remote auth-worker (g4)").requiredOption("--remote <url>", "Auth-worker base URL").requiredOption("--token-hash <hash>", "Token hash to revoke (from issue or list output)").action(async (opts) => {
|
|
29109
29310
|
const baseUrl = opts.remote;
|
|
29110
29311
|
printHeader("Auth worker \u2014 revoke Anthropic proxy token");
|
|
29111
|
-
|
|
29312
|
+
const serviceToken = resolveCfAccessServiceToken();
|
|
29313
|
+
let remoteOpts;
|
|
29314
|
+
if (serviceToken) {
|
|
29315
|
+
console.log(`
|
|
29316
|
+
${pc13.dim("Using CF Access service token (machine-to-machine; no cookie needed).")}`);
|
|
29317
|
+
remoteOpts = {
|
|
29318
|
+
baseUrl,
|
|
29319
|
+
cfAccessClientId: serviceToken.clientId,
|
|
29320
|
+
cfAccessClientSecret: serviceToken.clientSecret
|
|
29321
|
+
};
|
|
29322
|
+
} else {
|
|
29323
|
+
console.log(`
|
|
29112
29324
|
Open ${pc13.cyan(baseUrl.replace(/\/+$/, "") + "/v1/oauth/start")} in a browser to authenticate via CF Access SSO.`);
|
|
29113
|
-
|
|
29325
|
+
console.log(` Once you've completed SSO, paste your CF_Authorization cookie below.
|
|
29114
29326
|
`);
|
|
29115
|
-
|
|
29116
|
-
|
|
29117
|
-
|
|
29118
|
-
|
|
29119
|
-
|
|
29327
|
+
const rawCookie = await promptLine(` ${pc13.dim("CF_Authorization cookie:")} `);
|
|
29328
|
+
if (!rawCookie) {
|
|
29329
|
+
printError("No cookie provided. Aborting.");
|
|
29330
|
+
process.exitCode = 1;
|
|
29331
|
+
return;
|
|
29332
|
+
}
|
|
29333
|
+
remoteOpts = { baseUrl, cfAuthCookie: rawCookie };
|
|
29120
29334
|
}
|
|
29121
29335
|
try {
|
|
29122
|
-
const revoked = await remoteRevokeAnthropicToken(
|
|
29336
|
+
const revoked = await remoteRevokeAnthropicToken(remoteOpts, opts.tokenHash);
|
|
29123
29337
|
if (revoked) {
|
|
29124
29338
|
printSuccess(`Token ${opts.tokenHash} revoked.`);
|
|
29125
29339
|
} else {
|
|
@@ -31411,6 +31625,7 @@ Top-level commands (run \`olam <command> --help\` for flags and subcommands):
|
|
|
31411
31625
|
- \`olam enter\` \u2014 Open terminal to a world
|
|
31412
31626
|
- \`olam evict\` \u2014 Evict oldest snapshots until total size \u2264 cap (default 5GB; override via OLAM_SNAPSHOT_MAX_BYTES)
|
|
31413
31627
|
- \`olam get\` \u2014 Print the active substrate
|
|
31628
|
+
- \`olam graph\` \u2014 Query the cross-repo graph: locate a symbol, its relationships, or browse a repo (POST /v1/graph)
|
|
31414
31629
|
- \`olam hermes\` \u2014 Hermes integration commands
|
|
31415
31630
|
- \`olam host-cp\` \u2014 Manage the Olam host control plane container
|
|
31416
31631
|
- \`olam implode\` \u2014 Destroy ALL local olam install and configs (dry-run by default)
|
|
@@ -31418,6 +31633,7 @@ Top-level commands (run \`olam <command> --help\` for flags and subcommands):
|
|
|
31418
31633
|
- \`olam inspect\` \u2014 Diagnose warm-create cache hits/misses for a workspace (read-only; mutates nothing)
|
|
31419
31634
|
- \`olam install\` \u2014 Pick an archetype preset for this Olam install
|
|
31420
31635
|
- \`olam install-hook\` \u2014 Install kg-service hook (idempotent). --for hermes targets ~/.hermes/; default targets .claude/settings.json
|
|
31636
|
+
- \`olam install-model-router\` \u2014 Deploy the model-router.py UserPromptSubmit hook script to ~/.claude/hooks/ (idempotent; auto-run by
|
|
31421
31637
|
- \`olam issue-anthropic-token\` \u2014 Mint a new Anthropic proxy token via the remote auth-worker (g4)
|
|
31422
31638
|
- \`olam keys\` \u2014 Manage LLM API keys stored at ~/.olam/keys.yaml
|
|
31423
31639
|
- \`olam kg\` \u2014 Knowledge-graph operations (kg-service container)
|
|
@@ -31472,7 +31688,7 @@ Top-level commands (run \`olam <command> --help\` for flags and subcommands):
|
|
|
31472
31688
|
- \`olam substrate\` \u2014 Manage deployment substrate (beta)
|
|
31473
31689
|
- \`olam sync\` \u2014 Sync registered skill sources to ~/.claude/
|
|
31474
31690
|
- \`olam tls-install\` \u2014 Provision a locally-trusted TLS cert (mkcert) for the Traefik IngressRoute
|
|
31475
|
-
- \`olam uninstall\` \u2014 Remove /
|
|
31691
|
+
- \`olam uninstall\` \u2014 Remove /100x: chain skill symlinks from ~/.claude/skills (preserves user-authored skills + non-chain skill sources)
|
|
31476
31692
|
- \`olam uninstall-hook\` \u2014 Remove kg-service PreToolUse hook from .claude/settings.json (sentinel-matched; surgical)
|
|
31477
31693
|
- \`olam unset-prefix\` \u2014 Remove the deploy prefix from a registered skill source (reverts to canonical deploy names)
|
|
31478
31694
|
- \`olam unset-prefix-scope\` \u2014 Remove the prefix-scope override from a registered skill source (reverts to default: both skill and agent are renamed)
|
|
@@ -31678,12 +31894,12 @@ async function runRepl(deps = {}) {
|
|
|
31678
31894
|
closed = true;
|
|
31679
31895
|
onClose?.();
|
|
31680
31896
|
});
|
|
31681
|
-
const ask = () => new Promise((
|
|
31682
|
-
if (closed) return
|
|
31683
|
-
onClose = () =>
|
|
31897
|
+
const ask = () => new Promise((resolve31) => {
|
|
31898
|
+
if (closed) return resolve31(null);
|
|
31899
|
+
onClose = () => resolve31(null);
|
|
31684
31900
|
rl.question(pc14.cyan("olam ask> "), (line) => {
|
|
31685
31901
|
onClose = null;
|
|
31686
|
-
|
|
31902
|
+
resolve31(line);
|
|
31687
31903
|
});
|
|
31688
31904
|
});
|
|
31689
31905
|
try {
|
|
@@ -32221,15 +32437,15 @@ var AGENTMEMORY_LOCAL_URL = "http://host.docker.internal:3111";
|
|
|
32221
32437
|
var HOST_CP_URL = "http://127.0.0.1:19000";
|
|
32222
32438
|
async function readHostCpTokenForCreate() {
|
|
32223
32439
|
try {
|
|
32224
|
-
const { default:
|
|
32440
|
+
const { default: fs108 } = await import("node:fs");
|
|
32225
32441
|
const { default: os60 } = await import("node:os");
|
|
32226
32442
|
const { default: path106 } = await import("node:path");
|
|
32227
32443
|
const tp = path106.join(
|
|
32228
32444
|
process.env.OLAM_HOME ?? path106.join(os60.homedir(), ".olam"),
|
|
32229
32445
|
"host-cp.token"
|
|
32230
32446
|
);
|
|
32231
|
-
if (!
|
|
32232
|
-
return
|
|
32447
|
+
if (!fs108.existsSync(tp)) return null;
|
|
32448
|
+
return fs108.readFileSync(tp, "utf-8").trim();
|
|
32233
32449
|
} catch {
|
|
32234
32450
|
return null;
|
|
32235
32451
|
}
|
|
@@ -32241,7 +32457,7 @@ function registerCreate(program2) {
|
|
|
32241
32457
|
).option("--devbox-image <ref>", "Override the default devbox image (full registry/name:tag or @sha256: ref)").option("--allow-custom-registry", "Allow --devbox-image refs outside ghcr.io/pleri/* (logs a warning)").option("--runbook <name>", "Named runbook profile from ~/.olam/config.json").option(
|
|
32242
32458
|
"--claude-home <id-or-path>",
|
|
32243
32459
|
"Use a per-world Claude Code HOME (multi-account isolation; see docs/decisions/045-claude-home-override.md)"
|
|
32244
|
-
).action(async (opts) => {
|
|
32460
|
+
).option("--json", "Emit machine-readable JSON on success (suppresses interactive hints)").action(async (opts) => {
|
|
32245
32461
|
const { resolveDevboxImageOverride: resolveDevboxImageOverride2, decideAllowlist: decideAllowlist2 } = await Promise.resolve().then(() => (init_registry_allowlist(), registry_allowlist_exports));
|
|
32246
32462
|
const overrideRef = resolveDevboxImageOverride2(opts.devboxImage);
|
|
32247
32463
|
if (overrideRef) {
|
|
@@ -32729,12 +32945,12 @@ function defaultNameFromPrompt(prompt) {
|
|
|
32729
32945
|
}
|
|
32730
32946
|
async function readHostCpToken3() {
|
|
32731
32947
|
try {
|
|
32732
|
-
const { default:
|
|
32948
|
+
const { default: fs108 } = await import("node:fs");
|
|
32733
32949
|
const { default: os60 } = await import("node:os");
|
|
32734
32950
|
const { default: path106 } = await import("node:path");
|
|
32735
32951
|
const tp = path106.join(os60.homedir(), ".olam", "host-cp.token");
|
|
32736
|
-
if (!
|
|
32737
|
-
const raw =
|
|
32952
|
+
if (!fs108.existsSync(tp)) return null;
|
|
32953
|
+
const raw = fs108.readFileSync(tp, "utf-8").trim();
|
|
32738
32954
|
return raw.length > 0 ? raw : null;
|
|
32739
32955
|
} catch {
|
|
32740
32956
|
return null;
|
|
@@ -33108,7 +33324,7 @@ function parseRuntimeStatus(raw) {
|
|
|
33108
33324
|
last_event_age_seconds
|
|
33109
33325
|
};
|
|
33110
33326
|
}
|
|
33111
|
-
var fetchWorldRuntimeStatus = (worldId, token) => new Promise((
|
|
33327
|
+
var fetchWorldRuntimeStatus = (worldId, token) => new Promise((resolve31) => {
|
|
33112
33328
|
const opts = {
|
|
33113
33329
|
host: "127.0.0.1",
|
|
33114
33330
|
port: HOST_CP_PORT2,
|
|
@@ -33120,7 +33336,7 @@ var fetchWorldRuntimeStatus = (worldId, token) => new Promise((resolve30) => {
|
|
|
33120
33336
|
const req = http3.request(opts, (res) => {
|
|
33121
33337
|
if (res.statusCode !== 200) {
|
|
33122
33338
|
res.resume();
|
|
33123
|
-
return
|
|
33339
|
+
return resolve31(null);
|
|
33124
33340
|
}
|
|
33125
33341
|
let body = "";
|
|
33126
33342
|
res.setEncoding("utf-8");
|
|
@@ -33130,17 +33346,17 @@ var fetchWorldRuntimeStatus = (worldId, token) => new Promise((resolve30) => {
|
|
|
33130
33346
|
res.on("end", () => {
|
|
33131
33347
|
try {
|
|
33132
33348
|
const parsed = parseRuntimeStatus(JSON.parse(body));
|
|
33133
|
-
|
|
33349
|
+
resolve31(parsed);
|
|
33134
33350
|
} catch {
|
|
33135
|
-
|
|
33351
|
+
resolve31(null);
|
|
33136
33352
|
}
|
|
33137
33353
|
});
|
|
33138
|
-
res.on("error", () =>
|
|
33354
|
+
res.on("error", () => resolve31(null));
|
|
33139
33355
|
});
|
|
33140
|
-
req.on("error", () =>
|
|
33356
|
+
req.on("error", () => resolve31(null));
|
|
33141
33357
|
req.on("timeout", () => {
|
|
33142
33358
|
req.destroy();
|
|
33143
|
-
|
|
33359
|
+
resolve31(null);
|
|
33144
33360
|
});
|
|
33145
33361
|
req.end();
|
|
33146
33362
|
});
|
|
@@ -33196,7 +33412,7 @@ async function getMachineStatus(_probe, _loadCtx, _readToken) {
|
|
|
33196
33412
|
};
|
|
33197
33413
|
}
|
|
33198
33414
|
function registerStatus(program2) {
|
|
33199
|
-
program2.command("status").description("Show machine status, or world details when a world ID is given").argument("[world]", "World ID \u2014 omit to show machine status").option("--json", "Output as JSON").
|
|
33415
|
+
program2.command("status").description("Show machine status, or world details when a world ID is given").argument("[world]", "World ID \u2014 omit to show machine status").option("--json", "Output as JSON").action(async (worldId, opts) => {
|
|
33200
33416
|
if (!worldId) {
|
|
33201
33417
|
const ms = await getMachineStatus();
|
|
33202
33418
|
if (opts.json) {
|
|
@@ -33330,12 +33546,12 @@ async function readlineConfirm(world) {
|
|
|
33330
33546
|
|
|
33331
33547
|
`
|
|
33332
33548
|
);
|
|
33333
|
-
return new Promise((
|
|
33549
|
+
return new Promise((resolve31) => {
|
|
33334
33550
|
rl.question(
|
|
33335
33551
|
`Destroy ${pc20.bold(world.name)}? This cannot be undone. [y/N] `,
|
|
33336
33552
|
(answer) => {
|
|
33337
33553
|
rl.close();
|
|
33338
|
-
|
|
33554
|
+
resolve31(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
33339
33555
|
}
|
|
33340
33556
|
);
|
|
33341
33557
|
});
|
|
@@ -33690,14 +33906,14 @@ function printTable(entries) {
|
|
|
33690
33906
|
async function confirmInteractive() {
|
|
33691
33907
|
process.stdout.write(" Type `yes` to proceed: ");
|
|
33692
33908
|
const buf = [];
|
|
33693
|
-
return new Promise((
|
|
33909
|
+
return new Promise((resolve31) => {
|
|
33694
33910
|
const onData = (chunk) => {
|
|
33695
33911
|
buf.push(chunk);
|
|
33696
33912
|
if (Buffer.concat(buf).toString("utf-8").includes("\n")) {
|
|
33697
33913
|
process.stdin.removeListener("data", onData);
|
|
33698
33914
|
process.stdin.pause();
|
|
33699
33915
|
const answer = Buffer.concat(buf).toString("utf-8").trim();
|
|
33700
|
-
|
|
33916
|
+
resolve31(answer.toLowerCase() === "yes");
|
|
33701
33917
|
}
|
|
33702
33918
|
};
|
|
33703
33919
|
process.stdin.resume();
|
|
@@ -39893,10 +40109,10 @@ async function confirm2(message) {
|
|
|
39893
40109
|
if (!process.stdin.isTTY) return true;
|
|
39894
40110
|
const { createInterface: createInterface12 } = await import("node:readline");
|
|
39895
40111
|
const rl = createInterface12({ input: process.stdin, output: process.stdout });
|
|
39896
|
-
return new Promise((
|
|
40112
|
+
return new Promise((resolve31) => {
|
|
39897
40113
|
rl.question(`${message} [y/N] `, (answer) => {
|
|
39898
40114
|
rl.close();
|
|
39899
|
-
|
|
40115
|
+
resolve31(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
39900
40116
|
});
|
|
39901
40117
|
});
|
|
39902
40118
|
}
|
|
@@ -41140,7 +41356,15 @@ function registerPs(program2) {
|
|
|
41140
41356
|
process.exitCode = 1;
|
|
41141
41357
|
return;
|
|
41142
41358
|
}
|
|
41143
|
-
const
|
|
41359
|
+
const VALID_SORT_KEYS = ["cpu", "mem", "pid"];
|
|
41360
|
+
if (!VALID_SORT_KEYS.includes(opts.sort)) {
|
|
41361
|
+
printError(
|
|
41362
|
+
`Invalid --sort key "${opts.sort}". Valid values: ${VALID_SORT_KEYS.join(", ")}.`
|
|
41363
|
+
);
|
|
41364
|
+
process.exitCode = 1;
|
|
41365
|
+
return;
|
|
41366
|
+
}
|
|
41367
|
+
const sortKey = opts.sort;
|
|
41144
41368
|
const containerName = `olam-${worldId}-devbox`;
|
|
41145
41369
|
let watchInterval;
|
|
41146
41370
|
function fetchAndPrint() {
|
|
@@ -41880,7 +42104,7 @@ async function refreshWorld(worldId, portOffset, standaloneDir, opts) {
|
|
|
41880
42104
|
return { worldId, ok: true };
|
|
41881
42105
|
}
|
|
41882
42106
|
function registerRefresh(program2) {
|
|
41883
|
-
program2.command("refresh").description("Hot-refresh a running world's per-world CP
|
|
42107
|
+
program2.command("refresh").description("Hot-refresh a running world's per-world container-CP bundle (packages/control-plane/standalone/ \u2014 legacy per-world CP surface)").argument("[world]", "World ID").option("--all", "Refresh every running world sequentially (overrides positional arg)").option("--no-restart", "Copy files but skip CP restart (for debugging)").option("--skip-build", "Skip the prerequisite server.mjs presence check").action(async (worldId, opts) => {
|
|
41884
42108
|
if (!opts.all && !worldId) {
|
|
41885
42109
|
printError("Specify a world ID or use --all to refresh all running worlds.");
|
|
41886
42110
|
process.exitCode = 1;
|
|
@@ -42566,7 +42790,7 @@ async function runPeripheralProbes(peripheral, startPosition, kubectlContext, wr
|
|
|
42566
42790
|
})();
|
|
42567
42791
|
rows.push({ name: `${peripheral.name} ready`, result: reachableResult, position: startPosition });
|
|
42568
42792
|
const pfLivenessResult = await (async () => {
|
|
42569
|
-
return new Promise((
|
|
42793
|
+
return new Promise((resolve31) => {
|
|
42570
42794
|
const socket = new net4.Socket();
|
|
42571
42795
|
let done = false;
|
|
42572
42796
|
const finish = (alive) => {
|
|
@@ -42574,9 +42798,9 @@ async function runPeripheralProbes(peripheral, startPosition, kubectlContext, wr
|
|
|
42574
42798
|
done = true;
|
|
42575
42799
|
socket.destroy();
|
|
42576
42800
|
if (alive) {
|
|
42577
|
-
|
|
42801
|
+
resolve31({ ok: true, message: `${peripheral.name} port-forward live on :${peripheral.port}` });
|
|
42578
42802
|
} else {
|
|
42579
|
-
|
|
42803
|
+
resolve31({
|
|
42580
42804
|
ok: true,
|
|
42581
42805
|
warn: true,
|
|
42582
42806
|
message: `${peripheral.name} port-forward not live on :${peripheral.port}`,
|
|
@@ -43804,8 +44028,8 @@ function registerCompletion(program2) {
|
|
|
43804
44028
|
init_cli_version();
|
|
43805
44029
|
init_health_probes();
|
|
43806
44030
|
import { spawn as spawn8, spawnSync as spawnSync29 } from "node:child_process";
|
|
43807
|
-
import { existsSync as
|
|
43808
|
-
import { homedir as
|
|
44031
|
+
import { existsSync as existsSync92, readFileSync as readFileSync80 } from "node:fs";
|
|
44032
|
+
import { homedir as homedir54 } from "node:os";
|
|
43809
44033
|
import path84 from "node:path";
|
|
43810
44034
|
import { createInterface as createInterface5 } from "node:readline";
|
|
43811
44035
|
|
|
@@ -44052,9 +44276,9 @@ async function pickSkillSourcePhase(opts, deps) {
|
|
|
44052
44276
|
}
|
|
44053
44277
|
|
|
44054
44278
|
// src/commands/setup-phase-5b-project-sweep.ts
|
|
44055
|
-
import { homedir as
|
|
44279
|
+
import { homedir as homedir51 } from "node:os";
|
|
44056
44280
|
import * as path82 from "node:path";
|
|
44057
|
-
import * as
|
|
44281
|
+
import * as fs83 from "node:fs";
|
|
44058
44282
|
async function loadWalkFn() {
|
|
44059
44283
|
const m = await Promise.resolve().then(() => (init_project_sweep(), project_sweep_exports));
|
|
44060
44284
|
return m.walkProjectRoot;
|
|
@@ -44085,9 +44309,9 @@ async function runProjectSweepPhase(opts, deps, sweepDeps = {}) {
|
|
|
44085
44309
|
if (opts.skipProjectSweep) {
|
|
44086
44310
|
return { ok: true, skipped: true, message: "skipped via --skip-project-sweep" };
|
|
44087
44311
|
}
|
|
44088
|
-
const home = deps.home ??
|
|
44312
|
+
const home = deps.home ?? homedir51();
|
|
44089
44313
|
const projectsRoot = opts.projects ?? path82.join(home, "Projects");
|
|
44090
|
-
const existsSyncFn = sweepDeps.existsSync ??
|
|
44314
|
+
const existsSyncFn = sweepDeps.existsSync ?? fs83.existsSync;
|
|
44091
44315
|
if (!existsSyncFn(projectsRoot)) {
|
|
44092
44316
|
return {
|
|
44093
44317
|
ok: true,
|
|
@@ -44188,7 +44412,7 @@ async function runProjectSweepPhase(opts, deps, sweepDeps = {}) {
|
|
|
44188
44412
|
}
|
|
44189
44413
|
|
|
44190
44414
|
// src/commands/setup-phase-8-kg-hook.ts
|
|
44191
|
-
import * as
|
|
44415
|
+
import * as fs84 from "node:fs";
|
|
44192
44416
|
import * as path83 from "node:path";
|
|
44193
44417
|
import * as os47 from "node:os";
|
|
44194
44418
|
async function loadMergeHookFn() {
|
|
@@ -44218,7 +44442,7 @@ async function runKgHookPhase(opts, _deps, kgDeps = {}) {
|
|
|
44218
44442
|
message: `dry-run: would install KG hook into ${settingsPath}`
|
|
44219
44443
|
};
|
|
44220
44444
|
}
|
|
44221
|
-
const mkdirFn = kgDeps.mkdirSync ?? ((p, o) =>
|
|
44445
|
+
const mkdirFn = kgDeps.mkdirSync ?? ((p, o) => fs84.mkdirSync(p, o));
|
|
44222
44446
|
try {
|
|
44223
44447
|
mkdirFn(path83.dirname(settingsPath), { recursive: true });
|
|
44224
44448
|
} catch (err) {
|
|
@@ -44306,10 +44530,10 @@ var NEXT_STEPS_DOCS_KUBERNETES = [
|
|
|
44306
44530
|
"https://github.com/pleri/olam/blob/main/docs/architecture/config-spec.md \u2014 workspace .olam/config.yaml schema",
|
|
44307
44531
|
"https://github.com/pleri/olam/blob/main/docs/k8s/SETUP.md \u2014 k3d operator guide"
|
|
44308
44532
|
];
|
|
44309
|
-
var defaultSpawn2 = (cmd, args) => new Promise((
|
|
44533
|
+
var defaultSpawn2 = (cmd, args) => new Promise((resolve31) => {
|
|
44310
44534
|
const child = spawn8(cmd, [...args], { stdio: "inherit" });
|
|
44311
|
-
child.on("exit", (code) =>
|
|
44312
|
-
child.on("error", () =>
|
|
44535
|
+
child.on("exit", (code) => resolve31({ status: code }));
|
|
44536
|
+
child.on("error", () => resolve31({ status: 1 }));
|
|
44313
44537
|
});
|
|
44314
44538
|
var defaultPrompt = (question, defaultYes) => {
|
|
44315
44539
|
if (!process.stdin.isTTY) {
|
|
@@ -44319,18 +44543,18 @@ var defaultPrompt = (question, defaultYes) => {
|
|
|
44319
44543
|
);
|
|
44320
44544
|
return Promise.resolve(defaultYes);
|
|
44321
44545
|
}
|
|
44322
|
-
return new Promise((
|
|
44546
|
+
return new Promise((resolve31) => {
|
|
44323
44547
|
const rl = createInterface5({ input: process.stdin, output: process.stdout });
|
|
44324
44548
|
const suffix = defaultYes ? " [Y/n]: " : " [y/N]: ";
|
|
44325
44549
|
rl.question(`${question}${suffix}`, (answer) => {
|
|
44326
44550
|
rl.close();
|
|
44327
44551
|
const t = answer.trim().toLowerCase();
|
|
44328
|
-
if (t === "")
|
|
44329
|
-
else if (t === "y" || t === "yes")
|
|
44330
|
-
else if (t === "n" || t === "no")
|
|
44331
|
-
else
|
|
44552
|
+
if (t === "") resolve31(defaultYes);
|
|
44553
|
+
else if (t === "y" || t === "yes") resolve31(true);
|
|
44554
|
+
else if (t === "n" || t === "no") resolve31(false);
|
|
44555
|
+
else resolve31(defaultYes);
|
|
44332
44556
|
});
|
|
44333
|
-
rl.on("close", () =>
|
|
44557
|
+
rl.on("close", () => resolve31(defaultYes));
|
|
44334
44558
|
});
|
|
44335
44559
|
};
|
|
44336
44560
|
var CLUSTER_NAME_RE = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
@@ -44350,9 +44574,9 @@ function resolveSubstrate(opts, deps) {
|
|
|
44350
44574
|
if (opts.substrate === "kubernetes") return "kubernetes";
|
|
44351
44575
|
if (opts.substrate === "docker") return "docker";
|
|
44352
44576
|
const configPath = deps.configPath ?? OLAM_CONFIG_PATH;
|
|
44353
|
-
if (
|
|
44577
|
+
if (existsSync92(configPath)) {
|
|
44354
44578
|
try {
|
|
44355
|
-
const raw =
|
|
44579
|
+
const raw = readFileSync80(configPath, "utf8");
|
|
44356
44580
|
const parsed = JSON.parse(raw);
|
|
44357
44581
|
const host = parsed.host;
|
|
44358
44582
|
if (host?.substrate === "kubernetes") return "kubernetes";
|
|
@@ -44419,9 +44643,9 @@ async function phase0SubstratePicker(opts, deps) {
|
|
|
44419
44643
|
return { ok: true, skipped: true, message: "skipped via --skip-substrate-picker" };
|
|
44420
44644
|
}
|
|
44421
44645
|
const configPath = deps.configPath ?? OLAM_CONFIG_PATH;
|
|
44422
|
-
if (
|
|
44646
|
+
if (existsSync92(configPath)) {
|
|
44423
44647
|
try {
|
|
44424
|
-
const raw =
|
|
44648
|
+
const raw = readFileSync80(configPath, "utf8");
|
|
44425
44649
|
const parsed = JSON.parse(raw);
|
|
44426
44650
|
const host = parsed.host;
|
|
44427
44651
|
if (host?.substrate !== void 0 && host?.preferred_runtime !== void 0) {
|
|
@@ -44471,9 +44695,9 @@ async function phase0SubstratePicker(opts, deps) {
|
|
|
44471
44695
|
const choice = SUBSTRATE_CHOICES[Number(pickedIndex)] ?? DEFAULT_SUBSTRATE_CHOICE;
|
|
44472
44696
|
if (choice.requirePinnedContext) {
|
|
44473
44697
|
let hasPinnedContext = false;
|
|
44474
|
-
if (
|
|
44698
|
+
if (existsSync92(configPath)) {
|
|
44475
44699
|
try {
|
|
44476
|
-
const raw =
|
|
44700
|
+
const raw = readFileSync80(configPath, "utf8");
|
|
44477
44701
|
const parsed = JSON.parse(raw);
|
|
44478
44702
|
const host = parsed.host;
|
|
44479
44703
|
hasPinnedContext = typeof host?.kubectl_context_pinned === "string" && host.kubectl_context_pinned.length > 0;
|
|
@@ -44630,7 +44854,7 @@ async function phase1SystemCheck(substrate, deps) {
|
|
|
44630
44854
|
};
|
|
44631
44855
|
}
|
|
44632
44856
|
const platform2 = String(deps.osPlatform ?? process.platform);
|
|
44633
|
-
const home = deps.home ??
|
|
44857
|
+
const home = deps.home ?? homedir54();
|
|
44634
44858
|
const colimaLint = probeColimaKubernetesEnabled({ platform: platform2, home });
|
|
44635
44859
|
if (colimaLint.ok && "warn" in colimaLint && colimaLint.warn === true) {
|
|
44636
44860
|
const lintWithWarn = colimaLint;
|
|
@@ -44769,8 +44993,8 @@ async function phase2_5ProvisionCluster(substrate, clusterName, opts, deps, reus
|
|
|
44769
44993
|
process.stdout.write(`Creating k3d cluster ${clusterName}...
|
|
44770
44994
|
`);
|
|
44771
44995
|
const volumes = [];
|
|
44772
|
-
const ghConfigDir = `${
|
|
44773
|
-
if (
|
|
44996
|
+
const ghConfigDir = `${homedir54()}/.config/gh`;
|
|
44997
|
+
if (existsSync92(ghConfigDir)) {
|
|
44774
44998
|
volumes.push("--volume", `${ghConfigDir}:/host/.config/gh`);
|
|
44775
44999
|
} else {
|
|
44776
45000
|
process.stdout.write(
|
|
@@ -44779,7 +45003,7 @@ async function phase2_5ProvisionCluster(substrate, clusterName, opts, deps, reus
|
|
|
44779
45003
|
);
|
|
44780
45004
|
}
|
|
44781
45005
|
if (opts.hostCpDevPath) {
|
|
44782
|
-
if (!
|
|
45006
|
+
if (!existsSync92(opts.hostCpDevPath)) {
|
|
44783
45007
|
return {
|
|
44784
45008
|
ok: false,
|
|
44785
45009
|
message: `--host-cp-dev-path ${opts.hostCpDevPath} does not exist`,
|
|
@@ -44944,7 +45168,7 @@ async function phase3_5K3dHttpsBootstrap(substrate, opts, _deps) {
|
|
|
44944
45168
|
const result = await ensureTlsInstalled();
|
|
44945
45169
|
let hostsWarning = "";
|
|
44946
45170
|
try {
|
|
44947
|
-
const hostsBody =
|
|
45171
|
+
const hostsBody = readFileSync80("/etc/hosts", "utf-8");
|
|
44948
45172
|
if (!/^[^#\n]*\bolam\.local\b/m.test(hostsBody)) {
|
|
44949
45173
|
hostsWarning = " Add to /etc/hosts: echo '127.0.0.1 olam.local' | sudo tee -a /etc/hosts";
|
|
44950
45174
|
}
|
|
@@ -44970,7 +45194,7 @@ async function phase4ShellInit(opts, deps) {
|
|
|
44970
45194
|
if (opts.skipShellInit) {
|
|
44971
45195
|
return { ok: true, skipped: true, message: "skipped via --skip-shell-init" };
|
|
44972
45196
|
}
|
|
44973
|
-
const home = deps.home ??
|
|
45197
|
+
const home = deps.home ?? homedir54();
|
|
44974
45198
|
const shellEnv = deps.shellEnv ?? process.env.SHELL;
|
|
44975
45199
|
const rcPath = resolveShellRc(home, shellEnv);
|
|
44976
45200
|
if (rcPath === null) {
|
|
@@ -45484,24 +45708,24 @@ function registerSetupLinuxGate(program2) {
|
|
|
45484
45708
|
}
|
|
45485
45709
|
|
|
45486
45710
|
// src/commands/update.ts
|
|
45487
|
-
import * as
|
|
45711
|
+
import * as fs87 from "node:fs";
|
|
45488
45712
|
import * as os49 from "node:os";
|
|
45489
45713
|
import * as path87 from "node:path";
|
|
45490
45714
|
import { execSync as execSync15 } from "node:child_process";
|
|
45491
45715
|
import pc33 from "picocolors";
|
|
45492
45716
|
|
|
45493
45717
|
// src/lib/symlink-reconcile.ts
|
|
45494
|
-
import * as
|
|
45718
|
+
import * as fs85 from "node:fs";
|
|
45495
45719
|
import * as path85 from "node:path";
|
|
45496
45720
|
var realFs = {
|
|
45497
|
-
readdirSync: (p) =>
|
|
45498
|
-
existsSync: (p) =>
|
|
45499
|
-
lstatSync: (p) =>
|
|
45500
|
-
readlinkSync: (p) =>
|
|
45501
|
-
symlinkSync: (t, l) =>
|
|
45502
|
-
unlinkSync: (p) =>
|
|
45721
|
+
readdirSync: (p) => fs85.readdirSync(p),
|
|
45722
|
+
existsSync: (p) => fs85.existsSync(p),
|
|
45723
|
+
lstatSync: (p) => fs85.lstatSync(p),
|
|
45724
|
+
readlinkSync: (p) => fs85.readlinkSync(p),
|
|
45725
|
+
symlinkSync: (t, l) => fs85.symlinkSync(t, l),
|
|
45726
|
+
unlinkSync: (p) => fs85.unlinkSync(p),
|
|
45503
45727
|
mkdirSync: (p, o) => {
|
|
45504
|
-
|
|
45728
|
+
fs85.mkdirSync(p, o);
|
|
45505
45729
|
}
|
|
45506
45730
|
};
|
|
45507
45731
|
function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir2, _fs = realFs) {
|
|
@@ -45595,22 +45819,22 @@ function getCurrentVersion(_exec = defaultExec) {
|
|
|
45595
45819
|
}
|
|
45596
45820
|
function readLastStable(file = LAST_STABLE_FILE) {
|
|
45597
45821
|
try {
|
|
45598
|
-
const v =
|
|
45822
|
+
const v = fs87.readFileSync(file, "utf-8").trim();
|
|
45599
45823
|
return v || null;
|
|
45600
45824
|
} catch {
|
|
45601
45825
|
return null;
|
|
45602
45826
|
}
|
|
45603
45827
|
}
|
|
45604
45828
|
function writeLastStable(version, file = LAST_STABLE_FILE) {
|
|
45605
|
-
|
|
45606
|
-
|
|
45829
|
+
fs87.mkdirSync(path87.dirname(file), { recursive: true });
|
|
45830
|
+
fs87.writeFileSync(file, version, { mode: 420 });
|
|
45607
45831
|
}
|
|
45608
45832
|
function logUpdateFailure(stderr) {
|
|
45609
45833
|
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
45610
45834
|
const logFile = path87.join(LOG_DIR2, `update-${ts}.log`);
|
|
45611
45835
|
try {
|
|
45612
|
-
|
|
45613
|
-
|
|
45836
|
+
fs87.mkdirSync(LOG_DIR2, { recursive: true });
|
|
45837
|
+
fs87.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
45614
45838
|
${stderr}
|
|
45615
45839
|
`, "utf-8");
|
|
45616
45840
|
} catch {
|
|
@@ -45831,7 +46055,7 @@ function registerBegin(program2) {
|
|
|
45831
46055
|
// src/commands/config.ts
|
|
45832
46056
|
init_global_config();
|
|
45833
46057
|
init_store2();
|
|
45834
|
-
import * as
|
|
46058
|
+
import * as fs88 from "node:fs";
|
|
45835
46059
|
import { createRequire as createRequire4 } from "node:module";
|
|
45836
46060
|
var _require4 = createRequire4(import.meta.url);
|
|
45837
46061
|
var { parse: parseWithMap } = _require4("json-source-map");
|
|
@@ -45848,14 +46072,14 @@ function registerConfig(program2) {
|
|
|
45848
46072
|
const config = program2.command("config").description("Manage global olam configuration");
|
|
45849
46073
|
config.command("validate [path]").description("Validate ~/.olam/config.json (or a custom path) against the schema").action((filePath) => {
|
|
45850
46074
|
const resolvedPath = filePath ?? globalConfigPath();
|
|
45851
|
-
if (!
|
|
46075
|
+
if (!fs88.existsSync(resolvedPath)) {
|
|
45852
46076
|
process.stderr.write(`config file not found: ${resolvedPath}
|
|
45853
46077
|
`);
|
|
45854
46078
|
process.exit(1);
|
|
45855
46079
|
}
|
|
45856
46080
|
let raw;
|
|
45857
46081
|
try {
|
|
45858
|
-
raw =
|
|
46082
|
+
raw = fs88.readFileSync(resolvedPath, "utf-8");
|
|
45859
46083
|
} catch (err) {
|
|
45860
46084
|
const msg = err instanceof Error ? err.message : String(err);
|
|
45861
46085
|
process.stderr.write(`cannot read ${resolvedPath}: ${msg}
|
|
@@ -46303,9 +46527,9 @@ import * as readline3 from "node:readline";
|
|
|
46303
46527
|
import pc37 from "picocolors";
|
|
46304
46528
|
|
|
46305
46529
|
// src/commands/flywheel/install-shims.ts
|
|
46306
|
-
import { copyFileSync as copyFileSync9, existsSync as
|
|
46307
|
-
import { homedir as
|
|
46308
|
-
import { dirname as
|
|
46530
|
+
import { copyFileSync as copyFileSync9, existsSync as existsSync96, mkdirSync as mkdirSync57, readFileSync as readFileSync84, writeFileSync as writeFileSync50 } from "node:fs";
|
|
46531
|
+
import { homedir as homedir57 } from "node:os";
|
|
46532
|
+
import { dirname as dirname53, join as join97 } from "node:path";
|
|
46309
46533
|
|
|
46310
46534
|
// src/lib/shim-generator.ts
|
|
46311
46535
|
var SHIM_SPECS = Object.freeze([
|
|
@@ -46368,7 +46592,7 @@ ${argsBlock}
|
|
|
46368
46592
|
// src/commands/flywheel/install-shims.ts
|
|
46369
46593
|
var SHIM_HEADER_MARKER = "# AUTO-GENERATED by `olam flywheel install-shims`";
|
|
46370
46594
|
function refreshShims(opts = {}) {
|
|
46371
|
-
const targetDir = opts.targetDir ??
|
|
46595
|
+
const targetDir = opts.targetDir ?? join97(homedir57(), ".claude", "scripts");
|
|
46372
46596
|
const results = [];
|
|
46373
46597
|
let written = 0;
|
|
46374
46598
|
let overwritten = 0;
|
|
@@ -46398,22 +46622,22 @@ function isOlamGeneratedShim(text) {
|
|
|
46398
46622
|
return text.includes(SHIM_HEADER_MARKER);
|
|
46399
46623
|
}
|
|
46400
46624
|
function installOne(spec, targetDir, opts) {
|
|
46401
|
-
const targetPath =
|
|
46625
|
+
const targetPath = join97(targetDir, spec.basename);
|
|
46402
46626
|
const newContent = generateShim(spec);
|
|
46403
|
-
if (!
|
|
46627
|
+
if (!existsSync96(targetPath)) {
|
|
46404
46628
|
if (opts.dryRun !== true) {
|
|
46405
|
-
|
|
46406
|
-
|
|
46629
|
+
mkdirSync57(dirname53(targetPath), { recursive: true });
|
|
46630
|
+
writeFileSync50(targetPath, newContent, { mode: 493 });
|
|
46407
46631
|
}
|
|
46408
46632
|
return { basename: spec.basename, action: "written", targetPath };
|
|
46409
46633
|
}
|
|
46410
|
-
const existing =
|
|
46634
|
+
const existing = readFileSync84(targetPath, "utf8");
|
|
46411
46635
|
if (existing === newContent) {
|
|
46412
46636
|
return { basename: spec.basename, action: "unchanged", targetPath };
|
|
46413
46637
|
}
|
|
46414
46638
|
if (isOlamGeneratedShim(existing)) {
|
|
46415
46639
|
if (opts.dryRun !== true) {
|
|
46416
|
-
|
|
46640
|
+
writeFileSync50(targetPath, newContent, { mode: 493 });
|
|
46417
46641
|
}
|
|
46418
46642
|
return { basename: spec.basename, action: "overwritten", targetPath };
|
|
46419
46643
|
}
|
|
@@ -46421,7 +46645,7 @@ function installOne(spec, targetDir, opts) {
|
|
|
46421
46645
|
const backupPath = `${targetPath}.shim-backup-${Math.floor(Date.now() / 1e3)}`;
|
|
46422
46646
|
if (opts.dryRun !== true) {
|
|
46423
46647
|
copyFileSync9(targetPath, backupPath);
|
|
46424
|
-
|
|
46648
|
+
writeFileSync50(targetPath, newContent, { mode: 493 });
|
|
46425
46649
|
}
|
|
46426
46650
|
return { basename: spec.basename, action: "overwritten", targetPath, backupPath };
|
|
46427
46651
|
}
|
|
@@ -46429,7 +46653,7 @@ function installOne(spec, targetDir, opts) {
|
|
|
46429
46653
|
}
|
|
46430
46654
|
function registerFlywheelInstallShims(parent) {
|
|
46431
46655
|
parent.command("install-shims").description("Install backwards-compat bash shims under ~/.claude/scripts/ that delegate to olam flywheel <subcmd>").option("--force", "overwrite existing non-shim files (backs them up to .shim-backup-<ts>)").option("--dry-run", "preview which shims would be written without modifying disk").option("--target-dir <path>", "override target directory (default: ~/.claude/scripts/); for tests").action((opts) => {
|
|
46432
|
-
const targetDir = opts.targetDir ??
|
|
46656
|
+
const targetDir = opts.targetDir ?? join97(homedir57(), ".claude", "scripts");
|
|
46433
46657
|
const summary2 = refreshShims(opts);
|
|
46434
46658
|
const lines = [];
|
|
46435
46659
|
const dryRunSuffix = opts.dryRun === true ? " (dry-run)" : "";
|
|
@@ -46482,7 +46706,7 @@ async function decideTrust(opts) {
|
|
|
46482
46706
|
return { granted: !denied, method: "interactive" };
|
|
46483
46707
|
}
|
|
46484
46708
|
function defaultTrustPrompt(gitUrl) {
|
|
46485
|
-
return new Promise((
|
|
46709
|
+
return new Promise((resolve31) => {
|
|
46486
46710
|
const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
|
|
46487
46711
|
process.stdout.write(
|
|
46488
46712
|
`${pc37.yellow("Trust gate:")} register "${gitUrl}" as a skill source?
|
|
@@ -46492,12 +46716,12 @@ Trust this source? ${pc37.dim("[Y/n] ")}`
|
|
|
46492
46716
|
);
|
|
46493
46717
|
rl.question("", (a) => {
|
|
46494
46718
|
rl.close();
|
|
46495
|
-
|
|
46719
|
+
resolve31(a);
|
|
46496
46720
|
});
|
|
46497
46721
|
});
|
|
46498
46722
|
}
|
|
46499
46723
|
function defaultSourcePrefixPrompt(input2) {
|
|
46500
|
-
return new Promise((
|
|
46724
|
+
return new Promise((resolve31) => {
|
|
46501
46725
|
const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
|
|
46502
46726
|
const cfg = input2.newConfig;
|
|
46503
46727
|
const prefixLabel = cfg.prefix !== void 0 ? `'${cfg.prefix}:'` : "(no prefix)";
|
|
@@ -46509,12 +46733,12 @@ Adopt for this host? ${pc37.dim("[Y/n] ")}`
|
|
|
46509
46733
|
);
|
|
46510
46734
|
rl.question("", (a) => {
|
|
46511
46735
|
rl.close();
|
|
46512
|
-
|
|
46736
|
+
resolve31(!/^n(o)?$/i.test(a.trim()));
|
|
46513
46737
|
});
|
|
46514
46738
|
});
|
|
46515
46739
|
}
|
|
46516
46740
|
function defaultPostAddPrompt(input2) {
|
|
46517
|
-
return new Promise((
|
|
46741
|
+
return new Promise((resolve31) => {
|
|
46518
46742
|
const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
|
|
46519
46743
|
process.stdout.write(`
|
|
46520
46744
|
${pc37.bold("Sync now?")} ${pc37.dim("[Y/n] ")}`);
|
|
@@ -46522,7 +46746,7 @@ ${pc37.bold("Sync now?")} ${pc37.dim("[Y/n] ")}`);
|
|
|
46522
46746
|
const sync = !/^n(o)?$/i.test(syncAnswer.trim());
|
|
46523
46747
|
if (input2.hookAlreadyInstalled) {
|
|
46524
46748
|
rl.close();
|
|
46525
|
-
|
|
46749
|
+
resolve31({ syncNow: sync, installHook: false });
|
|
46526
46750
|
return;
|
|
46527
46751
|
}
|
|
46528
46752
|
process.stdout.write(
|
|
@@ -46531,7 +46755,7 @@ ${pc37.bold("Sync now?")} ${pc37.dim("[Y/n] ")}`);
|
|
|
46531
46755
|
rl.question("", (hookAnswer) => {
|
|
46532
46756
|
rl.close();
|
|
46533
46757
|
const installHook = !/^n(o)?$/i.test(hookAnswer.trim());
|
|
46534
|
-
|
|
46758
|
+
resolve31({ syncNow: sync, installHook });
|
|
46535
46759
|
});
|
|
46536
46760
|
});
|
|
46537
46761
|
});
|
|
@@ -47188,7 +47412,7 @@ function registerSkillsSource(program2) {
|
|
|
47188
47412
|
// src/commands/skills.ts
|
|
47189
47413
|
init_skill_sources();
|
|
47190
47414
|
init_output();
|
|
47191
|
-
import * as
|
|
47415
|
+
import * as fs89 from "node:fs";
|
|
47192
47416
|
import * as os50 from "node:os";
|
|
47193
47417
|
import * as path88 from "node:path";
|
|
47194
47418
|
import * as readline4 from "node:readline";
|
|
@@ -47199,18 +47423,18 @@ init_markdown_merger();
|
|
|
47199
47423
|
init_file_lock();
|
|
47200
47424
|
import {
|
|
47201
47425
|
copyFileSync as copyFileSync10,
|
|
47202
|
-
existsSync as
|
|
47426
|
+
existsSync as existsSync97,
|
|
47203
47427
|
lstatSync as lstatSync8,
|
|
47204
|
-
mkdirSync as
|
|
47428
|
+
mkdirSync as mkdirSync58,
|
|
47205
47429
|
readdirSync as readdirSync28,
|
|
47206
|
-
readFileSync as
|
|
47430
|
+
readFileSync as readFileSync85,
|
|
47207
47431
|
readlinkSync as readlinkSync4,
|
|
47208
47432
|
rmSync as rmSync11,
|
|
47209
47433
|
statSync as statSync28,
|
|
47210
|
-
writeFileSync as
|
|
47434
|
+
writeFileSync as writeFileSync51
|
|
47211
47435
|
} from "node:fs";
|
|
47212
|
-
import { homedir as
|
|
47213
|
-
import { basename as basename8, dirname as
|
|
47436
|
+
import { homedir as homedir58 } from "node:os";
|
|
47437
|
+
import { basename as basename8, dirname as dirname54, isAbsolute as isAbsolute4, join as join98, relative as relative5, resolve as resolve24 } from "node:path";
|
|
47214
47438
|
|
|
47215
47439
|
// src/commands/flywheel/sanitize-persona-output.ts
|
|
47216
47440
|
var FORBIDDEN_HEADERS = [
|
|
@@ -47272,23 +47496,23 @@ function registerFlywheelSanitizePersonaOutput(parent) {
|
|
|
47272
47496
|
|
|
47273
47497
|
// src/lib/skills-apply-overlays.ts
|
|
47274
47498
|
function claudeRoot(opts) {
|
|
47275
|
-
return opts.claudeDir ?? opts.fixtureRoot ??
|
|
47499
|
+
return opts.claudeDir ?? opts.fixtureRoot ?? join98(homedir58(), ".claude");
|
|
47276
47500
|
}
|
|
47277
47501
|
function ensureRealDir(p) {
|
|
47278
|
-
if (!
|
|
47279
|
-
|
|
47502
|
+
if (!existsSync97(p)) {
|
|
47503
|
+
mkdirSync58(p, { recursive: true });
|
|
47280
47504
|
return;
|
|
47281
47505
|
}
|
|
47282
47506
|
const stat = lstatSync8(p);
|
|
47283
47507
|
if (stat.isSymbolicLink()) {
|
|
47284
47508
|
const targetRaw = readlinkSync4(p);
|
|
47285
|
-
const target = isAbsolute4(targetRaw) ? targetRaw :
|
|
47509
|
+
const target = isAbsolute4(targetRaw) ? targetRaw : resolve24(dirname54(p), targetRaw);
|
|
47286
47510
|
rmSync11(p);
|
|
47287
|
-
|
|
47288
|
-
if (
|
|
47511
|
+
mkdirSync58(p, { recursive: true });
|
|
47512
|
+
if (existsSync97(target) && statSync28(target).isDirectory()) {
|
|
47289
47513
|
for (const entry of readdirSync28(target)) {
|
|
47290
|
-
const src =
|
|
47291
|
-
const dest =
|
|
47514
|
+
const src = join98(target, entry);
|
|
47515
|
+
const dest = join98(p, entry);
|
|
47292
47516
|
const srcStat = lstatSync8(src);
|
|
47293
47517
|
if (srcStat.isDirectory()) {
|
|
47294
47518
|
try {
|
|
@@ -47310,8 +47534,8 @@ function postMergeSanitize(mergedText, label) {
|
|
|
47310
47534
|
return { ok: false, reason: `[post-merge-sanitize] ${label} merged output failed sanitizer: ${result.reason}` };
|
|
47311
47535
|
}
|
|
47312
47536
|
function mergeOne(upstreamPath, overlayPath, destPath2, label, dryRun, messages) {
|
|
47313
|
-
const upstreamText =
|
|
47314
|
-
const overlayText =
|
|
47537
|
+
const upstreamText = readFileSync85(upstreamPath, "utf8");
|
|
47538
|
+
const overlayText = readFileSync85(overlayPath, "utf8");
|
|
47315
47539
|
const result = mergeMarkdown(upstreamText, overlayText, label, upstreamPath, overlayPath);
|
|
47316
47540
|
if ("error" in result) {
|
|
47317
47541
|
messages.push(`ERROR ${result.error.reason}`);
|
|
@@ -47323,15 +47547,15 @@ function mergeOne(upstreamPath, overlayPath, destPath2, label, dryRun, messages)
|
|
|
47323
47547
|
return { ok: false, kind: "sanitize" };
|
|
47324
47548
|
}
|
|
47325
47549
|
if (!dryRun) {
|
|
47326
|
-
|
|
47327
|
-
|
|
47550
|
+
mkdirSync58(dirname54(destPath2), { recursive: true });
|
|
47551
|
+
writeFileSync51(destPath2, result.merged, "utf8");
|
|
47328
47552
|
}
|
|
47329
47553
|
messages.push(`MERGED ${label} \u2192 ${destPath2}${dryRun ? " (dry-run)" : ""}`);
|
|
47330
47554
|
return { ok: true };
|
|
47331
47555
|
}
|
|
47332
47556
|
function isNewAgentOverlay(overlayPath) {
|
|
47333
47557
|
try {
|
|
47334
|
-
const text =
|
|
47558
|
+
const text = readFileSync85(overlayPath, "utf8");
|
|
47335
47559
|
const { fm } = parseFrontmatter3(text);
|
|
47336
47560
|
return fm["overlay-intent"] === "new-agent";
|
|
47337
47561
|
} catch {
|
|
@@ -47340,18 +47564,18 @@ function isNewAgentOverlay(overlayPath) {
|
|
|
47340
47564
|
}
|
|
47341
47565
|
function copyNewAgent(overlayPath, destPath2, label, dryRun, messages) {
|
|
47342
47566
|
if (!dryRun) {
|
|
47343
|
-
|
|
47567
|
+
mkdirSync58(dirname54(destPath2), { recursive: true });
|
|
47344
47568
|
copyFileSync10(overlayPath, destPath2);
|
|
47345
47569
|
}
|
|
47346
47570
|
messages.push(`NEW-AGENT ${label} \u2192 ${destPath2}${dryRun ? " (dry-run)" : ""}`);
|
|
47347
47571
|
}
|
|
47348
47572
|
function walkSkillsOverlays(skillsOverridesDir, skillsDir, opts, result) {
|
|
47349
|
-
if (!
|
|
47573
|
+
if (!existsSync97(skillsOverridesDir)) return;
|
|
47350
47574
|
for (const skillName of readdirSync28(skillsOverridesDir)) {
|
|
47351
|
-
const overlaySkillDir =
|
|
47575
|
+
const overlaySkillDir = join98(skillsOverridesDir, skillName);
|
|
47352
47576
|
if (!statSync28(overlaySkillDir).isDirectory()) continue;
|
|
47353
|
-
const upstreamSkillDir =
|
|
47354
|
-
if (!
|
|
47577
|
+
const upstreamSkillDir = join98(skillsDir, skillName);
|
|
47578
|
+
if (!existsSync97(upstreamSkillDir)) {
|
|
47355
47579
|
result.messages.push(`SKIP ${skillName}: no upstream skill at ${upstreamSkillDir} (skill overlays require an upstream skill dir)`);
|
|
47356
47580
|
continue;
|
|
47357
47581
|
}
|
|
@@ -47364,7 +47588,7 @@ function walkOverlayTree(overlayRoot, upstreamRoot, labelPrefix, opts, result, i
|
|
|
47364
47588
|
while (stack.length > 0) {
|
|
47365
47589
|
const current = stack.pop();
|
|
47366
47590
|
for (const entry of readdirSync28(current)) {
|
|
47367
|
-
const overlayPath =
|
|
47591
|
+
const overlayPath = join98(current, entry);
|
|
47368
47592
|
const stat = lstatSync8(overlayPath);
|
|
47369
47593
|
if (stat.isDirectory()) {
|
|
47370
47594
|
stack.push(overlayPath);
|
|
@@ -47372,17 +47596,17 @@ function walkOverlayTree(overlayRoot, upstreamRoot, labelPrefix, opts, result, i
|
|
|
47372
47596
|
}
|
|
47373
47597
|
if (!stat.isFile() && !stat.isSymbolicLink()) continue;
|
|
47374
47598
|
const rel = relative5(overlayRoot, overlayPath);
|
|
47375
|
-
const upstreamPath =
|
|
47599
|
+
const upstreamPath = join98(upstreamRoot, rel);
|
|
47376
47600
|
const label = `${labelPrefix} ${rel}`;
|
|
47377
47601
|
if (!entry.endsWith(".md")) {
|
|
47378
47602
|
if (!opts.dryRun) {
|
|
47379
|
-
|
|
47603
|
+
mkdirSync58(dirname54(upstreamPath), { recursive: true });
|
|
47380
47604
|
copyFileSync10(overlayPath, upstreamPath);
|
|
47381
47605
|
}
|
|
47382
47606
|
result.messages.push(`COPY ${label} \u2192 ${upstreamPath}${opts.dryRun === true ? " (dry-run)" : ""}`);
|
|
47383
47607
|
continue;
|
|
47384
47608
|
}
|
|
47385
|
-
if (!
|
|
47609
|
+
if (!existsSync97(upstreamPath)) {
|
|
47386
47610
|
if (isAgentsContext && isNewAgentOverlay(overlayPath)) {
|
|
47387
47611
|
copyNewAgent(overlayPath, upstreamPath, label, opts.dryRun === true, result.messages);
|
|
47388
47612
|
result.newAgentsCreated += 1;
|
|
@@ -47391,7 +47615,7 @@ function walkOverlayTree(overlayRoot, upstreamRoot, labelPrefix, opts, result, i
|
|
|
47391
47615
|
result.renameHalts += 1;
|
|
47392
47616
|
} else {
|
|
47393
47617
|
if (!opts.dryRun) {
|
|
47394
|
-
|
|
47618
|
+
mkdirSync58(dirname54(upstreamPath), { recursive: true });
|
|
47395
47619
|
copyFileSync10(overlayPath, upstreamPath);
|
|
47396
47620
|
}
|
|
47397
47621
|
result.messages.push(`NEW-FILE ${label} \u2192 ${upstreamPath}${opts.dryRun === true ? " (dry-run)" : ""}`);
|
|
@@ -47411,16 +47635,16 @@ function walkOverlayTree(overlayRoot, upstreamRoot, labelPrefix, opts, result, i
|
|
|
47411
47635
|
}
|
|
47412
47636
|
}
|
|
47413
47637
|
function walkAgentsOverlays(agentsOverridesDir, agentsDir, opts, result) {
|
|
47414
|
-
if (!
|
|
47638
|
+
if (!existsSync97(agentsOverridesDir)) return;
|
|
47415
47639
|
ensureRealDir(agentsDir);
|
|
47416
47640
|
walkOverlayTree(agentsOverridesDir, agentsDir, "agent", opts, result, true);
|
|
47417
47641
|
}
|
|
47418
47642
|
async function applyOverlays(opts = {}) {
|
|
47419
47643
|
const root = claudeRoot(opts);
|
|
47420
|
-
const skillsDir =
|
|
47421
|
-
const agentsDir =
|
|
47422
|
-
const skillsOverridesDir =
|
|
47423
|
-
const agentsOverridesDir =
|
|
47644
|
+
const skillsDir = join98(root, "skills");
|
|
47645
|
+
const agentsDir = join98(root, "agents");
|
|
47646
|
+
const skillsOverridesDir = join98(root, "skills.overrides");
|
|
47647
|
+
const agentsOverridesDir = join98(root, "agents.overrides");
|
|
47424
47648
|
const result = {
|
|
47425
47649
|
rc: 0,
|
|
47426
47650
|
skillsMerged: 0,
|
|
@@ -47463,6 +47687,44 @@ function formatSummary(result) {
|
|
|
47463
47687
|
return lines.join("\n") + "\n";
|
|
47464
47688
|
}
|
|
47465
47689
|
|
|
47690
|
+
// src/commands/skills-install-model-router.ts
|
|
47691
|
+
init_model_router_deploy();
|
|
47692
|
+
init_output();
|
|
47693
|
+
function registerSkillsInstallModelRouter(skills) {
|
|
47694
|
+
skills.command("install-model-router").description("Deploy the model-router.py UserPromptSubmit hook script to ~/.claude/hooks/ (idempotent; auto-run by `olam skills sync`)").option("--dry-run", "preview the action without writing to disk").option("--target-dir <path>", "override target directory (default: ~/.claude/hooks/); for tests").option("--source-path <path>", "override canonical source path; for tests").action((opts) => {
|
|
47695
|
+
try {
|
|
47696
|
+
const result = deployModelRouterScript({
|
|
47697
|
+
...opts.sourcePath !== void 0 ? { sourcePath: opts.sourcePath } : {},
|
|
47698
|
+
...opts.targetDir !== void 0 ? { targetDir: opts.targetDir } : {},
|
|
47699
|
+
...opts.dryRun !== void 0 ? { dryRun: opts.dryRun } : {}
|
|
47700
|
+
});
|
|
47701
|
+
const dryRunSuffix = opts.dryRun === true ? " (dry-run)" : "";
|
|
47702
|
+
switch (result.action) {
|
|
47703
|
+
case "written":
|
|
47704
|
+
process.stdout.write(` WRITTEN ${result.targetPath}${dryRunSuffix}
|
|
47705
|
+
`);
|
|
47706
|
+
break;
|
|
47707
|
+
case "unchanged":
|
|
47708
|
+
process.stdout.write(` UNCHANGED ${result.targetPath}
|
|
47709
|
+
`);
|
|
47710
|
+
break;
|
|
47711
|
+
case "source-missing":
|
|
47712
|
+
printError(
|
|
47713
|
+
`canonical model-router.py source not found \u2014 olam install may be corrupt. Expected at packages/cli/hooks/model-router.py.`
|
|
47714
|
+
);
|
|
47715
|
+
process.exitCode = 2;
|
|
47716
|
+
return;
|
|
47717
|
+
}
|
|
47718
|
+
process.stdout.write(`
|
|
47719
|
+
model-router hook script ready at ${result.targetPath}
|
|
47720
|
+
`);
|
|
47721
|
+
} catch (err) {
|
|
47722
|
+
printError(`[install-model-router-error] ${err instanceof Error ? err.message : "unknown error"}`);
|
|
47723
|
+
process.exitCode = 2;
|
|
47724
|
+
}
|
|
47725
|
+
});
|
|
47726
|
+
}
|
|
47727
|
+
|
|
47466
47728
|
// src/commands/skills.ts
|
|
47467
47729
|
function asMessage4(err) {
|
|
47468
47730
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -47470,11 +47732,11 @@ function asMessage4(err) {
|
|
|
47470
47732
|
var ATLAS_USER_PICKER_RE = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
47471
47733
|
function listMemberNames(clonePath) {
|
|
47472
47734
|
const membersDir = path88.join(clonePath, "members");
|
|
47473
|
-
if (!
|
|
47735
|
+
if (!fs89.existsSync(membersDir)) return [];
|
|
47474
47736
|
try {
|
|
47475
|
-
return
|
|
47737
|
+
return fs89.readdirSync(membersDir).filter((e) => {
|
|
47476
47738
|
try {
|
|
47477
|
-
return
|
|
47739
|
+
return fs89.statSync(path88.join(membersDir, e)).isDirectory();
|
|
47478
47740
|
} catch {
|
|
47479
47741
|
return false;
|
|
47480
47742
|
}
|
|
@@ -47490,7 +47752,7 @@ function formatSourcePrefix(cfg) {
|
|
|
47490
47752
|
return `${p}${s}`;
|
|
47491
47753
|
}
|
|
47492
47754
|
function defaultSourcePrefixSyncPrompt(input2) {
|
|
47493
|
-
return new Promise((
|
|
47755
|
+
return new Promise((resolve31) => {
|
|
47494
47756
|
const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
|
|
47495
47757
|
const newLabel = formatSourcePrefix(input2.newConfig);
|
|
47496
47758
|
let line;
|
|
@@ -47507,16 +47769,16 @@ Accept change? ${pc38.dim("[Y/n] ")}`;
|
|
|
47507
47769
|
process.stdout.write(line);
|
|
47508
47770
|
rl.question("", (a) => {
|
|
47509
47771
|
rl.close();
|
|
47510
|
-
|
|
47772
|
+
resolve31(!/^n(o)?$/i.test(a.trim()));
|
|
47511
47773
|
});
|
|
47512
47774
|
});
|
|
47513
47775
|
}
|
|
47514
47776
|
function defaultAtlasUserPrompt(question) {
|
|
47515
|
-
return new Promise((
|
|
47777
|
+
return new Promise((resolve31) => {
|
|
47516
47778
|
const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
|
|
47517
47779
|
rl.question(question, (a) => {
|
|
47518
47780
|
rl.close();
|
|
47519
|
-
|
|
47781
|
+
resolve31(a);
|
|
47520
47782
|
});
|
|
47521
47783
|
});
|
|
47522
47784
|
}
|
|
@@ -47525,8 +47787,8 @@ async function resolveAtlasUserWithPicker(cliOverride, opts) {
|
|
|
47525
47787
|
const ATLAS_USER_RE2 = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
47526
47788
|
const claudeDirPathForRead = opts?._testClaudeDir ?? (process.env["OLAM_CLAUDE_DIR"] ?? path88.join(os50.homedir(), ".claude"));
|
|
47527
47789
|
const atlasUserFile = path88.join(claudeDirPathForRead, ".atlas-user");
|
|
47528
|
-
if (
|
|
47529
|
-
const existing =
|
|
47790
|
+
if (fs89.existsSync(atlasUserFile)) {
|
|
47791
|
+
const existing = fs89.readFileSync(atlasUserFile, "utf-8").trim();
|
|
47530
47792
|
if (existing.length > 0) {
|
|
47531
47793
|
if (ATLAS_USER_RE2.test(existing)) {
|
|
47532
47794
|
return existing;
|
|
@@ -47586,8 +47848,8 @@ async function resolveAtlasUserWithPicker(cliOverride, opts) {
|
|
|
47586
47848
|
return void 0;
|
|
47587
47849
|
}
|
|
47588
47850
|
const claudeDirPath = opts?._testClaudeDir ?? (process.env["OLAM_CLAUDE_DIR"] ?? path88.join(os50.homedir(), ".claude"));
|
|
47589
|
-
|
|
47590
|
-
|
|
47851
|
+
fs89.mkdirSync(claudeDirPath, { recursive: true });
|
|
47852
|
+
fs89.writeFileSync(path88.join(claudeDirPath, ".atlas-user"), picked + "\n", "utf8");
|
|
47591
47853
|
process.stdout.write(pc38.green(`\u2713 atlas-user set to "${picked}" (written to ${path88.join(claudeDirPath, ".atlas-user")})
|
|
47592
47854
|
`));
|
|
47593
47855
|
return picked;
|
|
@@ -47601,13 +47863,13 @@ function listDeployed() {
|
|
|
47601
47863
|
const entries = [];
|
|
47602
47864
|
for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
|
|
47603
47865
|
const bucketDir = path88.join(dir, bucket);
|
|
47604
|
-
if (!
|
|
47605
|
-
for (const name of
|
|
47866
|
+
if (!fs89.existsSync(bucketDir)) continue;
|
|
47867
|
+
for (const name of fs89.readdirSync(bucketDir)) {
|
|
47606
47868
|
const full = path88.join(bucketDir, name);
|
|
47607
47869
|
try {
|
|
47608
|
-
const stat =
|
|
47870
|
+
const stat = fs89.lstatSync(full);
|
|
47609
47871
|
if (!stat.isSymbolicLink()) continue;
|
|
47610
|
-
const target =
|
|
47872
|
+
const target = fs89.readlinkSync(full);
|
|
47611
47873
|
let sourceId;
|
|
47612
47874
|
for (const [clonePath, id] of sourcePaths.entries()) {
|
|
47613
47875
|
if (target.startsWith(clonePath)) {
|
|
@@ -47823,17 +48085,18 @@ function registerSkills(program2) {
|
|
|
47823
48085
|
process.exitCode = 2;
|
|
47824
48086
|
}
|
|
47825
48087
|
});
|
|
48088
|
+
registerSkillsInstallModelRouter(skills);
|
|
47826
48089
|
}
|
|
47827
48090
|
|
|
47828
48091
|
// src/commands/skills-hook.ts
|
|
47829
48092
|
init_skill_sources();
|
|
47830
48093
|
init_output();
|
|
47831
|
-
import * as
|
|
48094
|
+
import * as fs90 from "node:fs";
|
|
47832
48095
|
function backup(filePath) {
|
|
47833
|
-
if (!
|
|
48096
|
+
if (!fs90.existsSync(filePath)) return null;
|
|
47834
48097
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
47835
48098
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
47836
|
-
|
|
48099
|
+
fs90.copyFileSync(filePath, backupPath);
|
|
47837
48100
|
return backupPath;
|
|
47838
48101
|
}
|
|
47839
48102
|
function registerSkillsHook(program2) {
|
|
@@ -47881,7 +48144,7 @@ function registerSkillsHook(program2) {
|
|
|
47881
48144
|
printInfo("olam-skills hook", `not found in ${filePath} \u2014 already uninstalled`);
|
|
47882
48145
|
if (backupPath) {
|
|
47883
48146
|
try {
|
|
47884
|
-
|
|
48147
|
+
fs90.unlinkSync(backupPath);
|
|
47885
48148
|
} catch {
|
|
47886
48149
|
}
|
|
47887
48150
|
}
|
|
@@ -48068,24 +48331,24 @@ init_skill_sources();
|
|
|
48068
48331
|
init_merge_settings();
|
|
48069
48332
|
init_skill_sources();
|
|
48070
48333
|
init_output();
|
|
48071
|
-
import * as
|
|
48334
|
+
import * as fs91 from "node:fs";
|
|
48072
48335
|
import * as path89 from "node:path";
|
|
48073
48336
|
var MIGRATE_FROM_TOOLBOX_COMMAND = "migrate-from-toolbox";
|
|
48074
48337
|
function asMessage6(err) {
|
|
48075
48338
|
return err instanceof Error ? err.message : String(err);
|
|
48076
48339
|
}
|
|
48077
48340
|
function isOlamSkillsHookPresent(filePath) {
|
|
48078
|
-
if (!
|
|
48341
|
+
if (!fs91.existsSync(filePath)) return false;
|
|
48079
48342
|
try {
|
|
48080
|
-
const raw =
|
|
48343
|
+
const raw = fs91.readFileSync(filePath, "utf-8");
|
|
48081
48344
|
return raw.includes(OLAM_SKILLS_HOOK_SENTINEL);
|
|
48082
48345
|
} catch {
|
|
48083
48346
|
return false;
|
|
48084
48347
|
}
|
|
48085
48348
|
}
|
|
48086
48349
|
function uninstallLegacyToolboxSessionStartHook(filePath, toolboxPath) {
|
|
48087
|
-
if (!
|
|
48088
|
-
const raw =
|
|
48350
|
+
if (!fs91.existsSync(filePath)) return { removed: 0 };
|
|
48351
|
+
const raw = fs91.readFileSync(filePath, "utf-8");
|
|
48089
48352
|
const settings = raw.trim() ? JSON.parse(raw) : {};
|
|
48090
48353
|
const ss = settings?.hooks?.SessionStart;
|
|
48091
48354
|
if (!Array.isArray(ss)) return { removed: 0 };
|
|
@@ -48114,7 +48377,7 @@ function uninstallLegacyToolboxSessionStartHook(filePath, toolboxPath) {
|
|
|
48114
48377
|
if (otherStages.length === 0) delete next.hooks;
|
|
48115
48378
|
else delete next.hooks.SessionStart;
|
|
48116
48379
|
}
|
|
48117
|
-
|
|
48380
|
+
fs91.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
48118
48381
|
return { removed };
|
|
48119
48382
|
}
|
|
48120
48383
|
function registerSkillsMigrate(program2) {
|
|
@@ -48193,7 +48456,7 @@ function registerSkillsMigrate(program2) {
|
|
|
48193
48456
|
const scope = opts.scope === "user" ? "user" : "project";
|
|
48194
48457
|
const olamHookPath = scope === "user" ? settingsFile : path89.join(process.cwd(), ".claude", "settings.json");
|
|
48195
48458
|
try {
|
|
48196
|
-
|
|
48459
|
+
fs91.mkdirSync(path89.dirname(olamHookPath), { recursive: true });
|
|
48197
48460
|
const result = mergeHomeSettingsJson(olamHookPath, {
|
|
48198
48461
|
ensureHook: {
|
|
48199
48462
|
stage: OLAM_SKILLS_HOOK_STAGE,
|
|
@@ -48226,7 +48489,7 @@ function registerSkillsMigrate(program2) {
|
|
|
48226
48489
|
// src/commands/skills-migrate-back.ts
|
|
48227
48490
|
init_skill_sources();
|
|
48228
48491
|
init_output();
|
|
48229
|
-
import * as
|
|
48492
|
+
import * as fs92 from "node:fs";
|
|
48230
48493
|
import * as path90 from "node:path";
|
|
48231
48494
|
var MIGRATE_BACK_TO_TOOLBOX_COMMAND = "migrate-back-to-toolbox";
|
|
48232
48495
|
function asMessage7(err) {
|
|
@@ -48242,9 +48505,9 @@ function restoreSessionStartFromSnapshot(filePath, originalSessionStartHook) {
|
|
|
48242
48505
|
return { restored: false };
|
|
48243
48506
|
}
|
|
48244
48507
|
let settings;
|
|
48245
|
-
if (
|
|
48508
|
+
if (fs92.existsSync(filePath)) {
|
|
48246
48509
|
try {
|
|
48247
|
-
const raw =
|
|
48510
|
+
const raw = fs92.readFileSync(filePath, "utf-8");
|
|
48248
48511
|
settings = raw.trim() ? JSON.parse(raw) : {};
|
|
48249
48512
|
} catch {
|
|
48250
48513
|
settings = {};
|
|
@@ -48260,8 +48523,8 @@ function restoreSessionStartFromSnapshot(filePath, originalSessionStartHook) {
|
|
|
48260
48523
|
SessionStart: originalSessionStartHook
|
|
48261
48524
|
}
|
|
48262
48525
|
};
|
|
48263
|
-
|
|
48264
|
-
|
|
48526
|
+
fs92.mkdirSync(path90.dirname(filePath), { recursive: true });
|
|
48527
|
+
fs92.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
48265
48528
|
return { restored: true };
|
|
48266
48529
|
}
|
|
48267
48530
|
function removeOlamManagedSymlinks() {
|
|
@@ -48271,15 +48534,15 @@ function removeOlamManagedSymlinks() {
|
|
|
48271
48534
|
let removed = 0;
|
|
48272
48535
|
for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
|
|
48273
48536
|
const dir = path90.join(claude, bucket);
|
|
48274
|
-
if (!
|
|
48275
|
-
for (const name of
|
|
48537
|
+
if (!fs92.existsSync(dir)) continue;
|
|
48538
|
+
for (const name of fs92.readdirSync(dir)) {
|
|
48276
48539
|
const linkPath = path90.join(dir, name);
|
|
48277
48540
|
try {
|
|
48278
|
-
const stat =
|
|
48541
|
+
const stat = fs92.lstatSync(linkPath);
|
|
48279
48542
|
if (!stat.isSymbolicLink()) continue;
|
|
48280
|
-
const target =
|
|
48543
|
+
const target = fs92.readlinkSync(linkPath);
|
|
48281
48544
|
if (olamClonePaths.some((cp) => target.startsWith(cp))) {
|
|
48282
|
-
|
|
48545
|
+
fs92.unlinkSync(linkPath);
|
|
48283
48546
|
removed += 1;
|
|
48284
48547
|
}
|
|
48285
48548
|
} catch {
|
|
@@ -48292,18 +48555,18 @@ function restoreToolboxSymlinks(symlinks) {
|
|
|
48292
48555
|
let restored = 0;
|
|
48293
48556
|
for (const { link, target } of symlinks) {
|
|
48294
48557
|
try {
|
|
48295
|
-
|
|
48296
|
-
if (
|
|
48558
|
+
fs92.mkdirSync(path90.dirname(link), { recursive: true });
|
|
48559
|
+
if (fs92.existsSync(link) || (() => {
|
|
48297
48560
|
try {
|
|
48298
|
-
|
|
48561
|
+
fs92.lstatSync(link);
|
|
48299
48562
|
return true;
|
|
48300
48563
|
} catch {
|
|
48301
48564
|
return false;
|
|
48302
48565
|
}
|
|
48303
48566
|
})()) {
|
|
48304
|
-
|
|
48567
|
+
fs92.unlinkSync(link);
|
|
48305
48568
|
}
|
|
48306
|
-
|
|
48569
|
+
fs92.symlinkSync(target, link);
|
|
48307
48570
|
restored += 1;
|
|
48308
48571
|
} catch {
|
|
48309
48572
|
}
|
|
@@ -48313,8 +48576,8 @@ function restoreToolboxSymlinks(symlinks) {
|
|
|
48313
48576
|
function restoreAtlasUserMarker(atlasUser) {
|
|
48314
48577
|
if (!atlasUser) return false;
|
|
48315
48578
|
const file = path90.join(claudeDirInternal4(), ".atlas-user");
|
|
48316
|
-
|
|
48317
|
-
|
|
48579
|
+
fs92.mkdirSync(path90.dirname(file), { recursive: true });
|
|
48580
|
+
fs92.writeFileSync(file, atlasUser);
|
|
48318
48581
|
return true;
|
|
48319
48582
|
}
|
|
48320
48583
|
function registerSkillsMigrateBack(program2) {
|
|
@@ -48328,7 +48591,7 @@ function registerSkillsMigrateBack(program2) {
|
|
|
48328
48591
|
try {
|
|
48329
48592
|
if (opts.snapshot) {
|
|
48330
48593
|
snapshotPath = path90.resolve(opts.snapshot);
|
|
48331
|
-
if (!
|
|
48594
|
+
if (!fs92.existsSync(snapshotPath)) {
|
|
48332
48595
|
printError(`snapshot not found at ${snapshotPath}`);
|
|
48333
48596
|
process.exitCode = 1;
|
|
48334
48597
|
return;
|
|
@@ -48412,7 +48675,7 @@ init_meta_hooks_migration_snapshot();
|
|
|
48412
48675
|
init_trust_audit_log();
|
|
48413
48676
|
init_atlas_hook_strip();
|
|
48414
48677
|
init_output();
|
|
48415
|
-
import * as
|
|
48678
|
+
import * as fs93 from "node:fs";
|
|
48416
48679
|
import * as path91 from "node:path";
|
|
48417
48680
|
import pc40 from "picocolors";
|
|
48418
48681
|
var MIGRATE_HOOKS_COMMAND = "migrate-hooks";
|
|
@@ -48434,16 +48697,16 @@ function settingsHasOlamMetaSentinel(settings) {
|
|
|
48434
48697
|
return false;
|
|
48435
48698
|
}
|
|
48436
48699
|
function readSettings2(filePath) {
|
|
48437
|
-
if (!
|
|
48438
|
-
const raw =
|
|
48700
|
+
if (!fs93.existsSync(filePath)) return null;
|
|
48701
|
+
const raw = fs93.readFileSync(filePath, "utf-8");
|
|
48439
48702
|
if (raw.trim().length === 0) return {};
|
|
48440
48703
|
return JSON.parse(raw);
|
|
48441
48704
|
}
|
|
48442
48705
|
function writeSettings(filePath, settings) {
|
|
48443
|
-
|
|
48706
|
+
fs93.mkdirSync(path91.dirname(filePath), { recursive: true });
|
|
48444
48707
|
const tmp = `${filePath}.tmp-migrate-hooks-${process.pid}-${Date.now()}`;
|
|
48445
|
-
|
|
48446
|
-
|
|
48708
|
+
fs93.writeFileSync(tmp, JSON.stringify(settings, null, 2) + "\n");
|
|
48709
|
+
fs93.renameSync(tmp, filePath);
|
|
48447
48710
|
}
|
|
48448
48711
|
function printSummary(candidates2, opts) {
|
|
48449
48712
|
if (candidates2.length === 0) {
|
|
@@ -48578,7 +48841,7 @@ function registerSkillsMigrateHooksBack(program2) {
|
|
|
48578
48841
|
// src/commands/skills-shadow-backups.ts
|
|
48579
48842
|
init_skill_sources();
|
|
48580
48843
|
init_output();
|
|
48581
|
-
import * as
|
|
48844
|
+
import * as fs94 from "node:fs";
|
|
48582
48845
|
import pc41 from "picocolors";
|
|
48583
48846
|
function asMessage10(err) {
|
|
48584
48847
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -48661,7 +48924,7 @@ function registerSkillsShadowBackups(program2) {
|
|
|
48661
48924
|
});
|
|
48662
48925
|
sb.command("restore").description("Move a shadow-backup file back to its original path").argument("<path>", "Absolute path to the .shadow-backup-<epoch> file").option("--force", "Overwrite the original path if it already exists").action((p, opts) => {
|
|
48663
48926
|
try {
|
|
48664
|
-
if (!
|
|
48927
|
+
if (!fs94.existsSync(p)) {
|
|
48665
48928
|
printError(`backup file not found: ${p}`);
|
|
48666
48929
|
process.exitCode = 1;
|
|
48667
48930
|
return;
|
|
@@ -48684,11 +48947,11 @@ function asMessage11(err) {
|
|
|
48684
48947
|
return err instanceof Error ? err.message : String(err);
|
|
48685
48948
|
}
|
|
48686
48949
|
function defaultDoctorPrompt(question) {
|
|
48687
|
-
return new Promise((
|
|
48950
|
+
return new Promise((resolve31) => {
|
|
48688
48951
|
const rl = readline5.createInterface({ input: process.stdin, output: process.stdout });
|
|
48689
48952
|
rl.question(question, (a) => {
|
|
48690
48953
|
rl.close();
|
|
48691
|
-
|
|
48954
|
+
resolve31(a);
|
|
48692
48955
|
});
|
|
48693
48956
|
});
|
|
48694
48957
|
}
|
|
@@ -48779,23 +49042,26 @@ function registerSkillsDoctor(program2) {
|
|
|
48779
49042
|
});
|
|
48780
49043
|
}
|
|
48781
49044
|
|
|
48782
|
-
// src/commands/skills-
|
|
49045
|
+
// src/commands/skills-100x.ts
|
|
48783
49046
|
init_skill_sources();
|
|
48784
49047
|
init_cli_version();
|
|
48785
49048
|
init_output();
|
|
48786
49049
|
import { execFileSync as execFileSync17 } from "node:child_process";
|
|
48787
|
-
import * as
|
|
49050
|
+
import * as fs95 from "node:fs";
|
|
48788
49051
|
import * as path93 from "node:path";
|
|
48789
49052
|
var CHAIN_SKILL_NAMES = [
|
|
48790
|
-
"
|
|
48791
|
-
"
|
|
48792
|
-
"
|
|
48793
|
-
"
|
|
48794
|
-
"
|
|
48795
|
-
"
|
|
48796
|
-
"
|
|
48797
|
-
"
|
|
49053
|
+
"100x:brainstorm",
|
|
49054
|
+
"100x:plan-hard",
|
|
49055
|
+
"100x:review-plan",
|
|
49056
|
+
"100x:break-plan",
|
|
49057
|
+
"100x:commit-plan",
|
|
49058
|
+
"100x:execute",
|
|
49059
|
+
"100x:retro",
|
|
49060
|
+
"100x:learn"
|
|
48798
49061
|
];
|
|
49062
|
+
var PLUGIN_MARKETPLACE = "atlas-builders/atlas-toolbox";
|
|
49063
|
+
var PLUGIN_SPEC = "100x@atlas-one";
|
|
49064
|
+
var PLUGIN_SCOPES = ["user", "project", "local"];
|
|
48799
49065
|
function asMessage12(err) {
|
|
48800
49066
|
return err instanceof Error ? err.message : String(err);
|
|
48801
49067
|
}
|
|
@@ -48808,13 +49074,13 @@ function hasBeadsCli() {
|
|
|
48808
49074
|
}
|
|
48809
49075
|
}
|
|
48810
49076
|
function hasBeadsProjectInit(cwd) {
|
|
48811
|
-
return
|
|
49077
|
+
return fs95.existsSync(path93.join(cwd, ".beads"));
|
|
48812
49078
|
}
|
|
48813
49079
|
function hasBeadsClaudeSetup() {
|
|
48814
49080
|
const settingsPath = path93.join(claudeDir(), "settings.json");
|
|
48815
|
-
if (!
|
|
49081
|
+
if (!fs95.existsSync(settingsPath)) return false;
|
|
48816
49082
|
try {
|
|
48817
|
-
const content =
|
|
49083
|
+
const content = fs95.readFileSync(settingsPath, "utf8");
|
|
48818
49084
|
return /"command"\s*:\s*"bd\b/.test(content) || /"bd setup\b/.test(content);
|
|
48819
49085
|
} catch {
|
|
48820
49086
|
return false;
|
|
@@ -48851,6 +49117,37 @@ async function bootstrapBeads(cwd) {
|
|
|
48851
49117
|
console.log("beads Claude hooks already installed \u2014 skipping bd setup");
|
|
48852
49118
|
}
|
|
48853
49119
|
}
|
|
49120
|
+
function normalizeScope(raw) {
|
|
49121
|
+
if (raw === void 0) return "user";
|
|
49122
|
+
if (PLUGIN_SCOPES.includes(raw)) {
|
|
49123
|
+
return raw;
|
|
49124
|
+
}
|
|
49125
|
+
throw new Error(
|
|
49126
|
+
`invalid --scope '${raw}' \u2014 expected one of: ${PLUGIN_SCOPES.join(", ")}`
|
|
49127
|
+
);
|
|
49128
|
+
}
|
|
49129
|
+
function addPluginMarketplace(scope) {
|
|
49130
|
+
console.log(
|
|
49131
|
+
`claude plugin marketplace add ${PLUGIN_MARKETPLACE} (scope: ${scope})`
|
|
49132
|
+
);
|
|
49133
|
+
try {
|
|
49134
|
+
execFileSync17(
|
|
49135
|
+
"claude",
|
|
49136
|
+
["plugin", "marketplace", "add", PLUGIN_MARKETPLACE, "--scope", scope],
|
|
49137
|
+
{ stdio: "inherit" }
|
|
49138
|
+
);
|
|
49139
|
+
} catch (err) {
|
|
49140
|
+
printWarning(
|
|
49141
|
+
`claude plugin marketplace add returned an error (continuing \u2014 likely already added): ${asMessage12(err)}`
|
|
49142
|
+
);
|
|
49143
|
+
}
|
|
49144
|
+
}
|
|
49145
|
+
function installPlugin(scope) {
|
|
49146
|
+
console.log(`claude plugin install ${PLUGIN_SPEC} (scope: ${scope})`);
|
|
49147
|
+
execFileSync17("claude", ["plugin", "install", PLUGIN_SPEC, "--scope", scope], {
|
|
49148
|
+
stdio: "inherit"
|
|
49149
|
+
});
|
|
49150
|
+
}
|
|
48854
49151
|
function captureSourceShas() {
|
|
48855
49152
|
return listSkillSources().map((s) => ({
|
|
48856
49153
|
id: s.id,
|
|
@@ -48880,11 +49177,11 @@ function shortSha(sha) {
|
|
|
48880
49177
|
}
|
|
48881
49178
|
function listInstalledClaudeSkills() {
|
|
48882
49179
|
const skillsDir = path93.join(claudeDir(), "skills");
|
|
48883
|
-
if (!
|
|
49180
|
+
if (!fs95.existsSync(skillsDir)) return [];
|
|
48884
49181
|
try {
|
|
48885
|
-
return
|
|
49182
|
+
return fs95.readdirSync(skillsDir).filter((name) => {
|
|
48886
49183
|
try {
|
|
48887
|
-
const stat =
|
|
49184
|
+
const stat = fs95.lstatSync(path93.join(skillsDir, name));
|
|
48888
49185
|
return stat.isSymbolicLink() || stat.isDirectory();
|
|
48889
49186
|
} catch {
|
|
48890
49187
|
return false;
|
|
@@ -48897,24 +49194,64 @@ function listInstalledClaudeSkills() {
|
|
|
48897
49194
|
function isChainSkill(name) {
|
|
48898
49195
|
const lower = name.toLowerCase();
|
|
48899
49196
|
return CHAIN_SKILL_NAMES.some((canonical) => {
|
|
48900
|
-
const slug = canonical.replace(/^
|
|
48901
|
-
return lower === canonical.toLowerCase() || lower === slug || lower === `
|
|
49197
|
+
const slug = canonical.replace(/^100x:/, "");
|
|
49198
|
+
return lower === canonical.toLowerCase() || lower === slug || lower === `100x-${slug}` || // Legacy pre-rename forms (10x:slug / 10x-slug).
|
|
49199
|
+
lower === `10x:${slug}` || lower === `10x-${slug}`;
|
|
48902
49200
|
});
|
|
48903
49201
|
}
|
|
48904
|
-
function
|
|
48905
|
-
|
|
48906
|
-
|
|
48907
|
-
|
|
49202
|
+
function registerSkills100x(program2) {
|
|
49203
|
+
registerTopLevel100x(program2);
|
|
49204
|
+
registerDeprecatedSkills10xAlias(program2);
|
|
49205
|
+
}
|
|
49206
|
+
function registerTopLevel100x(program2) {
|
|
49207
|
+
const onex = program2.command("100x").description(
|
|
49208
|
+
"Install the /100x: planning chain as a native Claude Code plugin + beads integration"
|
|
48908
49209
|
);
|
|
49210
|
+
onex.command("install").description(
|
|
49211
|
+
"Install the native Claude Code plugin (claude plugin marketplace add + plugin install) + auto-bootstrap beads (bd init + bd setup claude)."
|
|
49212
|
+
).option("--no-beads", "Skip beads auto-bootstrap (plugin install only)").option(
|
|
49213
|
+
"--scope <scope>",
|
|
49214
|
+
"Plugin scope passed through to claude (user|project|local)",
|
|
49215
|
+
"user"
|
|
49216
|
+
).action(async (opts) => {
|
|
49217
|
+
try {
|
|
49218
|
+
const scope = normalizeScope(opts.scope);
|
|
49219
|
+
console.log(
|
|
49220
|
+
"Installing the /100x: chain via the native Claude Code plugin..."
|
|
49221
|
+
);
|
|
49222
|
+
addPluginMarketplace(scope);
|
|
49223
|
+
installPlugin(scope);
|
|
49224
|
+
printSuccess(`Installed plugin ${PLUGIN_SPEC} (scope: ${scope})`);
|
|
49225
|
+
if (opts.beads !== false) {
|
|
49226
|
+
await bootstrapBeads(process.cwd());
|
|
49227
|
+
} else {
|
|
49228
|
+
console.log("--no-beads \u2014 skipping beads auto-bootstrap");
|
|
49229
|
+
}
|
|
49230
|
+
printSuccess("olam 100x install complete");
|
|
49231
|
+
} catch (err) {
|
|
49232
|
+
printError(`Install failed: ${asMessage12(err)}`);
|
|
49233
|
+
process.exitCode = 1;
|
|
49234
|
+
}
|
|
49235
|
+
});
|
|
49236
|
+
}
|
|
49237
|
+
function registerDeprecatedSkills10xAlias(program2) {
|
|
49238
|
+
const skills = program2.commands.find((c) => c.name() === "skills") ?? program2.command("skills").description("Manage skill sources and synchronization");
|
|
49239
|
+
const tenx = skills.command("10x", { hidden: true }).description(
|
|
49240
|
+
"DEPRECATED \u2014 use `olam 100x install`. Manage the /100x: planning chain skills via syncSkills() + beads."
|
|
49241
|
+
).hook("preAction", () => {
|
|
49242
|
+
printWarning(
|
|
49243
|
+
"DEPRECATED: `olam skills 10x` \u2014 use `olam 100x install` (native Claude Code plugin) instead."
|
|
49244
|
+
);
|
|
49245
|
+
});
|
|
48909
49246
|
tenx.command("install").description(
|
|
48910
|
-
"Sync /
|
|
49247
|
+
"Sync /100x: chain skills from registered sources + auto-bootstrap beads (bd init + bd setup claude). Surfaces source-SHA bumps + shadow-backups for sentinel-versioned upgrade."
|
|
48911
49248
|
).option("--no-beads", "Skip beads auto-bootstrap (chain skills only)").option(
|
|
48912
49249
|
"--force",
|
|
48913
49250
|
"Suppress shadow-backup warning + proceed without operator attention (shadow backups are still created by the sync engine; this flag only suppresses the surface-prominence)"
|
|
48914
49251
|
).action(async (opts) => {
|
|
48915
49252
|
try {
|
|
48916
49253
|
const preSync = captureSourceShas();
|
|
48917
|
-
console.log("Syncing /
|
|
49254
|
+
console.log("Syncing /100x: chain skills from registered sources...");
|
|
48918
49255
|
const summary2 = await syncSkills({});
|
|
48919
49256
|
printSuccess(
|
|
48920
49257
|
`Synced ${summary2.artifactCount} artifact(s) from ${summary2.sourceCount} source(s)`
|
|
@@ -48957,43 +49294,43 @@ function registerSkills10x(program2) {
|
|
|
48957
49294
|
}
|
|
48958
49295
|
});
|
|
48959
49296
|
tenx.command("uninstall").description(
|
|
48960
|
-
"Remove /
|
|
49297
|
+
"Remove /100x: chain skill symlinks from ~/.claude/skills (preserves user-authored skills + non-chain skill sources)"
|
|
48961
49298
|
).action(() => {
|
|
48962
49299
|
const skillsDir = path93.join(claudeDir(), "skills");
|
|
48963
|
-
if (!
|
|
49300
|
+
if (!fs95.existsSync(skillsDir)) {
|
|
48964
49301
|
printWarning("No ~/.claude/skills/ directory found; nothing to uninstall");
|
|
48965
49302
|
return;
|
|
48966
49303
|
}
|
|
48967
49304
|
let removed = 0;
|
|
48968
|
-
for (const name of
|
|
49305
|
+
for (const name of fs95.readdirSync(skillsDir)) {
|
|
48969
49306
|
const full = path93.join(skillsDir, name);
|
|
48970
49307
|
try {
|
|
48971
|
-
const stat =
|
|
49308
|
+
const stat = fs95.lstatSync(full);
|
|
48972
49309
|
if (!stat.isSymbolicLink()) continue;
|
|
48973
|
-
const target =
|
|
48974
|
-
if (isChainSkill(name) || /\/10x[-:]/.test(target)) {
|
|
48975
|
-
|
|
49310
|
+
const target = fs95.readlinkSync(full);
|
|
49311
|
+
if (isChainSkill(name) || /\/(100x|10x)[-:]/.test(target)) {
|
|
49312
|
+
fs95.unlinkSync(full);
|
|
48976
49313
|
removed += 1;
|
|
48977
49314
|
}
|
|
48978
49315
|
} catch {
|
|
48979
49316
|
}
|
|
48980
49317
|
}
|
|
48981
|
-
printSuccess(`Removed ${removed} /
|
|
49318
|
+
printSuccess(`Removed ${removed} /100x: chain skill symlink(s)`);
|
|
48982
49319
|
console.log("User-authored + non-chain skill sources preserved");
|
|
48983
49320
|
});
|
|
48984
49321
|
tenx.command("doctor").description(
|
|
48985
|
-
"Diagnose /
|
|
49322
|
+
"Diagnose /100x: chain skill installation + beads bootstrap state"
|
|
48986
49323
|
).action(() => {
|
|
48987
|
-
console.log("=== /
|
|
49324
|
+
console.log("=== /100x: chain skills + beads health ===");
|
|
48988
49325
|
const installed = listInstalledClaudeSkills();
|
|
48989
49326
|
const chainInstalled = installed.filter(isChainSkill);
|
|
48990
49327
|
console.log(
|
|
48991
|
-
` /
|
|
49328
|
+
` /100x: chain skills: ${chainInstalled.length} / ${CHAIN_SKILL_NAMES.length} installed`
|
|
48992
49329
|
);
|
|
48993
49330
|
for (const canonical of CHAIN_SKILL_NAMES) {
|
|
48994
|
-
const slug = canonical.replace(/^
|
|
49331
|
+
const slug = canonical.replace(/^100x:/, "");
|
|
48995
49332
|
const found = installed.some(
|
|
48996
|
-
(n) => n.toLowerCase() === canonical.toLowerCase() || n.toLowerCase() === slug || n.toLowerCase() === `10x-${slug}`
|
|
49333
|
+
(n) => n.toLowerCase() === canonical.toLowerCase() || n.toLowerCase() === slug || n.toLowerCase() === `100x-${slug}` || n.toLowerCase() === `10x:${slug}` || n.toLowerCase() === `10x-${slug}`
|
|
48997
49334
|
);
|
|
48998
49335
|
console.log(` ${found ? "\u2713" : "\u2717"} ${canonical}`);
|
|
48999
49336
|
}
|
|
@@ -49006,11 +49343,11 @@ function registerSkills10x(program2) {
|
|
|
49006
49343
|
const allChainPresent = chainInstalled.length === CHAIN_SKILL_NAMES.length;
|
|
49007
49344
|
const allOk = allChainPresent && bdCli && bdInit && bdHooks;
|
|
49008
49345
|
if (allOk) {
|
|
49009
|
-
printSuccess("All /
|
|
49346
|
+
printSuccess("All /100x: chain skill + beads checks pass");
|
|
49010
49347
|
return;
|
|
49011
49348
|
}
|
|
49012
49349
|
const fixHints = [];
|
|
49013
|
-
if (!allChainPresent) fixHints.push("olam
|
|
49350
|
+
if (!allChainPresent) fixHints.push("olam 100x install");
|
|
49014
49351
|
if (!bdCli) fixHints.push("brew install beads OR npm i -g @beads/bd");
|
|
49015
49352
|
if (!bdInit) fixHints.push("bd init");
|
|
49016
49353
|
if (!bdHooks) fixHints.push("bd setup claude");
|
|
@@ -49024,7 +49361,7 @@ function registerSkills10x(program2) {
|
|
|
49024
49361
|
const olamVersion = readCliVersion();
|
|
49025
49362
|
const sources = listSkillSources();
|
|
49026
49363
|
console.log(`olam-cli: ${olamVersion}`);
|
|
49027
|
-
console.log(`chain canonical: ${CHAIN_SKILL_NAMES.length} skills (/
|
|
49364
|
+
console.log(`chain canonical: ${CHAIN_SKILL_NAMES.length} skills (/100x: chain)`);
|
|
49028
49365
|
console.log(`registered sources: ${sources.length}`);
|
|
49029
49366
|
for (const s of sources) {
|
|
49030
49367
|
const shortId = s.id ? s.id.slice(0, 8) : "????????";
|
|
@@ -49040,7 +49377,7 @@ function registerSkills10x(program2) {
|
|
|
49040
49377
|
|
|
49041
49378
|
// src/commands/hermes.ts
|
|
49042
49379
|
init_output();
|
|
49043
|
-
import * as
|
|
49380
|
+
import * as fs96 from "node:fs";
|
|
49044
49381
|
import * as os51 from "node:os";
|
|
49045
49382
|
import * as path94 from "node:path";
|
|
49046
49383
|
import * as child_process from "node:child_process";
|
|
@@ -49055,7 +49392,7 @@ function claudeSkillsDir() {
|
|
|
49055
49392
|
return path94.join(os51.homedir(), ".claude", "skills");
|
|
49056
49393
|
}
|
|
49057
49394
|
function readHermesConfig(configPath) {
|
|
49058
|
-
const raw =
|
|
49395
|
+
const raw = fs96.readFileSync(configPath, "utf-8");
|
|
49059
49396
|
const parsed = yamlParse2(raw);
|
|
49060
49397
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
49061
49398
|
throw new Error(`${configPath} is not a YAML mapping`);
|
|
@@ -49063,13 +49400,13 @@ function readHermesConfig(configPath) {
|
|
|
49063
49400
|
return parsed;
|
|
49064
49401
|
}
|
|
49065
49402
|
function writeHermesConfig(configPath, config) {
|
|
49066
|
-
|
|
49403
|
+
fs96.writeFileSync(configPath, yamlStringify3(config), "utf-8");
|
|
49067
49404
|
}
|
|
49068
49405
|
function resolveOlamBinary() {
|
|
49069
49406
|
try {
|
|
49070
49407
|
const result = child_process.spawnSync("which", ["olam"], { encoding: "utf-8" });
|
|
49071
49408
|
const found = result.stdout.trim();
|
|
49072
|
-
if (found &&
|
|
49409
|
+
if (found && fs96.existsSync(found)) return found;
|
|
49073
49410
|
} catch {
|
|
49074
49411
|
}
|
|
49075
49412
|
return process.argv[1] ?? "olam";
|
|
@@ -49082,7 +49419,7 @@ function resolveWorkspaceDir() {
|
|
|
49082
49419
|
{ encoding: "utf-8" }
|
|
49083
49420
|
);
|
|
49084
49421
|
const out = result.stdout.trim();
|
|
49085
|
-
if (out &&
|
|
49422
|
+
if (out && fs96.existsSync(out)) return out;
|
|
49086
49423
|
} catch {
|
|
49087
49424
|
}
|
|
49088
49425
|
return process.cwd();
|
|
@@ -49152,22 +49489,22 @@ function ensureTerminalBackendLocal(config, dryRun, summary2) {
|
|
|
49152
49489
|
}
|
|
49153
49490
|
function mirrorSkillSymlinks(dryRun, summary2) {
|
|
49154
49491
|
const srcDir = claudeSkillsDir();
|
|
49155
|
-
if (!
|
|
49492
|
+
if (!fs96.existsSync(srcDir)) {
|
|
49156
49493
|
summary2.skipped.push("skills mirror (no ~/.claude/skills/ found)");
|
|
49157
49494
|
return;
|
|
49158
49495
|
}
|
|
49159
49496
|
const destDir = hermesSkillsDir();
|
|
49160
49497
|
if (!dryRun) {
|
|
49161
|
-
|
|
49498
|
+
fs96.mkdirSync(destDir, { recursive: true });
|
|
49162
49499
|
}
|
|
49163
|
-
const entries =
|
|
49500
|
+
const entries = fs96.readdirSync(srcDir);
|
|
49164
49501
|
let mirrored = 0;
|
|
49165
49502
|
let collisions = 0;
|
|
49166
49503
|
for (const entry of entries) {
|
|
49167
49504
|
const srcPath = path94.join(srcDir, entry);
|
|
49168
49505
|
const destPath2 = path94.join(destDir, entry);
|
|
49169
|
-
if (
|
|
49170
|
-
if (
|
|
49506
|
+
if (fs96.existsSync(destPath2) || fs96.lstatSync(srcPath).isFile()) {
|
|
49507
|
+
if (fs96.existsSync(destPath2)) collisions++;
|
|
49171
49508
|
continue;
|
|
49172
49509
|
}
|
|
49173
49510
|
if (dryRun) {
|
|
@@ -49175,7 +49512,7 @@ function mirrorSkillSymlinks(dryRun, summary2) {
|
|
|
49175
49512
|
continue;
|
|
49176
49513
|
}
|
|
49177
49514
|
try {
|
|
49178
|
-
|
|
49515
|
+
fs96.symlinkSync(srcPath, destPath2);
|
|
49179
49516
|
mirrored++;
|
|
49180
49517
|
} catch (err) {
|
|
49181
49518
|
printWarning(`skills mirror: skipping ${entry} \u2014 ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -49194,7 +49531,7 @@ async function runHermesBootstrap(opts, deps = {}) {
|
|
|
49194
49531
|
const writeConfig2 = deps.writeConfig ?? writeHermesConfig;
|
|
49195
49532
|
const mirrorSkillsFn = deps.mirrorSkills ?? mirrorSkillSymlinks;
|
|
49196
49533
|
const installHookFn = deps.installHook ?? installKgFirstHookForHermes;
|
|
49197
|
-
if (!
|
|
49534
|
+
if (!fs96.existsSync(configPath)) {
|
|
49198
49535
|
printError(`~/.hermes/config.yaml not found at ${configPath}`);
|
|
49199
49536
|
printInfo(
|
|
49200
49537
|
"remedy",
|
|
@@ -49311,7 +49648,7 @@ function registerStop(program2) {
|
|
|
49311
49648
|
}
|
|
49312
49649
|
|
|
49313
49650
|
// src/lib/upgrade-check.ts
|
|
49314
|
-
import * as
|
|
49651
|
+
import * as fs97 from "node:fs";
|
|
49315
49652
|
import * as os52 from "node:os";
|
|
49316
49653
|
import * as path95 from "node:path";
|
|
49317
49654
|
var UPGRADE_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -49330,7 +49667,7 @@ function isNewer(latest, current) {
|
|
|
49330
49667
|
}
|
|
49331
49668
|
function readCache(cachePath) {
|
|
49332
49669
|
try {
|
|
49333
|
-
const raw =
|
|
49670
|
+
const raw = fs97.readFileSync(cachePath, "utf-8");
|
|
49334
49671
|
const parsed = JSON.parse(raw);
|
|
49335
49672
|
if (typeof parsed === "object" && parsed !== null && typeof parsed["checkedAt"] === "number" && typeof parsed["latestVersion"] === "string") {
|
|
49336
49673
|
return parsed;
|
|
@@ -49342,8 +49679,8 @@ function readCache(cachePath) {
|
|
|
49342
49679
|
function writeCache(cachePath, data) {
|
|
49343
49680
|
try {
|
|
49344
49681
|
const dir = path95.dirname(cachePath);
|
|
49345
|
-
|
|
49346
|
-
|
|
49682
|
+
fs97.mkdirSync(dir, { recursive: true });
|
|
49683
|
+
fs97.writeFileSync(cachePath, JSON.stringify(data), "utf-8");
|
|
49347
49684
|
} catch {
|
|
49348
49685
|
}
|
|
49349
49686
|
}
|
|
@@ -49486,17 +49823,17 @@ function registerWorldUpgrade(program2) {
|
|
|
49486
49823
|
|
|
49487
49824
|
// src/commands/mcp/serve.ts
|
|
49488
49825
|
init_output();
|
|
49489
|
-
import { existsSync as
|
|
49490
|
-
import { dirname as
|
|
49491
|
-
import { fileURLToPath as
|
|
49492
|
-
var here2 =
|
|
49826
|
+
import { existsSync as existsSync106 } from "node:fs";
|
|
49827
|
+
import { dirname as dirname60, resolve as resolve27 } from "node:path";
|
|
49828
|
+
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
49829
|
+
var here2 = dirname60(fileURLToPath10(import.meta.url));
|
|
49493
49830
|
var BUNDLE_PATH_CANDIDATES = [
|
|
49494
49831
|
// bundled (`dist/index.js` after bundle-cli.mjs) — sibling
|
|
49495
|
-
|
|
49832
|
+
resolve27(here2, "mcp-server.js"),
|
|
49496
49833
|
// dev / tsc-only (`dist/commands/mcp/serve.js`) — up two levels
|
|
49497
|
-
|
|
49834
|
+
resolve27(here2, "..", "..", "mcp-server.js")
|
|
49498
49835
|
];
|
|
49499
|
-
function resolveBundlePath(candidates2 = BUNDLE_PATH_CANDIDATES, exists =
|
|
49836
|
+
function resolveBundlePath(candidates2 = BUNDLE_PATH_CANDIDATES, exists = existsSync106) {
|
|
49500
49837
|
return candidates2.find(exists) ?? null;
|
|
49501
49838
|
}
|
|
49502
49839
|
var MISSING_BUNDLE_REMEDY = "olam mcp server bundle missing. Searched: " + BUNDLE_PATH_CANDIDATES.join(", ") + ". For local dev, run: node packages/cli/scripts/bundle-mcp-server.mjs. A fresh `npm install -g @pleri/olam-cli@latest` should always include the bundle (see prepublishOnly in packages/cli/package.json); file an issue if it does not.";
|
|
@@ -49760,7 +50097,7 @@ function registerMcpComplete(cmd) {
|
|
|
49760
50097
|
init_output();
|
|
49761
50098
|
import * as readline6 from "node:readline";
|
|
49762
50099
|
async function readTokenSilent(prompt) {
|
|
49763
|
-
return new Promise((
|
|
50100
|
+
return new Promise((resolve31, reject) => {
|
|
49764
50101
|
const rl = readline6.createInterface({
|
|
49765
50102
|
input: process.stdin,
|
|
49766
50103
|
output: process.stdout,
|
|
@@ -49778,7 +50115,7 @@ async function readTokenSilent(prompt) {
|
|
|
49778
50115
|
process.stdin.removeListener("data", onData);
|
|
49779
50116
|
process.stdout.write("\n");
|
|
49780
50117
|
rl.close();
|
|
49781
|
-
|
|
50118
|
+
resolve31(token);
|
|
49782
50119
|
} else if (char === "") {
|
|
49783
50120
|
if (process.stdin.isTTY) process.stdin.setRawMode(false);
|
|
49784
50121
|
process.stdin.removeListener("data", onData);
|
|
@@ -49933,12 +50270,12 @@ import * as readline7 from "node:readline";
|
|
|
49933
50270
|
import pc45 from "picocolors";
|
|
49934
50271
|
|
|
49935
50272
|
// src/commands/mcp/import-discovery.ts
|
|
49936
|
-
import * as
|
|
50273
|
+
import * as fs98 from "node:fs";
|
|
49937
50274
|
import * as os53 from "node:os";
|
|
49938
50275
|
import * as path96 from "node:path";
|
|
49939
50276
|
function readJsonFile(filePath) {
|
|
49940
50277
|
try {
|
|
49941
|
-
const raw =
|
|
50278
|
+
const raw = fs98.readFileSync(filePath, "utf-8");
|
|
49942
50279
|
return JSON.parse(raw);
|
|
49943
50280
|
} catch {
|
|
49944
50281
|
return null;
|
|
@@ -49982,9 +50319,9 @@ function getOlamRepoPaths() {
|
|
|
49982
50319
|
];
|
|
49983
50320
|
const paths = [];
|
|
49984
50321
|
for (const configPath of configPaths) {
|
|
49985
|
-
if (!
|
|
50322
|
+
if (!fs98.existsSync(configPath)) continue;
|
|
49986
50323
|
try {
|
|
49987
|
-
const raw =
|
|
50324
|
+
const raw = fs98.readFileSync(configPath, "utf-8");
|
|
49988
50325
|
const repoMatches = [...raw.matchAll(/path:\s*["']?([^\s"'\n]+)/g)];
|
|
49989
50326
|
for (const m of repoMatches) {
|
|
49990
50327
|
if (m[1]) paths.push(m[1]);
|
|
@@ -50053,7 +50390,7 @@ async function discoverMcpSources(repoPaths) {
|
|
|
50053
50390
|
import { spawn as spawn10 } from "node:child_process";
|
|
50054
50391
|
var VALIDATION_TIMEOUT_MS = 5e3;
|
|
50055
50392
|
async function validateMcpEntry(entry) {
|
|
50056
|
-
return new Promise((
|
|
50393
|
+
return new Promise((resolve31) => {
|
|
50057
50394
|
let stdout = "";
|
|
50058
50395
|
let timedOut = false;
|
|
50059
50396
|
let child;
|
|
@@ -50063,7 +50400,7 @@ async function validateMcpEntry(entry) {
|
|
|
50063
50400
|
env: { ...process.env, ...entry.env ?? {} }
|
|
50064
50401
|
});
|
|
50065
50402
|
} catch (err) {
|
|
50066
|
-
|
|
50403
|
+
resolve31({
|
|
50067
50404
|
name: entry.name,
|
|
50068
50405
|
validated: false,
|
|
50069
50406
|
reason: err instanceof Error ? err.message : "spawn failed"
|
|
@@ -50080,11 +50417,11 @@ async function validateMcpEntry(entry) {
|
|
|
50080
50417
|
child.on("close", (code) => {
|
|
50081
50418
|
clearTimeout(timer);
|
|
50082
50419
|
if (timedOut) {
|
|
50083
|
-
|
|
50420
|
+
resolve31({ name: entry.name, validated: false, reason: "timeout (5s)" });
|
|
50084
50421
|
return;
|
|
50085
50422
|
}
|
|
50086
50423
|
const validated = code === 0 && stdout.trim().length > 0;
|
|
50087
|
-
|
|
50424
|
+
resolve31({
|
|
50088
50425
|
name: entry.name,
|
|
50089
50426
|
validated,
|
|
50090
50427
|
reason: validated ? "ok" : `exit code ${code ?? "null"}`
|
|
@@ -50092,7 +50429,7 @@ async function validateMcpEntry(entry) {
|
|
|
50092
50429
|
});
|
|
50093
50430
|
child.on("error", (err) => {
|
|
50094
50431
|
clearTimeout(timer);
|
|
50095
|
-
|
|
50432
|
+
resolve31({ name: entry.name, validated: false, reason: err.message });
|
|
50096
50433
|
});
|
|
50097
50434
|
});
|
|
50098
50435
|
}
|
|
@@ -50107,11 +50444,11 @@ async function multiSelectPicker(entries) {
|
|
|
50107
50444
|
);
|
|
50108
50445
|
});
|
|
50109
50446
|
console.log("\n" + pc45.dim('Enter numbers to import (e.g. 1,2,3 or "all" or Enter to skip):'));
|
|
50110
|
-
const answer = await new Promise((
|
|
50447
|
+
const answer = await new Promise((resolve31) => {
|
|
50111
50448
|
const rl = readline7.createInterface({ input: process.stdin, output: process.stdout });
|
|
50112
50449
|
rl.question("> ", (ans) => {
|
|
50113
50450
|
rl.close();
|
|
50114
|
-
|
|
50451
|
+
resolve31(ans.trim());
|
|
50115
50452
|
});
|
|
50116
50453
|
});
|
|
50117
50454
|
if (!answer || answer === "") return [];
|
|
@@ -50258,14 +50595,14 @@ init_output();
|
|
|
50258
50595
|
|
|
50259
50596
|
// src/lib/memory-host-process-migration.ts
|
|
50260
50597
|
init_paths2();
|
|
50261
|
-
import { existsSync as
|
|
50598
|
+
import { existsSync as existsSync108, readFileSync as readFileSync94, unlinkSync as unlinkSync23 } from "node:fs";
|
|
50262
50599
|
import { spawnSync as spawnSync31 } from "node:child_process";
|
|
50263
50600
|
var KILL_TIMEOUT_MS = 5e3;
|
|
50264
50601
|
function migrateFromHostProcess(opts = {}) {
|
|
50265
50602
|
const pidPath2 = opts.pidPath ?? MEMORY_PID_PATH;
|
|
50266
50603
|
const logPath = opts.logPath ?? MEMORY_LOG_PATH;
|
|
50267
|
-
const pidfileExists =
|
|
50268
|
-
const logExists =
|
|
50604
|
+
const pidfileExists = existsSync108(pidPath2);
|
|
50605
|
+
const logExists = existsSync108(logPath);
|
|
50269
50606
|
if (!pidfileExists && !logExists) {
|
|
50270
50607
|
return { cleaned: false, summary: "no legacy host-process state to clean" };
|
|
50271
50608
|
}
|
|
@@ -50304,7 +50641,7 @@ function migrateFromHostProcess(opts = {}) {
|
|
|
50304
50641
|
}
|
|
50305
50642
|
function readPidFromFile(pidPath2) {
|
|
50306
50643
|
try {
|
|
50307
|
-
const raw =
|
|
50644
|
+
const raw = readFileSync94(pidPath2, "utf8").trim();
|
|
50308
50645
|
const pid = parseInt(raw, 10);
|
|
50309
50646
|
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
50310
50647
|
return pid;
|
|
@@ -50434,7 +50771,7 @@ function registerMemoryStop(cmd) {
|
|
|
50434
50771
|
init_output();
|
|
50435
50772
|
init_memory_secret();
|
|
50436
50773
|
init_paths2();
|
|
50437
|
-
import { existsSync as
|
|
50774
|
+
import { existsSync as existsSync109 } from "node:fs";
|
|
50438
50775
|
var RESTART_CHURN_THRESHOLD = 3;
|
|
50439
50776
|
async function probe(secret) {
|
|
50440
50777
|
try {
|
|
@@ -50461,7 +50798,7 @@ async function collectMemoryStatus() {
|
|
|
50461
50798
|
livez,
|
|
50462
50799
|
secretSet: hasMemorySecret(),
|
|
50463
50800
|
port: MEMORY_REST_PORT,
|
|
50464
|
-
legacyPidfilePresent:
|
|
50801
|
+
legacyPidfilePresent: existsSync109(MEMORY_PID_PATH),
|
|
50465
50802
|
startedAt: runtime?.startedAt ?? null,
|
|
50466
50803
|
restartCount: runtime?.restartCount ?? null,
|
|
50467
50804
|
health: runtime?.health ?? "unknown"
|
|
@@ -50548,8 +50885,8 @@ async function runMemoryLogs(opts) {
|
|
|
50548
50885
|
args.push(MEMORY_SERVICE_CONTAINER);
|
|
50549
50886
|
printHeader(`olam memory logs (${opts.follow ? "follow" : `tail -n ${tailN}`})`);
|
|
50550
50887
|
const child = spawn11("docker", args, { stdio: "inherit" });
|
|
50551
|
-
return new Promise((
|
|
50552
|
-
child.on("exit", (code) =>
|
|
50888
|
+
return new Promise((resolve31) => {
|
|
50889
|
+
child.on("exit", (code) => resolve31(code ?? 0));
|
|
50553
50890
|
});
|
|
50554
50891
|
}
|
|
50555
50892
|
function registerMemoryLogs(cmd) {
|
|
@@ -50685,14 +51022,14 @@ function registerMemoryUninstall(cmd) {
|
|
|
50685
51022
|
init_schema2();
|
|
50686
51023
|
init_output();
|
|
50687
51024
|
init_memory_secret();
|
|
50688
|
-
import { existsSync as
|
|
50689
|
-
import { join as
|
|
51025
|
+
import { existsSync as existsSync110, readFileSync as readFileSync95, writeFileSync as writeFileSync58 } from "node:fs";
|
|
51026
|
+
import { join as join106 } from "node:path";
|
|
50690
51027
|
import * as readline8 from "node:readline/promises";
|
|
50691
51028
|
import { parse as parseYaml9, stringify as stringifyYaml7 } from "yaml";
|
|
50692
51029
|
var CONFIG_REL = ".olam/config.yaml";
|
|
50693
51030
|
function locateConfig(cwd) {
|
|
50694
|
-
const absPath =
|
|
50695
|
-
if (!
|
|
51031
|
+
const absPath = join106(cwd, CONFIG_REL);
|
|
51032
|
+
if (!existsSync110(absPath)) {
|
|
50696
51033
|
throw new Error(
|
|
50697
51034
|
`No ${CONFIG_REL} at ${cwd}. Run \`olam init\` in your workspace root first.`
|
|
50698
51035
|
);
|
|
@@ -50700,7 +51037,7 @@ function locateConfig(cwd) {
|
|
|
50700
51037
|
return { absPath };
|
|
50701
51038
|
}
|
|
50702
51039
|
function readConfigYaml(absPath) {
|
|
50703
|
-
const raw =
|
|
51040
|
+
const raw = readFileSync95(absPath, "utf-8");
|
|
50704
51041
|
const parsed = parseYaml9(raw) ?? {};
|
|
50705
51042
|
if (typeof parsed !== "object" || parsed === null) {
|
|
50706
51043
|
throw new Error(`${absPath} is not a YAML object`);
|
|
@@ -50709,7 +51046,7 @@ function readConfigYaml(absPath) {
|
|
|
50709
51046
|
}
|
|
50710
51047
|
function writeConfigYaml(absPath, parsed) {
|
|
50711
51048
|
const out = stringifyYaml7(parsed, { aliasDuplicateObjects: false });
|
|
50712
|
-
|
|
51049
|
+
writeFileSync58(absPath, out, "utf-8");
|
|
50713
51050
|
}
|
|
50714
51051
|
async function defaultPromptText(question) {
|
|
50715
51052
|
const rl = readline8.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -50830,20 +51167,20 @@ init_output();
|
|
|
50830
51167
|
init_memory_secret();
|
|
50831
51168
|
init_paths2();
|
|
50832
51169
|
import { spawn as spawn12 } from "node:child_process";
|
|
50833
|
-
import { existsSync as
|
|
50834
|
-
import { join as
|
|
51170
|
+
import { existsSync as existsSync111 } from "node:fs";
|
|
51171
|
+
import { join as join107 } from "node:path";
|
|
50835
51172
|
var DEFAULT_PORT2 = 8788;
|
|
50836
51173
|
function resolveMemoryServiceDir() {
|
|
50837
51174
|
for (const c of MEMORY_SERVICE_CANDIDATES) {
|
|
50838
|
-
if (
|
|
51175
|
+
if (existsSync111(c)) return c;
|
|
50839
51176
|
}
|
|
50840
51177
|
throw new Error(
|
|
50841
51178
|
`Could not find packages/memory-service/. Searched: ${MEMORY_SERVICE_CANDIDATES.join(", ")}. If running from a published @pleri/olam-cli tarball, this is a packaging bug \u2014 please file an issue.`
|
|
50842
51179
|
);
|
|
50843
51180
|
}
|
|
50844
51181
|
function resolveLocalBridgeScript(serviceDir) {
|
|
50845
|
-
const path106 =
|
|
50846
|
-
if (!
|
|
51182
|
+
const path106 = join107(serviceDir, "scripts", "local-bridge-server.mjs");
|
|
51183
|
+
if (!existsSync111(path106)) {
|
|
50847
51184
|
throw new Error(
|
|
50848
51185
|
`Could not find local-bridge-server.mjs at ${path106}. Verify packages/memory-service ships the scripts/ directory.`
|
|
50849
51186
|
);
|
|
@@ -50891,12 +51228,12 @@ async function runBridgeServe(opts, deps = {}) {
|
|
|
50891
51228
|
stdio: "inherit"
|
|
50892
51229
|
}));
|
|
50893
51230
|
const child = spawner(process.execPath, [scriptPath, ...args], env);
|
|
50894
|
-
return new Promise((
|
|
51231
|
+
return new Promise((resolve31) => {
|
|
50895
51232
|
let resolved = false;
|
|
50896
51233
|
const finish = (code) => {
|
|
50897
51234
|
if (resolved) return;
|
|
50898
51235
|
resolved = true;
|
|
50899
|
-
|
|
51236
|
+
resolve31(code);
|
|
50900
51237
|
};
|
|
50901
51238
|
const forward = (signal) => () => {
|
|
50902
51239
|
if (!child.killed) {
|
|
@@ -51184,38 +51521,38 @@ function registerMemoryStats(cmd) {
|
|
|
51184
51521
|
}
|
|
51185
51522
|
|
|
51186
51523
|
// src/commands/memory/install-hooks.ts
|
|
51187
|
-
import { copyFileSync as copyFileSync12, existsSync as
|
|
51188
|
-
import { homedir as
|
|
51189
|
-
import { dirname as
|
|
51190
|
-
import { fileURLToPath as
|
|
51524
|
+
import { copyFileSync as copyFileSync12, existsSync as existsSync112, mkdirSync as mkdirSync65, readFileSync as readFileSync96, writeFileSync as writeFileSync59 } from "node:fs";
|
|
51525
|
+
import { homedir as homedir63 } from "node:os";
|
|
51526
|
+
import { dirname as dirname61, join as join108, resolve as resolve28 } from "node:path";
|
|
51527
|
+
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
51191
51528
|
var HOOK_BASENAMES = [
|
|
51192
51529
|
"agentmemory-session-recall.js",
|
|
51193
51530
|
"agentmemory-recall-trigger.mjs",
|
|
51194
51531
|
"agentmemory-classify-queue.mjs"
|
|
51195
51532
|
];
|
|
51196
51533
|
function defaultSourceDir() {
|
|
51197
|
-
const here3 =
|
|
51198
|
-
const candidate =
|
|
51199
|
-
if (
|
|
51200
|
-
const srcCandidate =
|
|
51201
|
-
if (
|
|
51534
|
+
const here3 = dirname61(fileURLToPath11(import.meta.url));
|
|
51535
|
+
const candidate = resolve28(here3, "..", "..", "..", "memory-service", "hooks");
|
|
51536
|
+
if (existsSync112(candidate)) return candidate;
|
|
51537
|
+
const srcCandidate = resolve28(here3, "..", "..", "..", "..", "memory-service", "hooks");
|
|
51538
|
+
if (existsSync112(srcCandidate)) return srcCandidate;
|
|
51202
51539
|
return candidate;
|
|
51203
51540
|
}
|
|
51204
51541
|
function installOne2(basename17, sourceDir, targetDir, opts) {
|
|
51205
|
-
const sourcePath =
|
|
51206
|
-
const targetPath =
|
|
51207
|
-
if (!
|
|
51542
|
+
const sourcePath = join108(sourceDir, basename17);
|
|
51543
|
+
const targetPath = join108(targetDir, basename17);
|
|
51544
|
+
if (!existsSync112(sourcePath)) {
|
|
51208
51545
|
throw new Error(`canonical hook source missing at ${sourcePath} \u2014 olam install corrupt or sourceDir is wrong`);
|
|
51209
51546
|
}
|
|
51210
|
-
const newContent =
|
|
51211
|
-
if (!
|
|
51547
|
+
const newContent = readFileSync96(sourcePath, "utf8");
|
|
51548
|
+
if (!existsSync112(targetPath)) {
|
|
51212
51549
|
if (opts.dryRun !== true) {
|
|
51213
|
-
|
|
51214
|
-
|
|
51550
|
+
mkdirSync65(dirname61(targetPath), { recursive: true });
|
|
51551
|
+
writeFileSync59(targetPath, newContent, { mode: 493 });
|
|
51215
51552
|
}
|
|
51216
51553
|
return { basename: basename17, action: "written", targetPath };
|
|
51217
51554
|
}
|
|
51218
|
-
const existing =
|
|
51555
|
+
const existing = readFileSync96(targetPath, "utf8");
|
|
51219
51556
|
if (existing === newContent) {
|
|
51220
51557
|
return { basename: basename17, action: "unchanged", targetPath };
|
|
51221
51558
|
}
|
|
@@ -51223,7 +51560,7 @@ function installOne2(basename17, sourceDir, targetDir, opts) {
|
|
|
51223
51560
|
const backupPath = `${targetPath}.agentmemory-hook-backup-${Math.floor(Date.now() / 1e3)}`;
|
|
51224
51561
|
if (opts.dryRun !== true) {
|
|
51225
51562
|
copyFileSync12(targetPath, backupPath);
|
|
51226
|
-
|
|
51563
|
+
writeFileSync59(targetPath, newContent, { mode: 493 });
|
|
51227
51564
|
}
|
|
51228
51565
|
return { basename: basename17, action: "force-overwritten", targetPath, backupPath };
|
|
51229
51566
|
}
|
|
@@ -51238,13 +51575,13 @@ Add these hook entries to ~/.claude/settings.json:
|
|
|
51238
51575
|
{
|
|
51239
51576
|
"hooks": {
|
|
51240
51577
|
"SessionStart": [
|
|
51241
|
-
{ "command": "node ${
|
|
51578
|
+
{ "command": "node ${join108(targetDir, "agentmemory-session-recall.js")}" }
|
|
51242
51579
|
],
|
|
51243
51580
|
"PreToolUse": [
|
|
51244
|
-
{ "command": "node ${
|
|
51581
|
+
{ "command": "node ${join108(targetDir, "agentmemory-recall-trigger.mjs")}" }
|
|
51245
51582
|
],
|
|
51246
51583
|
"PostToolUse": [
|
|
51247
|
-
{ "command": "node ${
|
|
51584
|
+
{ "command": "node ${join108(targetDir, "agentmemory-classify-queue.mjs")}" }
|
|
51248
51585
|
]
|
|
51249
51586
|
}
|
|
51250
51587
|
}
|
|
@@ -51254,7 +51591,7 @@ If existing entries already point at the same paths, no edit needed.
|
|
|
51254
51591
|
}
|
|
51255
51592
|
function registerMemoryInstallHooks(parent) {
|
|
51256
51593
|
parent.command("install-hooks").description("Install agentmemory hooks (PreToolUse + PostToolUse + SessionStart) to ~/.claude/scripts/hooks/").option("--force", "overwrite existing non-canonical files (backs them up to .agentmemory-hook-backup-<ts>)").option("--dry-run", "preview which hooks would be written without modifying disk").option("--target-dir <path>", "override target directory (default: ~/.claude/scripts/hooks/); for tests").option("--source-dir <path>", "override source directory (default: packages/memory-service/hooks/); for tests").action((opts) => {
|
|
51257
|
-
const targetDir = opts.targetDir ??
|
|
51594
|
+
const targetDir = opts.targetDir ?? join108(homedir63(), ".claude", "scripts", "hooks");
|
|
51258
51595
|
const sourceDir = opts.sourceDir ?? defaultSourceDir();
|
|
51259
51596
|
let written = 0;
|
|
51260
51597
|
let unchanged = 0;
|
|
@@ -51330,7 +51667,7 @@ function registerMemory(program2) {
|
|
|
51330
51667
|
// src/commands/kg-build.ts
|
|
51331
51668
|
init_storage_paths();
|
|
51332
51669
|
init_workspace_name();
|
|
51333
|
-
import * as
|
|
51670
|
+
import * as fs104 from "node:fs";
|
|
51334
51671
|
import * as os57 from "node:os";
|
|
51335
51672
|
import * as path102 from "node:path";
|
|
51336
51673
|
|
|
@@ -51424,11 +51761,11 @@ init_storage_paths();
|
|
|
51424
51761
|
init_workspace_name();
|
|
51425
51762
|
init_kg_caps();
|
|
51426
51763
|
init_output();
|
|
51427
|
-
import
|
|
51428
|
-
import { homedir as
|
|
51764
|
+
import fs99 from "node:fs";
|
|
51765
|
+
import { homedir as homedir64 } from "node:os";
|
|
51429
51766
|
import path97 from "node:path";
|
|
51430
51767
|
function olamHome5() {
|
|
51431
|
-
return process.env.OLAM_HOME ?? path97.join(
|
|
51768
|
+
return process.env.OLAM_HOME ?? path97.join(homedir64(), ".olam");
|
|
51432
51769
|
}
|
|
51433
51770
|
function kgRoot2() {
|
|
51434
51771
|
return path97.join(olamHome5(), "kg");
|
|
@@ -51437,14 +51774,14 @@ function worldsRoot2() {
|
|
|
51437
51774
|
return path97.join(olamHome5(), "worlds");
|
|
51438
51775
|
}
|
|
51439
51776
|
function dirSizeBytes2(dir) {
|
|
51440
|
-
if (!
|
|
51777
|
+
if (!fs99.existsSync(dir)) return 0;
|
|
51441
51778
|
let total = 0;
|
|
51442
51779
|
const stack = [dir];
|
|
51443
51780
|
while (stack.length > 0) {
|
|
51444
51781
|
const cur = stack.pop();
|
|
51445
51782
|
let entries;
|
|
51446
51783
|
try {
|
|
51447
|
-
entries =
|
|
51784
|
+
entries = fs99.readdirSync(cur, { withFileTypes: true });
|
|
51448
51785
|
} catch {
|
|
51449
51786
|
continue;
|
|
51450
51787
|
}
|
|
@@ -51456,7 +51793,7 @@ function dirSizeBytes2(dir) {
|
|
|
51456
51793
|
continue;
|
|
51457
51794
|
}
|
|
51458
51795
|
try {
|
|
51459
|
-
total +=
|
|
51796
|
+
total += fs99.statSync(full).size;
|
|
51460
51797
|
} catch {
|
|
51461
51798
|
}
|
|
51462
51799
|
}
|
|
@@ -51471,9 +51808,9 @@ function formatBytes5(n) {
|
|
|
51471
51808
|
}
|
|
51472
51809
|
function readFreshness(workspace) {
|
|
51473
51810
|
const file = path97.join(kgPristinePath(workspace), "freshness.json");
|
|
51474
|
-
if (!
|
|
51811
|
+
if (!fs99.existsSync(file)) return null;
|
|
51475
51812
|
try {
|
|
51476
|
-
const raw = JSON.parse(
|
|
51813
|
+
const raw = JSON.parse(fs99.readFileSync(file, "utf-8"));
|
|
51477
51814
|
if (raw && typeof raw === "object") return raw;
|
|
51478
51815
|
return null;
|
|
51479
51816
|
} catch {
|
|
@@ -51482,9 +51819,9 @@ function readFreshness(workspace) {
|
|
|
51482
51819
|
}
|
|
51483
51820
|
function readOverlayNodeCount(graphifyOutDir) {
|
|
51484
51821
|
const graphPath = path97.join(graphifyOutDir, "graph.json");
|
|
51485
|
-
if (!
|
|
51822
|
+
if (!fs99.existsSync(graphPath)) return null;
|
|
51486
51823
|
try {
|
|
51487
|
-
const raw = JSON.parse(
|
|
51824
|
+
const raw = JSON.parse(fs99.readFileSync(graphPath, "utf-8"));
|
|
51488
51825
|
if (raw && typeof raw === "object") {
|
|
51489
51826
|
const nodes = raw.nodes;
|
|
51490
51827
|
if (Array.isArray(nodes)) return nodes.length;
|
|
@@ -51496,11 +51833,11 @@ function readOverlayNodeCount(graphifyOutDir) {
|
|
|
51496
51833
|
}
|
|
51497
51834
|
function listOverlays() {
|
|
51498
51835
|
const root = worldsRoot2();
|
|
51499
|
-
if (!
|
|
51836
|
+
if (!fs99.existsSync(root)) return [];
|
|
51500
51837
|
const records = [];
|
|
51501
51838
|
let worldDirs;
|
|
51502
51839
|
try {
|
|
51503
|
-
worldDirs =
|
|
51840
|
+
worldDirs = fs99.readdirSync(root, { withFileTypes: true });
|
|
51504
51841
|
} catch {
|
|
51505
51842
|
return [];
|
|
51506
51843
|
}
|
|
@@ -51510,14 +51847,14 @@ function listOverlays() {
|
|
|
51510
51847
|
const worldDir = path97.join(root, worldId);
|
|
51511
51848
|
let cloneDirs;
|
|
51512
51849
|
try {
|
|
51513
|
-
cloneDirs =
|
|
51850
|
+
cloneDirs = fs99.readdirSync(worldDir, { withFileTypes: true });
|
|
51514
51851
|
} catch {
|
|
51515
51852
|
continue;
|
|
51516
51853
|
}
|
|
51517
51854
|
for (const cloneEntry of cloneDirs) {
|
|
51518
51855
|
if (!cloneEntry.isDirectory()) continue;
|
|
51519
51856
|
const graphifyOut = path97.join(worldDir, cloneEntry.name, "graphify-out");
|
|
51520
|
-
if (!
|
|
51857
|
+
if (!fs99.existsSync(graphifyOut)) continue;
|
|
51521
51858
|
records.push({
|
|
51522
51859
|
world_id: worldId,
|
|
51523
51860
|
clone_dir: cloneEntry.name,
|
|
@@ -51531,11 +51868,11 @@ function listOverlays() {
|
|
|
51531
51868
|
}
|
|
51532
51869
|
function listPristines(overlays) {
|
|
51533
51870
|
const root = kgRoot2();
|
|
51534
|
-
if (!
|
|
51871
|
+
if (!fs99.existsSync(root)) return [];
|
|
51535
51872
|
const records = [];
|
|
51536
51873
|
let entries;
|
|
51537
51874
|
try {
|
|
51538
|
-
entries =
|
|
51875
|
+
entries = fs99.readdirSync(root, { withFileTypes: true });
|
|
51539
51876
|
} catch {
|
|
51540
51877
|
return [];
|
|
51541
51878
|
}
|
|
@@ -51684,7 +52021,7 @@ init_storage_paths();
|
|
|
51684
52021
|
init_workspace_name();
|
|
51685
52022
|
init_output();
|
|
51686
52023
|
import { spawn as spawn13 } from "node:child_process";
|
|
51687
|
-
import
|
|
52024
|
+
import fs100 from "node:fs";
|
|
51688
52025
|
import path98 from "node:path";
|
|
51689
52026
|
function pidFilePath2(workspace) {
|
|
51690
52027
|
return path98.join(kgPristinePath(workspace), ".watch.pid");
|
|
@@ -51702,33 +52039,33 @@ function isPidAlive3(pid) {
|
|
|
51702
52039
|
}
|
|
51703
52040
|
function readAndClassifyPid(workspace) {
|
|
51704
52041
|
const file = pidFilePath2(workspace);
|
|
51705
|
-
if (!
|
|
52042
|
+
if (!fs100.existsSync(file)) return { status: "no-pidfile", pid: null };
|
|
51706
52043
|
let pid;
|
|
51707
52044
|
try {
|
|
51708
|
-
const raw =
|
|
52045
|
+
const raw = fs100.readFileSync(file, "utf-8").trim();
|
|
51709
52046
|
pid = Number.parseInt(raw, 10);
|
|
51710
52047
|
} catch {
|
|
51711
|
-
|
|
52048
|
+
fs100.rmSync(file, { force: true });
|
|
51712
52049
|
return { status: "stale-reclaimed", pid: null };
|
|
51713
52050
|
}
|
|
51714
52051
|
if (!Number.isInteger(pid) || pid <= 0) {
|
|
51715
|
-
|
|
52052
|
+
fs100.rmSync(file, { force: true });
|
|
51716
52053
|
return { status: "stale-reclaimed", pid: null };
|
|
51717
52054
|
}
|
|
51718
52055
|
if (isPidAlive3(pid)) return { status: "active", pid };
|
|
51719
|
-
|
|
52056
|
+
fs100.rmSync(file, { force: true });
|
|
51720
52057
|
return { status: "stale-reclaimed", pid: null };
|
|
51721
52058
|
}
|
|
51722
52059
|
function writePidFile2(workspace, pid) {
|
|
51723
52060
|
const file = pidFilePath2(workspace);
|
|
51724
52061
|
const dir = path98.dirname(file);
|
|
51725
|
-
|
|
51726
|
-
|
|
52062
|
+
fs100.mkdirSync(dir, { recursive: true });
|
|
52063
|
+
fs100.writeFileSync(file, String(pid), { encoding: "utf-8" });
|
|
51727
52064
|
}
|
|
51728
52065
|
function removePidFile(workspace) {
|
|
51729
52066
|
const file = pidFilePath2(workspace);
|
|
51730
52067
|
try {
|
|
51731
|
-
|
|
52068
|
+
fs100.rmSync(file, { force: true });
|
|
51732
52069
|
} catch {
|
|
51733
52070
|
}
|
|
51734
52071
|
}
|
|
@@ -51782,16 +52119,16 @@ async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
|
51782
52119
|
process.on("SIGINT", () => forward("SIGINT"));
|
|
51783
52120
|
process.on("SIGTERM", () => forward("SIGTERM"));
|
|
51784
52121
|
}
|
|
51785
|
-
return new Promise((
|
|
52122
|
+
return new Promise((resolve31) => {
|
|
51786
52123
|
child.on("exit", (code, signal) => {
|
|
51787
52124
|
removePidFile(name);
|
|
51788
52125
|
const exitCode = typeof code === "number" ? code : signal === "SIGINT" || signal === "SIGTERM" ? 0 : 1;
|
|
51789
|
-
|
|
52126
|
+
resolve31({ exitCode, pidWritten: true });
|
|
51790
52127
|
});
|
|
51791
52128
|
child.on("error", (err) => {
|
|
51792
52129
|
removePidFile(name);
|
|
51793
52130
|
printError(`graphify subprocess error: ${err.message}`);
|
|
51794
|
-
|
|
52131
|
+
resolve31({ exitCode: 1, pidWritten: true });
|
|
51795
52132
|
});
|
|
51796
52133
|
});
|
|
51797
52134
|
}
|
|
@@ -52055,7 +52392,7 @@ function registerKgDoctorCommand(kg) {
|
|
|
52055
52392
|
init_merge_settings();
|
|
52056
52393
|
init_hook_template2();
|
|
52057
52394
|
init_output();
|
|
52058
|
-
import * as
|
|
52395
|
+
import * as fs101 from "node:fs";
|
|
52059
52396
|
import * as path99 from "node:path";
|
|
52060
52397
|
import * as os54 from "node:os";
|
|
52061
52398
|
import { parse as yamlParse3, stringify as yamlStringify4 } from "yaml";
|
|
@@ -52066,10 +52403,10 @@ function settingsPathFor2(scope) {
|
|
|
52066
52403
|
return path99.join(process.cwd(), ".claude", "settings.json");
|
|
52067
52404
|
}
|
|
52068
52405
|
function backup2(filePath) {
|
|
52069
|
-
if (!
|
|
52406
|
+
if (!fs101.existsSync(filePath)) return null;
|
|
52070
52407
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
52071
52408
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
52072
|
-
|
|
52409
|
+
fs101.copyFileSync(filePath, backupPath);
|
|
52073
52410
|
return backupPath;
|
|
52074
52411
|
}
|
|
52075
52412
|
var HERMES_HOOK_MATCHERS = ["terminal", "bash", "shell", "search_files", "grep", "ripgrep"];
|
|
@@ -52081,7 +52418,7 @@ function hermesHooksDir() {
|
|
|
52081
52418
|
}
|
|
52082
52419
|
function patchHermesConfigForHook(action) {
|
|
52083
52420
|
const configPath = hermesConfigPath2();
|
|
52084
|
-
const raw =
|
|
52421
|
+
const raw = fs101.readFileSync(configPath, "utf-8");
|
|
52085
52422
|
const config = yamlParse3(raw);
|
|
52086
52423
|
const hooks = config["hooks"] ?? {};
|
|
52087
52424
|
const preToolCall = Array.isArray(hooks["pre_tool_call"]) ? hooks["pre_tool_call"] : [];
|
|
@@ -52100,7 +52437,7 @@ function patchHermesConfigForHook(action) {
|
|
|
52100
52437
|
hooks: { ...hooks, pre_tool_call: [...preToolCall, entry] },
|
|
52101
52438
|
hooks_auto_accept: true
|
|
52102
52439
|
};
|
|
52103
|
-
|
|
52440
|
+
fs101.writeFileSync(configPath, yamlStringify4(updated2), "utf-8");
|
|
52104
52441
|
return "patched";
|
|
52105
52442
|
}
|
|
52106
52443
|
const filtered = preToolCall.filter(
|
|
@@ -52111,12 +52448,12 @@ function patchHermesConfigForHook(action) {
|
|
|
52111
52448
|
...config,
|
|
52112
52449
|
hooks: { ...hooks, pre_tool_call: filtered }
|
|
52113
52450
|
};
|
|
52114
|
-
|
|
52451
|
+
fs101.writeFileSync(configPath, yamlStringify4(updated), "utf-8");
|
|
52115
52452
|
return "patched";
|
|
52116
52453
|
}
|
|
52117
52454
|
function doInstallForHermes() {
|
|
52118
52455
|
const configPath = hermesConfigPath2();
|
|
52119
|
-
if (!
|
|
52456
|
+
if (!fs101.existsSync(configPath)) {
|
|
52120
52457
|
printError(`~/.hermes/config.yaml not found at ${configPath}`);
|
|
52121
52458
|
printInfo("remedy", "Install Hermes first, then re-run `olam kg install-hook --for hermes`");
|
|
52122
52459
|
process.exitCode = 1;
|
|
@@ -52146,15 +52483,15 @@ function doUninstallForHermes() {
|
|
|
52146
52483
|
const hooksDir = hermesHooksDir();
|
|
52147
52484
|
const hookScriptPath = path99.join(hooksDir, "kg-first.sh");
|
|
52148
52485
|
let scriptRemoved = false;
|
|
52149
|
-
if (
|
|
52150
|
-
const content =
|
|
52486
|
+
if (fs101.existsSync(hookScriptPath)) {
|
|
52487
|
+
const content = fs101.readFileSync(hookScriptPath, "utf-8");
|
|
52151
52488
|
if (content.includes(HERMES_KG_HOOK_SENTINEL)) {
|
|
52152
|
-
|
|
52489
|
+
fs101.unlinkSync(hookScriptPath);
|
|
52153
52490
|
scriptRemoved = true;
|
|
52154
52491
|
}
|
|
52155
52492
|
}
|
|
52156
52493
|
let configPatched = false;
|
|
52157
|
-
if (
|
|
52494
|
+
if (fs101.existsSync(configPath)) {
|
|
52158
52495
|
const result = patchHermesConfigForHook("uninstall");
|
|
52159
52496
|
configPatched = result === "patched";
|
|
52160
52497
|
}
|
|
@@ -52179,7 +52516,7 @@ function registerKgInstallHookCommand(kg) {
|
|
|
52179
52516
|
const scope = opts.scope === "user" ? "user" : "project";
|
|
52180
52517
|
const filePath = settingsPathFor2(scope);
|
|
52181
52518
|
try {
|
|
52182
|
-
|
|
52519
|
+
fs101.mkdirSync(path99.dirname(filePath), { recursive: true });
|
|
52183
52520
|
} catch (err) {
|
|
52184
52521
|
printError(`could not create ${path99.dirname(filePath)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
52185
52522
|
process.exitCode = 1;
|
|
@@ -52205,7 +52542,7 @@ function registerKgInstallHookCommand(kg) {
|
|
|
52205
52542
|
printInfo("kg-service hook", `already installed at ${filePath}`);
|
|
52206
52543
|
if (backupPath) {
|
|
52207
52544
|
try {
|
|
52208
|
-
|
|
52545
|
+
fs101.unlinkSync(backupPath);
|
|
52209
52546
|
} catch {
|
|
52210
52547
|
}
|
|
52211
52548
|
}
|
|
@@ -52225,7 +52562,7 @@ function registerKgInstallHookCommand(kg) {
|
|
|
52225
52562
|
// src/commands/kg-uninstall-hook.ts
|
|
52226
52563
|
init_hook_template2();
|
|
52227
52564
|
init_output();
|
|
52228
|
-
import * as
|
|
52565
|
+
import * as fs102 from "node:fs";
|
|
52229
52566
|
import * as path100 from "node:path";
|
|
52230
52567
|
import * as os55 from "node:os";
|
|
52231
52568
|
function settingsPathFor3(scope) {
|
|
@@ -52262,13 +52599,13 @@ function registerKgUninstallHookCommand(kg) {
|
|
|
52262
52599
|
kg.command("uninstall-hook").description("Remove kg-service PreToolUse hook from .claude/settings.json (sentinel-matched; surgical)").option("--scope <scope>", "project (default) or user", "project").action((opts) => {
|
|
52263
52600
|
const scope = opts.scope === "user" ? "user" : "project";
|
|
52264
52601
|
const filePath = settingsPathFor3(scope);
|
|
52265
|
-
if (!
|
|
52602
|
+
if (!fs102.existsSync(filePath)) {
|
|
52266
52603
|
printInfo("kg-service hook", `no settings.json at ${filePath} \u2014 nothing to remove`);
|
|
52267
52604
|
return;
|
|
52268
52605
|
}
|
|
52269
52606
|
let settings;
|
|
52270
52607
|
try {
|
|
52271
|
-
const raw =
|
|
52608
|
+
const raw = fs102.readFileSync(filePath, "utf-8");
|
|
52272
52609
|
settings = raw.trim() ? JSON.parse(raw) : {};
|
|
52273
52610
|
} catch (err) {
|
|
52274
52611
|
printError(`could not parse ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -52288,7 +52625,7 @@ function registerKgUninstallHookCommand(kg) {
|
|
|
52288
52625
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
52289
52626
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
52290
52627
|
try {
|
|
52291
|
-
|
|
52628
|
+
fs102.copyFileSync(filePath, backupPath);
|
|
52292
52629
|
} catch {
|
|
52293
52630
|
}
|
|
52294
52631
|
const next = {
|
|
@@ -52307,7 +52644,7 @@ function registerKgUninstallHookCommand(kg) {
|
|
|
52307
52644
|
}
|
|
52308
52645
|
}
|
|
52309
52646
|
try {
|
|
52310
|
-
|
|
52647
|
+
fs102.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
52311
52648
|
printSuccess(`kg-service hook removed from ${filePath}`);
|
|
52312
52649
|
printInfo("backup", backupPath);
|
|
52313
52650
|
} catch (err) {
|
|
@@ -52380,7 +52717,7 @@ function registerKgSavingsCommand(kg) {
|
|
|
52380
52717
|
|
|
52381
52718
|
// src/commands/kg-mirror.ts
|
|
52382
52719
|
init_output();
|
|
52383
|
-
import * as
|
|
52720
|
+
import * as fs103 from "node:fs";
|
|
52384
52721
|
import * as os56 from "node:os";
|
|
52385
52722
|
import * as path101 from "node:path";
|
|
52386
52723
|
function readEnvOrFile(envVar, fileName) {
|
|
@@ -52388,7 +52725,7 @@ function readEnvOrFile(envVar, fileName) {
|
|
|
52388
52725
|
if (fromEnv && fromEnv.length > 0) return fromEnv.trim();
|
|
52389
52726
|
try {
|
|
52390
52727
|
const file = path101.join(os56.homedir(), ".olam", fileName);
|
|
52391
|
-
const content =
|
|
52728
|
+
const content = fs103.readFileSync(file, "utf-8").trim();
|
|
52392
52729
|
if (content.length > 0) return content;
|
|
52393
52730
|
} catch {
|
|
52394
52731
|
}
|
|
@@ -52568,6 +52905,76 @@ async function runKgMirrorClassify(question, options = {}) {
|
|
|
52568
52905
|
printInfo("est. savings", `~${Math.round(Number(savings2) / 1e3)}k tokens`);
|
|
52569
52906
|
return { exitCode: 0 };
|
|
52570
52907
|
}
|
|
52908
|
+
async function runKgMirrorGraph(symbol, options = {}) {
|
|
52909
|
+
const cfg = resolveClassifier();
|
|
52910
|
+
if (!cfg) {
|
|
52911
|
+
printError(
|
|
52912
|
+
"kg-mirror URL/bearer not configured. Set OLAM_KG_PROXY_URL + OLAM_KG_PROXY_BEARER (or ~/.olam/kg-proxy-url + ~/.olam/kg-proxy-bearer)."
|
|
52913
|
+
);
|
|
52914
|
+
return { exitCode: 3 };
|
|
52915
|
+
}
|
|
52916
|
+
if (!options.workspace) {
|
|
52917
|
+
printError("graph query needs a --workspace (e.g. --workspace atlas-one).");
|
|
52918
|
+
return { exitCode: 2 };
|
|
52919
|
+
}
|
|
52920
|
+
const sym = (symbol ?? "").trim();
|
|
52921
|
+
if (!sym && !options.repo) {
|
|
52922
|
+
printError("provide a <symbol> to search, and/or --repo <name> to browse a repo.");
|
|
52923
|
+
return { exitCode: 2 };
|
|
52924
|
+
}
|
|
52925
|
+
const mode = options.relates ? "relates" : "where";
|
|
52926
|
+
const body = { workspace: options.workspace, symbol: sym, mode };
|
|
52927
|
+
if (options.repo) body.repo = options.repo;
|
|
52928
|
+
if (options.limit) {
|
|
52929
|
+
const n = Number.parseInt(options.limit, 10);
|
|
52930
|
+
if (Number.isFinite(n) && n > 0) body.limit = n;
|
|
52931
|
+
}
|
|
52932
|
+
let res;
|
|
52933
|
+
try {
|
|
52934
|
+
res = await fetch(`${cfg.url}/v1/graph`, {
|
|
52935
|
+
method: "POST",
|
|
52936
|
+
headers: { Authorization: `Bearer ${cfg.bearer}`, "Content-Type": "application/json" },
|
|
52937
|
+
body: JSON.stringify(body)
|
|
52938
|
+
});
|
|
52939
|
+
} catch (err) {
|
|
52940
|
+
printError(`kg-mirror unreachable: ${err instanceof Error ? err.message : String(err)}`);
|
|
52941
|
+
return { exitCode: 4 };
|
|
52942
|
+
}
|
|
52943
|
+
const text = await res.text();
|
|
52944
|
+
if (options.json) {
|
|
52945
|
+
process.stdout.write(text + "\n");
|
|
52946
|
+
return { exitCode: res.ok ? 0 : 1 };
|
|
52947
|
+
}
|
|
52948
|
+
let j;
|
|
52949
|
+
try {
|
|
52950
|
+
j = JSON.parse(text);
|
|
52951
|
+
} catch {
|
|
52952
|
+
printError(`kg-mirror returned non-JSON (HTTP ${res.status}): ${text.slice(0, 200)}`);
|
|
52953
|
+
return { exitCode: 1 };
|
|
52954
|
+
}
|
|
52955
|
+
if (!res.ok) {
|
|
52956
|
+
printError(`graph /v1/graph failed (HTTP ${res.status}): ${j.error ?? "?"}`);
|
|
52957
|
+
if (j.detail) printInfo("detail", String(j.detail));
|
|
52958
|
+
return { exitCode: 1 };
|
|
52959
|
+
}
|
|
52960
|
+
const matched = j.matched ?? [];
|
|
52961
|
+
printInfo("graph", `${options.workspace} \xB7 ${mode} \xB7 "${symbol}"`);
|
|
52962
|
+
if (matched.length === 0) {
|
|
52963
|
+
printInfo("matched", "no nodes match that symbol");
|
|
52964
|
+
}
|
|
52965
|
+
for (const m of matched) {
|
|
52966
|
+
printSuccess(`${m.label} ${m.file}:${String(m.loc ?? "").replace(/^L/, "")}`);
|
|
52967
|
+
}
|
|
52968
|
+
if (mode === "relates") {
|
|
52969
|
+
const relates = j.relates ?? [];
|
|
52970
|
+
for (const e of relates) {
|
|
52971
|
+
const arrow = e.direction === "out" ? "\u2192" : "\u2190";
|
|
52972
|
+
printInfo(String(e.relation), `${arrow} ${e.label} (${e.file})`);
|
|
52973
|
+
}
|
|
52974
|
+
}
|
|
52975
|
+
if (j.truncated) printInfo("note", "results truncated \u2014 pass --limit to widen");
|
|
52976
|
+
return { exitCode: 0 };
|
|
52977
|
+
}
|
|
52571
52978
|
function guessGitUrl(workspace) {
|
|
52572
52979
|
try {
|
|
52573
52980
|
const { spawnSync: spawnSync35 } = __require("node:child_process");
|
|
@@ -52578,7 +52985,7 @@ function guessGitUrl(workspace) {
|
|
|
52578
52985
|
path101.join(os56.homedir(), "Projects", workspace)
|
|
52579
52986
|
];
|
|
52580
52987
|
for (const dir of candidates2) {
|
|
52581
|
-
if (!
|
|
52988
|
+
if (!fs103.existsSync(path101.join(dir, ".git"))) continue;
|
|
52582
52989
|
const r = spawnSync35("git", ["-C", dir, "remote", "get-url", "origin"], {
|
|
52583
52990
|
encoding: "utf-8"
|
|
52584
52991
|
});
|
|
@@ -52607,12 +53014,16 @@ function registerKgMirrorCommand(kg) {
|
|
|
52607
53014
|
const r = await runKgMirrorClassify(question, opts);
|
|
52608
53015
|
if (r.exitCode !== 0) process.exitCode = r.exitCode;
|
|
52609
53016
|
});
|
|
53017
|
+
mirror.command("graph").description("Query the cross-repo graph: locate a symbol, its relationships, or browse a repo (POST /v1/graph)").argument("[symbol]", "symbol/label to look up (e.g. UserService); omit with --repo to browse a repo").requiredOption("--workspace <name>", "workspace to query (e.g. atlas-one)").option("--repo <name>", "scope to / browse a submodule by path prefix (e.g. diner-app)").option("--relates", "return relationships (calls/imports/contains) instead of just locations").option("--limit <n>", "max results (default 50)").option("--json", "emit raw JSON response").action(async (symbol, opts) => {
|
|
53018
|
+
const r = await runKgMirrorGraph(symbol, opts);
|
|
53019
|
+
if (r.exitCode !== 0) process.exitCode = r.exitCode;
|
|
53020
|
+
});
|
|
52610
53021
|
}
|
|
52611
53022
|
|
|
52612
53023
|
// src/commands/kg-build.ts
|
|
52613
53024
|
function readQueueFromDisk(queuePath) {
|
|
52614
|
-
if (!
|
|
52615
|
-
const raw =
|
|
53025
|
+
if (!fs104.existsSync(queuePath)) return [];
|
|
53026
|
+
const raw = fs104.readFileSync(queuePath, "utf-8");
|
|
52616
53027
|
const entries = [];
|
|
52617
53028
|
for (const line of raw.split("\n")) {
|
|
52618
53029
|
const t = line.trim();
|
|
@@ -52625,9 +53036,9 @@ function readQueueFromDisk(queuePath) {
|
|
|
52625
53036
|
return entries;
|
|
52626
53037
|
}
|
|
52627
53038
|
function writeQueueToDisk(queuePath, entries) {
|
|
52628
|
-
|
|
53039
|
+
fs104.mkdirSync(path102.dirname(queuePath), { recursive: true });
|
|
52629
53040
|
const content = entries.map((e) => JSON.stringify(e)).join("\n") + (entries.length > 0 ? "\n" : "");
|
|
52630
|
-
|
|
53041
|
+
fs104.writeFileSync(queuePath, content, "utf-8");
|
|
52631
53042
|
}
|
|
52632
53043
|
async function runKgBuildPending(opts = {}) {
|
|
52633
53044
|
const queuePath = opts.queuePath ?? (() => {
|
|
@@ -52717,7 +53128,7 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
52717
53128
|
return { exitCode: 2 };
|
|
52718
53129
|
}
|
|
52719
53130
|
const outDir = kgPristinePath(workspace.name);
|
|
52720
|
-
|
|
53131
|
+
fs104.mkdirSync(outDir, { recursive: true });
|
|
52721
53132
|
const human = !options.json;
|
|
52722
53133
|
if (human) {
|
|
52723
53134
|
printInfo("kg build", `workspace=${workspace.name} source=${workspace.sourcePath}`);
|
|
@@ -52750,7 +53161,7 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
52750
53161
|
workspace: workspace.name,
|
|
52751
53162
|
graphify_path: "container"
|
|
52752
53163
|
};
|
|
52753
|
-
|
|
53164
|
+
fs104.writeFileSync(
|
|
52754
53165
|
path102.join(outDir, "freshness.json"),
|
|
52755
53166
|
JSON.stringify(freshness, null, 2) + "\n",
|
|
52756
53167
|
"utf-8"
|
|
@@ -52797,13 +53208,13 @@ function registerKg(program2) {
|
|
|
52797
53208
|
|
|
52798
53209
|
// src/commands/flywheel/emit-breadcrumb.ts
|
|
52799
53210
|
init_file_lock();
|
|
52800
|
-
import { mkdirSync as
|
|
52801
|
-
import { homedir as
|
|
52802
|
-
import { dirname as
|
|
53211
|
+
import { mkdirSync as mkdirSync68, appendFileSync as appendFileSync6 } from "node:fs";
|
|
53212
|
+
import { homedir as homedir69 } from "node:os";
|
|
53213
|
+
import { dirname as dirname65, join as join113 } from "node:path";
|
|
52803
53214
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
52804
53215
|
var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "low", "info", "warn"]);
|
|
52805
53216
|
var PROMPT_FEEDING_FIELDS = ["extracted_pattern", "severity", "affected_persona", "proposed_edit"];
|
|
52806
|
-
var BREADCRUMBS_BASE =
|
|
53217
|
+
var BREADCRUMBS_BASE = join113(homedir69(), ".local", "share", "claude", "breadcrumbs");
|
|
52807
53218
|
var LOCK_FILENAME = ".flywheel-emit.lock";
|
|
52808
53219
|
function buildRecord(opts) {
|
|
52809
53220
|
const rec = {
|
|
@@ -52850,7 +53261,7 @@ function validatePromptFeeding(rec) {
|
|
|
52850
53261
|
}
|
|
52851
53262
|
function destPath(projectSlug) {
|
|
52852
53263
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
52853
|
-
return
|
|
53264
|
+
return join113(BREADCRUMBS_BASE, projectSlug, `${today}.jsonl`);
|
|
52854
53265
|
}
|
|
52855
53266
|
async function emitBreadcrumb(opts) {
|
|
52856
53267
|
if (!VALID_SEVERITIES.has(opts.severity)) {
|
|
@@ -52870,8 +53281,8 @@ async function emitBreadcrumb(opts) {
|
|
|
52870
53281
|
process.exit(2);
|
|
52871
53282
|
}
|
|
52872
53283
|
const path106 = destPath(rec.project_slug);
|
|
52873
|
-
const lockDir =
|
|
52874
|
-
|
|
53284
|
+
const lockDir = dirname65(path106);
|
|
53285
|
+
mkdirSync68(lockDir, { recursive: true });
|
|
52875
53286
|
const line = JSON.stringify(rec) + "\n";
|
|
52876
53287
|
await withFileLock(
|
|
52877
53288
|
lockDir,
|
|
@@ -52951,7 +53362,7 @@ function registerFlywheelK5Score(parent) {
|
|
|
52951
53362
|
}
|
|
52952
53363
|
|
|
52953
53364
|
// src/commands/flywheel/k5-validate.ts
|
|
52954
|
-
import { readFileSync as
|
|
53365
|
+
import { readFileSync as readFileSync101, statSync as statSync31 } from "node:fs";
|
|
52955
53366
|
import { parse as parseYAML } from "yaml";
|
|
52956
53367
|
var K5_DIMS = ["direction", "approach", "open_questions", "constraints", "reuse"];
|
|
52957
53368
|
var MAX_PLAN_BYTES = 1048576;
|
|
@@ -53033,7 +53444,7 @@ function validatePlan(path106) {
|
|
|
53033
53444
|
}
|
|
53034
53445
|
let text;
|
|
53035
53446
|
try {
|
|
53036
|
-
text =
|
|
53447
|
+
text = readFileSync101(path106, "utf8");
|
|
53037
53448
|
} catch (err) {
|
|
53038
53449
|
const m = `FAIL cannot read ${path106}: ${err instanceof Error ? err.message : "unknown"}`;
|
|
53039
53450
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
@@ -53157,7 +53568,7 @@ function registerFlywheelK5Validate(parent) {
|
|
|
53157
53568
|
}
|
|
53158
53569
|
|
|
53159
53570
|
// src/commands/flywheel/k10-measure.ts
|
|
53160
|
-
import { readFileSync as
|
|
53571
|
+
import { readFileSync as readFileSync102 } from "node:fs";
|
|
53161
53572
|
|
|
53162
53573
|
// ../core/dist/lib/k10-budget.js
|
|
53163
53574
|
var K10_TOKEN_CAP = 5500;
|
|
@@ -53214,7 +53625,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
53214
53625
|
parent.command("k10-measure").description("Measure K10 token budget for upstream + optional overlay; emit PASS/REJECT verdict").requiredOption("--upstream <path>", "path to upstream file (e.g. persona prompt)").option("--overlay <path>", "path to overlay file (omit if none \u2014 PASS without enforcement)").option("--json", "emit verdict as JSON instead of human-readable").action((opts) => {
|
|
53215
53626
|
let upstreamText;
|
|
53216
53627
|
try {
|
|
53217
|
-
upstreamText =
|
|
53628
|
+
upstreamText = readFileSync102(opts.upstream, "utf8");
|
|
53218
53629
|
} catch (err) {
|
|
53219
53630
|
process.stderr.write(
|
|
53220
53631
|
`[k10-measure-error] cannot read upstream ${opts.upstream}: ${err instanceof Error ? err.message : "unknown"}
|
|
@@ -53226,7 +53637,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
53226
53637
|
let overlayTokens = null;
|
|
53227
53638
|
if (opts.overlay !== void 0) {
|
|
53228
53639
|
try {
|
|
53229
|
-
const overlayText =
|
|
53640
|
+
const overlayText = readFileSync102(opts.overlay, "utf8");
|
|
53230
53641
|
overlayTokens = tokensFromText(overlayText);
|
|
53231
53642
|
} catch (err) {
|
|
53232
53643
|
process.stderr.write(
|
|
@@ -53260,13 +53671,13 @@ function registerFlywheelK10Measure(parent) {
|
|
|
53260
53671
|
}
|
|
53261
53672
|
|
|
53262
53673
|
// src/commands/flywheel/check-persona-skeleton.ts
|
|
53263
|
-
import { existsSync as
|
|
53264
|
-
import { homedir as
|
|
53265
|
-
import { basename as basename14, join as
|
|
53674
|
+
import { existsSync as existsSync117, readFileSync as readFileSync103, statSync as statSync32 } from "node:fs";
|
|
53675
|
+
import { homedir as homedir70 } from "node:os";
|
|
53676
|
+
import { basename as basename14, join as join114 } from "node:path";
|
|
53266
53677
|
import { parse as parseYAML2 } from "yaml";
|
|
53267
53678
|
var CHARS_PER_TOKEN3 = 4;
|
|
53268
53679
|
var K10_TOKEN_CAP2 = 6e3;
|
|
53269
|
-
var AGENTS_DIR =
|
|
53680
|
+
var AGENTS_DIR = join114(homedir70(), ".claude", "agents");
|
|
53270
53681
|
var REQUIRED_FRONTMATTER_KEYS = ["name", "description", "allowed-tools"];
|
|
53271
53682
|
var REQUIRED_SECTIONS = [
|
|
53272
53683
|
"## Role",
|
|
@@ -53306,10 +53717,10 @@ function countNamedPatterns(sectionText) {
|
|
|
53306
53717
|
return Math.max(h3Count, bulletCount);
|
|
53307
53718
|
}
|
|
53308
53719
|
function checkFile(filepath) {
|
|
53309
|
-
if (!
|
|
53720
|
+
if (!existsSync117(filepath) || !statSync32(filepath).isFile()) {
|
|
53310
53721
|
return { passed: false, failures: [`file not found: ${filepath}`], tokens: 0, mergedSkipped: false };
|
|
53311
53722
|
}
|
|
53312
|
-
const text =
|
|
53723
|
+
const text = readFileSync103(filepath, "utf8");
|
|
53313
53724
|
const { fm, body } = parseFile(text);
|
|
53314
53725
|
const failures = [];
|
|
53315
53726
|
for (const key of REQUIRED_FRONTMATTER_KEYS) {
|
|
@@ -53322,8 +53733,8 @@ function checkFile(filepath) {
|
|
|
53322
53733
|
const agentName = typeof fm.name === "string" ? fm.name : "";
|
|
53323
53734
|
let mergedSkipped = false;
|
|
53324
53735
|
if (!isNewAgent && agentName !== "") {
|
|
53325
|
-
const upstreamPath =
|
|
53326
|
-
if (
|
|
53736
|
+
const upstreamPath = join114(AGENTS_DIR, `${agentName}.md`);
|
|
53737
|
+
if (existsSync117(upstreamPath)) {
|
|
53327
53738
|
mergedSkipped = true;
|
|
53328
53739
|
}
|
|
53329
53740
|
}
|
|
@@ -53375,7 +53786,7 @@ Results: ${passCount} passed, ${failCount} failed
|
|
|
53375
53786
|
}
|
|
53376
53787
|
|
|
53377
53788
|
// src/commands/flywheel/diversity-check.ts
|
|
53378
|
-
import { readFileSync as
|
|
53789
|
+
import { readFileSync as readFileSync104 } from "node:fs";
|
|
53379
53790
|
import { basename as basename15 } from "node:path";
|
|
53380
53791
|
import { globSync as globSync2 } from "node:fs";
|
|
53381
53792
|
|
|
@@ -53455,7 +53866,7 @@ function formatRedivergencePrompt(personaA, personaB, score, drifted, revisionCo
|
|
|
53455
53866
|
` jaccard: ${score.toFixed(3)} (threshold: ${threshold})`,
|
|
53456
53867
|
` drifted: ${driftedName}`,
|
|
53457
53868
|
"",
|
|
53458
|
-
` Suggestion for next /
|
|
53869
|
+
` Suggestion for next /100x:learn revision of ${driftedName}:`,
|
|
53459
53870
|
` ADD content that reinforces ${driftedName}'s historically-owned cognitive patterns.`,
|
|
53460
53871
|
` DO NOT remove shared content \u2014 removing shared boilerplate lowers Jaccard arithmetically`,
|
|
53461
53872
|
` but does not restore identity differentiation.`,
|
|
@@ -53485,7 +53896,7 @@ function registerFlywheelDiversityCheck(parent) {
|
|
|
53485
53896
|
const personas = /* @__PURE__ */ new Map();
|
|
53486
53897
|
for (const filepath of files) {
|
|
53487
53898
|
try {
|
|
53488
|
-
const body =
|
|
53899
|
+
const body = readFileSync104(filepath, "utf8");
|
|
53489
53900
|
if (body.trim().length > 0) {
|
|
53490
53901
|
personas.set(basename15(filepath, ".md"), body);
|
|
53491
53902
|
}
|
|
@@ -53516,9 +53927,9 @@ ${formatRedivergencePrompt(persona_a, persona_b, score, void 0, void 0, threshol
|
|
|
53516
53927
|
}
|
|
53517
53928
|
|
|
53518
53929
|
// src/commands/flywheel/ping.ts
|
|
53519
|
-
import { mkdirSync as
|
|
53520
|
-
import { homedir as
|
|
53521
|
-
import { dirname as
|
|
53930
|
+
import { mkdirSync as mkdirSync69, writeFileSync as writeFileSync63 } from "node:fs";
|
|
53931
|
+
import { homedir as homedir71 } from "node:os";
|
|
53932
|
+
import { dirname as dirname66, join as join115 } from "node:path";
|
|
53522
53933
|
var COLD_START_BUDGET_GOOD_MS = 200;
|
|
53523
53934
|
var COLD_START_BUDGET_FAIR_MS = 500;
|
|
53524
53935
|
function classifyColdStart(coldStartMs) {
|
|
@@ -53534,9 +53945,9 @@ function readOlamVersion() {
|
|
|
53534
53945
|
}
|
|
53535
53946
|
}
|
|
53536
53947
|
function writeBaseline(record) {
|
|
53537
|
-
const baselinePath =
|
|
53538
|
-
|
|
53539
|
-
|
|
53948
|
+
const baselinePath = join115(homedir71(), ".local", "share", "olam", "flywheel-baseline.json");
|
|
53949
|
+
mkdirSync69(dirname66(baselinePath), { recursive: true });
|
|
53950
|
+
writeFileSync63(baselinePath, JSON.stringify(record, null, 2) + "\n", "utf8");
|
|
53540
53951
|
return baselinePath;
|
|
53541
53952
|
}
|
|
53542
53953
|
function registerFlywheelPing(parent) {
|
|
@@ -53576,16 +53987,16 @@ init_skill_sources();
|
|
|
53576
53987
|
init_prefix_rules();
|
|
53577
53988
|
import {
|
|
53578
53989
|
copyFileSync as copyFileSync15,
|
|
53579
|
-
existsSync as
|
|
53580
|
-
mkdirSync as
|
|
53581
|
-
readFileSync as
|
|
53990
|
+
existsSync as existsSync118,
|
|
53991
|
+
mkdirSync as mkdirSync70,
|
|
53992
|
+
readFileSync as readFileSync105,
|
|
53582
53993
|
readdirSync as readdirSync33,
|
|
53583
53994
|
statSync as statSync33,
|
|
53584
|
-
writeFileSync as
|
|
53995
|
+
writeFileSync as writeFileSync64
|
|
53585
53996
|
} from "node:fs";
|
|
53586
53997
|
import { spawnSync as spawnSync32 } from "node:child_process";
|
|
53587
|
-
import { homedir as
|
|
53588
|
-
import { dirname as
|
|
53998
|
+
import { homedir as homedir72 } from "node:os";
|
|
53999
|
+
import { dirname as dirname67, join as join116, relative as relative7 } from "node:path";
|
|
53589
54000
|
function escapeRegex(s) {
|
|
53590
54001
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
53591
54002
|
}
|
|
@@ -53622,7 +54033,7 @@ function walkOverlayFiles(dir) {
|
|
|
53622
54033
|
return [];
|
|
53623
54034
|
}
|
|
53624
54035
|
for (const entry of entries) {
|
|
53625
|
-
const fullPath =
|
|
54036
|
+
const fullPath = join116(dir, entry);
|
|
53626
54037
|
let stat;
|
|
53627
54038
|
try {
|
|
53628
54039
|
stat = statSync33(fullPath);
|
|
@@ -53661,10 +54072,10 @@ function resolveAtlasUser2(opts) {
|
|
|
53661
54072
|
assertValidAtlasUser(v);
|
|
53662
54073
|
return v;
|
|
53663
54074
|
}
|
|
53664
|
-
const claudeDir2 = opts._testClaudeDir ?? process.env["OLAM_CLAUDE_DIR"] ??
|
|
53665
|
-
const f =
|
|
53666
|
-
if (
|
|
53667
|
-
const v =
|
|
54075
|
+
const claudeDir2 = opts._testClaudeDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join116(homedir72(), ".claude");
|
|
54076
|
+
const f = join116(claudeDir2, ".atlas-user");
|
|
54077
|
+
if (existsSync118(f)) {
|
|
54078
|
+
const v = readFileSync105(f, "utf-8").trim();
|
|
53668
54079
|
if (v.length === 0) return null;
|
|
53669
54080
|
assertValidAtlasUser(v);
|
|
53670
54081
|
return v;
|
|
@@ -53686,8 +54097,8 @@ function runGit2(args, cwd) {
|
|
|
53686
54097
|
function walkPushSourceFiles(claudeDir2) {
|
|
53687
54098
|
const result = [];
|
|
53688
54099
|
const roots = [
|
|
53689
|
-
{ dir:
|
|
53690
|
-
{ dir:
|
|
54100
|
+
{ dir: join116(claudeDir2, "skills.overrides"), overlayKind: "skills" },
|
|
54101
|
+
{ dir: join116(claudeDir2, "agents.overrides"), overlayKind: "agents" }
|
|
53691
54102
|
];
|
|
53692
54103
|
for (const { dir, overlayKind } of roots) {
|
|
53693
54104
|
const files = walkOverlayFiles(dir);
|
|
@@ -53798,7 +54209,7 @@ function pushOverlays(opts) {
|
|
|
53798
54209
|
Run \`olam skills atlas-user set <name>\` to configure your atlas user.`
|
|
53799
54210
|
);
|
|
53800
54211
|
}
|
|
53801
|
-
const claudeDir2 = opts._testClaudeDir ?? opts.targetDir ?? process.env["OLAM_CLAUDE_DIR"] ??
|
|
54212
|
+
const claudeDir2 = opts._testClaudeDir ?? opts.targetDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join116(homedir72(), ".claude");
|
|
53802
54213
|
const sourceFiles = walkPushSourceFiles(claudeDir2);
|
|
53803
54214
|
const registeredPrefixes = (opts._testSkillSources ?? listSkillSources()).map((s) => s.prefix).filter((p) => typeof p === "string" && p.length > 0);
|
|
53804
54215
|
if (registeredPrefixes.length > 0) {
|
|
@@ -53806,7 +54217,7 @@ function pushOverlays(opts) {
|
|
|
53806
54217
|
const basename17 = relPath.split("/").pop() ?? relPath;
|
|
53807
54218
|
let content;
|
|
53808
54219
|
try {
|
|
53809
|
-
content =
|
|
54220
|
+
content = readFileSync105(srcFile);
|
|
53810
54221
|
} catch {
|
|
53811
54222
|
continue;
|
|
53812
54223
|
}
|
|
@@ -53845,21 +54256,21 @@ function pushOverlays(opts) {
|
|
|
53845
54256
|
` + preflightWarnings.map((w) => ` - ${w.split("\n")[0]}`).join("\n") + "\n"
|
|
53846
54257
|
);
|
|
53847
54258
|
}
|
|
53848
|
-
const membersBase2 =
|
|
54259
|
+
const membersBase2 = join116(clonePath, "members", atlasUser);
|
|
53849
54260
|
let wouldCopy = 0;
|
|
53850
54261
|
let wouldUnchange = 0;
|
|
53851
54262
|
let wouldCreate = 0;
|
|
53852
54263
|
for (const { srcFile, overlayKind, relPath } of sourceFiles) {
|
|
53853
|
-
const targetDir =
|
|
53854
|
-
const targetFile =
|
|
54264
|
+
const targetDir = join116(membersBase2, `${overlayKind}.overrides`);
|
|
54265
|
+
const targetFile = join116(targetDir, relPath);
|
|
53855
54266
|
let srcBuf;
|
|
53856
54267
|
try {
|
|
53857
|
-
srcBuf =
|
|
54268
|
+
srcBuf = readFileSync105(srcFile);
|
|
53858
54269
|
} catch {
|
|
53859
54270
|
continue;
|
|
53860
54271
|
}
|
|
53861
|
-
if (
|
|
53862
|
-
const dstBuf =
|
|
54272
|
+
if (existsSync118(targetFile)) {
|
|
54273
|
+
const dstBuf = readFileSync105(targetFile);
|
|
53863
54274
|
if (srcBuf.equals(dstBuf)) {
|
|
53864
54275
|
wouldUnchange += 1;
|
|
53865
54276
|
process.stdout.write(` [skip] ${overlayKind}.overrides/${relPath} (unchanged)
|
|
@@ -53900,32 +54311,32 @@ function pushOverlays(opts) {
|
|
|
53900
54311
|
`failed to create branch "${branchName}": ${err instanceof Error ? err.message : String(err)}`
|
|
53901
54312
|
);
|
|
53902
54313
|
}
|
|
53903
|
-
const membersBase =
|
|
54314
|
+
const membersBase = join116(clonePath, "members", atlasUser);
|
|
53904
54315
|
let filesCopied = 0;
|
|
53905
54316
|
let filesUnchanged = 0;
|
|
53906
54317
|
let filesCreated = 0;
|
|
53907
54318
|
try {
|
|
53908
54319
|
for (const { srcFile, overlayKind, relPath } of sourceFiles) {
|
|
53909
|
-
const targetDir =
|
|
53910
|
-
const targetFile =
|
|
54320
|
+
const targetDir = join116(membersBase, `${overlayKind}.overrides`, dirname67(relPath));
|
|
54321
|
+
const targetFile = join116(membersBase, `${overlayKind}.overrides`, relPath);
|
|
53911
54322
|
let srcBuf;
|
|
53912
54323
|
try {
|
|
53913
|
-
srcBuf =
|
|
54324
|
+
srcBuf = readFileSync105(srcFile);
|
|
53914
54325
|
} catch {
|
|
53915
54326
|
continue;
|
|
53916
54327
|
}
|
|
53917
|
-
const targetExists =
|
|
54328
|
+
const targetExists = existsSync118(targetFile);
|
|
53918
54329
|
if (targetExists) {
|
|
53919
|
-
const dstBuf =
|
|
54330
|
+
const dstBuf = readFileSync105(targetFile);
|
|
53920
54331
|
if (srcBuf.equals(dstBuf)) {
|
|
53921
54332
|
filesUnchanged += 1;
|
|
53922
54333
|
continue;
|
|
53923
54334
|
}
|
|
53924
|
-
|
|
54335
|
+
mkdirSync70(targetDir, { recursive: true });
|
|
53925
54336
|
copyFileSync15(srcFile, targetFile);
|
|
53926
54337
|
filesCopied += 1;
|
|
53927
54338
|
} else {
|
|
53928
|
-
|
|
54339
|
+
mkdirSync70(targetDir, { recursive: true });
|
|
53929
54340
|
copyFileSync15(srcFile, targetFile);
|
|
53930
54341
|
filesCreated += 1;
|
|
53931
54342
|
}
|
|
@@ -53993,8 +54404,8 @@ function initMember(opts) {
|
|
|
53993
54404
|
clonePath = skillSourceClonePath(source.id);
|
|
53994
54405
|
}
|
|
53995
54406
|
const atlasUser = resolveAtlasUser2(opts) ?? memberName;
|
|
53996
|
-
const memberDir =
|
|
53997
|
-
if (
|
|
54407
|
+
const memberDir = join116(clonePath, "members", memberName);
|
|
54408
|
+
if (existsSync118(memberDir)) {
|
|
53998
54409
|
throw new PushError(
|
|
53999
54410
|
1,
|
|
54000
54411
|
`members/${memberName}/ already exists; use --push to update; or remove manually first
|
|
@@ -54002,9 +54413,9 @@ function initMember(opts) {
|
|
|
54002
54413
|
);
|
|
54003
54414
|
}
|
|
54004
54415
|
const wouldCreate = [
|
|
54005
|
-
|
|
54006
|
-
|
|
54007
|
-
|
|
54416
|
+
join116(memberDir, "skills.overrides", ".gitkeep"),
|
|
54417
|
+
join116(memberDir, "agents.overrides", ".gitkeep"),
|
|
54418
|
+
join116(memberDir, "README.md")
|
|
54008
54419
|
];
|
|
54009
54420
|
if (opts.dryRun === true) {
|
|
54010
54421
|
const { preflightWarnings } = runPreFlight(clonePath, opts.forceCurrentBranch === true, true);
|
|
@@ -54060,12 +54471,12 @@ function initMember(opts) {
|
|
|
54060
54471
|
);
|
|
54061
54472
|
}
|
|
54062
54473
|
try {
|
|
54063
|
-
|
|
54064
|
-
|
|
54065
|
-
|
|
54066
|
-
|
|
54067
|
-
|
|
54068
|
-
|
|
54474
|
+
mkdirSync70(join116(memberDir, "skills.overrides"), { recursive: true });
|
|
54475
|
+
writeFileSync64(join116(memberDir, "skills.overrides", ".gitkeep"), "");
|
|
54476
|
+
mkdirSync70(join116(memberDir, "agents.overrides"), { recursive: true });
|
|
54477
|
+
writeFileSync64(join116(memberDir, "agents.overrides", ".gitkeep"), "");
|
|
54478
|
+
writeFileSync64(
|
|
54479
|
+
join116(memberDir, "README.md"),
|
|
54069
54480
|
`# Member overlays for \`${memberName}\`
|
|
54070
54481
|
|
|
54071
54482
|
See docs/plans/member-overlays-sync/ for layer architecture.
|
|
@@ -54106,10 +54517,10 @@ Next steps (run in ${clonePath}):`,
|
|
|
54106
54517
|
};
|
|
54107
54518
|
}
|
|
54108
54519
|
function migrateOverlays(opts = {}) {
|
|
54109
|
-
const root = opts.targetDir ??
|
|
54520
|
+
const root = opts.targetDir ?? join116(homedir72(), ".claude");
|
|
54110
54521
|
const overrideRoots = [
|
|
54111
|
-
|
|
54112
|
-
|
|
54522
|
+
join116(root, "skills.overrides"),
|
|
54523
|
+
join116(root, "agents.overrides")
|
|
54113
54524
|
];
|
|
54114
54525
|
const allFiles = [];
|
|
54115
54526
|
for (const overrideRoot of overrideRoots) {
|
|
@@ -54125,7 +54536,7 @@ function migrateOverlays(opts = {}) {
|
|
|
54125
54536
|
for (const filePath of allFiles) {
|
|
54126
54537
|
let original;
|
|
54127
54538
|
try {
|
|
54128
|
-
original =
|
|
54539
|
+
original = readFileSync105(filePath, "utf8");
|
|
54129
54540
|
} catch {
|
|
54130
54541
|
continue;
|
|
54131
54542
|
}
|
|
@@ -54136,7 +54547,7 @@ function migrateOverlays(opts = {}) {
|
|
|
54136
54547
|
continue;
|
|
54137
54548
|
}
|
|
54138
54549
|
if (opts.dryRun !== true) {
|
|
54139
|
-
|
|
54550
|
+
writeFileSync64(filePath, newContent, "utf8");
|
|
54140
54551
|
}
|
|
54141
54552
|
summary2.modified += 1;
|
|
54142
54553
|
summary2.totalReplacements += totalReplacements;
|
|
@@ -54228,7 +54639,7 @@ function registerFlywheelMigrateOverlays(parent) {
|
|
|
54228
54639
|
}
|
|
54229
54640
|
return;
|
|
54230
54641
|
}
|
|
54231
|
-
const root = opts.targetDir ??
|
|
54642
|
+
const root = opts.targetDir ?? join116(homedir72(), ".claude");
|
|
54232
54643
|
const summary2 = migrateOverlays(opts);
|
|
54233
54644
|
if (opts.json === true) {
|
|
54234
54645
|
process.stdout.write(JSON.stringify(summary2, null, 2) + "\n");
|
|
@@ -54267,9 +54678,9 @@ Per-file changes:
|
|
|
54267
54678
|
}
|
|
54268
54679
|
|
|
54269
54680
|
// src/commands/flywheel/session-start.ts
|
|
54270
|
-
import { readFileSync as
|
|
54271
|
-
import { homedir as
|
|
54272
|
-
import { join as
|
|
54681
|
+
import { readFileSync as readFileSync106, statSync as statSync34 } from "node:fs";
|
|
54682
|
+
import { homedir as homedir73 } from "node:os";
|
|
54683
|
+
import { join as join117 } from "node:path";
|
|
54273
54684
|
var SESSIONSTART_HOOK_SENTINEL = "olam-sessionstart-context-hook-v1";
|
|
54274
54685
|
var MAX_WAKE_BRIEF_BYTES = 8 * 1024;
|
|
54275
54686
|
var MAX_ACTIVE_WORLD_BYTES = 4 * 1024;
|
|
@@ -54285,7 +54696,7 @@ function tryReadCapped(path106, maxBytes) {
|
|
|
54285
54696
|
);
|
|
54286
54697
|
return null;
|
|
54287
54698
|
}
|
|
54288
|
-
return
|
|
54699
|
+
return readFileSync106(path106, "utf-8");
|
|
54289
54700
|
} catch (err) {
|
|
54290
54701
|
const code = err?.code;
|
|
54291
54702
|
if (code === "ENOENT") return null;
|
|
@@ -54310,15 +54721,15 @@ function tryParseJson(raw, label) {
|
|
|
54310
54721
|
}
|
|
54311
54722
|
function buildContextBlock(olamHome6) {
|
|
54312
54723
|
const config = tryParseJson(
|
|
54313
|
-
tryReadCapped(
|
|
54724
|
+
tryReadCapped(join117(olamHome6, "config.json"), MAX_CONFIG_BYTES),
|
|
54314
54725
|
"config.json"
|
|
54315
54726
|
);
|
|
54316
54727
|
const activeWorld = tryParseJson(
|
|
54317
|
-
tryReadCapped(
|
|
54728
|
+
tryReadCapped(join117(olamHome6, "state", "active-world.json"), MAX_ACTIVE_WORLD_BYTES),
|
|
54318
54729
|
"active-world.json"
|
|
54319
54730
|
);
|
|
54320
54731
|
const wakeBrief = tryReadCapped(
|
|
54321
|
-
|
|
54732
|
+
join117(olamHome6, "state", "wake-brief.md"),
|
|
54322
54733
|
MAX_WAKE_BRIEF_BYTES
|
|
54323
54734
|
);
|
|
54324
54735
|
const sections = [];
|
|
@@ -54370,7 +54781,7 @@ function registerFlywheelSessionStart(parent) {
|
|
|
54370
54781
|
parent.command("session-start").description(
|
|
54371
54782
|
"Emit operator-state context for the SessionStart hook (4th defense layer). Reads ~/.olam/state/* and writes the additionalContext JSON to stdout. Fail-soft: always exits 0."
|
|
54372
54783
|
).action(() => {
|
|
54373
|
-
const olamHome6 = process.env.OLAM_HOME ??
|
|
54784
|
+
const olamHome6 = process.env.OLAM_HOME ?? join117(homedir73(), ".olam");
|
|
54374
54785
|
emitSessionStartContext(olamHome6);
|
|
54375
54786
|
process.exit(0);
|
|
54376
54787
|
});
|
|
@@ -54379,9 +54790,9 @@ function registerFlywheelSessionStart(parent) {
|
|
|
54379
54790
|
// src/commands/flywheel/install-sessionstart-hook.ts
|
|
54380
54791
|
init_merge_settings();
|
|
54381
54792
|
init_output();
|
|
54382
|
-
import { existsSync as
|
|
54383
|
-
import { homedir as
|
|
54384
|
-
import { dirname as
|
|
54793
|
+
import { existsSync as existsSync119, copyFileSync as copyFileSync16, mkdirSync as mkdirSync71, readFileSync as readFileSync107, unlinkSync as unlinkSync25, writeFileSync as writeFileSync65 } from "node:fs";
|
|
54794
|
+
import { homedir as homedir74 } from "node:os";
|
|
54795
|
+
import { dirname as dirname68, join as join118 } from "node:path";
|
|
54385
54796
|
var SESSIONSTART_HOOK_STAGE = "SessionStart";
|
|
54386
54797
|
var SESSIONSTART_HOOK_TIMEOUT_MS = 5e3;
|
|
54387
54798
|
var NOOP_GUARD = "command -v olam >/dev/null 2>&1 || exit 0;";
|
|
@@ -54398,18 +54809,18 @@ function buildSessionStartHookEntry() {
|
|
|
54398
54809
|
};
|
|
54399
54810
|
}
|
|
54400
54811
|
function settingsPathFor4(scope, cwd) {
|
|
54401
|
-
if (scope === "user") return
|
|
54402
|
-
return
|
|
54812
|
+
if (scope === "user") return join118(homedir74(), ".claude", "settings.json");
|
|
54813
|
+
return join118(cwd ?? process.cwd(), ".claude", "settings.json");
|
|
54403
54814
|
}
|
|
54404
54815
|
function backup3(filePath) {
|
|
54405
|
-
if (!
|
|
54816
|
+
if (!existsSync119(filePath)) return null;
|
|
54406
54817
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
54407
54818
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
54408
54819
|
copyFileSync16(filePath, backupPath);
|
|
54409
54820
|
return backupPath;
|
|
54410
54821
|
}
|
|
54411
54822
|
function installSessionStartHook(filePath) {
|
|
54412
|
-
|
|
54823
|
+
mkdirSync71(dirname68(filePath), { recursive: true });
|
|
54413
54824
|
const backupPath = backup3(filePath);
|
|
54414
54825
|
const result = mergeHomeSettingsJson(filePath, {
|
|
54415
54826
|
ensureHook: {
|
|
@@ -54428,8 +54839,8 @@ function installSessionStartHook(filePath) {
|
|
|
54428
54839
|
return { status: result.status, filePath, backupPath };
|
|
54429
54840
|
}
|
|
54430
54841
|
function uninstallSessionStartHook(filePath) {
|
|
54431
|
-
if (!
|
|
54432
|
-
const raw =
|
|
54842
|
+
if (!existsSync119(filePath)) return { status: "no-settings", filePath };
|
|
54843
|
+
const raw = readFileSync107(filePath, "utf-8");
|
|
54433
54844
|
const settings = raw.trim() ? JSON.parse(raw) : {};
|
|
54434
54845
|
const matchers = settings.hooks?.SessionStart;
|
|
54435
54846
|
if (!Array.isArray(matchers) || matchers.length === 0) {
|
|
@@ -54469,7 +54880,7 @@ function uninstallSessionStartHook(filePath) {
|
|
|
54469
54880
|
delete next.hooks.SessionStart;
|
|
54470
54881
|
}
|
|
54471
54882
|
}
|
|
54472
|
-
|
|
54883
|
+
writeFileSync65(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
54473
54884
|
return { status: "removed", filePath };
|
|
54474
54885
|
}
|
|
54475
54886
|
function registerFlywheelInstallSessionStartHook(parent) {
|
|
@@ -54787,7 +55198,7 @@ init_manager();
|
|
|
54787
55198
|
init_context();
|
|
54788
55199
|
init_output();
|
|
54789
55200
|
import { spawnSync as defaultSpawnSync } from "node:child_process";
|
|
54790
|
-
import * as
|
|
55201
|
+
import * as fs105 from "node:fs";
|
|
54791
55202
|
import * as os58 from "node:os";
|
|
54792
55203
|
import * as path103 from "node:path";
|
|
54793
55204
|
function devboxContainerName(worldId) {
|
|
@@ -54807,8 +55218,8 @@ function defaultRestartContainer(name, spawn14 = defaultSpawnSync) {
|
|
|
54807
55218
|
};
|
|
54808
55219
|
}
|
|
54809
55220
|
function defaultAppendAuditLog(homeDir, line) {
|
|
54810
|
-
|
|
54811
|
-
|
|
55221
|
+
fs105.mkdirSync(homeDir, { recursive: true });
|
|
55222
|
+
fs105.appendFileSync(path103.join(homeDir, "usage.log"), line.endsWith("\n") ? line : line + "\n", {
|
|
54812
55223
|
encoding: "utf-8"
|
|
54813
55224
|
});
|
|
54814
55225
|
}
|
|
@@ -54854,18 +55265,18 @@ async function doRekey(worldId, deps) {
|
|
|
54854
55265
|
const rotatedAt = deps.now().toISOString();
|
|
54855
55266
|
const homeDir = deps.olamHomeDir();
|
|
54856
55267
|
const worldDir = path103.join(homeDir, "worlds", worldId);
|
|
54857
|
-
|
|
55268
|
+
fs105.mkdirSync(worldDir, { recursive: true });
|
|
54858
55269
|
const credentialsPath = path103.join(worldDir, "credentials.json");
|
|
54859
55270
|
const payload = {
|
|
54860
55271
|
worldRoleName,
|
|
54861
55272
|
password,
|
|
54862
55273
|
rotatedAt
|
|
54863
55274
|
};
|
|
54864
|
-
|
|
55275
|
+
fs105.writeFileSync(credentialsPath, JSON.stringify(payload, null, 2) + "\n", {
|
|
54865
55276
|
encoding: "utf-8",
|
|
54866
55277
|
mode: 384
|
|
54867
55278
|
});
|
|
54868
|
-
|
|
55279
|
+
fs105.chmodSync(credentialsPath, 384);
|
|
54869
55280
|
const restart = deps.restartContainer(devboxContainerName(worldId));
|
|
54870
55281
|
deps.appendAuditLog(`${rotatedAt} ${worldId} rekey`);
|
|
54871
55282
|
if (!restart.ok) {
|
|
@@ -54931,7 +55342,7 @@ function registerRekey(program2) {
|
|
|
54931
55342
|
// src/commands/yolo.ts
|
|
54932
55343
|
init_output();
|
|
54933
55344
|
import * as childProcess2 from "node:child_process";
|
|
54934
|
-
import * as
|
|
55345
|
+
import * as fs106 from "node:fs";
|
|
54935
55346
|
import * as os59 from "node:os";
|
|
54936
55347
|
import * as path104 from "node:path";
|
|
54937
55348
|
import pc49 from "picocolors";
|
|
@@ -54956,12 +55367,12 @@ function defaultRunner(cmd, args, opts) {
|
|
|
54956
55367
|
};
|
|
54957
55368
|
}
|
|
54958
55369
|
function defaultSleeper(ms) {
|
|
54959
|
-
return new Promise((
|
|
55370
|
+
return new Promise((resolve31) => setTimeout(resolve31, ms));
|
|
54960
55371
|
}
|
|
54961
55372
|
function detectTmuxBinary(runner = defaultRunner) {
|
|
54962
55373
|
for (const p of TMUX_PROBE_PATHS) {
|
|
54963
55374
|
if (TMUX_SHIM_MARKERS.some((m) => p.includes(m))) continue;
|
|
54964
|
-
if (
|
|
55375
|
+
if (fs106.existsSync(p)) return p;
|
|
54965
55376
|
}
|
|
54966
55377
|
const result = runner("which", ["tmux"]);
|
|
54967
55378
|
if (result.status === 0 && result.stdout) {
|
|
@@ -54976,8 +55387,8 @@ function resolveWorktreeRoot(runner = defaultRunner, cwd = process.cwd()) {
|
|
|
54976
55387
|
return process.env["OLAM_TMUX_YOLO_ROOT"];
|
|
54977
55388
|
}
|
|
54978
55389
|
const rootFile = path104.join(os59.homedir(), ".olam-tmux-yolo-root");
|
|
54979
|
-
if (
|
|
54980
|
-
const line =
|
|
55390
|
+
if (fs106.existsSync(rootFile)) {
|
|
55391
|
+
const line = fs106.readFileSync(rootFile, "utf-8").trim();
|
|
54981
55392
|
if (line) return line;
|
|
54982
55393
|
}
|
|
54983
55394
|
const gitResult = runner("git", ["rev-parse", "--show-toplevel"], { cwd });
|
|
@@ -55011,7 +55422,7 @@ async function spawnYolo(opts) {
|
|
|
55011
55422
|
);
|
|
55012
55423
|
}
|
|
55013
55424
|
try {
|
|
55014
|
-
|
|
55425
|
+
fs106.accessSync(opts.promptFile, fs106.constants.R_OK);
|
|
55015
55426
|
} catch {
|
|
55016
55427
|
throw new Error(
|
|
55017
55428
|
`Prompt file not found or not readable: ${opts.promptFile}
|
|
@@ -55027,7 +55438,7 @@ Create the file with your task description and try again.`
|
|
|
55027
55438
|
Run: olam yolo --cleanup ${opts.name} (or use --force to bypass the merged check)`
|
|
55028
55439
|
);
|
|
55029
55440
|
}
|
|
55030
|
-
if (
|
|
55441
|
+
if (fs106.existsSync(worktreePath)) {
|
|
55031
55442
|
throw new Error(
|
|
55032
55443
|
`Worktree directory already exists: ${worktreePath}
|
|
55033
55444
|
Run: olam yolo --cleanup ${opts.name} to remove it first.`
|
|
@@ -55095,7 +55506,7 @@ function listYoloWindows(opts = {}) {
|
|
|
55095
55506
|
const worktreePath = path104.join(worktreeRoot, name);
|
|
55096
55507
|
return {
|
|
55097
55508
|
name,
|
|
55098
|
-
worktreePath:
|
|
55509
|
+
worktreePath: fs106.existsSync(worktreePath) ? worktreePath : void 0
|
|
55099
55510
|
};
|
|
55100
55511
|
});
|
|
55101
55512
|
}
|
|
@@ -55229,18 +55640,18 @@ function registerYolo(program2) {
|
|
|
55229
55640
|
}
|
|
55230
55641
|
|
|
55231
55642
|
// src/pleri-config.ts
|
|
55232
|
-
import * as
|
|
55643
|
+
import * as fs107 from "node:fs";
|
|
55233
55644
|
import * as path105 from "node:path";
|
|
55234
55645
|
function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
55235
55646
|
if (process.env.PLERI_BASE_URL) {
|
|
55236
55647
|
return true;
|
|
55237
55648
|
}
|
|
55238
55649
|
const configPath = path105.join(configDir, "config.yaml");
|
|
55239
|
-
if (!
|
|
55650
|
+
if (!fs107.existsSync(configPath)) {
|
|
55240
55651
|
return false;
|
|
55241
55652
|
}
|
|
55242
55653
|
try {
|
|
55243
|
-
const contents =
|
|
55654
|
+
const contents = fs107.readFileSync(configPath, "utf8");
|
|
55244
55655
|
return /^[^#\n]*\bpleri:/m.test(contents);
|
|
55245
55656
|
} catch {
|
|
55246
55657
|
return false;
|
|
@@ -55279,7 +55690,7 @@ var HELP_GROUPS = [
|
|
|
55279
55690
|
},
|
|
55280
55691
|
{
|
|
55281
55692
|
title: "Skills & knowledge",
|
|
55282
|
-
names: ["skills", "kg", "ask", "flywheel"]
|
|
55693
|
+
names: ["skills", "100x", "kg", "ask", "flywheel"]
|
|
55283
55694
|
},
|
|
55284
55695
|
{
|
|
55285
55696
|
title: "Substrate & infra",
|
|
@@ -55442,7 +55853,7 @@ registerSkillsMigrateHooks(program);
|
|
|
55442
55853
|
registerSkillsMigrateHooksBack(program);
|
|
55443
55854
|
registerSkillsShadowBackups(program);
|
|
55444
55855
|
registerSkillsDoctor(program);
|
|
55445
|
-
|
|
55856
|
+
registerSkills100x(program);
|
|
55446
55857
|
registerHermes(program);
|
|
55447
55858
|
void scheduleUpgradeCheck(cliVersion);
|
|
55448
55859
|
await program.parseAsync();
|