@pleri/olam-cli 0.1.104 → 0.1.106
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/bootstrap.d.ts.map +1 -1
- package/dist/commands/bootstrap.js +29 -1
- package/dist/commands/bootstrap.js.map +1 -1
- package/dist/commands/kg-build.d.ts.map +1 -1
- package/dist/commands/kg-build.js +5 -0
- package/dist/commands/kg-build.js.map +1 -1
- package/dist/commands/kg-status.d.ts +59 -0
- package/dist/commands/kg-status.d.ts.map +1 -0
- package/dist/commands/kg-status.js +345 -0
- package/dist/commands/kg-status.js.map +1 -0
- package/dist/commands/kg-watch.d.ts +49 -0
- package/dist/commands/kg-watch.d.ts.map +1 -0
- package/dist/commands/kg-watch.js +172 -0
- package/dist/commands/kg-watch.js.map +1 -0
- package/dist/image-digests.json +4 -4
- package/dist/index.js +484 -83
- package/host-cp/src/server.mjs +1 -1
- 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: path52, errorMaps, issueData } = params;
|
|
491
|
+
const fullPath = [...path52, ...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, path52, key) {
|
|
800
800
|
this._cachedPath = [];
|
|
801
801
|
this.parent = parent;
|
|
802
802
|
this.data = value;
|
|
803
|
-
this._path =
|
|
803
|
+
this._path = path52;
|
|
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, path52, 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, path50, ctx, rejectSource) {
|
|
|
4289
4289
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4290
4290
|
ctx.addIssue({
|
|
4291
4291
|
code: external_exports.ZodIssueCode.custom,
|
|
4292
|
-
path: [...
|
|
4292
|
+
path: [...path52, key],
|
|
4293
4293
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
4294
4294
|
});
|
|
4295
4295
|
continue;
|
|
4296
4296
|
}
|
|
4297
|
-
if (rejectSource &&
|
|
4297
|
+
if (rejectSource && path52.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, path50, ctx, rejectSource) {
|
|
|
4302
4302
|
});
|
|
4303
4303
|
continue;
|
|
4304
4304
|
}
|
|
4305
|
-
refineForbiddenKeys(value[key], [...
|
|
4305
|
+
refineForbiddenKeys(value[key], [...path52, key], ctx, false);
|
|
4306
4306
|
}
|
|
4307
4307
|
}
|
|
4308
|
-
function rejectForbiddenKeys(value,
|
|
4308
|
+
function rejectForbiddenKeys(value, path52, 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] ${path52}: forbidden key "${key}" (prototype-pollution surface)`);
|
|
4315
4315
|
}
|
|
4316
4316
|
if (rejectSource && key === "source") {
|
|
4317
|
-
throw new Error(`[manifest] ${
|
|
4317
|
+
throw new Error(`[manifest] ${path52}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
|
|
4318
4318
|
}
|
|
4319
|
-
rejectForbiddenKeys(value[key], `${
|
|
4319
|
+
rejectForbiddenKeys(value[key], `${path52}.${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, path52, body, attempt = 0) {
|
|
5313
|
+
const url = `${this.baseUrl}${path52}`;
|
|
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, path52, 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(path52, method, body) {
|
|
6881
|
+
const url = `${this.config.workerUrl}${path52}`;
|
|
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, homedir28) {
|
|
8174
|
+
return p.replace(/^~(?=$|\/|\\)/, homedir28());
|
|
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 homedir28 = 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, homedir28);
|
|
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, path52, 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)}${path52}`;
|
|
13829
13829
|
try {
|
|
13830
13830
|
const headers = {
|
|
13831
13831
|
Authorization: `Bearer ${token}`
|
|
@@ -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(path52) {
|
|
14714
|
+
super(`Archetype inheritance cycle detected: ${path52.join(" \u2192 ")} \u2192 ${path52[0] ?? "?"}`);
|
|
14715
|
+
this.path = path52;
|
|
14716
14716
|
this.name = "ArchetypeCycleError";
|
|
14717
14717
|
}
|
|
14718
14718
|
};
|
|
@@ -15082,6 +15082,12 @@ async function runBootstrap2(opts, deps = {}) {
|
|
|
15082
15082
|
if (digests["mcp-auth"]) {
|
|
15083
15083
|
imageRefs.push({ name: "mcp-auth", ref: `${registry}/olam-mcp-auth@${digests["mcp-auth"]}` });
|
|
15084
15084
|
}
|
|
15085
|
+
if (digests["devbox-base"]) {
|
|
15086
|
+
imageRefs.push({
|
|
15087
|
+
name: "devbox-base",
|
|
15088
|
+
ref: `${registry}/olam-devbox@${digests["devbox-base"]}`
|
|
15089
|
+
});
|
|
15090
|
+
}
|
|
15085
15091
|
const pullSpinner = ora(`Pulling images (${imageRefs.length} parallel)`).start();
|
|
15086
15092
|
const pullStart = Date.now();
|
|
15087
15093
|
const pullResults = await Promise.all(
|
|
@@ -15111,7 +15117,7 @@ async function runBootstrap2(opts, deps = {}) {
|
|
|
15111
15117
|
summary: `pull failed: ${failed.map((r) => r.name).join(", ")}`
|
|
15112
15118
|
};
|
|
15113
15119
|
}
|
|
15114
|
-
pullSpinner.succeed(`Pulled
|
|
15120
|
+
pullSpinner.succeed(`Pulled ${imageRefs.length} images in ${pullElapsed}s`);
|
|
15115
15121
|
const handshakeSpinner = ora("Verifying olam.protocol.versions handshake").start();
|
|
15116
15122
|
for (const { name, ref } of imageRefs) {
|
|
15117
15123
|
const inspect = await docker2.inspectLabel(ref, "olam.protocol.versions");
|
|
@@ -15149,6 +15155,15 @@ async function runBootstrap2(opts, deps = {}) {
|
|
|
15149
15155
|
if (mcpAuthRef) {
|
|
15150
15156
|
tagPlan.push({ name: "mcp-auth", from: mcpAuthRef.ref, to: "olam-mcp-auth:local" });
|
|
15151
15157
|
}
|
|
15158
|
+
const devboxBaseRef = imageRefs.find((r) => r.name === "devbox-base");
|
|
15159
|
+
if (devboxBaseRef) {
|
|
15160
|
+
tagPlan.push({ name: "devbox-base (bare)", from: devboxBaseRef.ref, to: "olam-devbox:base" });
|
|
15161
|
+
tagPlan.push({
|
|
15162
|
+
name: "devbox-base (registry)",
|
|
15163
|
+
from: devboxBaseRef.ref,
|
|
15164
|
+
to: `${registry}/olam-devbox:base`
|
|
15165
|
+
});
|
|
15166
|
+
}
|
|
15152
15167
|
for (const { name, from, to } of tagPlan) {
|
|
15153
15168
|
const result = await docker2.tag(from, to);
|
|
15154
15169
|
if (result.exitCode !== 0) {
|
|
@@ -16078,9 +16093,9 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
|
|
|
16078
16093
|
"These source files have changed since the image was built; the",
|
|
16079
16094
|
"changes will NOT take effect in fresh worlds until you rebuild:"
|
|
16080
16095
|
];
|
|
16081
|
-
for (const { path:
|
|
16096
|
+
for (const { path: path52, mtimeMs } of result.newerSources) {
|
|
16082
16097
|
const when = new Date(mtimeMs).toISOString();
|
|
16083
|
-
lines.push(` \u2022 ${
|
|
16098
|
+
lines.push(` \u2022 ${path52} (modified ${when})`);
|
|
16084
16099
|
}
|
|
16085
16100
|
lines.push("");
|
|
16086
16101
|
lines.push("Rebuild with:");
|
|
@@ -16239,15 +16254,15 @@ init_host_cp();
|
|
|
16239
16254
|
var HOST_CP_URL = "http://127.0.0.1:19000";
|
|
16240
16255
|
async function readHostCpTokenForCreate() {
|
|
16241
16256
|
try {
|
|
16242
|
-
const { default:
|
|
16257
|
+
const { default: fs50 } = await import("node:fs");
|
|
16243
16258
|
const { default: os28 } = await import("node:os");
|
|
16244
|
-
const { default:
|
|
16245
|
-
const tp =
|
|
16246
|
-
process.env.OLAM_HOME ??
|
|
16259
|
+
const { default: path52 } = await import("node:path");
|
|
16260
|
+
const tp = path52.join(
|
|
16261
|
+
process.env.OLAM_HOME ?? path52.join(os28.homedir(), ".olam"),
|
|
16247
16262
|
"host-cp.token"
|
|
16248
16263
|
);
|
|
16249
|
-
if (!
|
|
16250
|
-
return
|
|
16264
|
+
if (!fs50.existsSync(tp)) return null;
|
|
16265
|
+
return fs50.readFileSync(tp, "utf-8").trim();
|
|
16251
16266
|
} catch {
|
|
16252
16267
|
return null;
|
|
16253
16268
|
}
|
|
@@ -16610,12 +16625,12 @@ function defaultNameFromPrompt(prompt) {
|
|
|
16610
16625
|
}
|
|
16611
16626
|
async function readHostCpToken3() {
|
|
16612
16627
|
try {
|
|
16613
|
-
const { default:
|
|
16628
|
+
const { default: fs50 } = await import("node:fs");
|
|
16614
16629
|
const { default: os28 } = await import("node:os");
|
|
16615
|
-
const { default:
|
|
16616
|
-
const tp =
|
|
16617
|
-
if (!
|
|
16618
|
-
const raw =
|
|
16630
|
+
const { default: path52 } = await import("node:path");
|
|
16631
|
+
const tp = path52.join(os28.homedir(), ".olam", "host-cp.token");
|
|
16632
|
+
if (!fs50.existsSync(tp)) return null;
|
|
16633
|
+
const raw = fs50.readFileSync(tp, "utf-8").trim();
|
|
16619
16634
|
return raw.length > 0 ? raw : null;
|
|
16620
16635
|
} catch {
|
|
16621
16636
|
return null;
|
|
@@ -20346,11 +20361,11 @@ function zodIssueToError(issue, doc, lineCounter) {
|
|
|
20346
20361
|
suggestion: deriveSuggestion(issue)
|
|
20347
20362
|
};
|
|
20348
20363
|
}
|
|
20349
|
-
function formatJsonPath(
|
|
20350
|
-
if (
|
|
20364
|
+
function formatJsonPath(path52) {
|
|
20365
|
+
if (path52.length === 0)
|
|
20351
20366
|
return "<root>";
|
|
20352
20367
|
let out = "";
|
|
20353
|
-
for (const seg of
|
|
20368
|
+
for (const seg of path52) {
|
|
20354
20369
|
if (typeof seg === "number") {
|
|
20355
20370
|
out += `[${seg}]`;
|
|
20356
20371
|
} else {
|
|
@@ -20359,11 +20374,11 @@ function formatJsonPath(path50) {
|
|
|
20359
20374
|
}
|
|
20360
20375
|
return out;
|
|
20361
20376
|
}
|
|
20362
|
-
function resolveYamlLocation(
|
|
20377
|
+
function resolveYamlLocation(path52, doc, lineCounter) {
|
|
20363
20378
|
let bestLine = 0;
|
|
20364
20379
|
let bestColumn = 0;
|
|
20365
|
-
for (let depth =
|
|
20366
|
-
const segment =
|
|
20380
|
+
for (let depth = path52.length; depth >= 0; depth -= 1) {
|
|
20381
|
+
const segment = path52.slice(0, depth);
|
|
20367
20382
|
try {
|
|
20368
20383
|
const node = doc.getIn(segment, true);
|
|
20369
20384
|
if (node && typeof node === "object" && "range" in node) {
|
|
@@ -20581,11 +20596,11 @@ function topoSort(nodes) {
|
|
|
20581
20596
|
}
|
|
20582
20597
|
function traceCycle(start, byId) {
|
|
20583
20598
|
const seen = /* @__PURE__ */ new Set();
|
|
20584
|
-
const
|
|
20599
|
+
const path52 = [];
|
|
20585
20600
|
let current = start;
|
|
20586
20601
|
while (current && !seen.has(current)) {
|
|
20587
20602
|
seen.add(current);
|
|
20588
|
-
|
|
20603
|
+
path52.push(current);
|
|
20589
20604
|
const node = byId.get(current);
|
|
20590
20605
|
const next = node?.dependsOn[0];
|
|
20591
20606
|
if (next === void 0)
|
|
@@ -20593,10 +20608,10 @@ function traceCycle(start, byId) {
|
|
|
20593
20608
|
current = next;
|
|
20594
20609
|
}
|
|
20595
20610
|
if (current && seen.has(current)) {
|
|
20596
|
-
const idx =
|
|
20597
|
-
return [...
|
|
20611
|
+
const idx = path52.indexOf(current);
|
|
20612
|
+
return [...path52.slice(idx), current];
|
|
20598
20613
|
}
|
|
20599
|
-
return
|
|
20614
|
+
return path52;
|
|
20600
20615
|
}
|
|
20601
20616
|
|
|
20602
20617
|
// ../core/dist/executor/types.js
|
|
@@ -25767,8 +25782,8 @@ var SECRET = process.env["OLAM_MCP_AUTH_SECRET"] ?? "";
|
|
|
25767
25782
|
function authHeaders() {
|
|
25768
25783
|
return SECRET ? { "X-Olam-Mcp-Secret": SECRET } : {};
|
|
25769
25784
|
}
|
|
25770
|
-
async function apiFetch(
|
|
25771
|
-
const res = await fetch(`${BASE_URL}${
|
|
25785
|
+
async function apiFetch(path52, init = {}) {
|
|
25786
|
+
const res = await fetch(`${BASE_URL}${path52}`, {
|
|
25772
25787
|
...init,
|
|
25773
25788
|
headers: {
|
|
25774
25789
|
"Content-Type": "application/json",
|
|
@@ -26346,8 +26361,8 @@ function registerMcp(program2) {
|
|
|
26346
26361
|
|
|
26347
26362
|
// src/commands/kg-build.ts
|
|
26348
26363
|
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
26349
|
-
import
|
|
26350
|
-
import
|
|
26364
|
+
import fs48 from "node:fs";
|
|
26365
|
+
import path50 from "node:path";
|
|
26351
26366
|
|
|
26352
26367
|
// ../core/dist/kg/storage-paths.js
|
|
26353
26368
|
import { homedir as homedir26 } from "node:os";
|
|
@@ -26380,17 +26395,17 @@ function kgRoot() {
|
|
|
26380
26395
|
function worldsRoot() {
|
|
26381
26396
|
return join48(olamHome3(), "worlds");
|
|
26382
26397
|
}
|
|
26383
|
-
function assertWithinPrefix(
|
|
26384
|
-
if (!
|
|
26385
|
-
throw new Error(`${label} escape: ${
|
|
26398
|
+
function assertWithinPrefix(path52, prefix, label) {
|
|
26399
|
+
if (!path52.startsWith(prefix + "/")) {
|
|
26400
|
+
throw new Error(`${label} escape: ${path52} not under ${prefix}/`);
|
|
26386
26401
|
}
|
|
26387
26402
|
}
|
|
26388
26403
|
function kgPristinePath(workspace) {
|
|
26389
26404
|
validateWorkspaceName(workspace);
|
|
26390
26405
|
const root = kgRoot();
|
|
26391
|
-
const
|
|
26392
|
-
assertWithinPrefix(
|
|
26393
|
-
return
|
|
26406
|
+
const path52 = resolve10(join48(root, workspace));
|
|
26407
|
+
assertWithinPrefix(path52, root, "kgPristinePath");
|
|
26408
|
+
return path52;
|
|
26394
26409
|
}
|
|
26395
26410
|
var KG_PATHS_INTERNALS = Object.freeze({
|
|
26396
26411
|
olamHome: olamHome3,
|
|
@@ -26400,10 +26415,394 @@ var KG_PATHS_INTERNALS = Object.freeze({
|
|
|
26400
26415
|
|
|
26401
26416
|
// src/commands/kg-build.ts
|
|
26402
26417
|
init_output();
|
|
26418
|
+
|
|
26419
|
+
// src/commands/kg-status.ts
|
|
26420
|
+
import fs46 from "node:fs";
|
|
26421
|
+
import { homedir as homedir27 } from "node:os";
|
|
26422
|
+
import path48 from "node:path";
|
|
26423
|
+
init_output();
|
|
26424
|
+
var SOFT_CAP_BYTES = 15e8;
|
|
26425
|
+
var HARD_CAP_BYTES = 5e9;
|
|
26426
|
+
function olamHome4() {
|
|
26427
|
+
return process.env.OLAM_HOME ?? path48.join(homedir27(), ".olam");
|
|
26428
|
+
}
|
|
26429
|
+
function kgRoot2() {
|
|
26430
|
+
return path48.join(olamHome4(), "kg");
|
|
26431
|
+
}
|
|
26432
|
+
function worldsRoot2() {
|
|
26433
|
+
return path48.join(olamHome4(), "worlds");
|
|
26434
|
+
}
|
|
26435
|
+
function dirSizeBytes(dir) {
|
|
26436
|
+
if (!fs46.existsSync(dir)) return 0;
|
|
26437
|
+
let total = 0;
|
|
26438
|
+
const stack = [dir];
|
|
26439
|
+
while (stack.length > 0) {
|
|
26440
|
+
const cur = stack.pop();
|
|
26441
|
+
let entries;
|
|
26442
|
+
try {
|
|
26443
|
+
entries = fs46.readdirSync(cur, { withFileTypes: true });
|
|
26444
|
+
} catch {
|
|
26445
|
+
continue;
|
|
26446
|
+
}
|
|
26447
|
+
for (const entry of entries) {
|
|
26448
|
+
const full = path48.join(cur, entry.name);
|
|
26449
|
+
if (entry.isSymbolicLink()) continue;
|
|
26450
|
+
if (entry.isDirectory()) {
|
|
26451
|
+
stack.push(full);
|
|
26452
|
+
continue;
|
|
26453
|
+
}
|
|
26454
|
+
try {
|
|
26455
|
+
total += fs46.statSync(full).size;
|
|
26456
|
+
} catch {
|
|
26457
|
+
}
|
|
26458
|
+
}
|
|
26459
|
+
}
|
|
26460
|
+
return total;
|
|
26461
|
+
}
|
|
26462
|
+
function formatBytes4(n) {
|
|
26463
|
+
if (n < 1024) return `${n} B`;
|
|
26464
|
+
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
26465
|
+
if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
26466
|
+
return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
26467
|
+
}
|
|
26468
|
+
function readFreshness(workspace) {
|
|
26469
|
+
const file = path48.join(kgPristinePath(workspace), "freshness.json");
|
|
26470
|
+
if (!fs46.existsSync(file)) return null;
|
|
26471
|
+
try {
|
|
26472
|
+
const raw = JSON.parse(fs46.readFileSync(file, "utf-8"));
|
|
26473
|
+
if (raw && typeof raw === "object") return raw;
|
|
26474
|
+
return null;
|
|
26475
|
+
} catch {
|
|
26476
|
+
return null;
|
|
26477
|
+
}
|
|
26478
|
+
}
|
|
26479
|
+
function readOverlayNodeCount(graphifyOutDir) {
|
|
26480
|
+
const graphPath = path48.join(graphifyOutDir, "graph.json");
|
|
26481
|
+
if (!fs46.existsSync(graphPath)) return null;
|
|
26482
|
+
try {
|
|
26483
|
+
const raw = JSON.parse(fs46.readFileSync(graphPath, "utf-8"));
|
|
26484
|
+
if (raw && typeof raw === "object") {
|
|
26485
|
+
const nodes = raw.nodes;
|
|
26486
|
+
if (Array.isArray(nodes)) return nodes.length;
|
|
26487
|
+
}
|
|
26488
|
+
return null;
|
|
26489
|
+
} catch {
|
|
26490
|
+
return null;
|
|
26491
|
+
}
|
|
26492
|
+
}
|
|
26493
|
+
function listOverlays() {
|
|
26494
|
+
const root = worldsRoot2();
|
|
26495
|
+
if (!fs46.existsSync(root)) return [];
|
|
26496
|
+
const records = [];
|
|
26497
|
+
let worldDirs;
|
|
26498
|
+
try {
|
|
26499
|
+
worldDirs = fs46.readdirSync(root, { withFileTypes: true });
|
|
26500
|
+
} catch {
|
|
26501
|
+
return [];
|
|
26502
|
+
}
|
|
26503
|
+
for (const worldEntry of worldDirs) {
|
|
26504
|
+
if (!worldEntry.isDirectory()) continue;
|
|
26505
|
+
const worldId = worldEntry.name;
|
|
26506
|
+
const worldDir = path48.join(root, worldId);
|
|
26507
|
+
let cloneDirs;
|
|
26508
|
+
try {
|
|
26509
|
+
cloneDirs = fs46.readdirSync(worldDir, { withFileTypes: true });
|
|
26510
|
+
} catch {
|
|
26511
|
+
continue;
|
|
26512
|
+
}
|
|
26513
|
+
for (const cloneEntry of cloneDirs) {
|
|
26514
|
+
if (!cloneEntry.isDirectory()) continue;
|
|
26515
|
+
const graphifyOut = path48.join(worldDir, cloneEntry.name, "graphify-out");
|
|
26516
|
+
if (!fs46.existsSync(graphifyOut)) continue;
|
|
26517
|
+
records.push({
|
|
26518
|
+
world_id: worldId,
|
|
26519
|
+
clone_dir: cloneEntry.name,
|
|
26520
|
+
graphify_out_path: graphifyOut,
|
|
26521
|
+
graphify_out_size_bytes: dirSizeBytes(graphifyOut),
|
|
26522
|
+
node_count: readOverlayNodeCount(graphifyOut)
|
|
26523
|
+
});
|
|
26524
|
+
}
|
|
26525
|
+
}
|
|
26526
|
+
return records;
|
|
26527
|
+
}
|
|
26528
|
+
function listPristines(overlays) {
|
|
26529
|
+
const root = kgRoot2();
|
|
26530
|
+
if (!fs46.existsSync(root)) return [];
|
|
26531
|
+
const records = [];
|
|
26532
|
+
let entries;
|
|
26533
|
+
try {
|
|
26534
|
+
entries = fs46.readdirSync(root, { withFileTypes: true });
|
|
26535
|
+
} catch {
|
|
26536
|
+
return [];
|
|
26537
|
+
}
|
|
26538
|
+
for (const entry of entries) {
|
|
26539
|
+
if (!entry.isDirectory()) continue;
|
|
26540
|
+
const workspace = entry.name;
|
|
26541
|
+
try {
|
|
26542
|
+
validateWorkspaceName(workspace);
|
|
26543
|
+
} catch {
|
|
26544
|
+
continue;
|
|
26545
|
+
}
|
|
26546
|
+
const fresh = readFreshness(workspace);
|
|
26547
|
+
const graphifyOut = path48.join(kgPristinePath(workspace), "graphify-out");
|
|
26548
|
+
const size = dirSizeBytes(graphifyOut);
|
|
26549
|
+
const worldCount = overlays.filter((o) => o.clone_dir === workspace).length;
|
|
26550
|
+
records.push({
|
|
26551
|
+
workspace,
|
|
26552
|
+
built_at: fresh?.built_at ?? null,
|
|
26553
|
+
node_count: fresh?.node_count ?? null,
|
|
26554
|
+
graphify_version: fresh?.graphify_version ?? null,
|
|
26555
|
+
graphify_out_size_bytes: size,
|
|
26556
|
+
world_count: worldCount
|
|
26557
|
+
});
|
|
26558
|
+
}
|
|
26559
|
+
return records.sort((a, b) => a.workspace.localeCompare(b.workspace));
|
|
26560
|
+
}
|
|
26561
|
+
function classifyCap(totalBytes) {
|
|
26562
|
+
if (totalBytes >= HARD_CAP_BYTES) return "hard-critical";
|
|
26563
|
+
if (totalBytes >= SOFT_CAP_BYTES) return "soft-warn";
|
|
26564
|
+
return "ok";
|
|
26565
|
+
}
|
|
26566
|
+
function buildReport(workspaceFilter) {
|
|
26567
|
+
if (workspaceFilter) validateWorkspaceName(workspaceFilter);
|
|
26568
|
+
const allOverlays = listOverlays();
|
|
26569
|
+
const allPristines = listPristines(allOverlays);
|
|
26570
|
+
const pristines = workspaceFilter ? allPristines.filter((p) => p.workspace === workspaceFilter) : allPristines;
|
|
26571
|
+
const overlays = workspaceFilter ? allOverlays.filter((o) => o.clone_dir === workspaceFilter) : allOverlays;
|
|
26572
|
+
const totalBytes = pristines.reduce((acc, p) => acc + p.graphify_out_size_bytes, 0) + overlays.reduce((acc, o) => acc + o.graphify_out_size_bytes, 0);
|
|
26573
|
+
return {
|
|
26574
|
+
pristines,
|
|
26575
|
+
overlays,
|
|
26576
|
+
total_bytes: totalBytes,
|
|
26577
|
+
cap_status: classifyCap(totalBytes)
|
|
26578
|
+
};
|
|
26579
|
+
}
|
|
26580
|
+
function renderHuman(report, workspaceFilter) {
|
|
26581
|
+
const lines = [];
|
|
26582
|
+
if (report.pristines.length === 0 && report.overlays.length === 0) {
|
|
26583
|
+
if (workspaceFilter) {
|
|
26584
|
+
lines.push(`No KG state for workspace "${workspaceFilter}".`);
|
|
26585
|
+
} else {
|
|
26586
|
+
lines.push("No KG state on this host yet. Run `olam kg build` from a workspace clone.");
|
|
26587
|
+
}
|
|
26588
|
+
return lines.join("\n");
|
|
26589
|
+
}
|
|
26590
|
+
if (report.pristines.length > 0) {
|
|
26591
|
+
lines.push("Pristines:");
|
|
26592
|
+
lines.push(
|
|
26593
|
+
[
|
|
26594
|
+
"workspace".padEnd(24),
|
|
26595
|
+
"built_at".padEnd(22),
|
|
26596
|
+
"nodes".padStart(8),
|
|
26597
|
+
"size".padStart(10),
|
|
26598
|
+
"worlds".padStart(7)
|
|
26599
|
+
].join(" ")
|
|
26600
|
+
);
|
|
26601
|
+
lines.push("-".repeat(74));
|
|
26602
|
+
for (const p of report.pristines) {
|
|
26603
|
+
lines.push(
|
|
26604
|
+
[
|
|
26605
|
+
p.workspace.padEnd(24),
|
|
26606
|
+
(p.built_at ?? "\u2014").padEnd(22),
|
|
26607
|
+
String(p.node_count ?? "\u2014").padStart(8),
|
|
26608
|
+
formatBytes4(p.graphify_out_size_bytes).padStart(10),
|
|
26609
|
+
String(p.world_count).padStart(7)
|
|
26610
|
+
].join(" ")
|
|
26611
|
+
);
|
|
26612
|
+
}
|
|
26613
|
+
lines.push("");
|
|
26614
|
+
}
|
|
26615
|
+
if (report.overlays.length > 0) {
|
|
26616
|
+
lines.push("Overlays:");
|
|
26617
|
+
lines.push(
|
|
26618
|
+
[
|
|
26619
|
+
"world_id".padEnd(24),
|
|
26620
|
+
"clone".padEnd(20),
|
|
26621
|
+
"nodes".padStart(8),
|
|
26622
|
+
"size".padStart(10)
|
|
26623
|
+
].join(" ")
|
|
26624
|
+
);
|
|
26625
|
+
lines.push("-".repeat(66));
|
|
26626
|
+
for (const o of report.overlays) {
|
|
26627
|
+
lines.push(
|
|
26628
|
+
[
|
|
26629
|
+
o.world_id.padEnd(24),
|
|
26630
|
+
o.clone_dir.padEnd(20),
|
|
26631
|
+
String(o.node_count ?? "\u2014").padStart(8),
|
|
26632
|
+
formatBytes4(o.graphify_out_size_bytes).padStart(10)
|
|
26633
|
+
].join(" ")
|
|
26634
|
+
);
|
|
26635
|
+
}
|
|
26636
|
+
lines.push("");
|
|
26637
|
+
}
|
|
26638
|
+
lines.push(`Total: ${formatBytes4(report.total_bytes)} (cap: ${report.cap_status})`);
|
|
26639
|
+
return lines.join("\n");
|
|
26640
|
+
}
|
|
26641
|
+
async function runKgStatus(workspaceArg, opts) {
|
|
26642
|
+
let report;
|
|
26643
|
+
try {
|
|
26644
|
+
report = buildReport(workspaceArg);
|
|
26645
|
+
} catch (err) {
|
|
26646
|
+
printError(err.message);
|
|
26647
|
+
return {
|
|
26648
|
+
exitCode: 1,
|
|
26649
|
+
report: { pristines: [], overlays: [], total_bytes: 0, cap_status: "ok" }
|
|
26650
|
+
};
|
|
26651
|
+
}
|
|
26652
|
+
if (opts.json) {
|
|
26653
|
+
process.stdout.write(JSON.stringify(report, null, 2) + "\n");
|
|
26654
|
+
} else {
|
|
26655
|
+
process.stdout.write(renderHuman(report, workspaceArg) + "\n");
|
|
26656
|
+
}
|
|
26657
|
+
if (report.cap_status === "soft-warn") {
|
|
26658
|
+
printWarning(
|
|
26659
|
+
`KG storage at ${formatBytes4(report.total_bytes)} \u2014 exceeds 1.5GB soft cap. Consider pruning stale pristines via \`rm -rf ~/.olam/kg/<workspace>\` after operator review.`
|
|
26660
|
+
);
|
|
26661
|
+
} else if (report.cap_status === "hard-critical") {
|
|
26662
|
+
printError(
|
|
26663
|
+
`KG storage at ${formatBytes4(report.total_bytes)} \u2014 exceeds 5GB hard cap. Prune stale pristines or overlays before running \`olam kg build\` again.`
|
|
26664
|
+
);
|
|
26665
|
+
return { exitCode: 1, report };
|
|
26666
|
+
}
|
|
26667
|
+
return { exitCode: 0, report };
|
|
26668
|
+
}
|
|
26669
|
+
function registerKgStatusCommand(kg) {
|
|
26670
|
+
kg.command("status").description(
|
|
26671
|
+
"Report pristine + overlay KG state for every workspace (or one named workspace). Emits 1.5GB soft-cap warning + 5GB hard-cap critical error on stderr."
|
|
26672
|
+
).argument("[workspace]", "workspace name (lowercase alphanumeric + hyphens/underscores)").option("--json", "emit the report as JSON instead of a compact table").action(async (workspaceArg, opts) => {
|
|
26673
|
+
const r = await runKgStatus(workspaceArg, opts);
|
|
26674
|
+
if (r.exitCode !== 0) process.exitCode = r.exitCode;
|
|
26675
|
+
});
|
|
26676
|
+
}
|
|
26677
|
+
|
|
26678
|
+
// src/commands/kg-watch.ts
|
|
26679
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
26680
|
+
import fs47 from "node:fs";
|
|
26681
|
+
import path49 from "node:path";
|
|
26682
|
+
init_output();
|
|
26683
|
+
function pidFilePath(workspace) {
|
|
26684
|
+
return path49.join(kgPristinePath(workspace), ".watch.pid");
|
|
26685
|
+
}
|
|
26686
|
+
function isPidAlive3(pid) {
|
|
26687
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
26688
|
+
try {
|
|
26689
|
+
process.kill(pid, 0);
|
|
26690
|
+
return true;
|
|
26691
|
+
} catch (err) {
|
|
26692
|
+
const code = err.code;
|
|
26693
|
+
if (code === "EPERM") return true;
|
|
26694
|
+
return false;
|
|
26695
|
+
}
|
|
26696
|
+
}
|
|
26697
|
+
function readAndClassifyPid(workspace) {
|
|
26698
|
+
const file = pidFilePath(workspace);
|
|
26699
|
+
if (!fs47.existsSync(file)) return { status: "no-pidfile", pid: null };
|
|
26700
|
+
let pid;
|
|
26701
|
+
try {
|
|
26702
|
+
const raw = fs47.readFileSync(file, "utf-8").trim();
|
|
26703
|
+
pid = Number.parseInt(raw, 10);
|
|
26704
|
+
} catch {
|
|
26705
|
+
fs47.rmSync(file, { force: true });
|
|
26706
|
+
return { status: "stale-reclaimed", pid: null };
|
|
26707
|
+
}
|
|
26708
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
26709
|
+
fs47.rmSync(file, { force: true });
|
|
26710
|
+
return { status: "stale-reclaimed", pid: null };
|
|
26711
|
+
}
|
|
26712
|
+
if (isPidAlive3(pid)) return { status: "active", pid };
|
|
26713
|
+
fs47.rmSync(file, { force: true });
|
|
26714
|
+
return { status: "stale-reclaimed", pid: null };
|
|
26715
|
+
}
|
|
26716
|
+
function writePidFile(workspace, pid) {
|
|
26717
|
+
const file = pidFilePath(workspace);
|
|
26718
|
+
const dir = path49.dirname(file);
|
|
26719
|
+
fs47.mkdirSync(dir, { recursive: true });
|
|
26720
|
+
fs47.writeFileSync(file, String(pid), { encoding: "utf-8" });
|
|
26721
|
+
}
|
|
26722
|
+
function removePidFile(workspace) {
|
|
26723
|
+
const file = pidFilePath(workspace);
|
|
26724
|
+
try {
|
|
26725
|
+
fs47.rmSync(file, { force: true });
|
|
26726
|
+
} catch {
|
|
26727
|
+
}
|
|
26728
|
+
}
|
|
26729
|
+
async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
26730
|
+
const cwd = deps.cwd ?? opts.cwd ?? process.cwd();
|
|
26731
|
+
const name = workspaceArg ?? path49.basename(cwd).toLowerCase();
|
|
26732
|
+
try {
|
|
26733
|
+
validateWorkspaceName(name);
|
|
26734
|
+
} catch (err) {
|
|
26735
|
+
printError(err.message);
|
|
26736
|
+
return { exitCode: 1, pidWritten: false };
|
|
26737
|
+
}
|
|
26738
|
+
const pristinePath = kgPristinePath(name);
|
|
26739
|
+
const graphPath = path49.join(pristinePath, "graphify-out", "graph.json");
|
|
26740
|
+
const pidState = readAndClassifyPid(name);
|
|
26741
|
+
if (pidState.status === "active") {
|
|
26742
|
+
printError(
|
|
26743
|
+
`olam kg watch ${name} \u2014 already running (PID ${pidState.pid}). Send SIGINT to that process to stop the existing watcher first.`
|
|
26744
|
+
);
|
|
26745
|
+
return { exitCode: 1, pidWritten: false };
|
|
26746
|
+
}
|
|
26747
|
+
if (pidState.status === "stale-reclaimed") {
|
|
26748
|
+
printInfo("stale-pid", `reclaimed dead PID file at ${pidFilePath(name)}`);
|
|
26749
|
+
}
|
|
26750
|
+
const spawnFn = deps.spawnImpl ?? spawn7;
|
|
26751
|
+
const child = spawnFn(
|
|
26752
|
+
"graphify",
|
|
26753
|
+
[cwd, "--watch", "--update", "--graph", graphPath],
|
|
26754
|
+
{
|
|
26755
|
+
cwd,
|
|
26756
|
+
env: process.env,
|
|
26757
|
+
detached: false,
|
|
26758
|
+
stdio: "inherit"
|
|
26759
|
+
}
|
|
26760
|
+
);
|
|
26761
|
+
if (typeof child.pid !== "number") {
|
|
26762
|
+
printError("graphify failed to launch (no PID assigned)");
|
|
26763
|
+
return { exitCode: 1, pidWritten: false };
|
|
26764
|
+
}
|
|
26765
|
+
writePidFile(name, child.pid);
|
|
26766
|
+
printSuccess(`olam kg watch ${name} \u2014 graphify PID ${child.pid} (Ctrl-C to stop)`);
|
|
26767
|
+
if (deps.registerSignalHandlers !== false) {
|
|
26768
|
+
const forward = (sig) => {
|
|
26769
|
+
if (child.pid && !child.killed) {
|
|
26770
|
+
try {
|
|
26771
|
+
process.kill(child.pid, sig);
|
|
26772
|
+
} catch {
|
|
26773
|
+
}
|
|
26774
|
+
}
|
|
26775
|
+
};
|
|
26776
|
+
process.on("SIGINT", () => forward("SIGINT"));
|
|
26777
|
+
process.on("SIGTERM", () => forward("SIGTERM"));
|
|
26778
|
+
}
|
|
26779
|
+
return new Promise((resolve11) => {
|
|
26780
|
+
child.on("exit", (code, signal) => {
|
|
26781
|
+
removePidFile(name);
|
|
26782
|
+
const exitCode = typeof code === "number" ? code : signal === "SIGINT" || signal === "SIGTERM" ? 0 : 1;
|
|
26783
|
+
resolve11({ exitCode, pidWritten: true });
|
|
26784
|
+
});
|
|
26785
|
+
child.on("error", (err) => {
|
|
26786
|
+
removePidFile(name);
|
|
26787
|
+
printError(`graphify subprocess error: ${err.message}`);
|
|
26788
|
+
resolve11({ exitCode: 1, pidWritten: true });
|
|
26789
|
+
});
|
|
26790
|
+
});
|
|
26791
|
+
}
|
|
26792
|
+
function registerKgWatchCommand(kg) {
|
|
26793
|
+
kg.command("watch").description(
|
|
26794
|
+
"Run graphify --watch against a workspace, keeping its pristine KG fresh as host-side commits land. Single-instance via PID file; Ctrl-C cleanly stops."
|
|
26795
|
+
).argument("[workspace]", "workspace name (lowercase alphanumeric + hyphens/underscores)").action(async (workspaceArg) => {
|
|
26796
|
+
const r = await runKgWatch(workspaceArg, {});
|
|
26797
|
+
if (r.exitCode !== 0) process.exitCode = r.exitCode;
|
|
26798
|
+
});
|
|
26799
|
+
}
|
|
26800
|
+
|
|
26801
|
+
// src/commands/kg-build.ts
|
|
26403
26802
|
var DEFAULT_DEVBOX_IMAGE2 = "olam-devbox:latest";
|
|
26404
26803
|
function resolveWorkspace(arg) {
|
|
26405
26804
|
const cwd = process.cwd();
|
|
26406
|
-
const name = arg ??
|
|
26805
|
+
const name = arg ?? path50.basename(cwd).toLowerCase();
|
|
26407
26806
|
validateWorkspaceName(name);
|
|
26408
26807
|
return { name, sourcePath: cwd };
|
|
26409
26808
|
}
|
|
@@ -26425,10 +26824,10 @@ function copyWorkspaceToScratch(source, scratch) {
|
|
|
26425
26824
|
return "cp-r";
|
|
26426
26825
|
}
|
|
26427
26826
|
function parseNodeCount(graphifyOutDir) {
|
|
26428
|
-
const graphPath =
|
|
26429
|
-
if (!
|
|
26827
|
+
const graphPath = path50.join(graphifyOutDir, "graph.json");
|
|
26828
|
+
if (!fs48.existsSync(graphPath)) return null;
|
|
26430
26829
|
try {
|
|
26431
|
-
const content =
|
|
26830
|
+
const content = fs48.readFileSync(graphPath, "utf-8");
|
|
26432
26831
|
const data = JSON.parse(content);
|
|
26433
26832
|
return Array.isArray(data.nodes) ? data.nodes.length : null;
|
|
26434
26833
|
} catch {
|
|
@@ -26462,10 +26861,10 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
26462
26861
|
return { exitCode: 2 };
|
|
26463
26862
|
}
|
|
26464
26863
|
const outDir = kgPristinePath(workspace.name);
|
|
26465
|
-
const scratchDir =
|
|
26466
|
-
|
|
26467
|
-
if (
|
|
26468
|
-
|
|
26864
|
+
const scratchDir = path50.join(outDir, "scratch");
|
|
26865
|
+
fs48.mkdirSync(outDir, { recursive: true });
|
|
26866
|
+
if (fs48.existsSync(scratchDir)) fs48.rmSync(scratchDir, { recursive: true, force: true });
|
|
26867
|
+
fs48.mkdirSync(scratchDir);
|
|
26469
26868
|
const human = !options.json;
|
|
26470
26869
|
if (human) {
|
|
26471
26870
|
printInfo("kg build", `workspace=${workspace.name} source=${workspace.sourcePath}`);
|
|
@@ -26493,14 +26892,14 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
26493
26892
|
printError(`graphify update failed (exit ${r.status})`);
|
|
26494
26893
|
return { exitCode: r.status ?? 1 };
|
|
26495
26894
|
}
|
|
26496
|
-
const scratchOut =
|
|
26497
|
-
const finalOut =
|
|
26498
|
-
if (!
|
|
26895
|
+
const scratchOut = path50.join(scratchDir, "graphify-out");
|
|
26896
|
+
const finalOut = path50.join(outDir, "graphify-out");
|
|
26897
|
+
if (!fs48.existsSync(scratchOut)) {
|
|
26499
26898
|
printError(`graphify produced no graphify-out/ in scratch (${scratchOut})`);
|
|
26500
26899
|
return { exitCode: 1 };
|
|
26501
26900
|
}
|
|
26502
|
-
if (
|
|
26503
|
-
|
|
26901
|
+
if (fs48.existsSync(finalOut)) fs48.rmSync(finalOut, { recursive: true, force: true });
|
|
26902
|
+
fs48.renameSync(scratchOut, finalOut);
|
|
26504
26903
|
const durationMs = Date.now() - started;
|
|
26505
26904
|
const nodeCount = parseNodeCount(finalOut);
|
|
26506
26905
|
const version = readGraphifyVersion(image);
|
|
@@ -26512,8 +26911,8 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
26512
26911
|
workspace: workspace.name,
|
|
26513
26912
|
scratch_strategy: scratchStrategy
|
|
26514
26913
|
};
|
|
26515
|
-
|
|
26516
|
-
|
|
26914
|
+
fs48.writeFileSync(
|
|
26915
|
+
path50.join(outDir, "freshness.json"),
|
|
26517
26916
|
JSON.stringify(freshness, null, 2) + "\n",
|
|
26518
26917
|
"utf-8"
|
|
26519
26918
|
);
|
|
@@ -26527,8 +26926,8 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
26527
26926
|
}
|
|
26528
26927
|
return { exitCode: 0, freshness, outputDir: finalOut };
|
|
26529
26928
|
} finally {
|
|
26530
|
-
if (
|
|
26531
|
-
|
|
26929
|
+
if (fs48.existsSync(scratchDir)) {
|
|
26930
|
+
fs48.rmSync(scratchDir, { recursive: true, force: true });
|
|
26532
26931
|
}
|
|
26533
26932
|
}
|
|
26534
26933
|
}
|
|
@@ -26540,21 +26939,23 @@ function registerKg(program2) {
|
|
|
26540
26939
|
const r = await runKgBuild(workspaceArg, opts);
|
|
26541
26940
|
if (r.exitCode !== 0) process.exitCode = r.exitCode;
|
|
26542
26941
|
});
|
|
26942
|
+
registerKgStatusCommand(kg);
|
|
26943
|
+
registerKgWatchCommand(kg);
|
|
26543
26944
|
}
|
|
26544
26945
|
|
|
26545
26946
|
// src/pleri-config.ts
|
|
26546
|
-
import * as
|
|
26547
|
-
import * as
|
|
26947
|
+
import * as fs49 from "node:fs";
|
|
26948
|
+
import * as path51 from "node:path";
|
|
26548
26949
|
function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
26549
26950
|
if (process.env.PLERI_BASE_URL) {
|
|
26550
26951
|
return true;
|
|
26551
26952
|
}
|
|
26552
|
-
const configPath =
|
|
26553
|
-
if (!
|
|
26953
|
+
const configPath = path51.join(configDir, "config.yaml");
|
|
26954
|
+
if (!fs49.existsSync(configPath)) {
|
|
26554
26955
|
return false;
|
|
26555
26956
|
}
|
|
26556
26957
|
try {
|
|
26557
|
-
const contents =
|
|
26958
|
+
const contents = fs49.readFileSync(configPath, "utf8");
|
|
26558
26959
|
return /^[^#\n]*\bpleri:/m.test(contents);
|
|
26559
26960
|
} catch {
|
|
26560
26961
|
return false;
|