@pleri/olam-cli 0.1.111 → 0.1.113
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/mcp/index.d.ts +6 -3
- package/dist/commands/mcp/index.d.ts.map +1 -1
- package/dist/commands/mcp/index.js +13 -4
- package/dist/commands/mcp/index.js.map +1 -1
- package/dist/commands/mcp/install-shared.d.ts +22 -0
- package/dist/commands/mcp/install-shared.d.ts.map +1 -0
- package/dist/commands/mcp/install-shared.js +29 -0
- package/dist/commands/mcp/install-shared.js.map +1 -0
- package/dist/commands/mcp/install.d.ts +20 -0
- package/dist/commands/mcp/install.d.ts.map +1 -0
- package/dist/commands/mcp/install.js +59 -0
- package/dist/commands/mcp/install.js.map +1 -0
- package/dist/commands/mcp/serve.d.ts +12 -0
- package/dist/commands/mcp/serve.d.ts.map +1 -0
- package/dist/commands/mcp/serve.js +36 -0
- package/dist/commands/mcp/serve.js.map +1 -0
- package/dist/commands/mcp/uninstall.d.ts +20 -0
- package/dist/commands/mcp/uninstall.d.ts.map +1 -0
- package/dist/commands/mcp/uninstall.js +69 -0
- package/dist/commands/mcp/uninstall.js.map +1 -0
- package/dist/image-digests.json +4 -4
- package/dist/index.js +345 -144
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.js +107 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21,11 +21,11 @@ import * as path from "node:path";
|
|
|
21
21
|
import { fileURLToPath } from "node:url";
|
|
22
22
|
function readCliVersion() {
|
|
23
23
|
try {
|
|
24
|
-
const
|
|
24
|
+
const here2 = path.dirname(fileURLToPath(import.meta.url));
|
|
25
25
|
for (const candidate of [
|
|
26
|
-
path.join(
|
|
27
|
-
path.join(
|
|
28
|
-
path.join(
|
|
26
|
+
path.join(here2, "package.json"),
|
|
27
|
+
path.join(here2, "..", "package.json"),
|
|
28
|
+
path.join(here2, "..", "..", "package.json")
|
|
29
29
|
]) {
|
|
30
30
|
if (fs.existsSync(candidate)) {
|
|
31
31
|
const pkg = JSON.parse(fs.readFileSync(candidate, "utf-8"));
|
|
@@ -5198,7 +5198,7 @@ async function safeText(res) {
|
|
|
5198
5198
|
}
|
|
5199
5199
|
}
|
|
5200
5200
|
function sleep(ms) {
|
|
5201
|
-
return new Promise((
|
|
5201
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
5202
5202
|
}
|
|
5203
5203
|
var DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, RETRY_COUNT, RETRY_BACKOFF_MS, AuthClient;
|
|
5204
5204
|
var init_client = __esm({
|
|
@@ -5345,12 +5345,12 @@ import { existsSync as existsSync9 } from "node:fs";
|
|
|
5345
5345
|
import * as path9 from "node:path";
|
|
5346
5346
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
5347
5347
|
function resolveAuthServicePath() {
|
|
5348
|
-
const
|
|
5349
|
-
const pkgsDir = path9.resolve(path9.dirname(
|
|
5348
|
+
const here2 = fileURLToPath2(import.meta.url);
|
|
5349
|
+
const pkgsDir = path9.resolve(path9.dirname(here2), "..", "..", "..");
|
|
5350
5350
|
return path9.join(pkgsDir, "auth-service");
|
|
5351
5351
|
}
|
|
5352
5352
|
function sleep2(ms) {
|
|
5353
|
-
return new Promise((
|
|
5353
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
5354
5354
|
}
|
|
5355
5355
|
var DEFAULT_PORT, DEFAULT_VOLUME, DEFAULT_CONTAINER, DEFAULT_IMAGE, AuthContainerController;
|
|
5356
5356
|
var init_container = __esm({
|
|
@@ -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((resolve12) => {
|
|
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
|
+
resolve12({ exitCode: -1, stdout, stderr: stderr + err.message });
|
|
5666
|
+
});
|
|
5667
|
+
child.on("close", (code) => {
|
|
5668
|
+
resolve12({ 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,
|
|
@@ -5951,7 +6050,7 @@ var demuxStream, execInContainer;
|
|
|
5951
6050
|
var init_exec = __esm({
|
|
5952
6051
|
"../adapters/dist/docker/exec.js"() {
|
|
5953
6052
|
"use strict";
|
|
5954
|
-
demuxStream = (stream) => new Promise((
|
|
6053
|
+
demuxStream = (stream) => new Promise((resolve12, reject) => {
|
|
5955
6054
|
const stdoutChunks = [];
|
|
5956
6055
|
const stderrChunks = [];
|
|
5957
6056
|
const stdout = new PassThrough();
|
|
@@ -5965,7 +6064,7 @@ var init_exec = __esm({
|
|
|
5965
6064
|
stream.pipe(stdout);
|
|
5966
6065
|
}
|
|
5967
6066
|
stream.on("end", () => {
|
|
5968
|
-
|
|
6067
|
+
resolve12({
|
|
5969
6068
|
stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
|
|
5970
6069
|
stderr: Buffer.concat(stderrChunks).toString("utf-8")
|
|
5971
6070
|
});
|
|
@@ -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",
|
|
@@ -6389,7 +6496,7 @@ var init_connection = __esm({
|
|
|
6389
6496
|
// -----------------------------------------------------------------------
|
|
6390
6497
|
async exec(host, command) {
|
|
6391
6498
|
const client = await this.getConnection(host);
|
|
6392
|
-
return new Promise((
|
|
6499
|
+
return new Promise((resolve12, reject) => {
|
|
6393
6500
|
client.exec(command, (err, stream) => {
|
|
6394
6501
|
if (err) {
|
|
6395
6502
|
reject(new Error(`SSH exec failed on ${host}: ${err.message}`));
|
|
@@ -6404,7 +6511,7 @@ var init_connection = __esm({
|
|
|
6404
6511
|
stderr += data.toString();
|
|
6405
6512
|
});
|
|
6406
6513
|
stream.on("close", (code) => {
|
|
6407
|
-
|
|
6514
|
+
resolve12({
|
|
6408
6515
|
exitCode: code ?? 0,
|
|
6409
6516
|
stdout: stdout.trimEnd(),
|
|
6410
6517
|
stderr: stderr.trimEnd()
|
|
@@ -6435,10 +6542,10 @@ var init_connection = __esm({
|
|
|
6435
6542
|
throw new Error(`No SSH configuration found for host: ${host}`);
|
|
6436
6543
|
}
|
|
6437
6544
|
const client = new SSHClient();
|
|
6438
|
-
return new Promise((
|
|
6545
|
+
return new Promise((resolve12, reject) => {
|
|
6439
6546
|
client.on("ready", () => {
|
|
6440
6547
|
this.connections.set(host, client);
|
|
6441
|
-
|
|
6548
|
+
resolve12(client);
|
|
6442
6549
|
}).on("error", (err) => {
|
|
6443
6550
|
this.connections.delete(host);
|
|
6444
6551
|
reject(new Error(`SSH connection to ${host} failed: ${err.message}`));
|
|
@@ -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
|
}
|
|
@@ -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" });
|
|
@@ -12976,8 +13086,8 @@ function isCloudflaredAvailable() {
|
|
|
12976
13086
|
}
|
|
12977
13087
|
}
|
|
12978
13088
|
function startTunnel(port) {
|
|
12979
|
-
return new Promise((
|
|
12980
|
-
const child =
|
|
13089
|
+
return new Promise((resolve12, reject) => {
|
|
13090
|
+
const child = spawn3("cloudflared", ["tunnel", "--url", `http://localhost:${port}`], {
|
|
12981
13091
|
stdio: ["ignore", "pipe", "pipe"],
|
|
12982
13092
|
detached: false
|
|
12983
13093
|
});
|
|
@@ -12998,7 +13108,7 @@ function startTunnel(port) {
|
|
|
12998
13108
|
if (match2) {
|
|
12999
13109
|
resolved = true;
|
|
13000
13110
|
clearTimeout(timeout);
|
|
13001
|
-
|
|
13111
|
+
resolve12(match2[0]);
|
|
13002
13112
|
}
|
|
13003
13113
|
}
|
|
13004
13114
|
child.stdout?.on("data", scan);
|
|
@@ -13085,8 +13195,8 @@ var init_dashboard = __esm({
|
|
|
13085
13195
|
}
|
|
13086
13196
|
throw err;
|
|
13087
13197
|
}
|
|
13088
|
-
await new Promise((
|
|
13089
|
-
this.server.on("listening",
|
|
13198
|
+
await new Promise((resolve12, reject) => {
|
|
13199
|
+
this.server.on("listening", resolve12);
|
|
13090
13200
|
this.server.on("error", reject);
|
|
13091
13201
|
});
|
|
13092
13202
|
this.info = { localUrl: `http://localhost:${port}` };
|
|
@@ -13132,8 +13242,8 @@ var init_dashboard = __esm({
|
|
|
13132
13242
|
async stop() {
|
|
13133
13243
|
stopTunnel();
|
|
13134
13244
|
if (this.server) {
|
|
13135
|
-
await new Promise((
|
|
13136
|
-
this.server.close(() =>
|
|
13245
|
+
await new Promise((resolve12) => {
|
|
13246
|
+
this.server.close(() => resolve12());
|
|
13137
13247
|
});
|
|
13138
13248
|
this.server = null;
|
|
13139
13249
|
}
|
|
@@ -13955,8 +14065,8 @@ import { existsSync as existsSync23 } from "node:fs";
|
|
|
13955
14065
|
import { dirname as dirname17, join as join28, resolve as resolve8 } from "node:path";
|
|
13956
14066
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
13957
14067
|
function installRoot(metaUrl = import.meta.url) {
|
|
13958
|
-
const
|
|
13959
|
-
return resolve8(dirname17(
|
|
14068
|
+
const here2 = fileURLToPath5(metaUrl);
|
|
14069
|
+
return resolve8(dirname17(here2), "..");
|
|
13960
14070
|
}
|
|
13961
14071
|
function isDevMode(env = process.env, installRootDir = installRoot()) {
|
|
13962
14072
|
if (env.OLAM_DEV !== "1") return false;
|
|
@@ -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",
|
|
@@ -15361,10 +15396,10 @@ async function confirm(message) {
|
|
|
15361
15396
|
if (!process.stdin.isTTY) return true;
|
|
15362
15397
|
const { createInterface: createInterface6 } = await import("node:readline");
|
|
15363
15398
|
const rl = createInterface6({ input: process.stdin, output: process.stdout });
|
|
15364
|
-
return new Promise((
|
|
15399
|
+
return new Promise((resolve12) => {
|
|
15365
15400
|
rl.question(`${message} [y/N] `, (answer) => {
|
|
15366
15401
|
rl.close();
|
|
15367
|
-
|
|
15402
|
+
resolve12(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
15368
15403
|
});
|
|
15369
15404
|
});
|
|
15370
15405
|
}
|
|
@@ -15738,7 +15773,7 @@ var McpAuthContainerController = class {
|
|
|
15738
15773
|
}
|
|
15739
15774
|
};
|
|
15740
15775
|
function sleep3(ms) {
|
|
15741
|
-
return new Promise((
|
|
15776
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
15742
15777
|
}
|
|
15743
15778
|
function dumpContainerLogs(container, tail = 40) {
|
|
15744
15779
|
try {
|
|
@@ -17298,14 +17333,14 @@ function printTable(entries) {
|
|
|
17298
17333
|
async function confirmInteractive() {
|
|
17299
17334
|
process.stdout.write(" Type `yes` to proceed: ");
|
|
17300
17335
|
const buf = [];
|
|
17301
|
-
return new Promise((
|
|
17336
|
+
return new Promise((resolve12) => {
|
|
17302
17337
|
const onData = (chunk) => {
|
|
17303
17338
|
buf.push(chunk);
|
|
17304
17339
|
if (Buffer.concat(buf).toString("utf-8").includes("\n")) {
|
|
17305
17340
|
process.stdin.removeListener("data", onData);
|
|
17306
17341
|
process.stdin.pause();
|
|
17307
17342
|
const answer = Buffer.concat(buf).toString("utf-8").trim();
|
|
17308
|
-
|
|
17343
|
+
resolve12(answer.toLowerCase() === "yes");
|
|
17309
17344
|
}
|
|
17310
17345
|
};
|
|
17311
17346
|
process.stdin.resume();
|
|
@@ -23020,10 +23055,10 @@ async function confirm2(message) {
|
|
|
23020
23055
|
if (!process.stdin.isTTY) return true;
|
|
23021
23056
|
const { createInterface: createInterface6 } = await import("node:readline");
|
|
23022
23057
|
const rl = createInterface6({ input: process.stdin, output: process.stdout });
|
|
23023
|
-
return new Promise((
|
|
23058
|
+
return new Promise((resolve12) => {
|
|
23024
23059
|
rl.question(`${message} [y/N] `, (answer) => {
|
|
23025
23060
|
rl.close();
|
|
23026
|
-
|
|
23061
|
+
resolve12(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
23027
23062
|
});
|
|
23028
23063
|
});
|
|
23029
23064
|
}
|
|
@@ -25540,10 +25575,10 @@ var NEXT_STEPS_DOCS = [
|
|
|
25540
25575
|
"docs/architecture/manifest-spec.md \u2014 per-repo .adb.yaml schema",
|
|
25541
25576
|
"docs/architecture/config-spec.md \u2014 workspace .olam/config.yaml schema"
|
|
25542
25577
|
];
|
|
25543
|
-
var defaultSpawn = (cmd, args) => new Promise((
|
|
25578
|
+
var defaultSpawn = (cmd, args) => new Promise((resolve12) => {
|
|
25544
25579
|
const child = spawn5(cmd, [...args], { stdio: "inherit" });
|
|
25545
|
-
child.on("exit", (code) =>
|
|
25546
|
-
child.on("error", () =>
|
|
25580
|
+
child.on("exit", (code) => resolve12({ status: code }));
|
|
25581
|
+
child.on("error", () => resolve12({ status: 1 }));
|
|
25547
25582
|
});
|
|
25548
25583
|
var defaultPrompt = (question, defaultYes) => {
|
|
25549
25584
|
if (!process.stdin.isTTY) {
|
|
@@ -25553,18 +25588,18 @@ var defaultPrompt = (question, defaultYes) => {
|
|
|
25553
25588
|
);
|
|
25554
25589
|
return Promise.resolve(defaultYes);
|
|
25555
25590
|
}
|
|
25556
|
-
return new Promise((
|
|
25591
|
+
return new Promise((resolve12) => {
|
|
25557
25592
|
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
25558
25593
|
const suffix = defaultYes ? " [Y/n]: " : " [y/N]: ";
|
|
25559
25594
|
rl.question(`${question}${suffix}`, (answer) => {
|
|
25560
25595
|
rl.close();
|
|
25561
25596
|
const t = answer.trim().toLowerCase();
|
|
25562
|
-
if (t === "")
|
|
25563
|
-
else if (t === "y" || t === "yes")
|
|
25564
|
-
else if (t === "n" || t === "no")
|
|
25565
|
-
else
|
|
25597
|
+
if (t === "") resolve12(defaultYes);
|
|
25598
|
+
else if (t === "y" || t === "yes") resolve12(true);
|
|
25599
|
+
else if (t === "n" || t === "no") resolve12(false);
|
|
25600
|
+
else resolve12(defaultYes);
|
|
25566
25601
|
});
|
|
25567
|
-
rl.on("close", () =>
|
|
25602
|
+
rl.on("close", () => resolve12(defaultYes));
|
|
25568
25603
|
});
|
|
25569
25604
|
};
|
|
25570
25605
|
async function phase1SystemCheck(deps) {
|
|
@@ -26531,6 +26566,157 @@ function registerWorldUpgrade(program2) {
|
|
|
26531
26566
|
});
|
|
26532
26567
|
}
|
|
26533
26568
|
|
|
26569
|
+
// src/commands/mcp/serve.ts
|
|
26570
|
+
init_output();
|
|
26571
|
+
import { existsSync as existsSync50 } from "node:fs";
|
|
26572
|
+
import { dirname as dirname25, resolve as resolve10 } from "node:path";
|
|
26573
|
+
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
26574
|
+
var here = dirname25(fileURLToPath6(import.meta.url));
|
|
26575
|
+
var BUNDLE_PATH = resolve10(here, "..", "..", "mcp-server.js");
|
|
26576
|
+
var MISSING_BUNDLE_REMEDY = "olam mcp server bundle missing at dist/mcp-server.js. For local dev, run: node packages/cli/scripts/bundle-mcp-server.mjs. Published @pleri/olam-cli tarballs always include this bundle (per prepublishOnly).";
|
|
26577
|
+
function registerMcpServe(cmd) {
|
|
26578
|
+
cmd.command("serve").description(
|
|
26579
|
+
"Run the olam MCP server (stdio transport). Claude Code wires this via `claude mcp add olam --scope user -- npx -y @pleri/olam-cli mcp serve`."
|
|
26580
|
+
).action(async () => {
|
|
26581
|
+
if (!existsSync50(BUNDLE_PATH)) {
|
|
26582
|
+
printError(MISSING_BUNDLE_REMEDY);
|
|
26583
|
+
process.exitCode = 1;
|
|
26584
|
+
return;
|
|
26585
|
+
}
|
|
26586
|
+
await import(BUNDLE_PATH);
|
|
26587
|
+
});
|
|
26588
|
+
}
|
|
26589
|
+
|
|
26590
|
+
// src/commands/mcp/install.ts
|
|
26591
|
+
init_output();
|
|
26592
|
+
|
|
26593
|
+
// src/commands/mcp/install-shared.ts
|
|
26594
|
+
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
26595
|
+
var DEFAULT_CLAUDE_SHELL_DEPS = {
|
|
26596
|
+
spawn: spawnSync15,
|
|
26597
|
+
log: (msg) => console.log(msg)
|
|
26598
|
+
};
|
|
26599
|
+
function isOnPath(deps, bin) {
|
|
26600
|
+
const probe = process.platform === "win32" ? "where" : "which";
|
|
26601
|
+
const result = deps.spawn(probe, [bin], {
|
|
26602
|
+
encoding: "utf8",
|
|
26603
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
26604
|
+
});
|
|
26605
|
+
return result.status === 0;
|
|
26606
|
+
}
|
|
26607
|
+
function normaliseScope(raw) {
|
|
26608
|
+
const value = (raw ?? "user").toLowerCase();
|
|
26609
|
+
return value === "user" || value === "project" || value === "local" ? value : null;
|
|
26610
|
+
}
|
|
26611
|
+
var REMEDY_CLAUDE_MISSING = "`claude` not found on PATH. Install Claude Code (https://docs.claude.com/claude-code) or paste the JSON snippet from docs/architecture/mcp-as-npx-served.md.";
|
|
26612
|
+
|
|
26613
|
+
// src/commands/mcp/install.ts
|
|
26614
|
+
var NPM_PACKAGE_NAME = "@pleri/olam-cli";
|
|
26615
|
+
function buildClaudeMcpAddArgs(scope, useGlobal) {
|
|
26616
|
+
const target = useGlobal ? { cmd: "olam", args: ["mcp", "serve"] } : { cmd: "npx", args: ["-y", NPM_PACKAGE_NAME, "mcp", "serve"] };
|
|
26617
|
+
return {
|
|
26618
|
+
command: "claude",
|
|
26619
|
+
args: ["mcp", "add", "olam", "--scope", scope, "--", target.cmd, ...target.args]
|
|
26620
|
+
};
|
|
26621
|
+
}
|
|
26622
|
+
async function runInstall(opts, deps = DEFAULT_CLAUDE_SHELL_DEPS) {
|
|
26623
|
+
if (!isOnPath(deps, "claude")) {
|
|
26624
|
+
printError(REMEDY_CLAUDE_MISSING);
|
|
26625
|
+
return 1;
|
|
26626
|
+
}
|
|
26627
|
+
const useGlobal = isOnPath(deps, "olam");
|
|
26628
|
+
const { command, args } = buildClaudeMcpAddArgs(opts.scope, useGlobal);
|
|
26629
|
+
deps.log(`Wiring: ${command} ${args.join(" ")}`);
|
|
26630
|
+
const result = deps.spawn(command, args, {
|
|
26631
|
+
encoding: "utf8",
|
|
26632
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
26633
|
+
});
|
|
26634
|
+
if (result.status !== 0) {
|
|
26635
|
+
const detail = result.stderr?.trim() || result.stdout?.trim() || "(no output)";
|
|
26636
|
+
printError(`claude mcp add failed (rc=${result.status ?? "unknown"}): ${detail}`);
|
|
26637
|
+
return result.status ?? 1;
|
|
26638
|
+
}
|
|
26639
|
+
printSuccess(
|
|
26640
|
+
`olam MCP registered with claude (--scope ${opts.scope}; command: ${useGlobal ? "olam" : "npx"}).`
|
|
26641
|
+
);
|
|
26642
|
+
return 0;
|
|
26643
|
+
}
|
|
26644
|
+
function registerMcpInstall(cmd) {
|
|
26645
|
+
cmd.command("install").description(
|
|
26646
|
+
"Add olam to Claude Code as an MCP server (auto-detects whether `olam` is on PATH; shells to `claude mcp add`)"
|
|
26647
|
+
).option("--scope <scope>", "claude mcp scope: user | project | local", "user").action(async (rawOpts) => {
|
|
26648
|
+
const scope = normaliseScope(rawOpts.scope);
|
|
26649
|
+
if (scope === null) {
|
|
26650
|
+
printError(`--scope must be one of: user, project, local (got: ${rawOpts.scope})`);
|
|
26651
|
+
process.exitCode = 1;
|
|
26652
|
+
return;
|
|
26653
|
+
}
|
|
26654
|
+
const rc = await runInstall({ scope });
|
|
26655
|
+
if (rc !== 0) {
|
|
26656
|
+
process.exitCode = rc;
|
|
26657
|
+
}
|
|
26658
|
+
});
|
|
26659
|
+
}
|
|
26660
|
+
|
|
26661
|
+
// src/commands/mcp/uninstall.ts
|
|
26662
|
+
init_output();
|
|
26663
|
+
var NOT_INSTALLED_PATTERN = /no\s+(?:\S+\s+)*mcp\s+server\s+found/i;
|
|
26664
|
+
function looksLikeNotInstalled(text) {
|
|
26665
|
+
return NOT_INSTALLED_PATTERN.test(text);
|
|
26666
|
+
}
|
|
26667
|
+
function buildClaudeMcpRemoveArgs(scope) {
|
|
26668
|
+
return {
|
|
26669
|
+
command: "claude",
|
|
26670
|
+
args: ["mcp", "remove", "olam", "--scope", scope]
|
|
26671
|
+
};
|
|
26672
|
+
}
|
|
26673
|
+
async function runUninstall(opts, deps = DEFAULT_CLAUDE_SHELL_DEPS) {
|
|
26674
|
+
if (!isOnPath(deps, "claude")) {
|
|
26675
|
+
printError(REMEDY_CLAUDE_MISSING);
|
|
26676
|
+
return 1;
|
|
26677
|
+
}
|
|
26678
|
+
const { command, args } = buildClaudeMcpRemoveArgs(opts.scope);
|
|
26679
|
+
deps.log(`Unwiring: ${command} ${args.join(" ")}`);
|
|
26680
|
+
const result = deps.spawn(command, args, {
|
|
26681
|
+
encoding: "utf8",
|
|
26682
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
26683
|
+
});
|
|
26684
|
+
if (result.status === 0) {
|
|
26685
|
+
printSuccess(`olam MCP removed from claude (--scope ${opts.scope}).`);
|
|
26686
|
+
return 0;
|
|
26687
|
+
}
|
|
26688
|
+
const stderr = result.stderr?.trim() ?? "";
|
|
26689
|
+
const stdout = result.stdout?.trim() ?? "";
|
|
26690
|
+
const combined = `${stderr}
|
|
26691
|
+
${stdout}`.trim();
|
|
26692
|
+
if (looksLikeNotInstalled(combined)) {
|
|
26693
|
+
printWarning(
|
|
26694
|
+
`olam MCP not registered with claude (--scope ${opts.scope}); nothing to remove.`
|
|
26695
|
+
);
|
|
26696
|
+
return 0;
|
|
26697
|
+
}
|
|
26698
|
+
printError(
|
|
26699
|
+
`claude mcp remove failed (rc=${result.status ?? "unknown"}): ${combined || "(no output)"}`
|
|
26700
|
+
);
|
|
26701
|
+
return result.status ?? 1;
|
|
26702
|
+
}
|
|
26703
|
+
function registerMcpUninstall(cmd) {
|
|
26704
|
+
cmd.command("uninstall").description(
|
|
26705
|
+
"Remove olam from Claude Code (symmetric with `install`; idempotent \u2014 exits 0 when olam is not registered)"
|
|
26706
|
+
).option("--scope <scope>", "claude mcp scope: user | project | local", "user").action(async (rawOpts) => {
|
|
26707
|
+
const scope = normaliseScope(rawOpts.scope);
|
|
26708
|
+
if (scope === null) {
|
|
26709
|
+
printError(`--scope must be one of: user, project, local (got: ${rawOpts.scope})`);
|
|
26710
|
+
process.exitCode = 1;
|
|
26711
|
+
return;
|
|
26712
|
+
}
|
|
26713
|
+
const rc = await runUninstall({ scope });
|
|
26714
|
+
if (rc !== 0) {
|
|
26715
|
+
process.exitCode = rc;
|
|
26716
|
+
}
|
|
26717
|
+
});
|
|
26718
|
+
}
|
|
26719
|
+
|
|
26534
26720
|
// src/commands/mcp/login.ts
|
|
26535
26721
|
init_output();
|
|
26536
26722
|
|
|
@@ -26628,7 +26814,7 @@ function registerMcpLogin(cmd) {
|
|
|
26628
26814
|
init_output();
|
|
26629
26815
|
import * as readline2 from "node:readline";
|
|
26630
26816
|
async function readTokenSilent(prompt) {
|
|
26631
|
-
return new Promise((
|
|
26817
|
+
return new Promise((resolve12, reject) => {
|
|
26632
26818
|
const rl = readline2.createInterface({
|
|
26633
26819
|
input: process.stdin,
|
|
26634
26820
|
output: process.stdout,
|
|
@@ -26646,7 +26832,7 @@ async function readTokenSilent(prompt) {
|
|
|
26646
26832
|
process.stdin.removeListener("data", onData);
|
|
26647
26833
|
process.stdout.write("\n");
|
|
26648
26834
|
rl.close();
|
|
26649
|
-
|
|
26835
|
+
resolve12(token);
|
|
26650
26836
|
} else if (char === "") {
|
|
26651
26837
|
if (process.stdin.isTTY) process.stdin.setRawMode(false);
|
|
26652
26838
|
process.stdin.removeListener("data", onData);
|
|
@@ -26921,7 +27107,7 @@ async function discoverMcpSources(repoPaths) {
|
|
|
26921
27107
|
import { spawn as spawn7 } from "node:child_process";
|
|
26922
27108
|
var VALIDATION_TIMEOUT_MS = 5e3;
|
|
26923
27109
|
async function validateMcpEntry(entry) {
|
|
26924
|
-
return new Promise((
|
|
27110
|
+
return new Promise((resolve12) => {
|
|
26925
27111
|
let stdout = "";
|
|
26926
27112
|
let timedOut = false;
|
|
26927
27113
|
let child;
|
|
@@ -26931,7 +27117,7 @@ async function validateMcpEntry(entry) {
|
|
|
26931
27117
|
env: { ...process.env, ...entry.env ?? {} }
|
|
26932
27118
|
});
|
|
26933
27119
|
} catch (err) {
|
|
26934
|
-
|
|
27120
|
+
resolve12({
|
|
26935
27121
|
name: entry.name,
|
|
26936
27122
|
validated: false,
|
|
26937
27123
|
reason: err instanceof Error ? err.message : "spawn failed"
|
|
@@ -26948,11 +27134,11 @@ async function validateMcpEntry(entry) {
|
|
|
26948
27134
|
child.on("close", (code) => {
|
|
26949
27135
|
clearTimeout(timer);
|
|
26950
27136
|
if (timedOut) {
|
|
26951
|
-
|
|
27137
|
+
resolve12({ name: entry.name, validated: false, reason: "timeout (5s)" });
|
|
26952
27138
|
return;
|
|
26953
27139
|
}
|
|
26954
27140
|
const validated = code === 0 && stdout.trim().length > 0;
|
|
26955
|
-
|
|
27141
|
+
resolve12({
|
|
26956
27142
|
name: entry.name,
|
|
26957
27143
|
validated,
|
|
26958
27144
|
reason: validated ? "ok" : `exit code ${code ?? "null"}`
|
|
@@ -26960,7 +27146,7 @@ async function validateMcpEntry(entry) {
|
|
|
26960
27146
|
});
|
|
26961
27147
|
child.on("error", (err) => {
|
|
26962
27148
|
clearTimeout(timer);
|
|
26963
|
-
|
|
27149
|
+
resolve12({ name: entry.name, validated: false, reason: err.message });
|
|
26964
27150
|
});
|
|
26965
27151
|
});
|
|
26966
27152
|
}
|
|
@@ -26975,11 +27161,11 @@ async function multiSelectPicker(entries) {
|
|
|
26975
27161
|
);
|
|
26976
27162
|
});
|
|
26977
27163
|
console.log("\n" + pc29.dim('Enter numbers to import (e.g. 1,2,3 or "all" or Enter to skip):'));
|
|
26978
|
-
const answer = await new Promise((
|
|
27164
|
+
const answer = await new Promise((resolve12) => {
|
|
26979
27165
|
const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
|
|
26980
27166
|
rl.question("> ", (ans) => {
|
|
26981
27167
|
rl.close();
|
|
26982
|
-
|
|
27168
|
+
resolve12(ans.trim());
|
|
26983
27169
|
});
|
|
26984
27170
|
});
|
|
26985
27171
|
if (!answer || answer === "") return [];
|
|
@@ -27107,7 +27293,10 @@ function registerMcpRevoke(cmd) {
|
|
|
27107
27293
|
|
|
27108
27294
|
// src/commands/mcp/index.ts
|
|
27109
27295
|
function registerMcp(program2) {
|
|
27110
|
-
const mcp = program2.command("mcp").description("
|
|
27296
|
+
const mcp = program2.command("mcp").description("Run the olam MCP server, wire it into Claude Code, or manage MCP credentials (serve, install, uninstall, login, add, list, remove, import, revoke)");
|
|
27297
|
+
registerMcpServe(mcp);
|
|
27298
|
+
registerMcpInstall(mcp);
|
|
27299
|
+
registerMcpUninstall(mcp);
|
|
27111
27300
|
registerMcpLogin(mcp);
|
|
27112
27301
|
registerMcpAdd(mcp);
|
|
27113
27302
|
registerMcpList(mcp);
|
|
@@ -27118,13 +27307,13 @@ function registerMcp(program2) {
|
|
|
27118
27307
|
}
|
|
27119
27308
|
|
|
27120
27309
|
// src/commands/kg-build.ts
|
|
27121
|
-
import { spawnSync as
|
|
27310
|
+
import { spawnSync as spawnSync16 } from "node:child_process";
|
|
27122
27311
|
import fs48 from "node:fs";
|
|
27123
27312
|
import path53 from "node:path";
|
|
27124
27313
|
|
|
27125
27314
|
// ../core/dist/kg/storage-paths.js
|
|
27126
27315
|
import { homedir as homedir28 } from "node:os";
|
|
27127
|
-
import { join as join48, resolve as
|
|
27316
|
+
import { join as join48, resolve as resolve11 } from "node:path";
|
|
27128
27317
|
|
|
27129
27318
|
// ../core/dist/world/workspace-name.js
|
|
27130
27319
|
var InvalidWorkspaceNameError = class extends Error {
|
|
@@ -27161,7 +27350,7 @@ function assertWithinPrefix(path55, prefix, label) {
|
|
|
27161
27350
|
function kgPristinePath(workspace) {
|
|
27162
27351
|
validateWorkspaceName(workspace);
|
|
27163
27352
|
const root = kgRoot();
|
|
27164
|
-
const path55 =
|
|
27353
|
+
const path55 = resolve11(join48(root, workspace));
|
|
27165
27354
|
assertWithinPrefix(path55, root, "kgPristinePath");
|
|
27166
27355
|
return path55;
|
|
27167
27356
|
}
|
|
@@ -27532,16 +27721,16 @@ async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
|
27532
27721
|
process.on("SIGINT", () => forward("SIGINT"));
|
|
27533
27722
|
process.on("SIGTERM", () => forward("SIGTERM"));
|
|
27534
27723
|
}
|
|
27535
|
-
return new Promise((
|
|
27724
|
+
return new Promise((resolve12) => {
|
|
27536
27725
|
child.on("exit", (code, signal) => {
|
|
27537
27726
|
removePidFile(name);
|
|
27538
27727
|
const exitCode = typeof code === "number" ? code : signal === "SIGINT" || signal === "SIGTERM" ? 0 : 1;
|
|
27539
|
-
|
|
27728
|
+
resolve12({ exitCode, pidWritten: true });
|
|
27540
27729
|
});
|
|
27541
27730
|
child.on("error", (err) => {
|
|
27542
27731
|
removePidFile(name);
|
|
27543
27732
|
printError(`graphify subprocess error: ${err.message}`);
|
|
27544
|
-
|
|
27733
|
+
resolve12({ exitCode: 1, pidWritten: true });
|
|
27545
27734
|
});
|
|
27546
27735
|
});
|
|
27547
27736
|
}
|
|
@@ -27564,13 +27753,13 @@ function resolveWorkspace(arg) {
|
|
|
27564
27753
|
}
|
|
27565
27754
|
function copyWorkspaceToScratch(source, scratch) {
|
|
27566
27755
|
if (process.platform === "darwin") {
|
|
27567
|
-
const r2 =
|
|
27756
|
+
const r2 = spawnSync16("cp", ["-c", "-r", source + "/.", scratch], {
|
|
27568
27757
|
stdio: ["ignore", "ignore", "pipe"],
|
|
27569
27758
|
encoding: "utf-8"
|
|
27570
27759
|
});
|
|
27571
27760
|
if (r2.status === 0) return "cp-c-r-reflink";
|
|
27572
27761
|
}
|
|
27573
|
-
const r =
|
|
27762
|
+
const r = spawnSync16("cp", ["-r", source + "/.", scratch], {
|
|
27574
27763
|
stdio: ["ignore", "ignore", "pipe"],
|
|
27575
27764
|
encoding: "utf-8"
|
|
27576
27765
|
});
|
|
@@ -27591,7 +27780,7 @@ function parseNodeCount(graphifyOutDir) {
|
|
|
27591
27780
|
}
|
|
27592
27781
|
}
|
|
27593
27782
|
function readGraphifyVersion(image) {
|
|
27594
|
-
const r =
|
|
27783
|
+
const r = spawnSync16(
|
|
27595
27784
|
"docker",
|
|
27596
27785
|
[
|
|
27597
27786
|
"run",
|
|
@@ -27643,7 +27832,7 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
27643
27832
|
"update",
|
|
27644
27833
|
"."
|
|
27645
27834
|
];
|
|
27646
|
-
const r = human ?
|
|
27835
|
+
const r = human ? spawnSync16("docker", dockerArgs, { stdio: "inherit" }) : spawnSync16("docker", dockerArgs, { stdio: ["ignore", "ignore", "pipe"] });
|
|
27647
27836
|
if (r.status !== 0) {
|
|
27648
27837
|
printError(`graphify update failed (exit ${r.status})`);
|
|
27649
27838
|
return { exitCode: r.status ?? 1 };
|
|
@@ -27720,7 +27909,19 @@ function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
|
27720
27909
|
|
|
27721
27910
|
// src/index.ts
|
|
27722
27911
|
var program = new Command();
|
|
27723
|
-
program.name("olam").description("Olam \u2014 isolated development worlds with thought graph capture").version(readCliVersion());
|
|
27912
|
+
program.name("olam").description("Olam \u2014 isolated development worlds with thought graph capture").option("--mcp", "Run the olam MCP server (stdio); alias for `olam mcp serve`").version(readCliVersion());
|
|
27913
|
+
var mcpFlagIndex = process.argv.indexOf("--mcp");
|
|
27914
|
+
if (mcpFlagIndex !== -1) {
|
|
27915
|
+
const afterFlag = process.argv.slice(mcpFlagIndex + 1).filter((a) => !a.startsWith("-"));
|
|
27916
|
+
if (afterFlag.length > 0) {
|
|
27917
|
+
process.stderr.write(
|
|
27918
|
+
`error: --mcp does not accept positional arguments (got ${JSON.stringify(afterFlag)}). Use 'olam mcp serve' directly if you need subcommand-level flags.
|
|
27919
|
+
`
|
|
27920
|
+
);
|
|
27921
|
+
process.exit(1);
|
|
27922
|
+
}
|
|
27923
|
+
process.argv.splice(mcpFlagIndex, 1, "mcp", "serve");
|
|
27924
|
+
}
|
|
27724
27925
|
registerInit(program);
|
|
27725
27926
|
registerInstall(program);
|
|
27726
27927
|
registerAuth(program);
|