@pleri/olam-cli 0.1.110 → 0.1.112
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 +2 -45
- package/dist/commands/bootstrap.d.ts.map +1 -1
- package/dist/commands/bootstrap.js +8 -101
- package/dist/commands/bootstrap.js.map +1 -1
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +10 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/setup.d.ts +71 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +344 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/image-digests.json +4 -4
- package/dist/index.js +544 -206
- package/dist/index.js.map +1 -1
- package/dist/lib/shell-rc.d.ts +90 -0
- package/dist/lib/shell-rc.d.ts.map +1 -0
- package/dist/lib/shell-rc.js +91 -0
- package/dist/lib/shell-rc.js.map +1 -0
- package/dist/mcp-server.js +107 -7
- 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: path55, errorMaps, issueData } = params;
|
|
491
|
+
const fullPath = [...path55, ...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, path55, key) {
|
|
800
800
|
this._cachedPath = [];
|
|
801
801
|
this.parent = parent;
|
|
802
802
|
this.data = value;
|
|
803
|
-
this._path =
|
|
803
|
+
this._path = path55;
|
|
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, path55, 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, path53, ctx, rejectSource) {
|
|
|
4289
4289
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4290
4290
|
ctx.addIssue({
|
|
4291
4291
|
code: external_exports.ZodIssueCode.custom,
|
|
4292
|
-
path: [...
|
|
4292
|
+
path: [...path55, key],
|
|
4293
4293
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
4294
4294
|
});
|
|
4295
4295
|
continue;
|
|
4296
4296
|
}
|
|
4297
|
-
if (rejectSource &&
|
|
4297
|
+
if (rejectSource && path55.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, path53, ctx, rejectSource) {
|
|
|
4302
4302
|
});
|
|
4303
4303
|
continue;
|
|
4304
4304
|
}
|
|
4305
|
-
refineForbiddenKeys(value[key], [...
|
|
4305
|
+
refineForbiddenKeys(value[key], [...path55, key], ctx, false);
|
|
4306
4306
|
}
|
|
4307
4307
|
}
|
|
4308
|
-
function rejectForbiddenKeys(value,
|
|
4308
|
+
function rejectForbiddenKeys(value, path55, 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] ${path55}: forbidden key "${key}" (prototype-pollution surface)`);
|
|
4315
4315
|
}
|
|
4316
4316
|
if (rejectSource && key === "source") {
|
|
4317
|
-
throw new Error(`[manifest] ${
|
|
4317
|
+
throw new Error(`[manifest] ${path55}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
|
|
4318
4318
|
}
|
|
4319
|
-
rejectForbiddenKeys(value[key], `${
|
|
4319
|
+
rejectForbiddenKeys(value[key], `${path55}.${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, path55, body, attempt = 0) {
|
|
5313
|
+
const url = `${this.baseUrl}${path55}`;
|
|
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, path55, body, attempt + 1);
|
|
5332
5332
|
}
|
|
5333
5333
|
throw err;
|
|
5334
5334
|
} finally {
|
|
@@ -5645,6 +5645,98 @@ var init_network = __esm({
|
|
|
5645
5645
|
}
|
|
5646
5646
|
});
|
|
5647
5647
|
|
|
5648
|
+
// ../adapters/dist/docker/pull.js
|
|
5649
|
+
import { spawn } from "node:child_process";
|
|
5650
|
+
function spawnAsync(cmd, args, opts = {}) {
|
|
5651
|
+
return new Promise((resolve11) => {
|
|
5652
|
+
const child = spawn(cmd, [...args], {
|
|
5653
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
5654
|
+
signal: opts.signal
|
|
5655
|
+
});
|
|
5656
|
+
let stdout = "";
|
|
5657
|
+
let stderr = "";
|
|
5658
|
+
child.stdout?.on("data", (chunk) => {
|
|
5659
|
+
stdout += chunk.toString();
|
|
5660
|
+
});
|
|
5661
|
+
child.stderr?.on("data", (chunk) => {
|
|
5662
|
+
stderr += chunk.toString();
|
|
5663
|
+
});
|
|
5664
|
+
child.on("error", (err) => {
|
|
5665
|
+
resolve11({ exitCode: -1, stdout, stderr: stderr + err.message });
|
|
5666
|
+
});
|
|
5667
|
+
child.on("close", (code) => {
|
|
5668
|
+
resolve11({ exitCode: code ?? -1, stdout, stderr });
|
|
5669
|
+
});
|
|
5670
|
+
});
|
|
5671
|
+
}
|
|
5672
|
+
function isTransientPullFailure(result) {
|
|
5673
|
+
const s = result.stderr.toLowerCase();
|
|
5674
|
+
return result.exitCode !== 0 && (/timeout|connection|temporarily|429|503|tls handshake|network/.test(s) || result.exitCode === 124 || result.exitCode === -1);
|
|
5675
|
+
}
|
|
5676
|
+
async function pullImageWithRetry(imageRef, docker2 = realDocker, policy = DEFAULT_PULL_POLICY) {
|
|
5677
|
+
const key = policy.platform ? `${imageRef}@@${policy.platform}` : imageRef;
|
|
5678
|
+
const existing = inflightPulls.get(key);
|
|
5679
|
+
if (existing)
|
|
5680
|
+
return existing;
|
|
5681
|
+
const promise = (async () => {
|
|
5682
|
+
let result = await pullOnce(imageRef, docker2, policy.perAttemptTimeoutMs, policy.platform);
|
|
5683
|
+
if (result.exitCode !== 0 && policy.retryOnce && isTransientPullFailure(result)) {
|
|
5684
|
+
result = await pullOnce(imageRef, docker2, policy.perAttemptTimeoutMs, policy.platform);
|
|
5685
|
+
}
|
|
5686
|
+
return result;
|
|
5687
|
+
})();
|
|
5688
|
+
inflightPulls.set(key, promise);
|
|
5689
|
+
try {
|
|
5690
|
+
return await promise;
|
|
5691
|
+
} finally {
|
|
5692
|
+
inflightPulls.delete(key);
|
|
5693
|
+
}
|
|
5694
|
+
}
|
|
5695
|
+
async function pullOnce(imageRef, docker2, timeoutMs, platform) {
|
|
5696
|
+
const ac = new AbortController();
|
|
5697
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs).unref?.();
|
|
5698
|
+
try {
|
|
5699
|
+
return await docker2.pull(imageRef, { signal: ac.signal, ...platform ? { platform } : {} });
|
|
5700
|
+
} finally {
|
|
5701
|
+
if (timer)
|
|
5702
|
+
clearTimeout(timer);
|
|
5703
|
+
}
|
|
5704
|
+
}
|
|
5705
|
+
var realDocker, inflightPulls, DEFAULT_PULL_POLICY;
|
|
5706
|
+
var init_pull = __esm({
|
|
5707
|
+
"../adapters/dist/docker/pull.js"() {
|
|
5708
|
+
"use strict";
|
|
5709
|
+
realDocker = {
|
|
5710
|
+
async info() {
|
|
5711
|
+
return spawnAsync("docker", ["info"]);
|
|
5712
|
+
},
|
|
5713
|
+
async pull(imageRef, opts) {
|
|
5714
|
+
const args = ["pull"];
|
|
5715
|
+
if (opts?.platform)
|
|
5716
|
+
args.push(`--platform=${opts.platform}`);
|
|
5717
|
+
args.push(imageRef);
|
|
5718
|
+
return spawnAsync("docker", args, { signal: opts?.signal });
|
|
5719
|
+
},
|
|
5720
|
+
async inspectLabel(imageRef, label) {
|
|
5721
|
+
return spawnAsync("docker", [
|
|
5722
|
+
"inspect",
|
|
5723
|
+
imageRef,
|
|
5724
|
+
"--format",
|
|
5725
|
+
`{{ index .Config.Labels "${label}" }}`
|
|
5726
|
+
]);
|
|
5727
|
+
},
|
|
5728
|
+
async tag(source, target) {
|
|
5729
|
+
return spawnAsync("docker", ["tag", source, target]);
|
|
5730
|
+
}
|
|
5731
|
+
};
|
|
5732
|
+
inflightPulls = /* @__PURE__ */ new Map();
|
|
5733
|
+
DEFAULT_PULL_POLICY = {
|
|
5734
|
+
perAttemptTimeoutMs: 18e4,
|
|
5735
|
+
retryOnce: true
|
|
5736
|
+
};
|
|
5737
|
+
}
|
|
5738
|
+
});
|
|
5739
|
+
|
|
5648
5740
|
// ../adapters/dist/docker/volume.js
|
|
5649
5741
|
var volumeName, createVolume;
|
|
5650
5742
|
var init_volume = __esm({
|
|
@@ -5736,12 +5828,14 @@ async function auditPortsForZombies(docker2, hostPorts) {
|
|
|
5736
5828
|
}
|
|
5737
5829
|
}
|
|
5738
5830
|
}
|
|
5739
|
-
var serviceContainerName, worldContainerName, miseCacheVolumeName, PACKAGE_MANAGER_CACHE_DIRS, createServiceContainer, DEFAULT_IMAGE2, CONTROL_PLANE_PORT, HOST_CONTROL_PLANE_BASE, HOST_APP_PORT_BASE_DELTA, DEFAULT_MEMORY_BYTES, PortHeldByZombieError, createWorldContainer, stopAndRemove;
|
|
5831
|
+
var realPullImage, serviceContainerName, worldContainerName, miseCacheVolumeName, PACKAGE_MANAGER_CACHE_DIRS, createServiceContainer, DEFAULT_IMAGE2, CONTROL_PLANE_PORT, HOST_CONTROL_PLANE_BASE, HOST_APP_PORT_BASE_DELTA, DEFAULT_MEMORY_BYTES, PortHeldByZombieError, createWorldContainer, stopAndRemove;
|
|
5740
5832
|
var init_container2 = __esm({
|
|
5741
5833
|
"../adapters/dist/docker/container.js"() {
|
|
5742
5834
|
"use strict";
|
|
5743
5835
|
init_network();
|
|
5836
|
+
init_pull();
|
|
5744
5837
|
init_volume();
|
|
5838
|
+
realPullImage = (imageRef, platform) => pullImageWithRetry(imageRef, void 0, platform ? { perAttemptTimeoutMs: 18e4, retryOnce: true, platform } : { perAttemptTimeoutMs: 18e4, retryOnce: true });
|
|
5745
5839
|
serviceContainerName = (worldId, serviceName) => `olam-${sanitizeContainerName(worldId)}-${sanitizeContainerName(serviceName)}`;
|
|
5746
5840
|
worldContainerName = (worldId) => `olam-${sanitizeContainerName(worldId)}-devbox`;
|
|
5747
5841
|
miseCacheVolumeName = (arch2 = process.arch) => `olam-mise-cache-${arch2}`;
|
|
@@ -5751,10 +5845,15 @@ var init_container2 = __esm({
|
|
|
5751
5845
|
{ name: "yarn", hostSubpath: ".olam/cache/yarn", containerPath: "/usr/local/share/.cache/yarn" },
|
|
5752
5846
|
{ name: "pip", hostSubpath: ".olam/cache/pip", containerPath: "/home/olam/.cache/pip" }
|
|
5753
5847
|
];
|
|
5754
|
-
createServiceContainer = async (docker2, worldId, worldName, service, portOffset) => {
|
|
5848
|
+
createServiceContainer = async (docker2, worldId, worldName, service, portOffset, pullImage = realPullImage) => {
|
|
5755
5849
|
const labels = olamLabels(worldId, worldName);
|
|
5756
5850
|
const hostPort = service.port + portOffset;
|
|
5757
5851
|
const envList = service.environment ? Object.entries(service.environment).map(([k, v]) => `${k}=${v}`) : [];
|
|
5852
|
+
const pullResult = await pullImage(service.image, service.platform);
|
|
5853
|
+
if (pullResult.exitCode !== 0) {
|
|
5854
|
+
const reason = pullResult.stderr.trim() || `exit ${pullResult.exitCode}`;
|
|
5855
|
+
throw new Error(`failed to pull ${service.image}${service.platform ? ` (platform=${service.platform})` : ""}: ${reason}`);
|
|
5856
|
+
}
|
|
5758
5857
|
const container = await docker2.createContainer({
|
|
5759
5858
|
name: serviceContainerName(worldId, service.name),
|
|
5760
5859
|
Image: service.image,
|
|
@@ -6112,10 +6211,18 @@ var init_provider = __esm({
|
|
|
6112
6211
|
};
|
|
6113
6212
|
docker;
|
|
6114
6213
|
dockerOptions;
|
|
6115
|
-
|
|
6214
|
+
/**
|
|
6215
|
+
* Injectable image-pull helper. Defaults to the real
|
|
6216
|
+
* `pullImageWithRetry` (docker CLI shell-out). Tests override with a
|
|
6217
|
+
* no-op so they don't need a real Docker daemon to exercise the
|
|
6218
|
+
* dockerode-mocked code paths.
|
|
6219
|
+
*/
|
|
6220
|
+
pullImage;
|
|
6221
|
+
constructor(dockerOptions, opts) {
|
|
6116
6222
|
super();
|
|
6117
6223
|
this.docker = new Dockerode(dockerOptions);
|
|
6118
6224
|
this.dockerOptions = dockerOptions;
|
|
6225
|
+
this.pullImage = opts?.pullImage;
|
|
6119
6226
|
}
|
|
6120
6227
|
// -----------------------------------------------------------------------
|
|
6121
6228
|
// createWorld
|
|
@@ -6134,7 +6241,7 @@ var init_provider = __esm({
|
|
|
6134
6241
|
await createVolume(this.docker, id, name, svc.name);
|
|
6135
6242
|
}
|
|
6136
6243
|
for (const svc of services) {
|
|
6137
|
-
await createServiceContainer(this.docker, id, name, svc, portOffset);
|
|
6244
|
+
await createServiceContainer(this.docker, id, name, svc, portOffset, this.pullImage);
|
|
6138
6245
|
}
|
|
6139
6246
|
const SERVICE_ENV_ALIASES = {
|
|
6140
6247
|
postgres: "POSTGRESQL",
|
|
@@ -6877,8 +6984,8 @@ var init_provider3 = __esm({
|
|
|
6877
6984
|
// -----------------------------------------------------------------------
|
|
6878
6985
|
// Internal fetch helper
|
|
6879
6986
|
// -----------------------------------------------------------------------
|
|
6880
|
-
async request(
|
|
6881
|
-
const url = `${this.config.workerUrl}${
|
|
6987
|
+
async request(path55, method, body) {
|
|
6988
|
+
const url = `${this.config.workerUrl}${path55}`;
|
|
6882
6989
|
const bearer = await this.config.mintToken();
|
|
6883
6990
|
const headers = {
|
|
6884
6991
|
Authorization: `Bearer ${bearer}`
|
|
@@ -7012,6 +7119,8 @@ __export(dist_exports, {
|
|
|
7012
7119
|
buildPackageManagerCacheBinds: () => buildPackageManagerCacheBinds,
|
|
7013
7120
|
cleanupOrphanedResources: () => cleanupOrphanedResources,
|
|
7014
7121
|
describeDockerEndpoint: () => describeDockerEndpoint,
|
|
7122
|
+
pullImageWithRetry: () => pullImageWithRetry,
|
|
7123
|
+
realDocker: () => realDocker,
|
|
7015
7124
|
resolveDockerHostOptions: () => resolveDockerHostOptions
|
|
7016
7125
|
});
|
|
7017
7126
|
var init_dist = __esm({
|
|
@@ -7023,6 +7132,7 @@ var init_dist = __esm({
|
|
|
7023
7132
|
init_host();
|
|
7024
7133
|
init_container2();
|
|
7025
7134
|
init_container2();
|
|
7135
|
+
init_pull();
|
|
7026
7136
|
init_provider2();
|
|
7027
7137
|
init_provider3();
|
|
7028
7138
|
}
|
|
@@ -8170,8 +8280,8 @@ import { execFileSync as execFileSync3 } from "node:child_process";
|
|
|
8170
8280
|
import * as fs14 from "node:fs";
|
|
8171
8281
|
import * as os9 from "node:os";
|
|
8172
8282
|
import * as path15 from "node:path";
|
|
8173
|
-
function expandHome(p,
|
|
8174
|
-
return p.replace(/^~(?=$|\/|\\)/,
|
|
8283
|
+
function expandHome(p, homedir30) {
|
|
8284
|
+
return p.replace(/^~(?=$|\/|\\)/, homedir30());
|
|
8175
8285
|
}
|
|
8176
8286
|
function sanitizeRepoFilename(name) {
|
|
8177
8287
|
const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -8194,7 +8304,7 @@ ${stderr}`;
|
|
|
8194
8304
|
}
|
|
8195
8305
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
8196
8306
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync3(cmd, args, opts));
|
|
8197
|
-
const
|
|
8307
|
+
const homedir30 = deps.homedir ?? (() => os9.homedir());
|
|
8198
8308
|
const baselineDir = path15.join(workspacePath, ".olam", "baseline");
|
|
8199
8309
|
try {
|
|
8200
8310
|
fs14.mkdirSync(baselineDir, { recursive: true });
|
|
@@ -8210,7 +8320,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
8210
8320
|
continue;
|
|
8211
8321
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
8212
8322
|
const outPath = path15.join(baselineDir, filename);
|
|
8213
|
-
const repoPath = expandHome(repo.path,
|
|
8323
|
+
const repoPath = expandHome(repo.path, homedir30);
|
|
8214
8324
|
if (!fs14.existsSync(repoPath)) {
|
|
8215
8325
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
8216
8326
|
# (skipped: path ${repoPath} does not exist)
|
|
@@ -9056,7 +9166,7 @@ import * as crypto4 from "node:crypto";
|
|
|
9056
9166
|
import * as fs16 from "node:fs";
|
|
9057
9167
|
import * as os10 from "node:os";
|
|
9058
9168
|
import * as path17 from "node:path";
|
|
9059
|
-
import { execFileSync as execFileSync4, spawn } from "node:child_process";
|
|
9169
|
+
import { execFileSync as execFileSync4, spawn as spawn2 } from "node:child_process";
|
|
9060
9170
|
import { gunzipSync } from "node:zlib";
|
|
9061
9171
|
function snapshotsDir() {
|
|
9062
9172
|
return process.env["OLAM_SNAPSHOTS_DIR"] ?? path17.join(os10.homedir(), ".olam", "snapshots");
|
|
@@ -9477,7 +9587,7 @@ function spawnAutoCapture(worldId, olamBin = "olam") {
|
|
|
9477
9587
|
if (!/^[a-zA-Z0-9_\-.]+$/.test(worldId))
|
|
9478
9588
|
return null;
|
|
9479
9589
|
try {
|
|
9480
|
-
const child =
|
|
9590
|
+
const child = spawn2(olamBin, ["world", "snapshot", "create", worldId, "--kind", "all"], {
|
|
9481
9591
|
detached: true,
|
|
9482
9592
|
stdio: "ignore",
|
|
9483
9593
|
// OLAM_INTERNAL_SNAPSHOT=1 sentinel — Phase D D1's deprecation
|
|
@@ -12966,7 +13076,7 @@ var init_state2 = __esm({
|
|
|
12966
13076
|
});
|
|
12967
13077
|
|
|
12968
13078
|
// ../core/dist/dashboard/tunnel.js
|
|
12969
|
-
import { spawn as
|
|
13079
|
+
import { spawn as spawn3, execSync as execSync6 } from "node:child_process";
|
|
12970
13080
|
function isCloudflaredAvailable() {
|
|
12971
13081
|
try {
|
|
12972
13082
|
execSync6("which cloudflared", { stdio: "ignore" });
|
|
@@ -12977,7 +13087,7 @@ function isCloudflaredAvailable() {
|
|
|
12977
13087
|
}
|
|
12978
13088
|
function startTunnel(port) {
|
|
12979
13089
|
return new Promise((resolve11, reject) => {
|
|
12980
|
-
const child =
|
|
13090
|
+
const child = spawn3("cloudflared", ["tunnel", "--url", `http://localhost:${port}`], {
|
|
12981
13091
|
stdio: ["ignore", "pipe", "pipe"],
|
|
12982
13092
|
detached: false
|
|
12983
13093
|
});
|
|
@@ -13822,10 +13932,10 @@ async function readHostCpToken2() {
|
|
|
13822
13932
|
if (!fs25.existsSync(tp)) return null;
|
|
13823
13933
|
return fs25.readFileSync(tp, "utf-8").trim();
|
|
13824
13934
|
}
|
|
13825
|
-
async function callHostCpProxy(method, worldId,
|
|
13935
|
+
async function callHostCpProxy(method, worldId, path55, body) {
|
|
13826
13936
|
const token = await readHostCpToken2();
|
|
13827
13937
|
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)}${
|
|
13938
|
+
const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path55}`;
|
|
13829
13939
|
try {
|
|
13830
13940
|
const headers = {
|
|
13831
13941
|
Authorization: `Bearer ${token}`
|
|
@@ -14285,7 +14395,7 @@ __export(machine_schema_exports, {
|
|
|
14285
14395
|
writeMachineConfig: () => writeMachineConfig
|
|
14286
14396
|
});
|
|
14287
14397
|
import * as fs41 from "node:fs";
|
|
14288
|
-
import * as
|
|
14398
|
+
import * as path47 from "node:path";
|
|
14289
14399
|
import * as os24 from "node:os";
|
|
14290
14400
|
import { parse as parseYaml5, stringify as stringifyYaml5 } from "yaml";
|
|
14291
14401
|
function readMachineConfig(configPath) {
|
|
@@ -14302,7 +14412,7 @@ function readMachineConfig(configPath) {
|
|
|
14302
14412
|
}
|
|
14303
14413
|
function writeMachineConfig(config, configPath) {
|
|
14304
14414
|
const p = configPath ?? DEFAULT_CONFIG_PATH;
|
|
14305
|
-
fs41.mkdirSync(
|
|
14415
|
+
fs41.mkdirSync(path47.dirname(p), { recursive: true });
|
|
14306
14416
|
fs41.writeFileSync(p, stringifyYaml5({ ...config }), { mode: 420 });
|
|
14307
14417
|
}
|
|
14308
14418
|
function initMachineConfig(opts = {}) {
|
|
@@ -14326,9 +14436,9 @@ var init_machine_schema = __esm({
|
|
|
14326
14436
|
channel: external_exports.enum(["stable", "beta", "edge"]).default("stable"),
|
|
14327
14437
|
auto_update: external_exports.boolean().default(true),
|
|
14328
14438
|
telemetry: external_exports.boolean().default(true),
|
|
14329
|
-
worlds_dir: external_exports.string().default(() =>
|
|
14439
|
+
worlds_dir: external_exports.string().default(() => path47.join(os24.homedir(), ".olam", "worlds"))
|
|
14330
14440
|
});
|
|
14331
|
-
DEFAULT_CONFIG_PATH =
|
|
14441
|
+
DEFAULT_CONFIG_PATH = path47.join(os24.homedir(), ".olam", "config.yaml");
|
|
14332
14442
|
}
|
|
14333
14443
|
});
|
|
14334
14444
|
|
|
@@ -14710,9 +14820,9 @@ var UnknownArchetypeError = class extends Error {
|
|
|
14710
14820
|
};
|
|
14711
14821
|
var ArchetypeCycleError = class extends Error {
|
|
14712
14822
|
path;
|
|
14713
|
-
constructor(
|
|
14714
|
-
super(`Archetype inheritance cycle detected: ${
|
|
14715
|
-
this.path =
|
|
14823
|
+
constructor(path55) {
|
|
14824
|
+
super(`Archetype inheritance cycle detected: ${path55.join(" \u2192 ")} \u2192 ${path55[0] ?? "?"}`);
|
|
14825
|
+
this.path = path55;
|
|
14716
14826
|
this.name = "ArchetypeCycleError";
|
|
14717
14827
|
}
|
|
14718
14828
|
};
|
|
@@ -14931,11 +15041,12 @@ import ora2 from "ora";
|
|
|
14931
15041
|
import pc7 from "picocolors";
|
|
14932
15042
|
|
|
14933
15043
|
// src/commands/bootstrap.ts
|
|
15044
|
+
init_dist();
|
|
14934
15045
|
init_install_root();
|
|
14935
15046
|
init_exit_codes();
|
|
14936
15047
|
init_protocol_version();
|
|
14937
15048
|
init_output();
|
|
14938
|
-
import {
|
|
15049
|
+
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
14939
15050
|
import { existsSync as existsSync24, readFileSync as readFileSync18 } from "node:fs";
|
|
14940
15051
|
import { join as join29 } from "node:path";
|
|
14941
15052
|
import ora from "ora";
|
|
@@ -14966,82 +15077,6 @@ function loadImageDigests(installRootDir = installRoot()) {
|
|
|
14966
15077
|
}
|
|
14967
15078
|
return parsed;
|
|
14968
15079
|
}
|
|
14969
|
-
var realDocker = {
|
|
14970
|
-
async info() {
|
|
14971
|
-
return spawnAsync("docker", ["info"]);
|
|
14972
|
-
},
|
|
14973
|
-
async pull(imageRef, opts) {
|
|
14974
|
-
return spawnAsync("docker", ["pull", imageRef], { signal: opts?.signal });
|
|
14975
|
-
},
|
|
14976
|
-
async inspectLabel(imageRef, label) {
|
|
14977
|
-
return spawnAsync("docker", [
|
|
14978
|
-
"inspect",
|
|
14979
|
-
imageRef,
|
|
14980
|
-
"--format",
|
|
14981
|
-
`{{ index .Config.Labels "${label}" }}`
|
|
14982
|
-
]);
|
|
14983
|
-
},
|
|
14984
|
-
async tag(source, target) {
|
|
14985
|
-
return spawnAsync("docker", ["tag", source, target]);
|
|
14986
|
-
}
|
|
14987
|
-
};
|
|
14988
|
-
function spawnAsync(cmd, args, opts = {}) {
|
|
14989
|
-
return new Promise((resolve11) => {
|
|
14990
|
-
const child = spawn3(cmd, [...args], {
|
|
14991
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
14992
|
-
signal: opts.signal
|
|
14993
|
-
});
|
|
14994
|
-
let stdout = "";
|
|
14995
|
-
let stderr = "";
|
|
14996
|
-
child.stdout?.on("data", (chunk) => {
|
|
14997
|
-
stdout += chunk.toString();
|
|
14998
|
-
});
|
|
14999
|
-
child.stderr?.on("data", (chunk) => {
|
|
15000
|
-
stderr += chunk.toString();
|
|
15001
|
-
});
|
|
15002
|
-
child.on("error", (err) => {
|
|
15003
|
-
resolve11({ exitCode: -1, stdout, stderr: stderr + err.message });
|
|
15004
|
-
});
|
|
15005
|
-
child.on("close", (code) => {
|
|
15006
|
-
resolve11({ exitCode: code ?? -1, stdout, stderr });
|
|
15007
|
-
});
|
|
15008
|
-
});
|
|
15009
|
-
}
|
|
15010
|
-
var inflightPulls = /* @__PURE__ */ new Map();
|
|
15011
|
-
var DEFAULT_PULL_POLICY = {
|
|
15012
|
-
perAttemptTimeoutMs: 18e4,
|
|
15013
|
-
retryOnce: true
|
|
15014
|
-
};
|
|
15015
|
-
function isTransientPullFailure(result) {
|
|
15016
|
-
const s = result.stderr.toLowerCase();
|
|
15017
|
-
return result.exitCode !== 0 && (/timeout|connection|temporarily|429|503|tls handshake|network/.test(s) || result.exitCode === 124 || result.exitCode === -1);
|
|
15018
|
-
}
|
|
15019
|
-
async function pullImageWithRetry(imageRef, docker2 = realDocker, policy = DEFAULT_PULL_POLICY) {
|
|
15020
|
-
const existing = inflightPulls.get(imageRef);
|
|
15021
|
-
if (existing) return existing;
|
|
15022
|
-
const promise = (async () => {
|
|
15023
|
-
let result = await pullOnce(imageRef, docker2, policy.perAttemptTimeoutMs);
|
|
15024
|
-
if (result.exitCode !== 0 && policy.retryOnce && isTransientPullFailure(result)) {
|
|
15025
|
-
result = await pullOnce(imageRef, docker2, policy.perAttemptTimeoutMs);
|
|
15026
|
-
}
|
|
15027
|
-
return result;
|
|
15028
|
-
})();
|
|
15029
|
-
inflightPulls.set(imageRef, promise);
|
|
15030
|
-
try {
|
|
15031
|
-
return await promise;
|
|
15032
|
-
} finally {
|
|
15033
|
-
inflightPulls.delete(imageRef);
|
|
15034
|
-
}
|
|
15035
|
-
}
|
|
15036
|
-
async function pullOnce(imageRef, docker2, timeoutMs) {
|
|
15037
|
-
const ac = new AbortController();
|
|
15038
|
-
const timer = setTimeout(() => ac.abort(), timeoutMs).unref?.();
|
|
15039
|
-
try {
|
|
15040
|
-
return await docker2.pull(imageRef, { signal: ac.signal });
|
|
15041
|
-
} finally {
|
|
15042
|
-
if (timer) clearTimeout(timer);
|
|
15043
|
-
}
|
|
15044
|
-
}
|
|
15045
15080
|
var REAL_OLAM_SUBCOMMAND = (args) => {
|
|
15046
15081
|
const result = spawnSync6(process.execPath, [
|
|
15047
15082
|
process.argv[1] ?? "olam",
|
|
@@ -15359,8 +15394,8 @@ function runStep(label, cmd, args, opts = {}) {
|
|
|
15359
15394
|
}
|
|
15360
15395
|
async function confirm(message) {
|
|
15361
15396
|
if (!process.stdin.isTTY) return true;
|
|
15362
|
-
const { createInterface:
|
|
15363
|
-
const rl =
|
|
15397
|
+
const { createInterface: createInterface6 } = await import("node:readline");
|
|
15398
|
+
const rl = createInterface6({ input: process.stdin, output: process.stdout });
|
|
15364
15399
|
return new Promise((resolve11) => {
|
|
15365
15400
|
rl.question(`${message} [y/N] `, (answer) => {
|
|
15366
15401
|
rl.close();
|
|
@@ -16093,9 +16128,9 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
|
|
|
16093
16128
|
"These source files have changed since the image was built; the",
|
|
16094
16129
|
"changes will NOT take effect in fresh worlds until you rebuild:"
|
|
16095
16130
|
];
|
|
16096
|
-
for (const { path:
|
|
16131
|
+
for (const { path: path55, mtimeMs } of result.newerSources) {
|
|
16097
16132
|
const when = new Date(mtimeMs).toISOString();
|
|
16098
|
-
lines.push(` \u2022 ${
|
|
16133
|
+
lines.push(` \u2022 ${path55} (modified ${when})`);
|
|
16099
16134
|
}
|
|
16100
16135
|
lines.push("");
|
|
16101
16136
|
lines.push("Rebuild with:");
|
|
@@ -16256,9 +16291,9 @@ async function readHostCpTokenForCreate() {
|
|
|
16256
16291
|
try {
|
|
16257
16292
|
const { default: fs50 } = await import("node:fs");
|
|
16258
16293
|
const { default: os28 } = await import("node:os");
|
|
16259
|
-
const { default:
|
|
16260
|
-
const tp =
|
|
16261
|
-
process.env.OLAM_HOME ??
|
|
16294
|
+
const { default: path55 } = await import("node:path");
|
|
16295
|
+
const tp = path55.join(
|
|
16296
|
+
process.env.OLAM_HOME ?? path55.join(os28.homedir(), ".olam"),
|
|
16262
16297
|
"host-cp.token"
|
|
16263
16298
|
);
|
|
16264
16299
|
if (!fs50.existsSync(tp)) return null;
|
|
@@ -16627,8 +16662,8 @@ async function readHostCpToken3() {
|
|
|
16627
16662
|
try {
|
|
16628
16663
|
const { default: fs50 } = await import("node:fs");
|
|
16629
16664
|
const { default: os28 } = await import("node:os");
|
|
16630
|
-
const { default:
|
|
16631
|
-
const tp =
|
|
16665
|
+
const { default: path55 } = await import("node:path");
|
|
16666
|
+
const tp = path55.join(os28.homedir(), ".olam", "host-cp.token");
|
|
16632
16667
|
if (!fs50.existsSync(tp)) return null;
|
|
16633
16668
|
const raw = fs50.readFileSync(tp, "utf-8").trim();
|
|
16634
16669
|
return raw.length > 0 ? raw : null;
|
|
@@ -20361,11 +20396,11 @@ function zodIssueToError(issue, doc, lineCounter) {
|
|
|
20361
20396
|
suggestion: deriveSuggestion(issue)
|
|
20362
20397
|
};
|
|
20363
20398
|
}
|
|
20364
|
-
function formatJsonPath(
|
|
20365
|
-
if (
|
|
20399
|
+
function formatJsonPath(path55) {
|
|
20400
|
+
if (path55.length === 0)
|
|
20366
20401
|
return "<root>";
|
|
20367
20402
|
let out = "";
|
|
20368
|
-
for (const seg of
|
|
20403
|
+
for (const seg of path55) {
|
|
20369
20404
|
if (typeof seg === "number") {
|
|
20370
20405
|
out += `[${seg}]`;
|
|
20371
20406
|
} else {
|
|
@@ -20374,11 +20409,11 @@ function formatJsonPath(path53) {
|
|
|
20374
20409
|
}
|
|
20375
20410
|
return out;
|
|
20376
20411
|
}
|
|
20377
|
-
function resolveYamlLocation(
|
|
20412
|
+
function resolveYamlLocation(path55, doc, lineCounter) {
|
|
20378
20413
|
let bestLine = 0;
|
|
20379
20414
|
let bestColumn = 0;
|
|
20380
|
-
for (let depth =
|
|
20381
|
-
const segment =
|
|
20415
|
+
for (let depth = path55.length; depth >= 0; depth -= 1) {
|
|
20416
|
+
const segment = path55.slice(0, depth);
|
|
20382
20417
|
try {
|
|
20383
20418
|
const node = doc.getIn(segment, true);
|
|
20384
20419
|
if (node && typeof node === "object" && "range" in node) {
|
|
@@ -20596,11 +20631,11 @@ function topoSort(nodes) {
|
|
|
20596
20631
|
}
|
|
20597
20632
|
function traceCycle(start, byId) {
|
|
20598
20633
|
const seen = /* @__PURE__ */ new Set();
|
|
20599
|
-
const
|
|
20634
|
+
const path55 = [];
|
|
20600
20635
|
let current = start;
|
|
20601
20636
|
while (current && !seen.has(current)) {
|
|
20602
20637
|
seen.add(current);
|
|
20603
|
-
|
|
20638
|
+
path55.push(current);
|
|
20604
20639
|
const node = byId.get(current);
|
|
20605
20640
|
const next = node?.dependsOn[0];
|
|
20606
20641
|
if (next === void 0)
|
|
@@ -20608,10 +20643,10 @@ function traceCycle(start, byId) {
|
|
|
20608
20643
|
current = next;
|
|
20609
20644
|
}
|
|
20610
20645
|
if (current && seen.has(current)) {
|
|
20611
|
-
const idx =
|
|
20612
|
-
return [...
|
|
20646
|
+
const idx = path55.indexOf(current);
|
|
20647
|
+
return [...path55.slice(idx), current];
|
|
20613
20648
|
}
|
|
20614
|
-
return
|
|
20649
|
+
return path55;
|
|
20615
20650
|
}
|
|
20616
20651
|
|
|
20617
20652
|
// ../core/dist/executor/types.js
|
|
@@ -23018,8 +23053,8 @@ function performRollbackSwap(plan) {
|
|
|
23018
23053
|
}
|
|
23019
23054
|
async function confirm2(message) {
|
|
23020
23055
|
if (!process.stdin.isTTY) return true;
|
|
23021
|
-
const { createInterface:
|
|
23022
|
-
const rl =
|
|
23056
|
+
const { createInterface: createInterface6 } = await import("node:readline");
|
|
23057
|
+
const rl = createInterface6({ input: process.stdin, output: process.stdout });
|
|
23023
23058
|
return new Promise((resolve11) => {
|
|
23024
23059
|
rl.question(`${message} [y/N] `, (answer) => {
|
|
23025
23060
|
rl.close();
|
|
@@ -25493,16 +25528,318 @@ function registerCompletion(program2) {
|
|
|
25493
25528
|
});
|
|
25494
25529
|
}
|
|
25495
25530
|
|
|
25531
|
+
// src/commands/setup.ts
|
|
25532
|
+
init_cli_version();
|
|
25533
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
25534
|
+
import { existsSync as existsSync45 } from "node:fs";
|
|
25535
|
+
import { homedir as homedir23 } from "node:os";
|
|
25536
|
+
import path45 from "node:path";
|
|
25537
|
+
import { createInterface as createInterface3 } from "node:readline";
|
|
25538
|
+
|
|
25539
|
+
// src/lib/shell-rc.ts
|
|
25540
|
+
import { copyFileSync as copyFileSync5, existsSync as existsSync44, readFileSync as readFileSync31, renameSync as renameSync4, writeFileSync as writeFileSync20 } from "node:fs";
|
|
25541
|
+
import path44 from "node:path";
|
|
25542
|
+
function appendIdempotent(opts) {
|
|
25543
|
+
const { rcPath, marker, contentLine, clock = () => /* @__PURE__ */ new Date() } = opts;
|
|
25544
|
+
if (!existsSync44(rcPath)) {
|
|
25545
|
+
return { status: "no-rc-file", backupPath: null };
|
|
25546
|
+
}
|
|
25547
|
+
const content = readFileSync31(rcPath, "utf-8");
|
|
25548
|
+
if (content.includes(marker)) {
|
|
25549
|
+
return { status: "already-present", backupPath: null };
|
|
25550
|
+
}
|
|
25551
|
+
const timestamp = clock().toISOString().replace(/[:.]/g, "-");
|
|
25552
|
+
const backupPath = `${rcPath}.olam-bak.${timestamp}`;
|
|
25553
|
+
copyFileSync5(rcPath, backupPath);
|
|
25554
|
+
const separator = content.length === 0 || content.endsWith("\n") ? "" : "\n";
|
|
25555
|
+
const trailing = contentLine.endsWith("\n") ? "" : "\n";
|
|
25556
|
+
const nextContent = `${content}${separator}${contentLine}${trailing}`;
|
|
25557
|
+
const tmpPath = `${rcPath}.olam-tmp.${process.pid}`;
|
|
25558
|
+
writeFileSync20(tmpPath, nextContent, { encoding: "utf-8" });
|
|
25559
|
+
renameSync4(tmpPath, rcPath);
|
|
25560
|
+
return { status: "appended", backupPath };
|
|
25561
|
+
}
|
|
25562
|
+
function resolveShellRc(home, shellEnv) {
|
|
25563
|
+
if (!shellEnv) return null;
|
|
25564
|
+
const basename6 = path44.basename(shellEnv);
|
|
25565
|
+
if (basename6 === "zsh") return path44.join(home, ".zshrc");
|
|
25566
|
+
if (basename6 === "bash") return path44.join(home, ".bashrc");
|
|
25567
|
+
return null;
|
|
25568
|
+
}
|
|
25569
|
+
|
|
25570
|
+
// src/commands/setup.ts
|
|
25571
|
+
init_output();
|
|
25572
|
+
var REQUIRED_NODE_MAJOR = 20;
|
|
25573
|
+
var NEXT_STEPS_DOCS = [
|
|
25574
|
+
"docs/architecture/devbox-contract.md \u2014 image contract",
|
|
25575
|
+
"docs/architecture/manifest-spec.md \u2014 per-repo .adb.yaml schema",
|
|
25576
|
+
"docs/architecture/config-spec.md \u2014 workspace .olam/config.yaml schema"
|
|
25577
|
+
];
|
|
25578
|
+
var defaultSpawn = (cmd, args) => new Promise((resolve11) => {
|
|
25579
|
+
const child = spawn5(cmd, [...args], { stdio: "inherit" });
|
|
25580
|
+
child.on("exit", (code) => resolve11({ status: code }));
|
|
25581
|
+
child.on("error", () => resolve11({ status: 1 }));
|
|
25582
|
+
});
|
|
25583
|
+
var defaultPrompt = (question, defaultYes) => {
|
|
25584
|
+
if (!process.stdin.isTTY) {
|
|
25585
|
+
process.stderr.write(
|
|
25586
|
+
`[olam setup] non-TTY stdin detected; using default answer (${defaultYes ? "yes" : "no"}). Re-run with \`--yes\` for explicit non-interactive mode.
|
|
25587
|
+
`
|
|
25588
|
+
);
|
|
25589
|
+
return Promise.resolve(defaultYes);
|
|
25590
|
+
}
|
|
25591
|
+
return new Promise((resolve11) => {
|
|
25592
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
25593
|
+
const suffix = defaultYes ? " [Y/n]: " : " [y/N]: ";
|
|
25594
|
+
rl.question(`${question}${suffix}`, (answer) => {
|
|
25595
|
+
rl.close();
|
|
25596
|
+
const t = answer.trim().toLowerCase();
|
|
25597
|
+
if (t === "") resolve11(defaultYes);
|
|
25598
|
+
else if (t === "y" || t === "yes") resolve11(true);
|
|
25599
|
+
else if (t === "n" || t === "no") resolve11(false);
|
|
25600
|
+
else resolve11(defaultYes);
|
|
25601
|
+
});
|
|
25602
|
+
rl.on("close", () => resolve11(defaultYes));
|
|
25603
|
+
});
|
|
25604
|
+
};
|
|
25605
|
+
async function phase1SystemCheck(deps) {
|
|
25606
|
+
const dockerProbe = await probeDockerDaemon(deps.dockerExec);
|
|
25607
|
+
if (!dockerProbe.ok) {
|
|
25608
|
+
return phaseFromProbe(dockerProbe);
|
|
25609
|
+
}
|
|
25610
|
+
const nodeVersion = deps.nodeVersion ?? process.version;
|
|
25611
|
+
const nodeMajor = parseNodeMajor(nodeVersion);
|
|
25612
|
+
if (nodeMajor === null || nodeMajor < REQUIRED_NODE_MAJOR) {
|
|
25613
|
+
return {
|
|
25614
|
+
ok: false,
|
|
25615
|
+
message: `Node.js ${nodeVersion} is too old (need \u2265${REQUIRED_NODE_MAJOR})`,
|
|
25616
|
+
remedy: `Install Node.js ${REQUIRED_NODE_MAJOR}+ LTS via nvm/fnm/asdf and re-run \`olam setup\`.`
|
|
25617
|
+
};
|
|
25618
|
+
}
|
|
25619
|
+
return {
|
|
25620
|
+
ok: true,
|
|
25621
|
+
message: `${dockerProbe.message}; node ${nodeVersion}`
|
|
25622
|
+
};
|
|
25623
|
+
}
|
|
25624
|
+
function parseNodeMajor(version) {
|
|
25625
|
+
const m = version.match(/^v?(\d+)\./);
|
|
25626
|
+
if (!m) return null;
|
|
25627
|
+
const n = Number.parseInt(m[1], 10);
|
|
25628
|
+
return Number.isFinite(n) ? n : null;
|
|
25629
|
+
}
|
|
25630
|
+
function phaseFromProbe(probe) {
|
|
25631
|
+
if (probe.ok) return { ok: true, message: probe.message };
|
|
25632
|
+
return { ok: false, message: probe.message, remedy: probe.remedy };
|
|
25633
|
+
}
|
|
25634
|
+
async function phase2CliSanity(deps) {
|
|
25635
|
+
const version = deps.olamCliVersion ?? safeReadCliVersion();
|
|
25636
|
+
if (!version || version === "unknown") {
|
|
25637
|
+
return {
|
|
25638
|
+
ok: false,
|
|
25639
|
+
message: "olam CLI version not detectable",
|
|
25640
|
+
remedy: "Re-install `olam` via `npm install -g @pleri/olam-cli@stable` and re-run."
|
|
25641
|
+
};
|
|
25642
|
+
}
|
|
25643
|
+
return { ok: true, message: `olam ${version}` };
|
|
25644
|
+
}
|
|
25645
|
+
function safeReadCliVersion() {
|
|
25646
|
+
try {
|
|
25647
|
+
return readCliVersion();
|
|
25648
|
+
} catch {
|
|
25649
|
+
return null;
|
|
25650
|
+
}
|
|
25651
|
+
}
|
|
25652
|
+
async function phase3Bootstrap(deps) {
|
|
25653
|
+
const spawnFn = deps.spawnSubprocess ?? defaultSpawn;
|
|
25654
|
+
const r = await spawnFn("olam", ["bootstrap", "--skip-auth-login"]);
|
|
25655
|
+
if (r.status === 0) {
|
|
25656
|
+
return { ok: true, message: "olam bootstrap succeeded" };
|
|
25657
|
+
}
|
|
25658
|
+
return {
|
|
25659
|
+
ok: false,
|
|
25660
|
+
message: `olam bootstrap exited ${r.status}`,
|
|
25661
|
+
remedy: "Re-run `olam setup` after inspecting the bootstrap error above (bootstrap is idempotent)."
|
|
25662
|
+
};
|
|
25663
|
+
}
|
|
25664
|
+
async function phase4ShellInit(opts, deps) {
|
|
25665
|
+
if (opts.skipShellInit) {
|
|
25666
|
+
return { ok: true, skipped: true, message: "skipped via --skip-shell-init" };
|
|
25667
|
+
}
|
|
25668
|
+
const home = deps.home ?? homedir23();
|
|
25669
|
+
const shellEnv = deps.shellEnv ?? process.env.SHELL;
|
|
25670
|
+
const rcPath = resolveShellRc(home, shellEnv);
|
|
25671
|
+
if (rcPath === null) {
|
|
25672
|
+
return {
|
|
25673
|
+
ok: true,
|
|
25674
|
+
skipped: true,
|
|
25675
|
+
message: `unsupported $SHELL (${shellEnv ?? "unset"}); add \`eval "$(olam completion <shell>)"\` to your shell rc manually`
|
|
25676
|
+
};
|
|
25677
|
+
}
|
|
25678
|
+
const shellBasename = path45.basename(shellEnv);
|
|
25679
|
+
const evalLine = `eval "$(olam completion ${shellBasename})"`;
|
|
25680
|
+
const result = appendIdempotent({
|
|
25681
|
+
rcPath,
|
|
25682
|
+
marker: "olam completion",
|
|
25683
|
+
contentLine: evalLine,
|
|
25684
|
+
clock: deps.clock
|
|
25685
|
+
});
|
|
25686
|
+
if (result.status === "no-rc-file") {
|
|
25687
|
+
return {
|
|
25688
|
+
ok: true,
|
|
25689
|
+
skipped: true,
|
|
25690
|
+
message: `${rcPath} not present; skipped (add \`${evalLine}\` to your shell rc manually)`
|
|
25691
|
+
};
|
|
25692
|
+
}
|
|
25693
|
+
if (result.status === "already-present") {
|
|
25694
|
+
return { ok: true, message: `${rcPath}: already configured (no change)` };
|
|
25695
|
+
}
|
|
25696
|
+
return {
|
|
25697
|
+
ok: true,
|
|
25698
|
+
message: `${rcPath}: appended (backup: ${result.backupPath})`
|
|
25699
|
+
};
|
|
25700
|
+
}
|
|
25701
|
+
async function phase5InitProject(opts, deps) {
|
|
25702
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
25703
|
+
const projectRoot = findProjectRoot(cwd);
|
|
25704
|
+
const configPath = path45.join(projectRoot, ".olam", "config.yaml");
|
|
25705
|
+
if (existsSync45(configPath)) {
|
|
25706
|
+
return { ok: true, message: `${configPath} present (no change)` };
|
|
25707
|
+
}
|
|
25708
|
+
const promptFn = deps.prompt ?? defaultPrompt;
|
|
25709
|
+
const shouldInit = opts.yes ? true : await promptFn(`No .olam/config.yaml in ${cwd}. Initialise project here?`, false);
|
|
25710
|
+
if (!shouldInit) {
|
|
25711
|
+
return {
|
|
25712
|
+
ok: true,
|
|
25713
|
+
skipped: true,
|
|
25714
|
+
message: "declined; run `olam init` later when ready"
|
|
25715
|
+
};
|
|
25716
|
+
}
|
|
25717
|
+
const spawnFn = deps.spawnSubprocess ?? defaultSpawn;
|
|
25718
|
+
const r = await spawnFn("olam", ["init"]);
|
|
25719
|
+
if (r.status === 0) {
|
|
25720
|
+
return { ok: true, message: "olam init completed" };
|
|
25721
|
+
}
|
|
25722
|
+
return {
|
|
25723
|
+
ok: false,
|
|
25724
|
+
message: `olam init exited ${r.status}`,
|
|
25725
|
+
remedy: "Inspect the init error above and re-run `olam setup`."
|
|
25726
|
+
};
|
|
25727
|
+
}
|
|
25728
|
+
async function phase6Auth(opts, deps) {
|
|
25729
|
+
if (opts.skipAuth) {
|
|
25730
|
+
return {
|
|
25731
|
+
ok: true,
|
|
25732
|
+
skipped: true,
|
|
25733
|
+
message: "skipped via --skip-auth (run `olam auth login` later)"
|
|
25734
|
+
};
|
|
25735
|
+
}
|
|
25736
|
+
const promptFn = deps.prompt ?? defaultPrompt;
|
|
25737
|
+
const shouldLaunch = opts.yes ? true : await promptFn(
|
|
25738
|
+
"`olam auth login` is interactive (PKCE browser flow, 5 min timeout). Launch now?",
|
|
25739
|
+
false
|
|
25740
|
+
);
|
|
25741
|
+
if (!shouldLaunch) {
|
|
25742
|
+
return {
|
|
25743
|
+
ok: true,
|
|
25744
|
+
skipped: true,
|
|
25745
|
+
message: "declined; run `olam auth login` later when ready"
|
|
25746
|
+
};
|
|
25747
|
+
}
|
|
25748
|
+
const spawnFn = deps.spawnSubprocess ?? defaultSpawn;
|
|
25749
|
+
const r = await spawnFn("olam", ["auth", "login"]);
|
|
25750
|
+
if (r.status === 0) {
|
|
25751
|
+
return { ok: true, message: "olam auth login succeeded" };
|
|
25752
|
+
}
|
|
25753
|
+
return {
|
|
25754
|
+
ok: true,
|
|
25755
|
+
skipped: true,
|
|
25756
|
+
message: `olam auth login exited ${r.status}; re-run \`olam auth login\` after resolving`
|
|
25757
|
+
};
|
|
25758
|
+
}
|
|
25759
|
+
async function phase7Verify(deps) {
|
|
25760
|
+
const spawnFn = deps.spawnSubprocess ?? defaultSpawn;
|
|
25761
|
+
const r = await spawnFn("olam", ["doctor"]);
|
|
25762
|
+
if (r.status === 0) {
|
|
25763
|
+
return { ok: true, message: "olam doctor: all probes green" };
|
|
25764
|
+
}
|
|
25765
|
+
return {
|
|
25766
|
+
ok: false,
|
|
25767
|
+
message: `olam doctor exited ${r.status}`,
|
|
25768
|
+
remedy: "Inspect doctor output above; the specific failing probe names its remedy."
|
|
25769
|
+
};
|
|
25770
|
+
}
|
|
25771
|
+
var PHASE_TITLES = [
|
|
25772
|
+
"Phase 1: System check",
|
|
25773
|
+
"Phase 2: olam CLI sanity",
|
|
25774
|
+
"Phase 3: Bootstrap",
|
|
25775
|
+
"Phase 4: Shell init",
|
|
25776
|
+
"Phase 5: Init project",
|
|
25777
|
+
"Phase 6: Auth prompt",
|
|
25778
|
+
"Phase 7: Final verification"
|
|
25779
|
+
];
|
|
25780
|
+
async function runSetup(opts, deps = {}) {
|
|
25781
|
+
printHeader("olam setup");
|
|
25782
|
+
const phaseFns = [
|
|
25783
|
+
() => phase1SystemCheck(deps),
|
|
25784
|
+
() => phase2CliSanity(deps),
|
|
25785
|
+
() => phase3Bootstrap(deps),
|
|
25786
|
+
() => phase4ShellInit(opts, deps),
|
|
25787
|
+
() => phase5InitProject(opts, deps),
|
|
25788
|
+
() => phase6Auth(opts, deps),
|
|
25789
|
+
() => phase7Verify(deps)
|
|
25790
|
+
];
|
|
25791
|
+
const results = [];
|
|
25792
|
+
let failureAt = null;
|
|
25793
|
+
for (let i = 0; i < phaseFns.length; i += 1) {
|
|
25794
|
+
const name = PHASE_TITLES[i];
|
|
25795
|
+
process.stdout.write(`
|
|
25796
|
+
${name}
|
|
25797
|
+
`);
|
|
25798
|
+
const result = await phaseFns[i]();
|
|
25799
|
+
results.push({ name, result });
|
|
25800
|
+
if (result.ok && result.skipped) {
|
|
25801
|
+
printWarning(` \u2298 ${result.message}`);
|
|
25802
|
+
} else if (result.ok) {
|
|
25803
|
+
printSuccess(` \u2713 ${result.message}`);
|
|
25804
|
+
} else {
|
|
25805
|
+
printError(` \u2717 ${result.message}`);
|
|
25806
|
+
if (result.remedy) printWarning(` remedy: ${result.remedy}`);
|
|
25807
|
+
failureAt = i + 1;
|
|
25808
|
+
break;
|
|
25809
|
+
}
|
|
25810
|
+
}
|
|
25811
|
+
process.stdout.write("\n");
|
|
25812
|
+
if (failureAt !== null) {
|
|
25813
|
+
printError(`Setup FAILED at Phase ${failureAt}`);
|
|
25814
|
+
return { phases: results, failureAt, exitCode: 1 };
|
|
25815
|
+
}
|
|
25816
|
+
printSuccess("Setup complete.");
|
|
25817
|
+
process.stdout.write("\nNext steps \u2014 read these in order for the 3-contract pattern:\n");
|
|
25818
|
+
for (const line of NEXT_STEPS_DOCS) {
|
|
25819
|
+
printInfo("docs", line);
|
|
25820
|
+
}
|
|
25821
|
+
process.stdout.write("\n");
|
|
25822
|
+
return { phases: results, failureAt: null, exitCode: 0 };
|
|
25823
|
+
}
|
|
25824
|
+
function registerSetup(program2) {
|
|
25825
|
+
program2.command("setup").description(
|
|
25826
|
+
"Fresh-host onboarding wizard. Runs 7 phases (system check \u2192 bootstrap \u2192 shell init \u2192 init project \u2192 auth prompt \u2192 doctor verification). Idempotent; safe to re-run."
|
|
25827
|
+
).option("--skip-shell-init", "Skip Phase 4 (do not append to ~/.zshrc / ~/.bashrc)").option("--skip-auth", "Skip Phase 6 (do not prompt for `olam auth login`)").option("-y, --yes", "Auto-affirm every prompt (non-interactive)").action(async (opts) => {
|
|
25828
|
+
const report = await runSetup(opts);
|
|
25829
|
+
if (report.exitCode !== 0) process.exitCode = report.exitCode;
|
|
25830
|
+
});
|
|
25831
|
+
}
|
|
25832
|
+
|
|
25496
25833
|
// src/commands/update.ts
|
|
25497
25834
|
import * as fs42 from "node:fs";
|
|
25498
25835
|
import * as os25 from "node:os";
|
|
25499
|
-
import * as
|
|
25836
|
+
import * as path48 from "node:path";
|
|
25500
25837
|
import { execSync as execSync13 } from "node:child_process";
|
|
25501
25838
|
import pc23 from "picocolors";
|
|
25502
25839
|
|
|
25503
25840
|
// src/lib/symlink-reconcile.ts
|
|
25504
25841
|
import * as fs40 from "node:fs";
|
|
25505
|
-
import * as
|
|
25842
|
+
import * as path46 from "node:path";
|
|
25506
25843
|
var realFs = {
|
|
25507
25844
|
readdirSync: (p) => fs40.readdirSync(p),
|
|
25508
25845
|
existsSync: (p) => fs40.existsSync(p),
|
|
@@ -25521,8 +25858,8 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
|
|
|
25521
25858
|
_fs.mkdirSync(claudeSkillsDir, { recursive: true });
|
|
25522
25859
|
const sourceSkills = _fs.existsSync(npmSkillsDir) ? _fs.readdirSync(npmSkillsDir).filter((d) => d.startsWith("olam-")) : [];
|
|
25523
25860
|
for (const skill of sourceSkills) {
|
|
25524
|
-
const linkPath =
|
|
25525
|
-
const target =
|
|
25861
|
+
const linkPath = path46.join(claudeSkillsDir, skill);
|
|
25862
|
+
const target = path46.join(npmSkillsDir, skill);
|
|
25526
25863
|
if (!_fs.existsSync(linkPath)) {
|
|
25527
25864
|
try {
|
|
25528
25865
|
_fs.symlinkSync(target, linkPath);
|
|
@@ -25535,7 +25872,7 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
|
|
|
25535
25872
|
}
|
|
25536
25873
|
const deployedEntries = _fs.existsSync(claudeSkillsDir) ? _fs.readdirSync(claudeSkillsDir).filter((d) => d.startsWith("olam-")) : [];
|
|
25537
25874
|
for (const entry of deployedEntries) {
|
|
25538
|
-
const linkPath =
|
|
25875
|
+
const linkPath = path46.join(claudeSkillsDir, entry);
|
|
25539
25876
|
let isSymlink = false;
|
|
25540
25877
|
try {
|
|
25541
25878
|
isSymlink = _fs.lstatSync(linkPath).isSymbolicLink();
|
|
@@ -25560,9 +25897,9 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
|
|
|
25560
25897
|
|
|
25561
25898
|
// src/commands/update.ts
|
|
25562
25899
|
var PACKAGE_NAME = "@pleri/olam-cli";
|
|
25563
|
-
var CACHE_DIR2 =
|
|
25564
|
-
var LOG_DIR2 =
|
|
25565
|
-
var LAST_STABLE_FILE =
|
|
25900
|
+
var CACHE_DIR2 = path48.join(os25.homedir(), ".olam", "cache");
|
|
25901
|
+
var LOG_DIR2 = path48.join(os25.homedir(), ".olam", "log");
|
|
25902
|
+
var LAST_STABLE_FILE = path48.join(CACHE_DIR2, "last-stable.txt");
|
|
25566
25903
|
function defaultExec(cmd) {
|
|
25567
25904
|
try {
|
|
25568
25905
|
const stdout = execSync13(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -25591,12 +25928,12 @@ function readLastStable(file = LAST_STABLE_FILE) {
|
|
|
25591
25928
|
}
|
|
25592
25929
|
}
|
|
25593
25930
|
function writeLastStable(version, file = LAST_STABLE_FILE) {
|
|
25594
|
-
fs42.mkdirSync(
|
|
25931
|
+
fs42.mkdirSync(path48.dirname(file), { recursive: true });
|
|
25595
25932
|
fs42.writeFileSync(file, version, { mode: 420 });
|
|
25596
25933
|
}
|
|
25597
25934
|
function logUpdateFailure(stderr) {
|
|
25598
25935
|
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
25599
|
-
const logFile =
|
|
25936
|
+
const logFile = path48.join(LOG_DIR2, `update-${ts}.log`);
|
|
25600
25937
|
try {
|
|
25601
25938
|
fs42.mkdirSync(LOG_DIR2, { recursive: true });
|
|
25602
25939
|
fs42.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
@@ -25686,8 +26023,8 @@ async function doUpdate(opts, _exec = defaultExec, _reconcile = reconcileSkillSy
|
|
|
25686
26023
|
let symlinkResult = { added: [], removed: [] };
|
|
25687
26024
|
if (npmRootResult.exitCode === 0) {
|
|
25688
26025
|
const npmRoot = npmRootResult.stdout.trim();
|
|
25689
|
-
const npmSkillsDir =
|
|
25690
|
-
const claudeSkillsDir =
|
|
26026
|
+
const npmSkillsDir = path48.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills");
|
|
26027
|
+
const claudeSkillsDir = path48.join(os25.homedir(), ".claude", "skills");
|
|
25691
26028
|
const rec = _reconcile(npmSkillsDir, claudeSkillsDir);
|
|
25692
26029
|
symlinkResult = { added: rec.added, removed: rec.removed };
|
|
25693
26030
|
if (!quiet && (rec.added.length > 0 || rec.removed.length > 0)) {
|
|
@@ -25733,8 +26070,8 @@ async function doRollback(_exec = defaultExec, _reconcile = reconcileSkillSymlin
|
|
|
25733
26070
|
if (npmRootResult.exitCode === 0) {
|
|
25734
26071
|
const npmRoot = npmRootResult.stdout.trim();
|
|
25735
26072
|
_reconcile(
|
|
25736
|
-
|
|
25737
|
-
|
|
26073
|
+
path48.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills"),
|
|
26074
|
+
path48.join(os25.homedir(), ".claude", "skills")
|
|
25738
26075
|
);
|
|
25739
26076
|
}
|
|
25740
26077
|
return { action: "rolled-back", restoredVersion: prev, exitCode: 0 };
|
|
@@ -25826,10 +26163,10 @@ init_store2();
|
|
|
25826
26163
|
init_store2();
|
|
25827
26164
|
import * as fs43 from "node:fs";
|
|
25828
26165
|
import * as os26 from "node:os";
|
|
25829
|
-
import * as
|
|
26166
|
+
import * as path49 from "node:path";
|
|
25830
26167
|
function expandPath(p) {
|
|
25831
26168
|
if (p === "~" || p.startsWith("~/")) {
|
|
25832
|
-
return
|
|
26169
|
+
return path49.join(os26.homedir(), p.slice(1));
|
|
25833
26170
|
}
|
|
25834
26171
|
return p;
|
|
25835
26172
|
}
|
|
@@ -26238,8 +26575,8 @@ var SECRET = process.env["OLAM_MCP_AUTH_SECRET"] ?? "";
|
|
|
26238
26575
|
function authHeaders() {
|
|
26239
26576
|
return SECRET ? { "X-Olam-Mcp-Secret": SECRET } : {};
|
|
26240
26577
|
}
|
|
26241
|
-
async function apiFetch(
|
|
26242
|
-
const res = await fetch(`${BASE_URL}${
|
|
26578
|
+
async function apiFetch(path55, init = {}) {
|
|
26579
|
+
const res = await fetch(`${BASE_URL}${path55}`, {
|
|
26243
26580
|
...init,
|
|
26244
26581
|
headers: {
|
|
26245
26582
|
"Content-Type": "application/json",
|
|
@@ -26294,11 +26631,11 @@ function getMcpAuthClient() {
|
|
|
26294
26631
|
}
|
|
26295
26632
|
|
|
26296
26633
|
// src/commands/mcp/login.ts
|
|
26297
|
-
import { spawn as
|
|
26634
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
26298
26635
|
function openBrowser2(url) {
|
|
26299
26636
|
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
26300
26637
|
try {
|
|
26301
|
-
const child =
|
|
26638
|
+
const child = spawn6(cmd, [url], { detached: true, stdio: "ignore" });
|
|
26302
26639
|
child.unref();
|
|
26303
26640
|
} catch {
|
|
26304
26641
|
}
|
|
@@ -26501,7 +26838,7 @@ import pc29 from "picocolors";
|
|
|
26501
26838
|
// src/commands/mcp/import-discovery.ts
|
|
26502
26839
|
import * as fs45 from "node:fs";
|
|
26503
26840
|
import * as os27 from "node:os";
|
|
26504
|
-
import * as
|
|
26841
|
+
import * as path50 from "node:path";
|
|
26505
26842
|
function readJsonFile(filePath) {
|
|
26506
26843
|
try {
|
|
26507
26844
|
const raw = fs45.readFileSync(filePath, "utf-8");
|
|
@@ -26533,18 +26870,18 @@ function extractMcpServers(obj, source, sourceLabel) {
|
|
|
26533
26870
|
}
|
|
26534
26871
|
function getClaudeDesktopPath() {
|
|
26535
26872
|
if (process.platform === "darwin") {
|
|
26536
|
-
return
|
|
26873
|
+
return path50.join(os27.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
26537
26874
|
}
|
|
26538
26875
|
if (process.platform === "win32") {
|
|
26539
|
-
const appData = process.env["APPDATA"] ??
|
|
26540
|
-
return
|
|
26876
|
+
const appData = process.env["APPDATA"] ?? path50.join(os27.homedir(), "AppData", "Roaming");
|
|
26877
|
+
return path50.join(appData, "Claude", "claude_desktop_config.json");
|
|
26541
26878
|
}
|
|
26542
|
-
return
|
|
26879
|
+
return path50.join(os27.homedir(), ".config", "Claude", "claude_desktop_config.json");
|
|
26543
26880
|
}
|
|
26544
26881
|
function getOlamRepoPaths() {
|
|
26545
26882
|
const configPaths = [
|
|
26546
|
-
|
|
26547
|
-
|
|
26883
|
+
path50.join(os27.homedir(), ".olam", "config.yaml"),
|
|
26884
|
+
path50.join(process.cwd(), ".olam", "config.yaml")
|
|
26548
26885
|
];
|
|
26549
26886
|
const paths = [];
|
|
26550
26887
|
for (const configPath of configPaths) {
|
|
@@ -26566,7 +26903,7 @@ async function discoverMcpSources(repoPaths) {
|
|
|
26566
26903
|
const sources = [];
|
|
26567
26904
|
const sourceDefs = [
|
|
26568
26905
|
{
|
|
26569
|
-
path:
|
|
26906
|
+
path: path50.join(os27.homedir(), ".claude.json"),
|
|
26570
26907
|
label: "Claude Code (~/.claude.json)"
|
|
26571
26908
|
},
|
|
26572
26909
|
{
|
|
@@ -26574,19 +26911,19 @@ async function discoverMcpSources(repoPaths) {
|
|
|
26574
26911
|
label: "Claude Desktop"
|
|
26575
26912
|
},
|
|
26576
26913
|
{
|
|
26577
|
-
path:
|
|
26914
|
+
path: path50.join(os27.homedir(), ".cursor", "mcp.json"),
|
|
26578
26915
|
label: "Cursor (~/.cursor/mcp.json)"
|
|
26579
26916
|
},
|
|
26580
26917
|
{
|
|
26581
|
-
path:
|
|
26918
|
+
path: path50.join(os27.homedir(), ".codeium", "windsurf", "mcp_config.json"),
|
|
26582
26919
|
label: "Windsurf (~/.codeium/windsurf/mcp_config.json)"
|
|
26583
26920
|
}
|
|
26584
26921
|
];
|
|
26585
26922
|
const resolvedRepoPaths = repoPaths ?? getOlamRepoPaths();
|
|
26586
26923
|
for (const repoPath of resolvedRepoPaths) {
|
|
26587
26924
|
sourceDefs.push({
|
|
26588
|
-
path:
|
|
26589
|
-
label: `.mcp.json (${
|
|
26925
|
+
path: path50.join(repoPath, ".mcp.json"),
|
|
26926
|
+
label: `.mcp.json (${path50.basename(repoPath)})`
|
|
26590
26927
|
});
|
|
26591
26928
|
}
|
|
26592
26929
|
const reads = await Promise.all(
|
|
@@ -26616,7 +26953,7 @@ async function discoverMcpSources(repoPaths) {
|
|
|
26616
26953
|
}
|
|
26617
26954
|
|
|
26618
26955
|
// src/commands/mcp/import-validate.ts
|
|
26619
|
-
import { spawn as
|
|
26956
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
26620
26957
|
var VALIDATION_TIMEOUT_MS = 5e3;
|
|
26621
26958
|
async function validateMcpEntry(entry) {
|
|
26622
26959
|
return new Promise((resolve11) => {
|
|
@@ -26624,7 +26961,7 @@ async function validateMcpEntry(entry) {
|
|
|
26624
26961
|
let timedOut = false;
|
|
26625
26962
|
let child;
|
|
26626
26963
|
try {
|
|
26627
|
-
child =
|
|
26964
|
+
child = spawn7(entry.command, [...entry.args ?? []], {
|
|
26628
26965
|
stdio: ["ignore", "pipe", "ignore"],
|
|
26629
26966
|
env: { ...process.env, ...entry.env ?? {} }
|
|
26630
26967
|
});
|
|
@@ -26818,10 +27155,10 @@ function registerMcp(program2) {
|
|
|
26818
27155
|
// src/commands/kg-build.ts
|
|
26819
27156
|
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
26820
27157
|
import fs48 from "node:fs";
|
|
26821
|
-
import
|
|
27158
|
+
import path53 from "node:path";
|
|
26822
27159
|
|
|
26823
27160
|
// ../core/dist/kg/storage-paths.js
|
|
26824
|
-
import { homedir as
|
|
27161
|
+
import { homedir as homedir28 } from "node:os";
|
|
26825
27162
|
import { join as join48, resolve as resolve10 } from "node:path";
|
|
26826
27163
|
|
|
26827
27164
|
// ../core/dist/world/workspace-name.js
|
|
@@ -26843,7 +27180,7 @@ function validateWorkspaceName(name) {
|
|
|
26843
27180
|
|
|
26844
27181
|
// ../core/dist/kg/storage-paths.js
|
|
26845
27182
|
function olamHome3() {
|
|
26846
|
-
return process.env.OLAM_HOME ?? join48(
|
|
27183
|
+
return process.env.OLAM_HOME ?? join48(homedir28(), ".olam");
|
|
26847
27184
|
}
|
|
26848
27185
|
function kgRoot() {
|
|
26849
27186
|
return join48(olamHome3(), "kg");
|
|
@@ -26851,17 +27188,17 @@ function kgRoot() {
|
|
|
26851
27188
|
function worldsRoot() {
|
|
26852
27189
|
return join48(olamHome3(), "worlds");
|
|
26853
27190
|
}
|
|
26854
|
-
function assertWithinPrefix(
|
|
26855
|
-
if (!
|
|
26856
|
-
throw new Error(`${label} escape: ${
|
|
27191
|
+
function assertWithinPrefix(path55, prefix, label) {
|
|
27192
|
+
if (!path55.startsWith(prefix + "/")) {
|
|
27193
|
+
throw new Error(`${label} escape: ${path55} not under ${prefix}/`);
|
|
26857
27194
|
}
|
|
26858
27195
|
}
|
|
26859
27196
|
function kgPristinePath(workspace) {
|
|
26860
27197
|
validateWorkspaceName(workspace);
|
|
26861
27198
|
const root = kgRoot();
|
|
26862
|
-
const
|
|
26863
|
-
assertWithinPrefix(
|
|
26864
|
-
return
|
|
27199
|
+
const path55 = resolve10(join48(root, workspace));
|
|
27200
|
+
assertWithinPrefix(path55, root, "kgPristinePath");
|
|
27201
|
+
return path55;
|
|
26865
27202
|
}
|
|
26866
27203
|
var KG_PATHS_INTERNALS = Object.freeze({
|
|
26867
27204
|
olamHome: olamHome3,
|
|
@@ -26874,17 +27211,17 @@ init_output();
|
|
|
26874
27211
|
|
|
26875
27212
|
// src/commands/kg-status.ts
|
|
26876
27213
|
import fs46 from "node:fs";
|
|
26877
|
-
import { homedir as
|
|
26878
|
-
import
|
|
27214
|
+
import { homedir as homedir29 } from "node:os";
|
|
27215
|
+
import path51 from "node:path";
|
|
26879
27216
|
init_output();
|
|
26880
27217
|
function olamHome4() {
|
|
26881
|
-
return process.env.OLAM_HOME ??
|
|
27218
|
+
return process.env.OLAM_HOME ?? path51.join(homedir29(), ".olam");
|
|
26882
27219
|
}
|
|
26883
27220
|
function kgRoot2() {
|
|
26884
|
-
return
|
|
27221
|
+
return path51.join(olamHome4(), "kg");
|
|
26885
27222
|
}
|
|
26886
27223
|
function worldsRoot2() {
|
|
26887
|
-
return
|
|
27224
|
+
return path51.join(olamHome4(), "worlds");
|
|
26888
27225
|
}
|
|
26889
27226
|
function dirSizeBytes2(dir) {
|
|
26890
27227
|
if (!fs46.existsSync(dir)) return 0;
|
|
@@ -26899,7 +27236,7 @@ function dirSizeBytes2(dir) {
|
|
|
26899
27236
|
continue;
|
|
26900
27237
|
}
|
|
26901
27238
|
for (const entry of entries) {
|
|
26902
|
-
const full =
|
|
27239
|
+
const full = path51.join(cur, entry.name);
|
|
26903
27240
|
if (entry.isSymbolicLink()) continue;
|
|
26904
27241
|
if (entry.isDirectory()) {
|
|
26905
27242
|
stack.push(full);
|
|
@@ -26920,7 +27257,7 @@ function formatBytes5(n) {
|
|
|
26920
27257
|
return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
26921
27258
|
}
|
|
26922
27259
|
function readFreshness(workspace) {
|
|
26923
|
-
const file =
|
|
27260
|
+
const file = path51.join(kgPristinePath(workspace), "freshness.json");
|
|
26924
27261
|
if (!fs46.existsSync(file)) return null;
|
|
26925
27262
|
try {
|
|
26926
27263
|
const raw = JSON.parse(fs46.readFileSync(file, "utf-8"));
|
|
@@ -26931,7 +27268,7 @@ function readFreshness(workspace) {
|
|
|
26931
27268
|
}
|
|
26932
27269
|
}
|
|
26933
27270
|
function readOverlayNodeCount(graphifyOutDir) {
|
|
26934
|
-
const graphPath =
|
|
27271
|
+
const graphPath = path51.join(graphifyOutDir, "graph.json");
|
|
26935
27272
|
if (!fs46.existsSync(graphPath)) return null;
|
|
26936
27273
|
try {
|
|
26937
27274
|
const raw = JSON.parse(fs46.readFileSync(graphPath, "utf-8"));
|
|
@@ -26957,7 +27294,7 @@ function listOverlays() {
|
|
|
26957
27294
|
for (const worldEntry of worldDirs) {
|
|
26958
27295
|
if (!worldEntry.isDirectory()) continue;
|
|
26959
27296
|
const worldId = worldEntry.name;
|
|
26960
|
-
const worldDir =
|
|
27297
|
+
const worldDir = path51.join(root, worldId);
|
|
26961
27298
|
let cloneDirs;
|
|
26962
27299
|
try {
|
|
26963
27300
|
cloneDirs = fs46.readdirSync(worldDir, { withFileTypes: true });
|
|
@@ -26966,7 +27303,7 @@ function listOverlays() {
|
|
|
26966
27303
|
}
|
|
26967
27304
|
for (const cloneEntry of cloneDirs) {
|
|
26968
27305
|
if (!cloneEntry.isDirectory()) continue;
|
|
26969
|
-
const graphifyOut =
|
|
27306
|
+
const graphifyOut = path51.join(worldDir, cloneEntry.name, "graphify-out");
|
|
26970
27307
|
if (!fs46.existsSync(graphifyOut)) continue;
|
|
26971
27308
|
records.push({
|
|
26972
27309
|
world_id: worldId,
|
|
@@ -26998,7 +27335,7 @@ function listPristines(overlays) {
|
|
|
26998
27335
|
continue;
|
|
26999
27336
|
}
|
|
27000
27337
|
const fresh = readFreshness(workspace);
|
|
27001
|
-
const graphifyOut =
|
|
27338
|
+
const graphifyOut = path51.join(kgPristinePath(workspace), "graphify-out");
|
|
27002
27339
|
const size = dirSizeBytes2(graphifyOut);
|
|
27003
27340
|
const worldCount = overlays.filter((o) => o.clone_dir === workspace).length;
|
|
27004
27341
|
records.push({
|
|
@@ -27130,12 +27467,12 @@ function registerKgStatusCommand(kg) {
|
|
|
27130
27467
|
}
|
|
27131
27468
|
|
|
27132
27469
|
// src/commands/kg-watch.ts
|
|
27133
|
-
import { spawn as
|
|
27470
|
+
import { spawn as spawn8 } from "node:child_process";
|
|
27134
27471
|
import fs47 from "node:fs";
|
|
27135
|
-
import
|
|
27472
|
+
import path52 from "node:path";
|
|
27136
27473
|
init_output();
|
|
27137
27474
|
function pidFilePath(workspace) {
|
|
27138
|
-
return
|
|
27475
|
+
return path52.join(kgPristinePath(workspace), ".watch.pid");
|
|
27139
27476
|
}
|
|
27140
27477
|
function isPidAlive3(pid) {
|
|
27141
27478
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
@@ -27169,7 +27506,7 @@ function readAndClassifyPid(workspace) {
|
|
|
27169
27506
|
}
|
|
27170
27507
|
function writePidFile(workspace, pid) {
|
|
27171
27508
|
const file = pidFilePath(workspace);
|
|
27172
|
-
const dir =
|
|
27509
|
+
const dir = path52.dirname(file);
|
|
27173
27510
|
fs47.mkdirSync(dir, { recursive: true });
|
|
27174
27511
|
fs47.writeFileSync(file, String(pid), { encoding: "utf-8" });
|
|
27175
27512
|
}
|
|
@@ -27182,7 +27519,7 @@ function removePidFile(workspace) {
|
|
|
27182
27519
|
}
|
|
27183
27520
|
async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
27184
27521
|
const cwd = deps.cwd ?? opts.cwd ?? process.cwd();
|
|
27185
|
-
const name = workspaceArg ??
|
|
27522
|
+
const name = workspaceArg ?? path52.basename(cwd).toLowerCase();
|
|
27186
27523
|
try {
|
|
27187
27524
|
validateWorkspaceName(name);
|
|
27188
27525
|
} catch (err) {
|
|
@@ -27190,7 +27527,7 @@ async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
|
27190
27527
|
return { exitCode: 1, pidWritten: false };
|
|
27191
27528
|
}
|
|
27192
27529
|
const pristinePath = kgPristinePath(name);
|
|
27193
|
-
const graphPath =
|
|
27530
|
+
const graphPath = path52.join(pristinePath, "graphify-out", "graph.json");
|
|
27194
27531
|
const pidState = readAndClassifyPid(name);
|
|
27195
27532
|
if (pidState.status === "active") {
|
|
27196
27533
|
printError(
|
|
@@ -27201,7 +27538,7 @@ async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
|
27201
27538
|
if (pidState.status === "stale-reclaimed") {
|
|
27202
27539
|
printInfo("stale-pid", `reclaimed dead PID file at ${pidFilePath(name)}`);
|
|
27203
27540
|
}
|
|
27204
|
-
const spawnFn = deps.spawnImpl ??
|
|
27541
|
+
const spawnFn = deps.spawnImpl ?? spawn8;
|
|
27205
27542
|
const child = spawnFn(
|
|
27206
27543
|
"graphify",
|
|
27207
27544
|
[cwd, "--watch", "--update", "--graph", graphPath],
|
|
@@ -27256,7 +27593,7 @@ function registerKgWatchCommand(kg) {
|
|
|
27256
27593
|
var DEFAULT_DEVBOX_IMAGE2 = "olam-devbox:latest";
|
|
27257
27594
|
function resolveWorkspace(arg) {
|
|
27258
27595
|
const cwd = process.cwd();
|
|
27259
|
-
const name = arg ??
|
|
27596
|
+
const name = arg ?? path53.basename(cwd).toLowerCase();
|
|
27260
27597
|
validateWorkspaceName(name);
|
|
27261
27598
|
return { name, sourcePath: cwd };
|
|
27262
27599
|
}
|
|
@@ -27278,7 +27615,7 @@ function copyWorkspaceToScratch(source, scratch) {
|
|
|
27278
27615
|
return "cp-r";
|
|
27279
27616
|
}
|
|
27280
27617
|
function parseNodeCount(graphifyOutDir) {
|
|
27281
|
-
const graphPath =
|
|
27618
|
+
const graphPath = path53.join(graphifyOutDir, "graph.json");
|
|
27282
27619
|
if (!fs48.existsSync(graphPath)) return null;
|
|
27283
27620
|
try {
|
|
27284
27621
|
const content = fs48.readFileSync(graphPath, "utf-8");
|
|
@@ -27315,7 +27652,7 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
27315
27652
|
return { exitCode: 2 };
|
|
27316
27653
|
}
|
|
27317
27654
|
const outDir = kgPristinePath(workspace.name);
|
|
27318
|
-
const scratchDir =
|
|
27655
|
+
const scratchDir = path53.join(outDir, "scratch");
|
|
27319
27656
|
fs48.mkdirSync(outDir, { recursive: true });
|
|
27320
27657
|
if (fs48.existsSync(scratchDir)) fs48.rmSync(scratchDir, { recursive: true, force: true });
|
|
27321
27658
|
fs48.mkdirSync(scratchDir);
|
|
@@ -27346,8 +27683,8 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
27346
27683
|
printError(`graphify update failed (exit ${r.status})`);
|
|
27347
27684
|
return { exitCode: r.status ?? 1 };
|
|
27348
27685
|
}
|
|
27349
|
-
const scratchOut =
|
|
27350
|
-
const finalOut =
|
|
27686
|
+
const scratchOut = path53.join(scratchDir, "graphify-out");
|
|
27687
|
+
const finalOut = path53.join(outDir, "graphify-out");
|
|
27351
27688
|
if (!fs48.existsSync(scratchOut)) {
|
|
27352
27689
|
printError(`graphify produced no graphify-out/ in scratch (${scratchOut})`);
|
|
27353
27690
|
return { exitCode: 1 };
|
|
@@ -27366,7 +27703,7 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
27366
27703
|
scratch_strategy: scratchStrategy
|
|
27367
27704
|
};
|
|
27368
27705
|
fs48.writeFileSync(
|
|
27369
|
-
|
|
27706
|
+
path53.join(outDir, "freshness.json"),
|
|
27370
27707
|
JSON.stringify(freshness, null, 2) + "\n",
|
|
27371
27708
|
"utf-8"
|
|
27372
27709
|
);
|
|
@@ -27399,12 +27736,12 @@ function registerKg(program2) {
|
|
|
27399
27736
|
|
|
27400
27737
|
// src/pleri-config.ts
|
|
27401
27738
|
import * as fs49 from "node:fs";
|
|
27402
|
-
import * as
|
|
27739
|
+
import * as path54 from "node:path";
|
|
27403
27740
|
function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
27404
27741
|
if (process.env.PLERI_BASE_URL) {
|
|
27405
27742
|
return true;
|
|
27406
27743
|
}
|
|
27407
|
-
const configPath =
|
|
27744
|
+
const configPath = path54.join(configDir, "config.yaml");
|
|
27408
27745
|
if (!fs49.existsSync(configPath)) {
|
|
27409
27746
|
return false;
|
|
27410
27747
|
}
|
|
@@ -27448,6 +27785,7 @@ registerBootstrap(program);
|
|
|
27448
27785
|
registerDiagnose(program);
|
|
27449
27786
|
registerDoctor(program);
|
|
27450
27787
|
registerCompletion(program);
|
|
27788
|
+
registerSetup(program);
|
|
27451
27789
|
registerUpdate(program);
|
|
27452
27790
|
registerBegin(program);
|
|
27453
27791
|
registerStop(program);
|