@pleri/olam-cli 0.1.106 → 0.1.107
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/commands/diagnose.d.ts +16 -0
- package/dist/commands/diagnose.d.ts.map +1 -1
- package/dist/commands/diagnose.js +16 -0
- package/dist/commands/diagnose.js.map +1 -1
- package/dist/commands/doctor.d.ts +60 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +144 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/kg-status.d.ts.map +1 -1
- package/dist/commands/kg-status.js +1 -2
- package/dist/commands/kg-status.js.map +1 -1
- package/dist/image-digests.json +1 -1
- package/dist/index.js +463 -132
- package/dist/index.js.map +1 -1
- package/dist/lib/health-probes.d.ts +116 -0
- package/dist/lib/health-probes.d.ts.map +1 -0
- package/dist/lib/health-probes.js +390 -0
- package/dist/lib/health-probes.js.map +1 -0
- package/dist/lib/kg-caps.d.ts +19 -0
- package/dist/lib/kg-caps.d.ts.map +1 -0
- package/dist/lib/kg-caps.js +19 -0
- package/dist/lib/kg-caps.js.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -487,8 +487,8 @@ var init_parseUtil = __esm({
|
|
|
487
487
|
init_errors();
|
|
488
488
|
init_en();
|
|
489
489
|
makeIssue = (params) => {
|
|
490
|
-
const { data, path:
|
|
491
|
-
const fullPath = [...
|
|
490
|
+
const { data, path: path53, errorMaps, issueData } = params;
|
|
491
|
+
const fullPath = [...path53, ...issueData.path || []];
|
|
492
492
|
const fullIssue = {
|
|
493
493
|
...issueData,
|
|
494
494
|
path: fullPath
|
|
@@ -796,11 +796,11 @@ var init_types = __esm({
|
|
|
796
796
|
init_parseUtil();
|
|
797
797
|
init_util();
|
|
798
798
|
ParseInputLazyPath = class {
|
|
799
|
-
constructor(parent, value,
|
|
799
|
+
constructor(parent, value, path53, key) {
|
|
800
800
|
this._cachedPath = [];
|
|
801
801
|
this.parent = parent;
|
|
802
802
|
this.data = value;
|
|
803
|
-
this._path =
|
|
803
|
+
this._path = path53;
|
|
804
804
|
this._key = key;
|
|
805
805
|
}
|
|
806
806
|
get path() {
|
|
@@ -4281,7 +4281,7 @@ import YAML from "yaml";
|
|
|
4281
4281
|
function bootstrapStepCmd(entry) {
|
|
4282
4282
|
return typeof entry === "string" ? entry : entry.cmd;
|
|
4283
4283
|
}
|
|
4284
|
-
function refineForbiddenKeys(value,
|
|
4284
|
+
function refineForbiddenKeys(value, path53, ctx, rejectSource) {
|
|
4285
4285
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
4286
4286
|
return;
|
|
4287
4287
|
}
|
|
@@ -4289,12 +4289,12 @@ function refineForbiddenKeys(value, path52, ctx, rejectSource) {
|
|
|
4289
4289
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4290
4290
|
ctx.addIssue({
|
|
4291
4291
|
code: external_exports.ZodIssueCode.custom,
|
|
4292
|
-
path: [...
|
|
4292
|
+
path: [...path53, key],
|
|
4293
4293
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
4294
4294
|
});
|
|
4295
4295
|
continue;
|
|
4296
4296
|
}
|
|
4297
|
-
if (rejectSource &&
|
|
4297
|
+
if (rejectSource && path53.length === 0 && key === "source") {
|
|
4298
4298
|
ctx.addIssue({
|
|
4299
4299
|
code: external_exports.ZodIssueCode.custom,
|
|
4300
4300
|
path: ["source"],
|
|
@@ -4302,21 +4302,21 @@ function refineForbiddenKeys(value, path52, ctx, rejectSource) {
|
|
|
4302
4302
|
});
|
|
4303
4303
|
continue;
|
|
4304
4304
|
}
|
|
4305
|
-
refineForbiddenKeys(value[key], [...
|
|
4305
|
+
refineForbiddenKeys(value[key], [...path53, key], ctx, false);
|
|
4306
4306
|
}
|
|
4307
4307
|
}
|
|
4308
|
-
function rejectForbiddenKeys(value,
|
|
4308
|
+
function rejectForbiddenKeys(value, path53, rejectSource) {
|
|
4309
4309
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
4310
4310
|
return;
|
|
4311
4311
|
}
|
|
4312
4312
|
for (const key of Object.keys(value)) {
|
|
4313
4313
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4314
|
-
throw new Error(`[manifest] ${
|
|
4314
|
+
throw new Error(`[manifest] ${path53}: forbidden key "${key}" (prototype-pollution surface)`);
|
|
4315
4315
|
}
|
|
4316
4316
|
if (rejectSource && key === "source") {
|
|
4317
|
-
throw new Error(`[manifest] ${
|
|
4317
|
+
throw new Error(`[manifest] ${path53}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
|
|
4318
4318
|
}
|
|
4319
|
-
rejectForbiddenKeys(value[key], `${
|
|
4319
|
+
rejectForbiddenKeys(value[key], `${path53}.${key}`, false);
|
|
4320
4320
|
}
|
|
4321
4321
|
}
|
|
4322
4322
|
function unknownTopLevelKeys(parsed) {
|
|
@@ -5309,8 +5309,8 @@ var init_client = __esm({
|
|
|
5309
5309
|
throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
|
|
5310
5310
|
}
|
|
5311
5311
|
}
|
|
5312
|
-
async request(method,
|
|
5313
|
-
const url = `${this.baseUrl}${
|
|
5312
|
+
async request(method, path53, body, attempt = 0) {
|
|
5313
|
+
const url = `${this.baseUrl}${path53}`;
|
|
5314
5314
|
const controller = new AbortController();
|
|
5315
5315
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
5316
5316
|
const headers = {};
|
|
@@ -5328,7 +5328,7 @@ var init_client = __esm({
|
|
|
5328
5328
|
} catch (err) {
|
|
5329
5329
|
if (attempt < RETRY_COUNT && isTransient(err)) {
|
|
5330
5330
|
await sleep(RETRY_BACKOFF_MS * (attempt + 1));
|
|
5331
|
-
return this.request(method,
|
|
5331
|
+
return this.request(method, path53, body, attempt + 1);
|
|
5332
5332
|
}
|
|
5333
5333
|
throw err;
|
|
5334
5334
|
} finally {
|
|
@@ -6877,8 +6877,8 @@ var init_provider3 = __esm({
|
|
|
6877
6877
|
// -----------------------------------------------------------------------
|
|
6878
6878
|
// Internal fetch helper
|
|
6879
6879
|
// -----------------------------------------------------------------------
|
|
6880
|
-
async request(
|
|
6881
|
-
const url = `${this.config.workerUrl}${
|
|
6880
|
+
async request(path53, method, body) {
|
|
6881
|
+
const url = `${this.config.workerUrl}${path53}`;
|
|
6882
6882
|
const bearer = await this.config.mintToken();
|
|
6883
6883
|
const headers = {
|
|
6884
6884
|
Authorization: `Bearer ${bearer}`
|
|
@@ -8170,8 +8170,8 @@ import { execFileSync as execFileSync3 } from "node:child_process";
|
|
|
8170
8170
|
import * as fs14 from "node:fs";
|
|
8171
8171
|
import * as os9 from "node:os";
|
|
8172
8172
|
import * as path15 from "node:path";
|
|
8173
|
-
function expandHome(p,
|
|
8174
|
-
return p.replace(/^~(?=$|\/|\\)/,
|
|
8173
|
+
function expandHome(p, homedir29) {
|
|
8174
|
+
return p.replace(/^~(?=$|\/|\\)/, homedir29());
|
|
8175
8175
|
}
|
|
8176
8176
|
function sanitizeRepoFilename(name) {
|
|
8177
8177
|
const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -8194,7 +8194,7 @@ ${stderr}`;
|
|
|
8194
8194
|
}
|
|
8195
8195
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
8196
8196
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync3(cmd, args, opts));
|
|
8197
|
-
const
|
|
8197
|
+
const homedir29 = deps.homedir ?? (() => os9.homedir());
|
|
8198
8198
|
const baselineDir = path15.join(workspacePath, ".olam", "baseline");
|
|
8199
8199
|
try {
|
|
8200
8200
|
fs14.mkdirSync(baselineDir, { recursive: true });
|
|
@@ -8210,7 +8210,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
8210
8210
|
continue;
|
|
8211
8211
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
8212
8212
|
const outPath = path15.join(baselineDir, filename);
|
|
8213
|
-
const repoPath = expandHome(repo.path,
|
|
8213
|
+
const repoPath = expandHome(repo.path, homedir29);
|
|
8214
8214
|
if (!fs14.existsSync(repoPath)) {
|
|
8215
8215
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
8216
8216
|
# (skipped: path ${repoPath} does not exist)
|
|
@@ -13822,10 +13822,10 @@ async function readHostCpToken2() {
|
|
|
13822
13822
|
if (!fs25.existsSync(tp)) return null;
|
|
13823
13823
|
return fs25.readFileSync(tp, "utf-8").trim();
|
|
13824
13824
|
}
|
|
13825
|
-
async function callHostCpProxy(method, worldId,
|
|
13825
|
+
async function callHostCpProxy(method, worldId, path53, body) {
|
|
13826
13826
|
const token = await readHostCpToken2();
|
|
13827
13827
|
if (!token) return { ok: false, status: 0, error: "no token (host CP not started)" };
|
|
13828
|
-
const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${
|
|
13828
|
+
const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path53}`;
|
|
13829
13829
|
try {
|
|
13830
13830
|
const headers = {
|
|
13831
13831
|
Authorization: `Bearer ${token}`
|
|
@@ -14285,7 +14285,7 @@ __export(machine_schema_exports, {
|
|
|
14285
14285
|
writeMachineConfig: () => writeMachineConfig
|
|
14286
14286
|
});
|
|
14287
14287
|
import * as fs41 from "node:fs";
|
|
14288
|
-
import * as
|
|
14288
|
+
import * as path45 from "node:path";
|
|
14289
14289
|
import * as os24 from "node:os";
|
|
14290
14290
|
import { parse as parseYaml5, stringify as stringifyYaml5 } from "yaml";
|
|
14291
14291
|
function readMachineConfig(configPath) {
|
|
@@ -14302,7 +14302,7 @@ function readMachineConfig(configPath) {
|
|
|
14302
14302
|
}
|
|
14303
14303
|
function writeMachineConfig(config, configPath) {
|
|
14304
14304
|
const p = configPath ?? DEFAULT_CONFIG_PATH;
|
|
14305
|
-
fs41.mkdirSync(
|
|
14305
|
+
fs41.mkdirSync(path45.dirname(p), { recursive: true });
|
|
14306
14306
|
fs41.writeFileSync(p, stringifyYaml5({ ...config }), { mode: 420 });
|
|
14307
14307
|
}
|
|
14308
14308
|
function initMachineConfig(opts = {}) {
|
|
@@ -14326,9 +14326,9 @@ var init_machine_schema = __esm({
|
|
|
14326
14326
|
channel: external_exports.enum(["stable", "beta", "edge"]).default("stable"),
|
|
14327
14327
|
auto_update: external_exports.boolean().default(true),
|
|
14328
14328
|
telemetry: external_exports.boolean().default(true),
|
|
14329
|
-
worlds_dir: external_exports.string().default(() =>
|
|
14329
|
+
worlds_dir: external_exports.string().default(() => path45.join(os24.homedir(), ".olam", "worlds"))
|
|
14330
14330
|
});
|
|
14331
|
-
DEFAULT_CONFIG_PATH =
|
|
14331
|
+
DEFAULT_CONFIG_PATH = path45.join(os24.homedir(), ".olam", "config.yaml");
|
|
14332
14332
|
}
|
|
14333
14333
|
});
|
|
14334
14334
|
|
|
@@ -14710,9 +14710,9 @@ var UnknownArchetypeError = class extends Error {
|
|
|
14710
14710
|
};
|
|
14711
14711
|
var ArchetypeCycleError = class extends Error {
|
|
14712
14712
|
path;
|
|
14713
|
-
constructor(
|
|
14714
|
-
super(`Archetype inheritance cycle detected: ${
|
|
14715
|
-
this.path =
|
|
14713
|
+
constructor(path53) {
|
|
14714
|
+
super(`Archetype inheritance cycle detected: ${path53.join(" \u2192 ")} \u2192 ${path53[0] ?? "?"}`);
|
|
14715
|
+
this.path = path53;
|
|
14716
14716
|
this.name = "ArchetypeCycleError";
|
|
14717
14717
|
}
|
|
14718
14718
|
};
|
|
@@ -16093,9 +16093,9 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
|
|
|
16093
16093
|
"These source files have changed since the image was built; the",
|
|
16094
16094
|
"changes will NOT take effect in fresh worlds until you rebuild:"
|
|
16095
16095
|
];
|
|
16096
|
-
for (const { path:
|
|
16096
|
+
for (const { path: path53, mtimeMs } of result.newerSources) {
|
|
16097
16097
|
const when = new Date(mtimeMs).toISOString();
|
|
16098
|
-
lines.push(` \u2022 ${
|
|
16098
|
+
lines.push(` \u2022 ${path53} (modified ${when})`);
|
|
16099
16099
|
}
|
|
16100
16100
|
lines.push("");
|
|
16101
16101
|
lines.push("Rebuild with:");
|
|
@@ -16256,9 +16256,9 @@ async function readHostCpTokenForCreate() {
|
|
|
16256
16256
|
try {
|
|
16257
16257
|
const { default: fs50 } = await import("node:fs");
|
|
16258
16258
|
const { default: os28 } = await import("node:os");
|
|
16259
|
-
const { default:
|
|
16260
|
-
const tp =
|
|
16261
|
-
process.env.OLAM_HOME ??
|
|
16259
|
+
const { default: path53 } = await import("node:path");
|
|
16260
|
+
const tp = path53.join(
|
|
16261
|
+
process.env.OLAM_HOME ?? path53.join(os28.homedir(), ".olam"),
|
|
16262
16262
|
"host-cp.token"
|
|
16263
16263
|
);
|
|
16264
16264
|
if (!fs50.existsSync(tp)) return null;
|
|
@@ -16627,8 +16627,8 @@ async function readHostCpToken3() {
|
|
|
16627
16627
|
try {
|
|
16628
16628
|
const { default: fs50 } = await import("node:fs");
|
|
16629
16629
|
const { default: os28 } = await import("node:os");
|
|
16630
|
-
const { default:
|
|
16631
|
-
const tp =
|
|
16630
|
+
const { default: path53 } = await import("node:path");
|
|
16631
|
+
const tp = path53.join(os28.homedir(), ".olam", "host-cp.token");
|
|
16632
16632
|
if (!fs50.existsSync(tp)) return null;
|
|
16633
16633
|
const raw = fs50.readFileSync(tp, "utf-8").trim();
|
|
16634
16634
|
return raw.length > 0 ? raw : null;
|
|
@@ -20361,11 +20361,11 @@ function zodIssueToError(issue, doc, lineCounter) {
|
|
|
20361
20361
|
suggestion: deriveSuggestion(issue)
|
|
20362
20362
|
};
|
|
20363
20363
|
}
|
|
20364
|
-
function formatJsonPath(
|
|
20365
|
-
if (
|
|
20364
|
+
function formatJsonPath(path53) {
|
|
20365
|
+
if (path53.length === 0)
|
|
20366
20366
|
return "<root>";
|
|
20367
20367
|
let out = "";
|
|
20368
|
-
for (const seg of
|
|
20368
|
+
for (const seg of path53) {
|
|
20369
20369
|
if (typeof seg === "number") {
|
|
20370
20370
|
out += `[${seg}]`;
|
|
20371
20371
|
} else {
|
|
@@ -20374,11 +20374,11 @@ function formatJsonPath(path52) {
|
|
|
20374
20374
|
}
|
|
20375
20375
|
return out;
|
|
20376
20376
|
}
|
|
20377
|
-
function resolveYamlLocation(
|
|
20377
|
+
function resolveYamlLocation(path53, doc, lineCounter) {
|
|
20378
20378
|
let bestLine = 0;
|
|
20379
20379
|
let bestColumn = 0;
|
|
20380
|
-
for (let depth =
|
|
20381
|
-
const segment =
|
|
20380
|
+
for (let depth = path53.length; depth >= 0; depth -= 1) {
|
|
20381
|
+
const segment = path53.slice(0, depth);
|
|
20382
20382
|
try {
|
|
20383
20383
|
const node = doc.getIn(segment, true);
|
|
20384
20384
|
if (node && typeof node === "object" && "range" in node) {
|
|
@@ -20596,11 +20596,11 @@ function topoSort(nodes) {
|
|
|
20596
20596
|
}
|
|
20597
20597
|
function traceCycle(start, byId) {
|
|
20598
20598
|
const seen = /* @__PURE__ */ new Set();
|
|
20599
|
-
const
|
|
20599
|
+
const path53 = [];
|
|
20600
20600
|
let current = start;
|
|
20601
20601
|
while (current && !seen.has(current)) {
|
|
20602
20602
|
seen.add(current);
|
|
20603
|
-
|
|
20603
|
+
path53.push(current);
|
|
20604
20604
|
const node = byId.get(current);
|
|
20605
20605
|
const next = node?.dependsOn[0];
|
|
20606
20606
|
if (next === void 0)
|
|
@@ -20608,10 +20608,10 @@ function traceCycle(start, byId) {
|
|
|
20608
20608
|
current = next;
|
|
20609
20609
|
}
|
|
20610
20610
|
if (current && seen.has(current)) {
|
|
20611
|
-
const idx =
|
|
20612
|
-
return [...
|
|
20611
|
+
const idx = path53.indexOf(current);
|
|
20612
|
+
return [...path53.slice(idx), current];
|
|
20613
20613
|
}
|
|
20614
|
-
return
|
|
20614
|
+
return path53;
|
|
20615
20615
|
}
|
|
20616
20616
|
|
|
20617
20617
|
// ../core/dist/executor/types.js
|
|
@@ -23987,7 +23987,7 @@ function registerLogs(program2) {
|
|
|
23987
23987
|
resolveStream();
|
|
23988
23988
|
}
|
|
23989
23989
|
};
|
|
23990
|
-
const
|
|
23990
|
+
const emit2 = (line, service) => {
|
|
23991
23991
|
process.stdout.write(formatLine(line, service, showService) + "\n");
|
|
23992
23992
|
lineCount++;
|
|
23993
23993
|
if (!opts.follow && lineCount >= tailLimit) {
|
|
@@ -24016,13 +24016,13 @@ function registerLogs(program2) {
|
|
|
24016
24016
|
if (!ev) continue;
|
|
24017
24017
|
if (ev.type === "replay") {
|
|
24018
24018
|
for (const l of ev.lines) {
|
|
24019
|
-
if (!
|
|
24019
|
+
if (!emit2(l, ev.service)) {
|
|
24020
24020
|
req.destroy();
|
|
24021
24021
|
break;
|
|
24022
24022
|
}
|
|
24023
24023
|
}
|
|
24024
24024
|
} else if (ev.type === "line") {
|
|
24025
|
-
if (!
|
|
24025
|
+
if (!emit2(ev.line, ev.service)) req.destroy();
|
|
24026
24026
|
}
|
|
24027
24027
|
}
|
|
24028
24028
|
});
|
|
@@ -25037,16 +25037,348 @@ function registerDiagnose(program2) {
|
|
|
25037
25037
|
});
|
|
25038
25038
|
}
|
|
25039
25039
|
|
|
25040
|
+
// src/lib/health-probes.ts
|
|
25041
|
+
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
25042
|
+
import { existsSync as existsSync43, readdirSync as readdirSync11, readFileSync as readFileSync30, statSync as statSync13 } from "node:fs";
|
|
25043
|
+
import { homedir as homedir22 } from "node:os";
|
|
25044
|
+
import path43 from "node:path";
|
|
25045
|
+
|
|
25046
|
+
// src/lib/kg-caps.ts
|
|
25047
|
+
var SOFT_CAP_BYTES = 15e8;
|
|
25048
|
+
var HARD_CAP_BYTES = 5e9;
|
|
25049
|
+
|
|
25050
|
+
// src/lib/health-probes.ts
|
|
25051
|
+
var HEALTH_TIMEOUT_MS2 = 5e3;
|
|
25052
|
+
var defaultDockerExec2 = (cmd, args) => {
|
|
25053
|
+
const r = spawnSync14(cmd, [...args], {
|
|
25054
|
+
encoding: "utf-8",
|
|
25055
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
25056
|
+
});
|
|
25057
|
+
return {
|
|
25058
|
+
status: r.status,
|
|
25059
|
+
stdout: r.stdout ?? "",
|
|
25060
|
+
stderr: r.stderr ?? ""
|
|
25061
|
+
};
|
|
25062
|
+
};
|
|
25063
|
+
var defaultFetch = (input, init) => fetch(input, init);
|
|
25064
|
+
async function probeDockerDaemon(dockerExec = defaultDockerExec2) {
|
|
25065
|
+
const r = dockerExec("docker", ["info", "--format", "{{.ServerVersion}}"]);
|
|
25066
|
+
if (r.status === 0 && r.stdout.trim().length > 0) {
|
|
25067
|
+
return { ok: true, message: `docker ${r.stdout.trim()} reachable` };
|
|
25068
|
+
}
|
|
25069
|
+
return {
|
|
25070
|
+
ok: false,
|
|
25071
|
+
message: "docker daemon not reachable",
|
|
25072
|
+
remedy: "Start Docker Desktop (or your docker daemon) and re-run."
|
|
25073
|
+
};
|
|
25074
|
+
}
|
|
25075
|
+
async function probeImagePresence(refs, dockerExec = defaultDockerExec2) {
|
|
25076
|
+
for (const ref of refs) {
|
|
25077
|
+
const r = dockerExec("docker", ["image", "inspect", "--format", "{{.Id}}", ref]);
|
|
25078
|
+
if (r.status !== 0) {
|
|
25079
|
+
return {
|
|
25080
|
+
ok: false,
|
|
25081
|
+
message: `image ${ref} not present locally`,
|
|
25082
|
+
remedy: "Run `olam bootstrap` to pull the published image, or build locally."
|
|
25083
|
+
};
|
|
25084
|
+
}
|
|
25085
|
+
}
|
|
25086
|
+
return { ok: true, message: `${refs.length} image(s) present` };
|
|
25087
|
+
}
|
|
25088
|
+
async function probeHostCpHealth(fetchImpl = defaultFetch) {
|
|
25089
|
+
const controller = new AbortController();
|
|
25090
|
+
const timeout = setTimeout(() => controller.abort(), HEALTH_TIMEOUT_MS2);
|
|
25091
|
+
try {
|
|
25092
|
+
const res = await fetchImpl("http://127.0.0.1:19000/health", { signal: controller.signal });
|
|
25093
|
+
const body = await res.text().catch(() => "");
|
|
25094
|
+
if (res.status !== 200) {
|
|
25095
|
+
return {
|
|
25096
|
+
ok: false,
|
|
25097
|
+
message: `host-cp /health returned ${res.status}`,
|
|
25098
|
+
remedy: "Restart host-cp via `olam host-cp start`; verify port 19000 is bound to 127.0.0.1."
|
|
25099
|
+
};
|
|
25100
|
+
}
|
|
25101
|
+
if (isHostCpHealthEnvelope(body)) {
|
|
25102
|
+
return { ok: true, message: "host-cp /health returned 200" };
|
|
25103
|
+
}
|
|
25104
|
+
return {
|
|
25105
|
+
ok: false,
|
|
25106
|
+
message: "host-cp /health returned 200 but body did not match the host-cp envelope (possible port collision on :19000)",
|
|
25107
|
+
remedy: "Check `lsof -iTCP:19000`; another process may have bound the port. Restart host-cp via `olam host-cp start`."
|
|
25108
|
+
};
|
|
25109
|
+
} catch (err) {
|
|
25110
|
+
const e = err;
|
|
25111
|
+
const reason = e.name === "AbortError" ? `timeout (${HEALTH_TIMEOUT_MS2}ms)` : e.message;
|
|
25112
|
+
return {
|
|
25113
|
+
ok: false,
|
|
25114
|
+
message: `host-cp /health unreachable: ${reason}`,
|
|
25115
|
+
remedy: "Restart host-cp via `olam host-cp start`; verify port 19000 is bound to 127.0.0.1."
|
|
25116
|
+
};
|
|
25117
|
+
} finally {
|
|
25118
|
+
clearTimeout(timeout);
|
|
25119
|
+
}
|
|
25120
|
+
}
|
|
25121
|
+
function isHostCpHealthEnvelope(body) {
|
|
25122
|
+
let parsed;
|
|
25123
|
+
try {
|
|
25124
|
+
parsed = JSON.parse(body);
|
|
25125
|
+
} catch {
|
|
25126
|
+
return false;
|
|
25127
|
+
}
|
|
25128
|
+
if (!parsed || typeof parsed !== "object") return false;
|
|
25129
|
+
const obj = parsed;
|
|
25130
|
+
if (typeof obj.phase !== "string") return false;
|
|
25131
|
+
if (!obj.cache || typeof obj.cache !== "object") return false;
|
|
25132
|
+
const mode = obj.mode;
|
|
25133
|
+
if (!mode || typeof mode !== "object") return false;
|
|
25134
|
+
if (typeof mode.deployment !== "string") return false;
|
|
25135
|
+
return true;
|
|
25136
|
+
}
|
|
25137
|
+
async function probeAuthVault(olamHomeOverride) {
|
|
25138
|
+
const vaultPath = resolveAccountsPath(olamHomeOverride);
|
|
25139
|
+
if (!existsSync43(vaultPath)) {
|
|
25140
|
+
return {
|
|
25141
|
+
ok: false,
|
|
25142
|
+
message: `auth vault missing at ${vaultPath}`,
|
|
25143
|
+
remedy: "Run `olam auth up && olam auth login` to provision the vault."
|
|
25144
|
+
};
|
|
25145
|
+
}
|
|
25146
|
+
let parsed;
|
|
25147
|
+
try {
|
|
25148
|
+
parsed = JSON.parse(readFileSync30(vaultPath, "utf-8"));
|
|
25149
|
+
} catch (err) {
|
|
25150
|
+
return {
|
|
25151
|
+
ok: false,
|
|
25152
|
+
message: `auth vault malformed: ${err.message}`,
|
|
25153
|
+
remedy: "Inspect the accounts.json file; restore from backup or re-run `olam auth up`."
|
|
25154
|
+
};
|
|
25155
|
+
}
|
|
25156
|
+
if (!Array.isArray(parsed)) {
|
|
25157
|
+
return {
|
|
25158
|
+
ok: false,
|
|
25159
|
+
message: "auth vault malformed: expected JSON array at top level",
|
|
25160
|
+
remedy: "Restore the vault from backup or re-run `olam auth up && olam auth login`."
|
|
25161
|
+
};
|
|
25162
|
+
}
|
|
25163
|
+
const accounts = parsed.filter((a) => a !== null && typeof a === "object");
|
|
25164
|
+
const now = Date.now();
|
|
25165
|
+
const activeClaude = accounts.filter((a) => a.provider === "claude" && effectiveState2(a, now) === "active");
|
|
25166
|
+
if (activeClaude.length === 0) {
|
|
25167
|
+
return {
|
|
25168
|
+
ok: false,
|
|
25169
|
+
message: `no active claude credentials (vault has ${accounts.length} account(s))`,
|
|
25170
|
+
remedy: "Run `olam auth login` to add a credential, or wait for the next reset."
|
|
25171
|
+
};
|
|
25172
|
+
}
|
|
25173
|
+
return { ok: true, message: `${activeClaude.length} active claude credential(s)` };
|
|
25174
|
+
}
|
|
25175
|
+
function resolveAccountsPath(olamHomeOverride) {
|
|
25176
|
+
const explicit = process.env.OLAM_AUTH_DATA_PATH;
|
|
25177
|
+
if (explicit) return explicit;
|
|
25178
|
+
const olamHome5 = olamHomeOverride ?? process.env.OLAM_HOME ?? path43.join(homedir22(), ".olam");
|
|
25179
|
+
return path43.join(olamHome5, "auth-data", "accounts.json");
|
|
25180
|
+
}
|
|
25181
|
+
function effectiveState2(account, now) {
|
|
25182
|
+
const persisted = account.state ?? (account.rateLimited ? "cooldown" : "active");
|
|
25183
|
+
if (persisted === "disabled") return "disabled";
|
|
25184
|
+
if (typeof account.expiresAt === "number" && account.expiresAt <= now) return "expired";
|
|
25185
|
+
if (persisted === "cooldown") {
|
|
25186
|
+
const reset = account.rateLimitResetsAt ? new Date(account.rateLimitResetsAt).getTime() : 0;
|
|
25187
|
+
if (reset > 0 && reset <= now) return "active";
|
|
25188
|
+
}
|
|
25189
|
+
return persisted;
|
|
25190
|
+
}
|
|
25191
|
+
async function probeKgStorage(olamHomeOverride) {
|
|
25192
|
+
const olamHome5 = olamHomeOverride ?? process.env.OLAM_HOME ?? path43.join(homedir22(), ".olam");
|
|
25193
|
+
const kgRoot3 = path43.join(olamHome5, "kg");
|
|
25194
|
+
const worldsRoot3 = path43.join(olamHome5, "worlds");
|
|
25195
|
+
const kgBytes = enumerateGraphifyOut(kgRoot3, "pristine");
|
|
25196
|
+
const overlayBytes = enumerateGraphifyOut(worldsRoot3, "overlay");
|
|
25197
|
+
const totalBytes = kgBytes + overlayBytes;
|
|
25198
|
+
if (totalBytes >= HARD_CAP_BYTES) {
|
|
25199
|
+
return {
|
|
25200
|
+
ok: false,
|
|
25201
|
+
message: `KG storage ${formatBytes4(totalBytes)} exceeds 5 GB hard cap`,
|
|
25202
|
+
remedy: "Prune stale pristines: `rm -rf ~/.olam/kg/<workspace>` after operator review."
|
|
25203
|
+
};
|
|
25204
|
+
}
|
|
25205
|
+
if (totalBytes >= SOFT_CAP_BYTES) {
|
|
25206
|
+
return {
|
|
25207
|
+
ok: true,
|
|
25208
|
+
message: `KG storage ${formatBytes4(totalBytes)} (soft-warn \u2014 exceeds 1.5 GB; consider pruning)`
|
|
25209
|
+
};
|
|
25210
|
+
}
|
|
25211
|
+
return { ok: true, message: `KG storage ${formatBytes4(totalBytes)} (under cap)` };
|
|
25212
|
+
}
|
|
25213
|
+
function enumerateGraphifyOut(root, layout) {
|
|
25214
|
+
if (!existsSync43(root)) return 0;
|
|
25215
|
+
let total = 0;
|
|
25216
|
+
let entries;
|
|
25217
|
+
try {
|
|
25218
|
+
entries = readdirSync11(root, { withFileTypes: true });
|
|
25219
|
+
} catch {
|
|
25220
|
+
return 0;
|
|
25221
|
+
}
|
|
25222
|
+
for (const entry of entries) {
|
|
25223
|
+
if (!entry.isDirectory()) continue;
|
|
25224
|
+
if (layout === "pristine") {
|
|
25225
|
+
total += dirSizeBytes(path43.join(root, entry.name, "graphify-out"));
|
|
25226
|
+
} else {
|
|
25227
|
+
const worldDir = path43.join(root, entry.name);
|
|
25228
|
+
let clones;
|
|
25229
|
+
try {
|
|
25230
|
+
clones = readdirSync11(worldDir, { withFileTypes: true });
|
|
25231
|
+
} catch {
|
|
25232
|
+
continue;
|
|
25233
|
+
}
|
|
25234
|
+
for (const clone of clones) {
|
|
25235
|
+
if (!clone.isDirectory()) continue;
|
|
25236
|
+
total += dirSizeBytes(path43.join(worldDir, clone.name, "graphify-out"));
|
|
25237
|
+
}
|
|
25238
|
+
}
|
|
25239
|
+
}
|
|
25240
|
+
return total;
|
|
25241
|
+
}
|
|
25242
|
+
function dirSizeBytes(dir) {
|
|
25243
|
+
if (!existsSync43(dir)) return 0;
|
|
25244
|
+
let total = 0;
|
|
25245
|
+
const stack = [dir];
|
|
25246
|
+
while (stack.length > 0) {
|
|
25247
|
+
const cur = stack.pop();
|
|
25248
|
+
let entries;
|
|
25249
|
+
try {
|
|
25250
|
+
entries = readdirSync11(cur, { withFileTypes: true });
|
|
25251
|
+
} catch {
|
|
25252
|
+
continue;
|
|
25253
|
+
}
|
|
25254
|
+
for (const entry of entries) {
|
|
25255
|
+
const full = path43.join(cur, entry.name);
|
|
25256
|
+
if (entry.isSymbolicLink()) continue;
|
|
25257
|
+
if (entry.isDirectory()) {
|
|
25258
|
+
stack.push(full);
|
|
25259
|
+
continue;
|
|
25260
|
+
}
|
|
25261
|
+
try {
|
|
25262
|
+
total += statSync13(full).size;
|
|
25263
|
+
} catch {
|
|
25264
|
+
}
|
|
25265
|
+
}
|
|
25266
|
+
}
|
|
25267
|
+
return total;
|
|
25268
|
+
}
|
|
25269
|
+
function formatBytes4(n) {
|
|
25270
|
+
if (n < 1024) return `${n} B`;
|
|
25271
|
+
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
25272
|
+
if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
25273
|
+
return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
25274
|
+
}
|
|
25275
|
+
|
|
25276
|
+
// src/commands/doctor.ts
|
|
25277
|
+
init_output();
|
|
25278
|
+
var DEFAULT_REGISTRY = "ghcr.io/pleri";
|
|
25279
|
+
var REQUIRED_IMAGE_PAIRS = [
|
|
25280
|
+
{ bare: "olam-host-cp:latest", registryName: "olam-host-cp:latest" },
|
|
25281
|
+
{ bare: "olam-auth:local" },
|
|
25282
|
+
{ bare: "olam-devbox:base", registryName: "olam-devbox:base" },
|
|
25283
|
+
{ bare: "olam-mcp-auth:local" }
|
|
25284
|
+
];
|
|
25285
|
+
function buildRequiredImageRefs(registry) {
|
|
25286
|
+
const refs = [];
|
|
25287
|
+
for (const pair of REQUIRED_IMAGE_PAIRS) {
|
|
25288
|
+
refs.push(pair.bare);
|
|
25289
|
+
if (pair.registryName) refs.push(`${registry}/${pair.registryName}`);
|
|
25290
|
+
}
|
|
25291
|
+
return refs;
|
|
25292
|
+
}
|
|
25293
|
+
async function runDoctor(opts, deps = {}) {
|
|
25294
|
+
const dockerExec = deps.dockerExec;
|
|
25295
|
+
const fetchImpl = deps.fetchImpl;
|
|
25296
|
+
const olamHomeOverride = deps.olamHomeOverride;
|
|
25297
|
+
const registry = deps.registry ?? DEFAULT_REGISTRY;
|
|
25298
|
+
const dockerResult = await probeDockerDaemon(dockerExec);
|
|
25299
|
+
const rows = [{ name: "docker daemon", result: dockerResult }];
|
|
25300
|
+
if (!dockerResult.ok) {
|
|
25301
|
+
return emit({ rows, summary: "FAILED", failureCount: 1 }, opts);
|
|
25302
|
+
}
|
|
25303
|
+
const imageRefs = buildRequiredImageRefs(registry);
|
|
25304
|
+
const [imageResult, hostCpResult, authResult, kgResult] = await Promise.all([
|
|
25305
|
+
probeImagePresence(imageRefs, dockerExec),
|
|
25306
|
+
probeHostCpHealth(fetchImpl),
|
|
25307
|
+
probeAuthVault(olamHomeOverride),
|
|
25308
|
+
probeKgStorage(olamHomeOverride)
|
|
25309
|
+
]);
|
|
25310
|
+
rows.push(
|
|
25311
|
+
{ name: "images", result: imageResult },
|
|
25312
|
+
{ name: "host-cp /health", result: hostCpResult },
|
|
25313
|
+
{ name: "auth vault", result: authResult },
|
|
25314
|
+
{ name: "KG storage", result: kgResult }
|
|
25315
|
+
);
|
|
25316
|
+
const failureCount = rows.filter((r) => !r.result.ok).length;
|
|
25317
|
+
const summary = failureCount === 0 ? "OK" : "FAILED";
|
|
25318
|
+
return emit({ rows, summary, failureCount }, opts);
|
|
25319
|
+
}
|
|
25320
|
+
function emit(report, opts) {
|
|
25321
|
+
if (opts.json) {
|
|
25322
|
+
process.stdout.write(
|
|
25323
|
+
JSON.stringify(
|
|
25324
|
+
{
|
|
25325
|
+
summary: report.summary,
|
|
25326
|
+
failureCount: report.failureCount,
|
|
25327
|
+
probes: report.rows.map((r) => ({
|
|
25328
|
+
name: r.name,
|
|
25329
|
+
ok: r.result.ok,
|
|
25330
|
+
message: r.result.message,
|
|
25331
|
+
...r.result.ok ? {} : { remedy: r.result.remedy }
|
|
25332
|
+
}))
|
|
25333
|
+
},
|
|
25334
|
+
null,
|
|
25335
|
+
2
|
|
25336
|
+
) + "\n"
|
|
25337
|
+
);
|
|
25338
|
+
} else {
|
|
25339
|
+
renderHuman(report);
|
|
25340
|
+
}
|
|
25341
|
+
const exitCode = report.summary === "OK" ? 0 : 1;
|
|
25342
|
+
return { exitCode, report };
|
|
25343
|
+
}
|
|
25344
|
+
function renderHuman(report) {
|
|
25345
|
+
printHeader("olam doctor");
|
|
25346
|
+
const namePad = Math.max(...report.rows.map((r) => r.name.length));
|
|
25347
|
+
for (const row of report.rows) {
|
|
25348
|
+
const label = row.name.padEnd(namePad);
|
|
25349
|
+
if (row.result.ok) {
|
|
25350
|
+
printSuccess(`${label} ${row.result.message}`);
|
|
25351
|
+
} else {
|
|
25352
|
+
printError(`${label} ${row.result.message}`);
|
|
25353
|
+
printWarning(`${"".padEnd(namePad)} remedy: ${row.result.remedy}`);
|
|
25354
|
+
}
|
|
25355
|
+
}
|
|
25356
|
+
process.stdout.write("\n");
|
|
25357
|
+
if (report.summary === "OK") {
|
|
25358
|
+
printSuccess(`OK \u2014 all ${report.rows.length} probes green`);
|
|
25359
|
+
} else {
|
|
25360
|
+
printError(`FAILED \u2014 ${report.failureCount} of ${report.rows.length} probes failed`);
|
|
25361
|
+
}
|
|
25362
|
+
}
|
|
25363
|
+
function registerDoctor(program2) {
|
|
25364
|
+
program2.command("doctor").description(
|
|
25365
|
+
"Pass/fail host-health check. Exits 0 on a healthy host; 1 on any failed probe. Runs Docker daemon / image presence / host-cp /health / auth vault / KG storage probes."
|
|
25366
|
+
).option("--json", "emit the report as JSON instead of a human-readable table").action(async (opts) => {
|
|
25367
|
+
const r = await runDoctor(opts);
|
|
25368
|
+
if (r.exitCode !== 0) process.exitCode = r.exitCode;
|
|
25369
|
+
});
|
|
25370
|
+
}
|
|
25371
|
+
|
|
25040
25372
|
// src/commands/update.ts
|
|
25041
25373
|
import * as fs42 from "node:fs";
|
|
25042
25374
|
import * as os25 from "node:os";
|
|
25043
|
-
import * as
|
|
25375
|
+
import * as path46 from "node:path";
|
|
25044
25376
|
import { execSync as execSync13 } from "node:child_process";
|
|
25045
25377
|
import pc23 from "picocolors";
|
|
25046
25378
|
|
|
25047
25379
|
// src/lib/symlink-reconcile.ts
|
|
25048
25380
|
import * as fs40 from "node:fs";
|
|
25049
|
-
import * as
|
|
25381
|
+
import * as path44 from "node:path";
|
|
25050
25382
|
var realFs = {
|
|
25051
25383
|
readdirSync: (p) => fs40.readdirSync(p),
|
|
25052
25384
|
existsSync: (p) => fs40.existsSync(p),
|
|
@@ -25065,8 +25397,8 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
|
|
|
25065
25397
|
_fs.mkdirSync(claudeSkillsDir, { recursive: true });
|
|
25066
25398
|
const sourceSkills = _fs.existsSync(npmSkillsDir) ? _fs.readdirSync(npmSkillsDir).filter((d) => d.startsWith("olam-")) : [];
|
|
25067
25399
|
for (const skill of sourceSkills) {
|
|
25068
|
-
const linkPath =
|
|
25069
|
-
const target =
|
|
25400
|
+
const linkPath = path44.join(claudeSkillsDir, skill);
|
|
25401
|
+
const target = path44.join(npmSkillsDir, skill);
|
|
25070
25402
|
if (!_fs.existsSync(linkPath)) {
|
|
25071
25403
|
try {
|
|
25072
25404
|
_fs.symlinkSync(target, linkPath);
|
|
@@ -25079,7 +25411,7 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
|
|
|
25079
25411
|
}
|
|
25080
25412
|
const deployedEntries = _fs.existsSync(claudeSkillsDir) ? _fs.readdirSync(claudeSkillsDir).filter((d) => d.startsWith("olam-")) : [];
|
|
25081
25413
|
for (const entry of deployedEntries) {
|
|
25082
|
-
const linkPath =
|
|
25414
|
+
const linkPath = path44.join(claudeSkillsDir, entry);
|
|
25083
25415
|
let isSymlink = false;
|
|
25084
25416
|
try {
|
|
25085
25417
|
isSymlink = _fs.lstatSync(linkPath).isSymbolicLink();
|
|
@@ -25104,9 +25436,9 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
|
|
|
25104
25436
|
|
|
25105
25437
|
// src/commands/update.ts
|
|
25106
25438
|
var PACKAGE_NAME = "@pleri/olam-cli";
|
|
25107
|
-
var CACHE_DIR2 =
|
|
25108
|
-
var LOG_DIR2 =
|
|
25109
|
-
var LAST_STABLE_FILE =
|
|
25439
|
+
var CACHE_DIR2 = path46.join(os25.homedir(), ".olam", "cache");
|
|
25440
|
+
var LOG_DIR2 = path46.join(os25.homedir(), ".olam", "log");
|
|
25441
|
+
var LAST_STABLE_FILE = path46.join(CACHE_DIR2, "last-stable.txt");
|
|
25110
25442
|
function defaultExec(cmd) {
|
|
25111
25443
|
try {
|
|
25112
25444
|
const stdout = execSync13(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -25135,12 +25467,12 @@ function readLastStable(file = LAST_STABLE_FILE) {
|
|
|
25135
25467
|
}
|
|
25136
25468
|
}
|
|
25137
25469
|
function writeLastStable(version, file = LAST_STABLE_FILE) {
|
|
25138
|
-
fs42.mkdirSync(
|
|
25470
|
+
fs42.mkdirSync(path46.dirname(file), { recursive: true });
|
|
25139
25471
|
fs42.writeFileSync(file, version, { mode: 420 });
|
|
25140
25472
|
}
|
|
25141
25473
|
function logUpdateFailure(stderr) {
|
|
25142
25474
|
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
25143
|
-
const logFile =
|
|
25475
|
+
const logFile = path46.join(LOG_DIR2, `update-${ts}.log`);
|
|
25144
25476
|
try {
|
|
25145
25477
|
fs42.mkdirSync(LOG_DIR2, { recursive: true });
|
|
25146
25478
|
fs42.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
@@ -25230,8 +25562,8 @@ async function doUpdate(opts, _exec = defaultExec, _reconcile = reconcileSkillSy
|
|
|
25230
25562
|
let symlinkResult = { added: [], removed: [] };
|
|
25231
25563
|
if (npmRootResult.exitCode === 0) {
|
|
25232
25564
|
const npmRoot = npmRootResult.stdout.trim();
|
|
25233
|
-
const npmSkillsDir =
|
|
25234
|
-
const claudeSkillsDir =
|
|
25565
|
+
const npmSkillsDir = path46.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills");
|
|
25566
|
+
const claudeSkillsDir = path46.join(os25.homedir(), ".claude", "skills");
|
|
25235
25567
|
const rec = _reconcile(npmSkillsDir, claudeSkillsDir);
|
|
25236
25568
|
symlinkResult = { added: rec.added, removed: rec.removed };
|
|
25237
25569
|
if (!quiet && (rec.added.length > 0 || rec.removed.length > 0)) {
|
|
@@ -25277,8 +25609,8 @@ async function doRollback(_exec = defaultExec, _reconcile = reconcileSkillSymlin
|
|
|
25277
25609
|
if (npmRootResult.exitCode === 0) {
|
|
25278
25610
|
const npmRoot = npmRootResult.stdout.trim();
|
|
25279
25611
|
_reconcile(
|
|
25280
|
-
|
|
25281
|
-
|
|
25612
|
+
path46.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills"),
|
|
25613
|
+
path46.join(os25.homedir(), ".claude", "skills")
|
|
25282
25614
|
);
|
|
25283
25615
|
}
|
|
25284
25616
|
return { action: "rolled-back", restoredVersion: prev, exitCode: 0 };
|
|
@@ -25370,10 +25702,10 @@ init_store2();
|
|
|
25370
25702
|
init_store2();
|
|
25371
25703
|
import * as fs43 from "node:fs";
|
|
25372
25704
|
import * as os26 from "node:os";
|
|
25373
|
-
import * as
|
|
25705
|
+
import * as path47 from "node:path";
|
|
25374
25706
|
function expandPath(p) {
|
|
25375
25707
|
if (p === "~" || p.startsWith("~/")) {
|
|
25376
|
-
return
|
|
25708
|
+
return path47.join(os26.homedir(), p.slice(1));
|
|
25377
25709
|
}
|
|
25378
25710
|
return p;
|
|
25379
25711
|
}
|
|
@@ -25782,8 +26114,8 @@ var SECRET = process.env["OLAM_MCP_AUTH_SECRET"] ?? "";
|
|
|
25782
26114
|
function authHeaders() {
|
|
25783
26115
|
return SECRET ? { "X-Olam-Mcp-Secret": SECRET } : {};
|
|
25784
26116
|
}
|
|
25785
|
-
async function apiFetch(
|
|
25786
|
-
const res = await fetch(`${BASE_URL}${
|
|
26117
|
+
async function apiFetch(path53, init = {}) {
|
|
26118
|
+
const res = await fetch(`${BASE_URL}${path53}`, {
|
|
25787
26119
|
...init,
|
|
25788
26120
|
headers: {
|
|
25789
26121
|
"Content-Type": "application/json",
|
|
@@ -26045,7 +26377,7 @@ import pc29 from "picocolors";
|
|
|
26045
26377
|
// src/commands/mcp/import-discovery.ts
|
|
26046
26378
|
import * as fs45 from "node:fs";
|
|
26047
26379
|
import * as os27 from "node:os";
|
|
26048
|
-
import * as
|
|
26380
|
+
import * as path48 from "node:path";
|
|
26049
26381
|
function readJsonFile(filePath) {
|
|
26050
26382
|
try {
|
|
26051
26383
|
const raw = fs45.readFileSync(filePath, "utf-8");
|
|
@@ -26077,18 +26409,18 @@ function extractMcpServers(obj, source, sourceLabel) {
|
|
|
26077
26409
|
}
|
|
26078
26410
|
function getClaudeDesktopPath() {
|
|
26079
26411
|
if (process.platform === "darwin") {
|
|
26080
|
-
return
|
|
26412
|
+
return path48.join(os27.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
26081
26413
|
}
|
|
26082
26414
|
if (process.platform === "win32") {
|
|
26083
|
-
const appData = process.env["APPDATA"] ??
|
|
26084
|
-
return
|
|
26415
|
+
const appData = process.env["APPDATA"] ?? path48.join(os27.homedir(), "AppData", "Roaming");
|
|
26416
|
+
return path48.join(appData, "Claude", "claude_desktop_config.json");
|
|
26085
26417
|
}
|
|
26086
|
-
return
|
|
26418
|
+
return path48.join(os27.homedir(), ".config", "Claude", "claude_desktop_config.json");
|
|
26087
26419
|
}
|
|
26088
26420
|
function getOlamRepoPaths() {
|
|
26089
26421
|
const configPaths = [
|
|
26090
|
-
|
|
26091
|
-
|
|
26422
|
+
path48.join(os27.homedir(), ".olam", "config.yaml"),
|
|
26423
|
+
path48.join(process.cwd(), ".olam", "config.yaml")
|
|
26092
26424
|
];
|
|
26093
26425
|
const paths = [];
|
|
26094
26426
|
for (const configPath of configPaths) {
|
|
@@ -26110,7 +26442,7 @@ async function discoverMcpSources(repoPaths) {
|
|
|
26110
26442
|
const sources = [];
|
|
26111
26443
|
const sourceDefs = [
|
|
26112
26444
|
{
|
|
26113
|
-
path:
|
|
26445
|
+
path: path48.join(os27.homedir(), ".claude.json"),
|
|
26114
26446
|
label: "Claude Code (~/.claude.json)"
|
|
26115
26447
|
},
|
|
26116
26448
|
{
|
|
@@ -26118,19 +26450,19 @@ async function discoverMcpSources(repoPaths) {
|
|
|
26118
26450
|
label: "Claude Desktop"
|
|
26119
26451
|
},
|
|
26120
26452
|
{
|
|
26121
|
-
path:
|
|
26453
|
+
path: path48.join(os27.homedir(), ".cursor", "mcp.json"),
|
|
26122
26454
|
label: "Cursor (~/.cursor/mcp.json)"
|
|
26123
26455
|
},
|
|
26124
26456
|
{
|
|
26125
|
-
path:
|
|
26457
|
+
path: path48.join(os27.homedir(), ".codeium", "windsurf", "mcp_config.json"),
|
|
26126
26458
|
label: "Windsurf (~/.codeium/windsurf/mcp_config.json)"
|
|
26127
26459
|
}
|
|
26128
26460
|
];
|
|
26129
26461
|
const resolvedRepoPaths = repoPaths ?? getOlamRepoPaths();
|
|
26130
26462
|
for (const repoPath of resolvedRepoPaths) {
|
|
26131
26463
|
sourceDefs.push({
|
|
26132
|
-
path:
|
|
26133
|
-
label: `.mcp.json (${
|
|
26464
|
+
path: path48.join(repoPath, ".mcp.json"),
|
|
26465
|
+
label: `.mcp.json (${path48.basename(repoPath)})`
|
|
26134
26466
|
});
|
|
26135
26467
|
}
|
|
26136
26468
|
const reads = await Promise.all(
|
|
@@ -26360,12 +26692,12 @@ function registerMcp(program2) {
|
|
|
26360
26692
|
}
|
|
26361
26693
|
|
|
26362
26694
|
// src/commands/kg-build.ts
|
|
26363
|
-
import { spawnSync as
|
|
26695
|
+
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
26364
26696
|
import fs48 from "node:fs";
|
|
26365
|
-
import
|
|
26697
|
+
import path51 from "node:path";
|
|
26366
26698
|
|
|
26367
26699
|
// ../core/dist/kg/storage-paths.js
|
|
26368
|
-
import { homedir as
|
|
26700
|
+
import { homedir as homedir27 } from "node:os";
|
|
26369
26701
|
import { join as join48, resolve as resolve10 } from "node:path";
|
|
26370
26702
|
|
|
26371
26703
|
// ../core/dist/world/workspace-name.js
|
|
@@ -26387,7 +26719,7 @@ function validateWorkspaceName(name) {
|
|
|
26387
26719
|
|
|
26388
26720
|
// ../core/dist/kg/storage-paths.js
|
|
26389
26721
|
function olamHome3() {
|
|
26390
|
-
return process.env.OLAM_HOME ?? join48(
|
|
26722
|
+
return process.env.OLAM_HOME ?? join48(homedir27(), ".olam");
|
|
26391
26723
|
}
|
|
26392
26724
|
function kgRoot() {
|
|
26393
26725
|
return join48(olamHome3(), "kg");
|
|
@@ -26395,17 +26727,17 @@ function kgRoot() {
|
|
|
26395
26727
|
function worldsRoot() {
|
|
26396
26728
|
return join48(olamHome3(), "worlds");
|
|
26397
26729
|
}
|
|
26398
|
-
function assertWithinPrefix(
|
|
26399
|
-
if (!
|
|
26400
|
-
throw new Error(`${label} escape: ${
|
|
26730
|
+
function assertWithinPrefix(path53, prefix, label) {
|
|
26731
|
+
if (!path53.startsWith(prefix + "/")) {
|
|
26732
|
+
throw new Error(`${label} escape: ${path53} not under ${prefix}/`);
|
|
26401
26733
|
}
|
|
26402
26734
|
}
|
|
26403
26735
|
function kgPristinePath(workspace) {
|
|
26404
26736
|
validateWorkspaceName(workspace);
|
|
26405
26737
|
const root = kgRoot();
|
|
26406
|
-
const
|
|
26407
|
-
assertWithinPrefix(
|
|
26408
|
-
return
|
|
26738
|
+
const path53 = resolve10(join48(root, workspace));
|
|
26739
|
+
assertWithinPrefix(path53, root, "kgPristinePath");
|
|
26740
|
+
return path53;
|
|
26409
26741
|
}
|
|
26410
26742
|
var KG_PATHS_INTERNALS = Object.freeze({
|
|
26411
26743
|
olamHome: olamHome3,
|
|
@@ -26418,21 +26750,19 @@ init_output();
|
|
|
26418
26750
|
|
|
26419
26751
|
// src/commands/kg-status.ts
|
|
26420
26752
|
import fs46 from "node:fs";
|
|
26421
|
-
import { homedir as
|
|
26422
|
-
import
|
|
26753
|
+
import { homedir as homedir28 } from "node:os";
|
|
26754
|
+
import path49 from "node:path";
|
|
26423
26755
|
init_output();
|
|
26424
|
-
var SOFT_CAP_BYTES = 15e8;
|
|
26425
|
-
var HARD_CAP_BYTES = 5e9;
|
|
26426
26756
|
function olamHome4() {
|
|
26427
|
-
return process.env.OLAM_HOME ??
|
|
26757
|
+
return process.env.OLAM_HOME ?? path49.join(homedir28(), ".olam");
|
|
26428
26758
|
}
|
|
26429
26759
|
function kgRoot2() {
|
|
26430
|
-
return
|
|
26760
|
+
return path49.join(olamHome4(), "kg");
|
|
26431
26761
|
}
|
|
26432
26762
|
function worldsRoot2() {
|
|
26433
|
-
return
|
|
26763
|
+
return path49.join(olamHome4(), "worlds");
|
|
26434
26764
|
}
|
|
26435
|
-
function
|
|
26765
|
+
function dirSizeBytes2(dir) {
|
|
26436
26766
|
if (!fs46.existsSync(dir)) return 0;
|
|
26437
26767
|
let total = 0;
|
|
26438
26768
|
const stack = [dir];
|
|
@@ -26445,7 +26775,7 @@ function dirSizeBytes(dir) {
|
|
|
26445
26775
|
continue;
|
|
26446
26776
|
}
|
|
26447
26777
|
for (const entry of entries) {
|
|
26448
|
-
const full =
|
|
26778
|
+
const full = path49.join(cur, entry.name);
|
|
26449
26779
|
if (entry.isSymbolicLink()) continue;
|
|
26450
26780
|
if (entry.isDirectory()) {
|
|
26451
26781
|
stack.push(full);
|
|
@@ -26459,14 +26789,14 @@ function dirSizeBytes(dir) {
|
|
|
26459
26789
|
}
|
|
26460
26790
|
return total;
|
|
26461
26791
|
}
|
|
26462
|
-
function
|
|
26792
|
+
function formatBytes5(n) {
|
|
26463
26793
|
if (n < 1024) return `${n} B`;
|
|
26464
26794
|
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
26465
26795
|
if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
26466
26796
|
return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
26467
26797
|
}
|
|
26468
26798
|
function readFreshness(workspace) {
|
|
26469
|
-
const file =
|
|
26799
|
+
const file = path49.join(kgPristinePath(workspace), "freshness.json");
|
|
26470
26800
|
if (!fs46.existsSync(file)) return null;
|
|
26471
26801
|
try {
|
|
26472
26802
|
const raw = JSON.parse(fs46.readFileSync(file, "utf-8"));
|
|
@@ -26477,7 +26807,7 @@ function readFreshness(workspace) {
|
|
|
26477
26807
|
}
|
|
26478
26808
|
}
|
|
26479
26809
|
function readOverlayNodeCount(graphifyOutDir) {
|
|
26480
|
-
const graphPath =
|
|
26810
|
+
const graphPath = path49.join(graphifyOutDir, "graph.json");
|
|
26481
26811
|
if (!fs46.existsSync(graphPath)) return null;
|
|
26482
26812
|
try {
|
|
26483
26813
|
const raw = JSON.parse(fs46.readFileSync(graphPath, "utf-8"));
|
|
@@ -26503,7 +26833,7 @@ function listOverlays() {
|
|
|
26503
26833
|
for (const worldEntry of worldDirs) {
|
|
26504
26834
|
if (!worldEntry.isDirectory()) continue;
|
|
26505
26835
|
const worldId = worldEntry.name;
|
|
26506
|
-
const worldDir =
|
|
26836
|
+
const worldDir = path49.join(root, worldId);
|
|
26507
26837
|
let cloneDirs;
|
|
26508
26838
|
try {
|
|
26509
26839
|
cloneDirs = fs46.readdirSync(worldDir, { withFileTypes: true });
|
|
@@ -26512,13 +26842,13 @@ function listOverlays() {
|
|
|
26512
26842
|
}
|
|
26513
26843
|
for (const cloneEntry of cloneDirs) {
|
|
26514
26844
|
if (!cloneEntry.isDirectory()) continue;
|
|
26515
|
-
const graphifyOut =
|
|
26845
|
+
const graphifyOut = path49.join(worldDir, cloneEntry.name, "graphify-out");
|
|
26516
26846
|
if (!fs46.existsSync(graphifyOut)) continue;
|
|
26517
26847
|
records.push({
|
|
26518
26848
|
world_id: worldId,
|
|
26519
26849
|
clone_dir: cloneEntry.name,
|
|
26520
26850
|
graphify_out_path: graphifyOut,
|
|
26521
|
-
graphify_out_size_bytes:
|
|
26851
|
+
graphify_out_size_bytes: dirSizeBytes2(graphifyOut),
|
|
26522
26852
|
node_count: readOverlayNodeCount(graphifyOut)
|
|
26523
26853
|
});
|
|
26524
26854
|
}
|
|
@@ -26544,8 +26874,8 @@ function listPristines(overlays) {
|
|
|
26544
26874
|
continue;
|
|
26545
26875
|
}
|
|
26546
26876
|
const fresh = readFreshness(workspace);
|
|
26547
|
-
const graphifyOut =
|
|
26548
|
-
const size =
|
|
26877
|
+
const graphifyOut = path49.join(kgPristinePath(workspace), "graphify-out");
|
|
26878
|
+
const size = dirSizeBytes2(graphifyOut);
|
|
26549
26879
|
const worldCount = overlays.filter((o) => o.clone_dir === workspace).length;
|
|
26550
26880
|
records.push({
|
|
26551
26881
|
workspace,
|
|
@@ -26577,7 +26907,7 @@ function buildReport(workspaceFilter) {
|
|
|
26577
26907
|
cap_status: classifyCap(totalBytes)
|
|
26578
26908
|
};
|
|
26579
26909
|
}
|
|
26580
|
-
function
|
|
26910
|
+
function renderHuman2(report, workspaceFilter) {
|
|
26581
26911
|
const lines = [];
|
|
26582
26912
|
if (report.pristines.length === 0 && report.overlays.length === 0) {
|
|
26583
26913
|
if (workspaceFilter) {
|
|
@@ -26605,7 +26935,7 @@ function renderHuman(report, workspaceFilter) {
|
|
|
26605
26935
|
p.workspace.padEnd(24),
|
|
26606
26936
|
(p.built_at ?? "\u2014").padEnd(22),
|
|
26607
26937
|
String(p.node_count ?? "\u2014").padStart(8),
|
|
26608
|
-
|
|
26938
|
+
formatBytes5(p.graphify_out_size_bytes).padStart(10),
|
|
26609
26939
|
String(p.world_count).padStart(7)
|
|
26610
26940
|
].join(" ")
|
|
26611
26941
|
);
|
|
@@ -26629,13 +26959,13 @@ function renderHuman(report, workspaceFilter) {
|
|
|
26629
26959
|
o.world_id.padEnd(24),
|
|
26630
26960
|
o.clone_dir.padEnd(20),
|
|
26631
26961
|
String(o.node_count ?? "\u2014").padStart(8),
|
|
26632
|
-
|
|
26962
|
+
formatBytes5(o.graphify_out_size_bytes).padStart(10)
|
|
26633
26963
|
].join(" ")
|
|
26634
26964
|
);
|
|
26635
26965
|
}
|
|
26636
26966
|
lines.push("");
|
|
26637
26967
|
}
|
|
26638
|
-
lines.push(`Total: ${
|
|
26968
|
+
lines.push(`Total: ${formatBytes5(report.total_bytes)} (cap: ${report.cap_status})`);
|
|
26639
26969
|
return lines.join("\n");
|
|
26640
26970
|
}
|
|
26641
26971
|
async function runKgStatus(workspaceArg, opts) {
|
|
@@ -26652,15 +26982,15 @@ async function runKgStatus(workspaceArg, opts) {
|
|
|
26652
26982
|
if (opts.json) {
|
|
26653
26983
|
process.stdout.write(JSON.stringify(report, null, 2) + "\n");
|
|
26654
26984
|
} else {
|
|
26655
|
-
process.stdout.write(
|
|
26985
|
+
process.stdout.write(renderHuman2(report, workspaceArg) + "\n");
|
|
26656
26986
|
}
|
|
26657
26987
|
if (report.cap_status === "soft-warn") {
|
|
26658
26988
|
printWarning(
|
|
26659
|
-
`KG storage at ${
|
|
26989
|
+
`KG storage at ${formatBytes5(report.total_bytes)} \u2014 exceeds 1.5GB soft cap. Consider pruning stale pristines via \`rm -rf ~/.olam/kg/<workspace>\` after operator review.`
|
|
26660
26990
|
);
|
|
26661
26991
|
} else if (report.cap_status === "hard-critical") {
|
|
26662
26992
|
printError(
|
|
26663
|
-
`KG storage at ${
|
|
26993
|
+
`KG storage at ${formatBytes5(report.total_bytes)} \u2014 exceeds 5GB hard cap. Prune stale pristines or overlays before running \`olam kg build\` again.`
|
|
26664
26994
|
);
|
|
26665
26995
|
return { exitCode: 1, report };
|
|
26666
26996
|
}
|
|
@@ -26678,10 +27008,10 @@ function registerKgStatusCommand(kg) {
|
|
|
26678
27008
|
// src/commands/kg-watch.ts
|
|
26679
27009
|
import { spawn as spawn7 } from "node:child_process";
|
|
26680
27010
|
import fs47 from "node:fs";
|
|
26681
|
-
import
|
|
27011
|
+
import path50 from "node:path";
|
|
26682
27012
|
init_output();
|
|
26683
27013
|
function pidFilePath(workspace) {
|
|
26684
|
-
return
|
|
27014
|
+
return path50.join(kgPristinePath(workspace), ".watch.pid");
|
|
26685
27015
|
}
|
|
26686
27016
|
function isPidAlive3(pid) {
|
|
26687
27017
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
@@ -26715,7 +27045,7 @@ function readAndClassifyPid(workspace) {
|
|
|
26715
27045
|
}
|
|
26716
27046
|
function writePidFile(workspace, pid) {
|
|
26717
27047
|
const file = pidFilePath(workspace);
|
|
26718
|
-
const dir =
|
|
27048
|
+
const dir = path50.dirname(file);
|
|
26719
27049
|
fs47.mkdirSync(dir, { recursive: true });
|
|
26720
27050
|
fs47.writeFileSync(file, String(pid), { encoding: "utf-8" });
|
|
26721
27051
|
}
|
|
@@ -26728,7 +27058,7 @@ function removePidFile(workspace) {
|
|
|
26728
27058
|
}
|
|
26729
27059
|
async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
26730
27060
|
const cwd = deps.cwd ?? opts.cwd ?? process.cwd();
|
|
26731
|
-
const name = workspaceArg ??
|
|
27061
|
+
const name = workspaceArg ?? path50.basename(cwd).toLowerCase();
|
|
26732
27062
|
try {
|
|
26733
27063
|
validateWorkspaceName(name);
|
|
26734
27064
|
} catch (err) {
|
|
@@ -26736,7 +27066,7 @@ async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
|
26736
27066
|
return { exitCode: 1, pidWritten: false };
|
|
26737
27067
|
}
|
|
26738
27068
|
const pristinePath = kgPristinePath(name);
|
|
26739
|
-
const graphPath =
|
|
27069
|
+
const graphPath = path50.join(pristinePath, "graphify-out", "graph.json");
|
|
26740
27070
|
const pidState = readAndClassifyPid(name);
|
|
26741
27071
|
if (pidState.status === "active") {
|
|
26742
27072
|
printError(
|
|
@@ -26802,19 +27132,19 @@ function registerKgWatchCommand(kg) {
|
|
|
26802
27132
|
var DEFAULT_DEVBOX_IMAGE2 = "olam-devbox:latest";
|
|
26803
27133
|
function resolveWorkspace(arg) {
|
|
26804
27134
|
const cwd = process.cwd();
|
|
26805
|
-
const name = arg ??
|
|
27135
|
+
const name = arg ?? path51.basename(cwd).toLowerCase();
|
|
26806
27136
|
validateWorkspaceName(name);
|
|
26807
27137
|
return { name, sourcePath: cwd };
|
|
26808
27138
|
}
|
|
26809
27139
|
function copyWorkspaceToScratch(source, scratch) {
|
|
26810
27140
|
if (process.platform === "darwin") {
|
|
26811
|
-
const r2 =
|
|
27141
|
+
const r2 = spawnSync15("cp", ["-c", "-r", source + "/.", scratch], {
|
|
26812
27142
|
stdio: ["ignore", "ignore", "pipe"],
|
|
26813
27143
|
encoding: "utf-8"
|
|
26814
27144
|
});
|
|
26815
27145
|
if (r2.status === 0) return "cp-c-r-reflink";
|
|
26816
27146
|
}
|
|
26817
|
-
const r =
|
|
27147
|
+
const r = spawnSync15("cp", ["-r", source + "/.", scratch], {
|
|
26818
27148
|
stdio: ["ignore", "ignore", "pipe"],
|
|
26819
27149
|
encoding: "utf-8"
|
|
26820
27150
|
});
|
|
@@ -26824,7 +27154,7 @@ function copyWorkspaceToScratch(source, scratch) {
|
|
|
26824
27154
|
return "cp-r";
|
|
26825
27155
|
}
|
|
26826
27156
|
function parseNodeCount(graphifyOutDir) {
|
|
26827
|
-
const graphPath =
|
|
27157
|
+
const graphPath = path51.join(graphifyOutDir, "graph.json");
|
|
26828
27158
|
if (!fs48.existsSync(graphPath)) return null;
|
|
26829
27159
|
try {
|
|
26830
27160
|
const content = fs48.readFileSync(graphPath, "utf-8");
|
|
@@ -26835,7 +27165,7 @@ function parseNodeCount(graphifyOutDir) {
|
|
|
26835
27165
|
}
|
|
26836
27166
|
}
|
|
26837
27167
|
function readGraphifyVersion(image) {
|
|
26838
|
-
const r =
|
|
27168
|
+
const r = spawnSync15(
|
|
26839
27169
|
"docker",
|
|
26840
27170
|
[
|
|
26841
27171
|
"run",
|
|
@@ -26861,7 +27191,7 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
26861
27191
|
return { exitCode: 2 };
|
|
26862
27192
|
}
|
|
26863
27193
|
const outDir = kgPristinePath(workspace.name);
|
|
26864
|
-
const scratchDir =
|
|
27194
|
+
const scratchDir = path51.join(outDir, "scratch");
|
|
26865
27195
|
fs48.mkdirSync(outDir, { recursive: true });
|
|
26866
27196
|
if (fs48.existsSync(scratchDir)) fs48.rmSync(scratchDir, { recursive: true, force: true });
|
|
26867
27197
|
fs48.mkdirSync(scratchDir);
|
|
@@ -26887,13 +27217,13 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
26887
27217
|
"update",
|
|
26888
27218
|
"."
|
|
26889
27219
|
];
|
|
26890
|
-
const r = human ?
|
|
27220
|
+
const r = human ? spawnSync15("docker", dockerArgs, { stdio: "inherit" }) : spawnSync15("docker", dockerArgs, { stdio: ["ignore", "ignore", "pipe"] });
|
|
26891
27221
|
if (r.status !== 0) {
|
|
26892
27222
|
printError(`graphify update failed (exit ${r.status})`);
|
|
26893
27223
|
return { exitCode: r.status ?? 1 };
|
|
26894
27224
|
}
|
|
26895
|
-
const scratchOut =
|
|
26896
|
-
const finalOut =
|
|
27225
|
+
const scratchOut = path51.join(scratchDir, "graphify-out");
|
|
27226
|
+
const finalOut = path51.join(outDir, "graphify-out");
|
|
26897
27227
|
if (!fs48.existsSync(scratchOut)) {
|
|
26898
27228
|
printError(`graphify produced no graphify-out/ in scratch (${scratchOut})`);
|
|
26899
27229
|
return { exitCode: 1 };
|
|
@@ -26912,7 +27242,7 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
26912
27242
|
scratch_strategy: scratchStrategy
|
|
26913
27243
|
};
|
|
26914
27244
|
fs48.writeFileSync(
|
|
26915
|
-
|
|
27245
|
+
path51.join(outDir, "freshness.json"),
|
|
26916
27246
|
JSON.stringify(freshness, null, 2) + "\n",
|
|
26917
27247
|
"utf-8"
|
|
26918
27248
|
);
|
|
@@ -26945,12 +27275,12 @@ function registerKg(program2) {
|
|
|
26945
27275
|
|
|
26946
27276
|
// src/pleri-config.ts
|
|
26947
27277
|
import * as fs49 from "node:fs";
|
|
26948
|
-
import * as
|
|
27278
|
+
import * as path52 from "node:path";
|
|
26949
27279
|
function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
26950
27280
|
if (process.env.PLERI_BASE_URL) {
|
|
26951
27281
|
return true;
|
|
26952
27282
|
}
|
|
26953
|
-
const configPath =
|
|
27283
|
+
const configPath = path52.join(configDir, "config.yaml");
|
|
26954
27284
|
if (!fs49.existsSync(configPath)) {
|
|
26955
27285
|
return false;
|
|
26956
27286
|
}
|
|
@@ -26992,6 +27322,7 @@ registerWorldSnapshot(program);
|
|
|
26992
27322
|
registerRefresh(program);
|
|
26993
27323
|
registerBootstrap(program);
|
|
26994
27324
|
registerDiagnose(program);
|
|
27325
|
+
registerDoctor(program);
|
|
26995
27326
|
registerUpdate(program);
|
|
26996
27327
|
registerBegin(program);
|
|
26997
27328
|
registerStop(program);
|