@pleri/olam-cli 0.1.50 → 0.1.53
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/__tests__/cli-mcp-revoke.test.d.ts +8 -0
- package/dist/__tests__/cli-mcp-revoke.test.d.ts.map +1 -0
- package/dist/__tests__/cli-mcp-revoke.test.js +124 -0
- package/dist/__tests__/cli-mcp-revoke.test.js.map +1 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +9 -1
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/mcp/index.d.ts.map +1 -1
- package/dist/commands/mcp/index.js +3 -1
- package/dist/commands/mcp/index.js.map +1 -1
- package/dist/commands/mcp/revoke.d.ts +11 -0
- package/dist/commands/mcp/revoke.d.ts.map +1 -0
- package/dist/commands/mcp/revoke.js +51 -0
- package/dist/commands/mcp/revoke.js.map +1 -0
- package/dist/image-digests.json +4 -4
- package/dist/index.js +725 -509
- package/dist/mcp-server.js +427 -268
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
5
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
6
|
+
}) : x)(function(x) {
|
|
7
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
8
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
9
|
+
});
|
|
4
10
|
var __esm = (fn, res) => function __init() {
|
|
5
11
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
12
|
};
|
|
@@ -454,8 +460,8 @@ var init_parseUtil = __esm({
|
|
|
454
460
|
init_errors();
|
|
455
461
|
init_en();
|
|
456
462
|
makeIssue = (params) => {
|
|
457
|
-
const { data, path:
|
|
458
|
-
const fullPath = [...
|
|
463
|
+
const { data, path: path45, errorMaps, issueData } = params;
|
|
464
|
+
const fullPath = [...path45, ...issueData.path || []];
|
|
459
465
|
const fullIssue = {
|
|
460
466
|
...issueData,
|
|
461
467
|
path: fullPath
|
|
@@ -763,11 +769,11 @@ var init_types = __esm({
|
|
|
763
769
|
init_parseUtil();
|
|
764
770
|
init_util();
|
|
765
771
|
ParseInputLazyPath = class {
|
|
766
|
-
constructor(parent, value,
|
|
772
|
+
constructor(parent, value, path45, key) {
|
|
767
773
|
this._cachedPath = [];
|
|
768
774
|
this.parent = parent;
|
|
769
775
|
this.data = value;
|
|
770
|
-
this._path =
|
|
776
|
+
this._path = path45;
|
|
771
777
|
this._key = key;
|
|
772
778
|
}
|
|
773
779
|
get path() {
|
|
@@ -4248,7 +4254,7 @@ import YAML from "yaml";
|
|
|
4248
4254
|
function bootstrapStepCmd(entry) {
|
|
4249
4255
|
return typeof entry === "string" ? entry : entry.cmd;
|
|
4250
4256
|
}
|
|
4251
|
-
function refineForbiddenKeys(value,
|
|
4257
|
+
function refineForbiddenKeys(value, path45, ctx, rejectSource) {
|
|
4252
4258
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
4253
4259
|
return;
|
|
4254
4260
|
}
|
|
@@ -4256,12 +4262,12 @@ function refineForbiddenKeys(value, path44, ctx, rejectSource) {
|
|
|
4256
4262
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4257
4263
|
ctx.addIssue({
|
|
4258
4264
|
code: external_exports.ZodIssueCode.custom,
|
|
4259
|
-
path: [...
|
|
4265
|
+
path: [...path45, key],
|
|
4260
4266
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
4261
4267
|
});
|
|
4262
4268
|
continue;
|
|
4263
4269
|
}
|
|
4264
|
-
if (rejectSource &&
|
|
4270
|
+
if (rejectSource && path45.length === 0 && key === "source") {
|
|
4265
4271
|
ctx.addIssue({
|
|
4266
4272
|
code: external_exports.ZodIssueCode.custom,
|
|
4267
4273
|
path: ["source"],
|
|
@@ -4269,21 +4275,21 @@ function refineForbiddenKeys(value, path44, ctx, rejectSource) {
|
|
|
4269
4275
|
});
|
|
4270
4276
|
continue;
|
|
4271
4277
|
}
|
|
4272
|
-
refineForbiddenKeys(value[key], [...
|
|
4278
|
+
refineForbiddenKeys(value[key], [...path45, key], ctx, false);
|
|
4273
4279
|
}
|
|
4274
4280
|
}
|
|
4275
|
-
function rejectForbiddenKeys(value,
|
|
4281
|
+
function rejectForbiddenKeys(value, path45, rejectSource) {
|
|
4276
4282
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
4277
4283
|
return;
|
|
4278
4284
|
}
|
|
4279
4285
|
for (const key of Object.keys(value)) {
|
|
4280
4286
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4281
|
-
throw new Error(`[manifest] ${
|
|
4287
|
+
throw new Error(`[manifest] ${path45}: forbidden key "${key}" (prototype-pollution surface)`);
|
|
4282
4288
|
}
|
|
4283
4289
|
if (rejectSource && key === "source") {
|
|
4284
|
-
throw new Error(`[manifest] ${
|
|
4290
|
+
throw new Error(`[manifest] ${path45}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
|
|
4285
4291
|
}
|
|
4286
|
-
rejectForbiddenKeys(value[key], `${
|
|
4292
|
+
rejectForbiddenKeys(value[key], `${path45}.${key}`, false);
|
|
4287
4293
|
}
|
|
4288
4294
|
}
|
|
4289
4295
|
function unknownTopLevelKeys(parsed) {
|
|
@@ -5224,8 +5230,8 @@ var init_client = __esm({
|
|
|
5224
5230
|
throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
|
|
5225
5231
|
}
|
|
5226
5232
|
}
|
|
5227
|
-
async request(method,
|
|
5228
|
-
const url = `${this.baseUrl}${
|
|
5233
|
+
async request(method, path45, body, attempt = 0) {
|
|
5234
|
+
const url = `${this.baseUrl}${path45}`;
|
|
5229
5235
|
const controller = new AbortController();
|
|
5230
5236
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
5231
5237
|
const headers = {};
|
|
@@ -5243,7 +5249,7 @@ var init_client = __esm({
|
|
|
5243
5249
|
} catch (err) {
|
|
5244
5250
|
if (attempt < RETRY_COUNT && isTransient(err)) {
|
|
5245
5251
|
await sleep(RETRY_BACKOFF_MS * (attempt + 1));
|
|
5246
|
-
return this.request(method,
|
|
5252
|
+
return this.request(method, path45, body, attempt + 1);
|
|
5247
5253
|
}
|
|
5248
5254
|
throw err;
|
|
5249
5255
|
} finally {
|
|
@@ -6722,8 +6728,8 @@ var init_provider3 = __esm({
|
|
|
6722
6728
|
// -----------------------------------------------------------------------
|
|
6723
6729
|
// Internal fetch helper
|
|
6724
6730
|
// -----------------------------------------------------------------------
|
|
6725
|
-
async request(
|
|
6726
|
-
const url = `${this.config.workerUrl}${
|
|
6731
|
+
async request(path45, method, body) {
|
|
6732
|
+
const url = `${this.config.workerUrl}${path45}`;
|
|
6727
6733
|
const bearer = await this.config.mintToken();
|
|
6728
6734
|
const headers = {
|
|
6729
6735
|
Authorization: `Bearer ${bearer}`
|
|
@@ -7437,14 +7443,25 @@ function generateHooksConfig(hookServerUrl = DEFAULT_HOOK_SERVER_URL) {
|
|
|
7437
7443
|
hooks: {
|
|
7438
7444
|
// Codex adversarial review — fires on every user prompt in-world
|
|
7439
7445
|
// Uses $HOME so sanitizeContainerClaudeHooks does not strip it
|
|
7440
|
-
UserPromptSubmit: [
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7446
|
+
UserPromptSubmit: [
|
|
7447
|
+
{
|
|
7448
|
+
matcher: "",
|
|
7449
|
+
hooks: [{
|
|
7450
|
+
type: "command",
|
|
7451
|
+
command: "$HOME/.claude/scripts/codex-on-prompt.sh",
|
|
7452
|
+
timeout: 15
|
|
7453
|
+
}]
|
|
7454
|
+
},
|
|
7455
|
+
// C02: surface first-call hint when MCP creds are missing
|
|
7456
|
+
{
|
|
7457
|
+
matcher: "",
|
|
7458
|
+
hooks: [{
|
|
7459
|
+
type: "command",
|
|
7460
|
+
command: "node /opt/olam/scripts/mcp-status-hint.mjs",
|
|
7461
|
+
timeout: 2
|
|
7462
|
+
}]
|
|
7463
|
+
}
|
|
7464
|
+
],
|
|
7448
7465
|
// Tool execution events → high-frequency thought capture
|
|
7449
7466
|
// Layer 1: Upstream Codex review (PreToolUse) — runs after thought capture
|
|
7450
7467
|
PreToolUse: [
|
|
@@ -7502,87 +7519,192 @@ var init_hooks_config = __esm({
|
|
|
7502
7519
|
}
|
|
7503
7520
|
});
|
|
7504
7521
|
|
|
7505
|
-
// ../core/dist/world/
|
|
7506
|
-
import * as crypto2 from "node:crypto";
|
|
7522
|
+
// ../core/dist/world/merge-settings.js
|
|
7507
7523
|
import * as fs12 from "node:fs";
|
|
7508
|
-
import * as os8 from "node:os";
|
|
7509
7524
|
import * as path13 from "node:path";
|
|
7525
|
+
import * as crypto2 from "node:crypto";
|
|
7526
|
+
function mergeHomeSettingsJson(filePath, options) {
|
|
7527
|
+
let settings;
|
|
7528
|
+
try {
|
|
7529
|
+
settings = readSettings(filePath);
|
|
7530
|
+
} catch (err) {
|
|
7531
|
+
throw new Error(`merge-settings: failed to parse existing settings.json: ${err?.message ?? err}`);
|
|
7532
|
+
}
|
|
7533
|
+
let changed = false;
|
|
7534
|
+
if (options.ensureHook) {
|
|
7535
|
+
const { stage, sentinel, entry } = options.ensureHook;
|
|
7536
|
+
if (!settings.hooks || typeof settings.hooks !== "object") {
|
|
7537
|
+
settings = { ...settings, hooks: {} };
|
|
7538
|
+
changed = true;
|
|
7539
|
+
}
|
|
7540
|
+
const hooks = settings.hooks;
|
|
7541
|
+
if (!Array.isArray(hooks[stage])) {
|
|
7542
|
+
settings = {
|
|
7543
|
+
...settings,
|
|
7544
|
+
hooks: { ...hooks, [stage]: [] }
|
|
7545
|
+
};
|
|
7546
|
+
changed = true;
|
|
7547
|
+
}
|
|
7548
|
+
const stageArr = settings.hooks[stage];
|
|
7549
|
+
if (isHookSentinelPresent(stageArr, sentinel)) {
|
|
7550
|
+
if (!changed) {
|
|
7551
|
+
return { status: "already-present", message: `hook already present at ${filePath}` };
|
|
7552
|
+
}
|
|
7553
|
+
} else {
|
|
7554
|
+
settings = {
|
|
7555
|
+
...settings,
|
|
7556
|
+
hooks: {
|
|
7557
|
+
...settings.hooks,
|
|
7558
|
+
[stage]: [...stageArr, entry]
|
|
7559
|
+
}
|
|
7560
|
+
};
|
|
7561
|
+
changed = true;
|
|
7562
|
+
}
|
|
7563
|
+
}
|
|
7564
|
+
if (options.env) {
|
|
7565
|
+
const existingEnv = settings.env && typeof settings.env === "object" ? settings.env : {};
|
|
7566
|
+
const mergedEnv = { ...existingEnv, ...options.env };
|
|
7567
|
+
const sameKeys = Object.keys(mergedEnv).length === Object.keys(existingEnv).length && Object.keys(mergedEnv).every((k) => existingEnv[k] === mergedEnv[k]);
|
|
7568
|
+
if (!sameKeys) {
|
|
7569
|
+
settings = { ...settings, env: mergedEnv };
|
|
7570
|
+
changed = true;
|
|
7571
|
+
}
|
|
7572
|
+
}
|
|
7573
|
+
if (!changed) {
|
|
7574
|
+
return { status: "no-op", message: `no change needed at ${filePath}` };
|
|
7575
|
+
}
|
|
7576
|
+
try {
|
|
7577
|
+
atomicWriteJson(filePath, settings);
|
|
7578
|
+
} catch (err) {
|
|
7579
|
+
throw new Error(`merge-settings: failed to write settings.json: ${err?.message ?? err}`);
|
|
7580
|
+
}
|
|
7581
|
+
return { status: "installed", message: `settings.json updated at ${filePath}` };
|
|
7582
|
+
}
|
|
7583
|
+
function readSettings(filePath) {
|
|
7584
|
+
if (!fs12.existsSync(filePath)) {
|
|
7585
|
+
return {};
|
|
7586
|
+
}
|
|
7587
|
+
const raw = fs12.readFileSync(filePath, "utf-8");
|
|
7588
|
+
if (!raw.trim())
|
|
7589
|
+
return {};
|
|
7590
|
+
return JSON.parse(raw);
|
|
7591
|
+
}
|
|
7592
|
+
function isHookSentinelPresent(matchers, sentinel) {
|
|
7593
|
+
for (const matcher of matchers) {
|
|
7594
|
+
if (typeof matcher?.command === "string" && matcher.command.includes(sentinel)) {
|
|
7595
|
+
return true;
|
|
7596
|
+
}
|
|
7597
|
+
if (Array.isArray(matcher?.hooks)) {
|
|
7598
|
+
for (const h of matcher.hooks) {
|
|
7599
|
+
if (typeof h?.command === "string" && h.command.includes(sentinel)) {
|
|
7600
|
+
return true;
|
|
7601
|
+
}
|
|
7602
|
+
}
|
|
7603
|
+
}
|
|
7604
|
+
}
|
|
7605
|
+
return false;
|
|
7606
|
+
}
|
|
7607
|
+
function atomicWriteJson(filePath, data) {
|
|
7608
|
+
const dir = path13.dirname(filePath);
|
|
7609
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
7610
|
+
const rand = crypto2.randomBytes(6).toString("hex");
|
|
7611
|
+
const tmp = `${filePath}.tmp.${process.pid}.${rand}`;
|
|
7612
|
+
const json = JSON.stringify(data, null, 2) + "\n";
|
|
7613
|
+
fs12.writeFileSync(tmp, json, { mode: 420 });
|
|
7614
|
+
fs12.renameSync(tmp, filePath);
|
|
7615
|
+
}
|
|
7616
|
+
var init_merge_settings = __esm({
|
|
7617
|
+
"../core/dist/world/merge-settings.js"() {
|
|
7618
|
+
"use strict";
|
|
7619
|
+
}
|
|
7620
|
+
});
|
|
7621
|
+
|
|
7622
|
+
// ../core/dist/world/env-setup.js
|
|
7623
|
+
import * as crypto3 from "node:crypto";
|
|
7624
|
+
import * as fs13 from "node:fs";
|
|
7625
|
+
import * as os8 from "node:os";
|
|
7626
|
+
import * as path14 from "node:path";
|
|
7510
7627
|
import { globSync } from "node:fs";
|
|
7511
7628
|
function copyClaudeConfig(workspacePath, homeDir, configCtx) {
|
|
7512
|
-
const sourceClaudeDir =
|
|
7513
|
-
const destClaudeDir =
|
|
7629
|
+
const sourceClaudeDir = path14.join(homeDir ?? os8.homedir(), ".claude");
|
|
7630
|
+
const destClaudeDir = path14.join(workspacePath, ".claude-host-config");
|
|
7514
7631
|
void configCtx;
|
|
7515
|
-
if (!
|
|
7632
|
+
if (!fs13.existsSync(sourceClaudeDir))
|
|
7516
7633
|
return;
|
|
7517
|
-
|
|
7518
|
-
const settingsPath =
|
|
7634
|
+
fs13.mkdirSync(destClaudeDir, { recursive: true });
|
|
7635
|
+
const settingsPath = path14.join(sourceClaudeDir, "settings.json");
|
|
7519
7636
|
let settings = {};
|
|
7520
|
-
if (
|
|
7637
|
+
if (fs13.existsSync(settingsPath)) {
|
|
7521
7638
|
try {
|
|
7522
|
-
settings = JSON.parse(
|
|
7639
|
+
settings = JSON.parse(fs13.readFileSync(settingsPath, "utf-8"));
|
|
7523
7640
|
delete settings["hooks"];
|
|
7524
7641
|
} catch {
|
|
7525
7642
|
}
|
|
7526
7643
|
}
|
|
7527
7644
|
const hooksConfig = generateHooksConfig(DEFAULT_HOOK_SERVER_URL);
|
|
7528
7645
|
settings["hooks"] = hooksConfig["hooks"];
|
|
7529
|
-
|
|
7530
|
-
const claudeMdPath =
|
|
7531
|
-
if (
|
|
7532
|
-
|
|
7646
|
+
fs13.writeFileSync(path14.join(destClaudeDir, "settings.json"), JSON.stringify(settings, null, 2));
|
|
7647
|
+
const claudeMdPath = path14.join(sourceClaudeDir, "CLAUDE.md");
|
|
7648
|
+
if (fs13.existsSync(claudeMdPath)) {
|
|
7649
|
+
fs13.copyFileSync(claudeMdPath, path14.join(destClaudeDir, "CLAUDE.md"));
|
|
7533
7650
|
}
|
|
7534
|
-
const rulesDir =
|
|
7535
|
-
if (
|
|
7536
|
-
copyDirRecursive(rulesDir,
|
|
7651
|
+
const rulesDir = path14.join(sourceClaudeDir, "rules");
|
|
7652
|
+
if (fs13.existsSync(rulesDir)) {
|
|
7653
|
+
copyDirRecursive(rulesDir, path14.join(destClaudeDir, "rules"));
|
|
7537
7654
|
}
|
|
7538
|
-
const agentsDir =
|
|
7539
|
-
if (
|
|
7540
|
-
copyDirRecursive(agentsDir,
|
|
7655
|
+
const agentsDir = path14.join(sourceClaudeDir, "agents");
|
|
7656
|
+
if (fs13.existsSync(agentsDir)) {
|
|
7657
|
+
copyDirRecursive(agentsDir, path14.join(destClaudeDir, "agents"));
|
|
7541
7658
|
}
|
|
7542
|
-
const pluginsDir =
|
|
7543
|
-
if (
|
|
7544
|
-
copyDirRecursive(pluginsDir,
|
|
7659
|
+
const pluginsDir = path14.join(sourceClaudeDir, "plugins");
|
|
7660
|
+
if (fs13.existsSync(pluginsDir)) {
|
|
7661
|
+
copyDirRecursive(pluginsDir, path14.join(destClaudeDir, "plugins"), 0, SKIP_FILES);
|
|
7545
7662
|
}
|
|
7546
|
-
const skillsDir =
|
|
7547
|
-
if (
|
|
7548
|
-
copyDirRecursive(skillsDir,
|
|
7663
|
+
const skillsDir = path14.join(sourceClaudeDir, "skills");
|
|
7664
|
+
if (fs13.existsSync(skillsDir)) {
|
|
7665
|
+
copyDirRecursive(skillsDir, path14.join(destClaudeDir, "skills"));
|
|
7549
7666
|
}
|
|
7550
|
-
const scriptsDir =
|
|
7551
|
-
if (
|
|
7552
|
-
copyDirRecursive(scriptsDir,
|
|
7667
|
+
const scriptsDir = path14.join(sourceClaudeDir, "scripts");
|
|
7668
|
+
if (fs13.existsSync(scriptsDir)) {
|
|
7669
|
+
copyDirRecursive(scriptsDir, path14.join(destClaudeDir, "scripts"));
|
|
7553
7670
|
}
|
|
7554
7671
|
applyProjectClaudeOverlay(workspacePath, destClaudeDir);
|
|
7555
7672
|
writeStrippedMcpServersSnapshot(homeDir ?? os8.homedir(), workspacePath, destClaudeDir);
|
|
7673
|
+
if (configCtx != null && configCtx.worlds_default?.agent_teams_enabled !== false) {
|
|
7674
|
+
mergeHomeSettingsJson(path14.join(destClaudeDir, "settings.json"), {
|
|
7675
|
+
env: { CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: "1" }
|
|
7676
|
+
});
|
|
7677
|
+
}
|
|
7556
7678
|
}
|
|
7557
7679
|
function applyProjectClaudeOverlay(workspacePath, destClaudeDir) {
|
|
7558
|
-
const projectClaudeDir =
|
|
7559
|
-
if (!
|
|
7680
|
+
const projectClaudeDir = path14.join(workspacePath, ".claude");
|
|
7681
|
+
if (!fs13.existsSync(projectClaudeDir))
|
|
7560
7682
|
return;
|
|
7561
|
-
const projectSettingsPath =
|
|
7562
|
-
const destSettingsPath =
|
|
7563
|
-
if (
|
|
7683
|
+
const projectSettingsPath = path14.join(projectClaudeDir, "settings.json");
|
|
7684
|
+
const destSettingsPath = path14.join(destClaudeDir, "settings.json");
|
|
7685
|
+
if (fs13.existsSync(projectSettingsPath)) {
|
|
7564
7686
|
try {
|
|
7565
|
-
const projectSettings = JSON.parse(
|
|
7687
|
+
const projectSettings = JSON.parse(fs13.readFileSync(projectSettingsPath, "utf-8"));
|
|
7566
7688
|
delete projectSettings["hooks"];
|
|
7567
|
-
const existing =
|
|
7689
|
+
const existing = fs13.existsSync(destSettingsPath) ? JSON.parse(fs13.readFileSync(destSettingsPath, "utf-8")) : {};
|
|
7568
7690
|
const merged = { ...existing, ...projectSettings, hooks: existing["hooks"] };
|
|
7569
|
-
|
|
7691
|
+
fs13.writeFileSync(destSettingsPath, JSON.stringify(merged, null, 2));
|
|
7570
7692
|
} catch {
|
|
7571
7693
|
}
|
|
7572
7694
|
}
|
|
7573
|
-
const projectClaudeMd =
|
|
7574
|
-
if (
|
|
7575
|
-
|
|
7695
|
+
const projectClaudeMd = path14.join(projectClaudeDir, "CLAUDE.md");
|
|
7696
|
+
if (fs13.existsSync(projectClaudeMd)) {
|
|
7697
|
+
fs13.copyFileSync(projectClaudeMd, path14.join(destClaudeDir, "CLAUDE.md"));
|
|
7576
7698
|
}
|
|
7577
|
-
const projectAgentsMd =
|
|
7578
|
-
if (
|
|
7579
|
-
|
|
7699
|
+
const projectAgentsMd = path14.join(projectClaudeDir, "AGENTS.md");
|
|
7700
|
+
if (fs13.existsSync(projectAgentsMd)) {
|
|
7701
|
+
fs13.copyFileSync(projectAgentsMd, path14.join(destClaudeDir, "AGENTS.md"));
|
|
7580
7702
|
}
|
|
7581
7703
|
for (const subdir of ["rules", "agents", "plugins", "skills", "scripts"]) {
|
|
7582
|
-
const projectSubdir =
|
|
7583
|
-
if (
|
|
7704
|
+
const projectSubdir = path14.join(projectClaudeDir, subdir);
|
|
7705
|
+
if (fs13.existsSync(projectSubdir)) {
|
|
7584
7706
|
const skip = subdir === "plugins" ? SKIP_FILES : /* @__PURE__ */ new Set();
|
|
7585
|
-
copyDirRecursive(projectSubdir,
|
|
7707
|
+
copyDirRecursive(projectSubdir, path14.join(destClaudeDir, subdir), 0, skip);
|
|
7586
7708
|
}
|
|
7587
7709
|
}
|
|
7588
7710
|
}
|
|
@@ -7612,8 +7734,8 @@ function stripMcpServers(mcpServers) {
|
|
|
7612
7734
|
return out;
|
|
7613
7735
|
}
|
|
7614
7736
|
function writeStrippedMcpServersSnapshot(homeDir, workspacePath, destClaudeDir) {
|
|
7615
|
-
const hostMcpServers = readMcpServersFromFile(
|
|
7616
|
-
const projectMcpServers = readMcpServersFromFile(
|
|
7737
|
+
const hostMcpServers = readMcpServersFromFile(path14.join(homeDir, ".claude.json"));
|
|
7738
|
+
const projectMcpServers = readMcpServersFromFile(path14.join(workspacePath, ".mcp.json"));
|
|
7617
7739
|
if (Object.keys(hostMcpServers).length === 0 && Object.keys(projectMcpServers).length === 0) {
|
|
7618
7740
|
return;
|
|
7619
7741
|
}
|
|
@@ -7622,11 +7744,11 @@ function writeStrippedMcpServersSnapshot(homeDir, workspacePath, destClaudeDir)
|
|
|
7622
7744
|
...stripMcpServers(projectMcpServers)
|
|
7623
7745
|
};
|
|
7624
7746
|
const output = { mcpServers: stripped };
|
|
7625
|
-
|
|
7747
|
+
fs13.writeFileSync(path14.join(destClaudeDir, ".claude.json"), JSON.stringify(output, null, 2), { mode: 384 });
|
|
7626
7748
|
}
|
|
7627
7749
|
function writeWorldEntitlementsJson(workspacePath, configCtx) {
|
|
7628
|
-
const olamDir =
|
|
7629
|
-
|
|
7750
|
+
const olamDir = path14.join(workspacePath, ".olam");
|
|
7751
|
+
fs13.mkdirSync(olamDir, { recursive: true });
|
|
7630
7752
|
const resolvedRepos = configCtx.repos.map((repo) => {
|
|
7631
7753
|
const repoEntitlement = repo;
|
|
7632
7754
|
return {
|
|
@@ -7640,14 +7762,14 @@ function writeWorldEntitlementsJson(workspacePath, configCtx) {
|
|
|
7640
7762
|
worlds_default: configCtx.worlds_default,
|
|
7641
7763
|
repos: resolvedRepos
|
|
7642
7764
|
};
|
|
7643
|
-
const filePath =
|
|
7644
|
-
|
|
7765
|
+
const filePath = path14.join(olamDir, "world-entitlements.json");
|
|
7766
|
+
fs13.writeFileSync(filePath, JSON.stringify(resolved, null, 2), { mode: 420 });
|
|
7645
7767
|
}
|
|
7646
7768
|
function readMcpServersFromFile(filePath) {
|
|
7647
|
-
if (!
|
|
7769
|
+
if (!fs13.existsSync(filePath))
|
|
7648
7770
|
return {};
|
|
7649
7771
|
try {
|
|
7650
|
-
const raw =
|
|
7772
|
+
const raw = fs13.readFileSync(filePath, "utf-8");
|
|
7651
7773
|
if (!raw.trim())
|
|
7652
7774
|
return {};
|
|
7653
7775
|
const parsed = JSON.parse(raw);
|
|
@@ -7662,8 +7784,8 @@ function readMcpServersFromFile(filePath) {
|
|
|
7662
7784
|
function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new Set()) {
|
|
7663
7785
|
if (depth > 10)
|
|
7664
7786
|
return;
|
|
7665
|
-
|
|
7666
|
-
for (const entry of
|
|
7787
|
+
fs13.mkdirSync(dest, { recursive: true });
|
|
7788
|
+
for (const entry of fs13.readdirSync(src, { withFileTypes: true })) {
|
|
7667
7789
|
const { name } = entry;
|
|
7668
7790
|
if (skipFiles.has(name))
|
|
7669
7791
|
continue;
|
|
@@ -7673,12 +7795,12 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
|
|
|
7673
7795
|
continue;
|
|
7674
7796
|
if (entry.isDirectory() && SKIP_DIRS.has(name))
|
|
7675
7797
|
continue;
|
|
7676
|
-
const srcPath =
|
|
7677
|
-
const destPath =
|
|
7798
|
+
const srcPath = path14.join(src, name);
|
|
7799
|
+
const destPath = path14.join(dest, name);
|
|
7678
7800
|
if (entry.isSymbolicLink()) {
|
|
7679
7801
|
let stat;
|
|
7680
7802
|
try {
|
|
7681
|
-
stat =
|
|
7803
|
+
stat = fs13.statSync(srcPath);
|
|
7682
7804
|
} catch {
|
|
7683
7805
|
continue;
|
|
7684
7806
|
}
|
|
@@ -7687,12 +7809,12 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
|
|
|
7687
7809
|
continue;
|
|
7688
7810
|
copyDirRecursive(srcPath, destPath, depth + 1, skipFiles);
|
|
7689
7811
|
} else if (stat.isFile()) {
|
|
7690
|
-
|
|
7812
|
+
fs13.copyFileSync(srcPath, destPath);
|
|
7691
7813
|
}
|
|
7692
7814
|
} else if (entry.isDirectory()) {
|
|
7693
7815
|
copyDirRecursive(srcPath, destPath, depth + 1, skipFiles);
|
|
7694
7816
|
} else {
|
|
7695
|
-
|
|
7817
|
+
fs13.copyFileSync(srcPath, destPath);
|
|
7696
7818
|
}
|
|
7697
7819
|
}
|
|
7698
7820
|
}
|
|
@@ -7830,9 +7952,9 @@ function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}, conf
|
|
|
7830
7952
|
}
|
|
7831
7953
|
}
|
|
7832
7954
|
for (const repo of repos) {
|
|
7833
|
-
const worktreePath =
|
|
7955
|
+
const worktreePath = path14.join(workspacePath, repo.name);
|
|
7834
7956
|
const sourcePath = repo.path;
|
|
7835
|
-
if (!sourcePath || !
|
|
7957
|
+
if (!sourcePath || !fs13.existsSync(worktreePath))
|
|
7836
7958
|
continue;
|
|
7837
7959
|
const envSetup = repo.env_setup;
|
|
7838
7960
|
if (!envSetup)
|
|
@@ -7851,23 +7973,23 @@ function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}, conf
|
|
|
7851
7973
|
}
|
|
7852
7974
|
}
|
|
7853
7975
|
function copyMatchingFiles(sourcePath, destPath, pattern) {
|
|
7854
|
-
const fullPattern =
|
|
7976
|
+
const fullPattern = path14.join(sourcePath, pattern);
|
|
7855
7977
|
if (!pattern.includes("*")) {
|
|
7856
|
-
const sourceFile =
|
|
7857
|
-
const destFile =
|
|
7858
|
-
if (
|
|
7859
|
-
|
|
7860
|
-
|
|
7978
|
+
const sourceFile = path14.join(sourcePath, pattern);
|
|
7979
|
+
const destFile = path14.join(destPath, pattern);
|
|
7980
|
+
if (fs13.existsSync(sourceFile)) {
|
|
7981
|
+
fs13.mkdirSync(path14.dirname(destFile), { recursive: true });
|
|
7982
|
+
fs13.copyFileSync(sourceFile, destFile);
|
|
7861
7983
|
}
|
|
7862
7984
|
return;
|
|
7863
7985
|
}
|
|
7864
7986
|
try {
|
|
7865
7987
|
const matches2 = globSync(fullPattern);
|
|
7866
7988
|
for (const match2 of matches2) {
|
|
7867
|
-
const relative2 =
|
|
7868
|
-
const dest =
|
|
7869
|
-
|
|
7870
|
-
|
|
7989
|
+
const relative2 = path14.relative(sourcePath, match2);
|
|
7990
|
+
const dest = path14.join(destPath, relative2);
|
|
7991
|
+
fs13.mkdirSync(path14.dirname(dest), { recursive: true });
|
|
7992
|
+
fs13.copyFileSync(match2, dest);
|
|
7871
7993
|
}
|
|
7872
7994
|
} catch {
|
|
7873
7995
|
}
|
|
@@ -7875,14 +7997,14 @@ function copyMatchingFiles(sourcePath, destPath, pattern) {
|
|
|
7875
7997
|
function generateEnvFromExample(repoPath, overrides) {
|
|
7876
7998
|
const exampleFiles = [".env.example", ".env.sample", ".env.local.example"];
|
|
7877
7999
|
for (const exampleName of exampleFiles) {
|
|
7878
|
-
const examplePath =
|
|
7879
|
-
if (!
|
|
8000
|
+
const examplePath = path14.join(repoPath, exampleName);
|
|
8001
|
+
if (!fs13.existsSync(examplePath))
|
|
7880
8002
|
continue;
|
|
7881
8003
|
const targetName = exampleName.replace(".example", "").replace(".sample", "");
|
|
7882
|
-
const targetPath =
|
|
7883
|
-
if (
|
|
8004
|
+
const targetPath = path14.join(repoPath, targetName);
|
|
8005
|
+
if (fs13.existsSync(targetPath))
|
|
7884
8006
|
continue;
|
|
7885
|
-
const template =
|
|
8007
|
+
const template = fs13.readFileSync(examplePath, "utf-8");
|
|
7886
8008
|
const generated = template.split("\n").map((line) => {
|
|
7887
8009
|
const match2 = /^([A-Z_][A-Z0-9_]*)=(.*)$/.exec(line);
|
|
7888
8010
|
if (match2) {
|
|
@@ -7893,13 +8015,13 @@ function generateEnvFromExample(repoPath, overrides) {
|
|
|
7893
8015
|
}
|
|
7894
8016
|
return line;
|
|
7895
8017
|
}).join("\n");
|
|
7896
|
-
|
|
8018
|
+
fs13.writeFileSync(targetPath, generated);
|
|
7897
8019
|
}
|
|
7898
8020
|
}
|
|
7899
8021
|
function applyEnvOverrides(repoPath, overrides) {
|
|
7900
|
-
const envPath =
|
|
7901
|
-
if (
|
|
7902
|
-
const existing =
|
|
8022
|
+
const envPath = path14.join(repoPath, ".env");
|
|
8023
|
+
if (fs13.existsSync(envPath)) {
|
|
8024
|
+
const existing = fs13.readFileSync(envPath, "utf-8");
|
|
7903
8025
|
const existingKeys = new Set(existing.split("\n").map((l) => l.split("=")[0]?.trim()).filter(Boolean));
|
|
7904
8026
|
const additions = [];
|
|
7905
8027
|
for (const [key, value] of Object.entries(overrides)) {
|
|
@@ -7908,7 +8030,7 @@ function applyEnvOverrides(repoPath, overrides) {
|
|
|
7908
8030
|
}
|
|
7909
8031
|
}
|
|
7910
8032
|
if (additions.length > 0) {
|
|
7911
|
-
|
|
8033
|
+
fs13.appendFileSync(envPath, "\n# Olam injected\n" + additions.join("\n") + "\n");
|
|
7912
8034
|
}
|
|
7913
8035
|
}
|
|
7914
8036
|
}
|
|
@@ -7917,6 +8039,7 @@ var init_env_setup = __esm({
|
|
|
7917
8039
|
"../core/dist/world/env-setup.js"() {
|
|
7918
8040
|
"use strict";
|
|
7919
8041
|
init_hooks_config();
|
|
8042
|
+
init_merge_settings();
|
|
7920
8043
|
MCP_SERVER_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
7921
8044
|
"command",
|
|
7922
8045
|
"args",
|
|
@@ -7980,9 +8103,9 @@ var init_env_setup = __esm({
|
|
|
7980
8103
|
|
|
7981
8104
|
// ../core/dist/world/baseline-diff.js
|
|
7982
8105
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
7983
|
-
import * as
|
|
8106
|
+
import * as fs14 from "node:fs";
|
|
7984
8107
|
import * as os9 from "node:os";
|
|
7985
|
-
import * as
|
|
8108
|
+
import * as path15 from "node:path";
|
|
7986
8109
|
function expandHome(p, homedir22) {
|
|
7987
8110
|
return p.replace(/^~(?=$|\/|\\)/, homedir22());
|
|
7988
8111
|
}
|
|
@@ -8008,9 +8131,9 @@ ${stderr}`;
|
|
|
8008
8131
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
8009
8132
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync3(cmd, args, opts));
|
|
8010
8133
|
const homedir22 = deps.homedir ?? (() => os9.homedir());
|
|
8011
|
-
const baselineDir =
|
|
8134
|
+
const baselineDir = path15.join(workspacePath, ".olam", "baseline");
|
|
8012
8135
|
try {
|
|
8013
|
-
|
|
8136
|
+
fs14.mkdirSync(baselineDir, { recursive: true });
|
|
8014
8137
|
} catch (err) {
|
|
8015
8138
|
const msg = err instanceof Error ? err.message : String(err);
|
|
8016
8139
|
console.warn(`[baseline-diff] mkdir ${baselineDir} failed: ${msg}; reaper will see no baseline at all`);
|
|
@@ -8022,9 +8145,9 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
8022
8145
|
if (!repo.path)
|
|
8023
8146
|
continue;
|
|
8024
8147
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
8025
|
-
const outPath =
|
|
8148
|
+
const outPath = path15.join(baselineDir, filename);
|
|
8026
8149
|
const repoPath = expandHome(repo.path, homedir22);
|
|
8027
|
-
if (!
|
|
8150
|
+
if (!fs14.existsSync(repoPath)) {
|
|
8028
8151
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
8029
8152
|
# (skipped: path ${repoPath} does not exist)
|
|
8030
8153
|
`);
|
|
@@ -8091,7 +8214,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
8091
8214
|
}
|
|
8092
8215
|
function writeBaselineFile(outPath, content) {
|
|
8093
8216
|
try {
|
|
8094
|
-
|
|
8217
|
+
fs14.writeFileSync(outPath, content);
|
|
8095
8218
|
} catch (err) {
|
|
8096
8219
|
const msg = err instanceof Error ? err.message : String(err);
|
|
8097
8220
|
console.warn(`[baseline-diff] write to ${outPath} failed: ${msg}`);
|
|
@@ -8099,8 +8222,8 @@ function writeBaselineFile(outPath, content) {
|
|
|
8099
8222
|
}
|
|
8100
8223
|
function stripWorktreeEdits(repos, workspacePath) {
|
|
8101
8224
|
for (const repo of repos) {
|
|
8102
|
-
const worktreePath =
|
|
8103
|
-
if (!
|
|
8225
|
+
const worktreePath = path15.join(workspacePath, repo.name);
|
|
8226
|
+
if (!fs14.existsSync(worktreePath))
|
|
8104
8227
|
continue;
|
|
8105
8228
|
try {
|
|
8106
8229
|
execFileSync3("git", ["checkout", "--", "."], {
|
|
@@ -8137,12 +8260,12 @@ var init_baseline_diff = __esm({
|
|
|
8137
8260
|
});
|
|
8138
8261
|
|
|
8139
8262
|
// ../core/dist/world/context-injection.js
|
|
8140
|
-
import * as
|
|
8141
|
-
import * as
|
|
8263
|
+
import * as fs15 from "node:fs";
|
|
8264
|
+
import * as path16 from "node:path";
|
|
8142
8265
|
function injectWorldContext(opts) {
|
|
8143
8266
|
const { world, task, linearTicketId, claudeMdExtra, taskContext, services, pleriPlaneUrl } = opts;
|
|
8144
|
-
const claudeDir =
|
|
8145
|
-
|
|
8267
|
+
const claudeDir = path16.join(world.workspacePath, ".claude");
|
|
8268
|
+
fs15.mkdirSync(claudeDir, { recursive: true });
|
|
8146
8269
|
const sections = [];
|
|
8147
8270
|
sections.push(`# Olam World: ${world.name}`);
|
|
8148
8271
|
sections.push("");
|
|
@@ -8303,7 +8426,7 @@ function injectWorldContext(opts) {
|
|
|
8303
8426
|
sections.push("");
|
|
8304
8427
|
}
|
|
8305
8428
|
const content = sections.join("\n");
|
|
8306
|
-
|
|
8429
|
+
fs15.writeFileSync(path16.join(claudeDir, "CLAUDE.md"), content);
|
|
8307
8430
|
}
|
|
8308
8431
|
function formatTaskSource(ctx) {
|
|
8309
8432
|
if (ctx.source === "linear" && ctx.ticketId) {
|
|
@@ -8317,9 +8440,9 @@ function formatTaskSource(ctx) {
|
|
|
8317
8440
|
function hasPlanFile(world) {
|
|
8318
8441
|
if (world.repos.length === 0)
|
|
8319
8442
|
return false;
|
|
8320
|
-
const plansDir =
|
|
8443
|
+
const plansDir = path16.join(world.workspacePath, world.repos[0], "docs", "plans");
|
|
8321
8444
|
try {
|
|
8322
|
-
return
|
|
8445
|
+
return fs15.existsSync(plansDir) && fs15.readdirSync(plansDir).length > 0;
|
|
8323
8446
|
} catch {
|
|
8324
8447
|
return false;
|
|
8325
8448
|
}
|
|
@@ -8564,7 +8687,7 @@ var init_stack_install = __esm({
|
|
|
8564
8687
|
|
|
8565
8688
|
// ../core/dist/world/stack-image.js
|
|
8566
8689
|
import { execSync as execSync2 } from "node:child_process";
|
|
8567
|
-
import * as
|
|
8690
|
+
import * as crypto4 from "node:crypto";
|
|
8568
8691
|
function computeFingerprint(runtimes) {
|
|
8569
8692
|
const parts = [];
|
|
8570
8693
|
for (const [runtime, versions] of runtimes) {
|
|
@@ -8614,14 +8737,14 @@ function getBaseImageDigest() {
|
|
|
8614
8737
|
cachedBaseDigest = digest.replace("sha256:", "").slice(0, 16);
|
|
8615
8738
|
return cachedBaseDigest;
|
|
8616
8739
|
} catch {
|
|
8617
|
-
cachedBaseDigest =
|
|
8740
|
+
cachedBaseDigest = crypto4.createHash("sha256").update("unknown").digest("hex").slice(0, 16);
|
|
8618
8741
|
return cachedBaseDigest;
|
|
8619
8742
|
}
|
|
8620
8743
|
}
|
|
8621
8744
|
function sanitizeTag(raw) {
|
|
8622
8745
|
let tag = raw.toLowerCase().replace(/[^a-z0-9._-]/g, "-");
|
|
8623
8746
|
if (tag.length > MAX_TAG_LENGTH) {
|
|
8624
|
-
const hash =
|
|
8747
|
+
const hash = crypto4.createHash("sha256").update(raw).digest("hex").slice(0, 12);
|
|
8625
8748
|
tag = tag.slice(0, MAX_TAG_LENGTH - 13) + "_" + hash;
|
|
8626
8749
|
}
|
|
8627
8750
|
return tag;
|
|
@@ -9023,14 +9146,14 @@ var init_secrets_fetcher = __esm({
|
|
|
9023
9146
|
});
|
|
9024
9147
|
|
|
9025
9148
|
// ../core/dist/world/olam-yaml.js
|
|
9026
|
-
import * as
|
|
9149
|
+
import * as path17 from "node:path";
|
|
9027
9150
|
import YAML2 from "yaml";
|
|
9028
9151
|
function enrichReposWithManifests(repos, workspacePath) {
|
|
9029
9152
|
return repos.map((repo) => {
|
|
9030
9153
|
if (repo.manifest !== void 0 && repo.manifest !== null) {
|
|
9031
9154
|
return repo;
|
|
9032
9155
|
}
|
|
9033
|
-
const repoDir =
|
|
9156
|
+
const repoDir = path17.join(workspacePath, repo.name);
|
|
9034
9157
|
let manifest = null;
|
|
9035
9158
|
try {
|
|
9036
9159
|
manifest = loadRepoManifest(repoDir);
|
|
@@ -9051,8 +9174,8 @@ var init_olam_yaml = __esm({
|
|
|
9051
9174
|
});
|
|
9052
9175
|
|
|
9053
9176
|
// ../core/dist/policies/loader.js
|
|
9054
|
-
import * as
|
|
9055
|
-
import * as
|
|
9177
|
+
import * as fs16 from "node:fs";
|
|
9178
|
+
import * as path18 from "node:path";
|
|
9056
9179
|
import { parse as parseYaml3 } from "yaml";
|
|
9057
9180
|
function parseFrontmatter(content) {
|
|
9058
9181
|
const match2 = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
|
|
@@ -9072,20 +9195,20 @@ function toStringArray(v) {
|
|
|
9072
9195
|
return v.filter((x) => typeof x === "string");
|
|
9073
9196
|
}
|
|
9074
9197
|
function loadPolicies(workspaceRoot) {
|
|
9075
|
-
const policiesDir =
|
|
9076
|
-
if (!
|
|
9198
|
+
const policiesDir = path18.join(workspaceRoot, ".olam", "policies");
|
|
9199
|
+
if (!fs16.existsSync(policiesDir))
|
|
9077
9200
|
return [];
|
|
9078
9201
|
let files;
|
|
9079
9202
|
try {
|
|
9080
|
-
files =
|
|
9203
|
+
files = fs16.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
|
|
9081
9204
|
} catch {
|
|
9082
9205
|
return [];
|
|
9083
9206
|
}
|
|
9084
9207
|
const policies = [];
|
|
9085
9208
|
for (const file of files) {
|
|
9086
|
-
const filePath =
|
|
9209
|
+
const filePath = path18.join(policiesDir, file);
|
|
9087
9210
|
try {
|
|
9088
|
-
const content =
|
|
9211
|
+
const content = fs16.readFileSync(filePath, "utf8");
|
|
9089
9212
|
const parsed = parseFrontmatter(content);
|
|
9090
9213
|
if (!parsed) {
|
|
9091
9214
|
console.warn(`[policies] skipping ${file}: no valid frontmatter block`);
|
|
@@ -9249,6 +9372,7 @@ var manager_exports = {};
|
|
|
9249
9372
|
__export(manager_exports, {
|
|
9250
9373
|
AuthPreflightError: () => AuthPreflightError,
|
|
9251
9374
|
BotIdentityError: () => BotIdentityError,
|
|
9375
|
+
RepoSelectionRequiredError: () => RepoSelectionRequiredError,
|
|
9252
9376
|
WorkspaceNotFoundError: () => WorkspaceNotFoundError,
|
|
9253
9377
|
WorldManager: () => WorldManager,
|
|
9254
9378
|
buildManifestRuntimeForTest: () => buildManifestRuntime,
|
|
@@ -9257,11 +9381,11 @@ __export(manager_exports, {
|
|
|
9257
9381
|
planManifestPipeline: () => planManifestPipeline,
|
|
9258
9382
|
runManifestRuntime: () => runManifestRuntime
|
|
9259
9383
|
});
|
|
9260
|
-
import * as
|
|
9384
|
+
import * as crypto5 from "node:crypto";
|
|
9261
9385
|
import { execSync as execSync4 } from "node:child_process";
|
|
9262
|
-
import * as
|
|
9386
|
+
import * as fs17 from "node:fs";
|
|
9263
9387
|
import * as os10 from "node:os";
|
|
9264
|
-
import * as
|
|
9388
|
+
import * as path19 from "node:path";
|
|
9265
9389
|
import YAML3 from "yaml";
|
|
9266
9390
|
function getTokenScopes(ghToken, _exec = execSync4) {
|
|
9267
9391
|
try {
|
|
@@ -9343,12 +9467,42 @@ ${stderr.split("\n").slice(0, 3).join(" ")}`);
|
|
|
9343
9467
|
dockerExec(`cd ${repoDir} && git checkout -b ${branch}`);
|
|
9344
9468
|
}
|
|
9345
9469
|
if (ghToken) {
|
|
9470
|
+
const olamUserPresent = (() => {
|
|
9471
|
+
try {
|
|
9472
|
+
dockerExec(`id olam`);
|
|
9473
|
+
return true;
|
|
9474
|
+
} catch {
|
|
9475
|
+
return false;
|
|
9476
|
+
}
|
|
9477
|
+
})();
|
|
9478
|
+
if (!olamUserPresent) {
|
|
9479
|
+
const imageName = (() => {
|
|
9480
|
+
try {
|
|
9481
|
+
const { execSync: execSync12 } = __require("node:child_process");
|
|
9482
|
+
return execSync12(`docker inspect ${containerName} --format '{{.Config.Image}}'`, {
|
|
9483
|
+
encoding: "utf8",
|
|
9484
|
+
timeout: 5e3
|
|
9485
|
+
}).trim() || "(unknown)";
|
|
9486
|
+
} catch {
|
|
9487
|
+
return "(unknown)";
|
|
9488
|
+
}
|
|
9489
|
+
})();
|
|
9490
|
+
console.warn(`[world] gh auth setup skipped for ${containerName}: container has no \`olam\` user.
|
|
9491
|
+
Image: ${imageName}
|
|
9492
|
+
Likely cause: corrupt local image, a custom devbox image without
|
|
9493
|
+
the olam user (line 10 of devbox.Dockerfile), or NSS resolver
|
|
9494
|
+
failure under cross-arch QEMU emulation.
|
|
9495
|
+
Remedy: docker rmi olam-devbox:latest && olam upgrade -y
|
|
9496
|
+
(or set OLAM_DEVBOX_IMAGE to a known-good ref before \`olam create\`).
|
|
9497
|
+
PR push from inside the world will not work until this is resolved.`);
|
|
9498
|
+
return;
|
|
9499
|
+
}
|
|
9346
9500
|
let tokenWritten = false;
|
|
9347
9501
|
try {
|
|
9348
9502
|
dockerExec(`which gh || (sudo apt-get update -qq && sudo apt-get install -y -qq gh) 2>/dev/null`);
|
|
9349
9503
|
dockerExec(`printf '%s' '${ghToken.replace(/'/g, "'\\''")}' > /tmp/.gh-token && chmod 600 /tmp/.gh-token`);
|
|
9350
9504
|
tokenWritten = true;
|
|
9351
|
-
dockerExec(`sudo chown olam:olam /home/olam/.config`);
|
|
9505
|
+
dockerExec(`sudo chown olam:olam /home/olam/.config 2>/dev/null || true`);
|
|
9352
9506
|
dockerExec(`gh auth login --with-token < /tmp/.gh-token`);
|
|
9353
9507
|
dockerExec(`gh auth setup-git`);
|
|
9354
9508
|
} catch (err) {
|
|
@@ -9570,7 +9724,7 @@ function buildManifestRuntime(worldId, repos) {
|
|
|
9570
9724
|
}
|
|
9571
9725
|
return { worldId, repos: runtimeRepos };
|
|
9572
9726
|
}
|
|
9573
|
-
var BotIdentityError, ADJECTIVES, NOUNS, AuthPreflightError, WorkspaceNotFoundError, WorldManager;
|
|
9727
|
+
var BotIdentityError, ADJECTIVES, NOUNS, AuthPreflightError, WorkspaceNotFoundError, RepoSelectionRequiredError, WorldManager;
|
|
9574
9728
|
var init_manager = __esm({
|
|
9575
9729
|
"../core/dist/world/manager.js"() {
|
|
9576
9730
|
"use strict";
|
|
@@ -9619,6 +9773,15 @@ var init_manager = __esm({
|
|
|
9619
9773
|
this.name = "WorkspaceNotFoundError";
|
|
9620
9774
|
}
|
|
9621
9775
|
};
|
|
9776
|
+
RepoSelectionRequiredError = class extends Error {
|
|
9777
|
+
availableRepos;
|
|
9778
|
+
constructor(availableRepos) {
|
|
9779
|
+
const list = availableRepos.length > 0 ? availableRepos.join(", ") : "(none configured)";
|
|
9780
|
+
super(`--repos or --workspace is required. Available repos: ${list}. Pick the subset you actually want \u2014 implicit "all repos" was removed to prevent accidental multi-repo bootstraps.`);
|
|
9781
|
+
this.availableRepos = availableRepos;
|
|
9782
|
+
this.name = "RepoSelectionRequiredError";
|
|
9783
|
+
}
|
|
9784
|
+
};
|
|
9622
9785
|
WorldManager = class {
|
|
9623
9786
|
config;
|
|
9624
9787
|
provider;
|
|
@@ -9646,7 +9809,7 @@ var init_manager = __esm({
|
|
|
9646
9809
|
}
|
|
9647
9810
|
}
|
|
9648
9811
|
const worldId = generateWorldId();
|
|
9649
|
-
const workspacePath =
|
|
9812
|
+
const workspacePath = path19.join(os10.homedir(), ".olam", "worlds", worldId);
|
|
9650
9813
|
const portOffset = this.registry.getNextPortOffset();
|
|
9651
9814
|
const branch = opts.branchName ?? `olam/${worldId}`;
|
|
9652
9815
|
const repos = this.resolveReposWithWorkspace(opts);
|
|
@@ -9703,37 +9866,37 @@ var init_manager = __esm({
|
|
|
9703
9866
|
if (!repo.path)
|
|
9704
9867
|
continue;
|
|
9705
9868
|
const sourceRoot = repo.path.replace(/^~/, os10.homedir());
|
|
9706
|
-
const worktreeRoot =
|
|
9707
|
-
if (!
|
|
9869
|
+
const worktreeRoot = path19.join(workspacePath, repo.name);
|
|
9870
|
+
if (!fs17.existsSync(sourceRoot) || !fs17.existsSync(worktreeRoot))
|
|
9708
9871
|
continue;
|
|
9709
9872
|
let copied = 0;
|
|
9710
9873
|
for (const pattern of RUNTIME_FILE_PATTERNS) {
|
|
9711
9874
|
const matches2 = [];
|
|
9712
9875
|
if (pattern.includes("*")) {
|
|
9713
|
-
const [dir, glob] = [
|
|
9714
|
-
const sourceDir =
|
|
9715
|
-
if (
|
|
9876
|
+
const [dir, glob] = [path19.dirname(pattern), path19.basename(pattern)];
|
|
9877
|
+
const sourceDir = path19.join(sourceRoot, dir);
|
|
9878
|
+
if (fs17.existsSync(sourceDir)) {
|
|
9716
9879
|
const ext2 = glob.replace(/^\*+/, "");
|
|
9717
9880
|
try {
|
|
9718
|
-
for (const entry of
|
|
9881
|
+
for (const entry of fs17.readdirSync(sourceDir)) {
|
|
9719
9882
|
if (ext2 === "" || entry.endsWith(ext2))
|
|
9720
|
-
matches2.push(
|
|
9883
|
+
matches2.push(path19.join(dir, entry));
|
|
9721
9884
|
}
|
|
9722
9885
|
} catch {
|
|
9723
9886
|
}
|
|
9724
9887
|
}
|
|
9725
|
-
} else if (
|
|
9888
|
+
} else if (fs17.existsSync(path19.join(sourceRoot, pattern))) {
|
|
9726
9889
|
matches2.push(pattern);
|
|
9727
9890
|
}
|
|
9728
9891
|
for (const rel of matches2) {
|
|
9729
|
-
const src =
|
|
9730
|
-
const dst =
|
|
9892
|
+
const src = path19.join(sourceRoot, rel);
|
|
9893
|
+
const dst = path19.join(worktreeRoot, rel);
|
|
9731
9894
|
try {
|
|
9732
|
-
const st =
|
|
9895
|
+
const st = fs17.statSync(src);
|
|
9733
9896
|
if (!st.isFile())
|
|
9734
9897
|
continue;
|
|
9735
|
-
|
|
9736
|
-
|
|
9898
|
+
fs17.mkdirSync(path19.dirname(dst), { recursive: true });
|
|
9899
|
+
fs17.copyFileSync(src, dst);
|
|
9737
9900
|
copied++;
|
|
9738
9901
|
} catch {
|
|
9739
9902
|
}
|
|
@@ -9833,7 +9996,7 @@ var init_manager = __esm({
|
|
|
9833
9996
|
try {
|
|
9834
9997
|
const hostExec = makeHostExecFn();
|
|
9835
9998
|
for (const repo of repos) {
|
|
9836
|
-
const repoDir =
|
|
9999
|
+
const repoDir = path19.join(workspacePath, repo.name);
|
|
9837
10000
|
if (repo.stack && Object.keys(repo.stack).length > 0) {
|
|
9838
10001
|
preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
|
|
9839
10002
|
} else {
|
|
@@ -9890,10 +10053,10 @@ var init_manager = __esm({
|
|
|
9890
10053
|
const worldEnv = {};
|
|
9891
10054
|
if (opts.task)
|
|
9892
10055
|
worldEnv.OLAM_TASK = opts.task;
|
|
9893
|
-
const r2CredsPath =
|
|
9894
|
-
if (
|
|
10056
|
+
const r2CredsPath = path19.join(os10.homedir(), ".olam", "r2-credentials.json");
|
|
10057
|
+
if (fs17.existsSync(r2CredsPath)) {
|
|
9895
10058
|
try {
|
|
9896
|
-
const r2Raw =
|
|
10059
|
+
const r2Raw = fs17.readFileSync(r2CredsPath, "utf-8").trim();
|
|
9897
10060
|
if (r2Raw.length > 0) {
|
|
9898
10061
|
const r2 = JSON.parse(r2Raw);
|
|
9899
10062
|
if (typeof r2.account_id === "string")
|
|
@@ -9910,10 +10073,10 @@ var init_manager = __esm({
|
|
|
9910
10073
|
} catch {
|
|
9911
10074
|
}
|
|
9912
10075
|
}
|
|
9913
|
-
const keysYamlPath =
|
|
9914
|
-
if (
|
|
10076
|
+
const keysYamlPath = path19.join(os10.homedir(), ".olam", "keys.yaml");
|
|
10077
|
+
if (fs17.existsSync(keysYamlPath)) {
|
|
9915
10078
|
try {
|
|
9916
|
-
const keysRaw =
|
|
10079
|
+
const keysRaw = fs17.readFileSync(keysYamlPath, "utf-8").trim();
|
|
9917
10080
|
if (keysRaw.length > 0) {
|
|
9918
10081
|
const parsed = YAML3.parse(keysRaw);
|
|
9919
10082
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
@@ -9960,10 +10123,10 @@ var init_manager = __esm({
|
|
|
9960
10123
|
worldEnv[k] = v;
|
|
9961
10124
|
}
|
|
9962
10125
|
for (const { repoName, relativePath, content } of fileWrites) {
|
|
9963
|
-
const absPath =
|
|
10126
|
+
const absPath = path19.join(workspacePath, repoName, relativePath);
|
|
9964
10127
|
try {
|
|
9965
|
-
|
|
9966
|
-
|
|
10128
|
+
fs17.mkdirSync(path19.dirname(absPath), { recursive: true });
|
|
10129
|
+
fs17.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
|
|
9967
10130
|
mode: 384
|
|
9968
10131
|
});
|
|
9969
10132
|
console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
|
|
@@ -10115,7 +10278,7 @@ var init_manager = __esm({
|
|
|
10115
10278
|
let taskWithPolicies = opts.task;
|
|
10116
10279
|
try {
|
|
10117
10280
|
const allPolicies = repos.flatMap((repo) => {
|
|
10118
|
-
const repoWorktree =
|
|
10281
|
+
const repoWorktree = path19.join(workspacePath, repo.name);
|
|
10119
10282
|
return loadPolicies(repoWorktree);
|
|
10120
10283
|
});
|
|
10121
10284
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -10131,8 +10294,8 @@ var init_manager = __esm({
|
|
|
10131
10294
|
${opts.task}`;
|
|
10132
10295
|
execSync4(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
|
|
10133
10296
|
for (const repo of repos) {
|
|
10134
|
-
const policiesDir =
|
|
10135
|
-
if (
|
|
10297
|
+
const policiesDir = path19.join(workspacePath, repo.name, ".olam", "policies");
|
|
10298
|
+
if (fs17.existsSync(policiesDir)) {
|
|
10136
10299
|
execSync4(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
|
|
10137
10300
|
}
|
|
10138
10301
|
}
|
|
@@ -10211,8 +10374,8 @@ ${opts.task}`;
|
|
|
10211
10374
|
} catch {
|
|
10212
10375
|
}
|
|
10213
10376
|
try {
|
|
10214
|
-
|
|
10215
|
-
if (
|
|
10377
|
+
fs17.rmSync(world.workspacePath, { recursive: true, force: true });
|
|
10378
|
+
if (fs17.existsSync(world.workspacePath)) {
|
|
10216
10379
|
console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
|
|
10217
10380
|
}
|
|
10218
10381
|
} catch (err) {
|
|
@@ -10267,7 +10430,10 @@ ${opts.task}`;
|
|
|
10267
10430
|
* Resolution precedence (matches the CF worker exactly):
|
|
10268
10431
|
* 1. inline `opts.repos` names → look up in `config.repos`
|
|
10269
10432
|
* 2. named `opts.workspace` → load catalog YAML, map via workspaceToRepoConfigs
|
|
10270
|
-
* 3.
|
|
10433
|
+
* 3. neither → throw `RepoSelectionRequiredError`. The historical
|
|
10434
|
+
* "include every repo in config.yaml" fallback silently fanned a
|
|
10435
|
+
* single-repo audit into 7-repo bootstraps and steered
|
|
10436
|
+
* `image_selectors` to a wider tag than intended.
|
|
10271
10437
|
*/
|
|
10272
10438
|
resolveReposWithWorkspace(opts) {
|
|
10273
10439
|
if (opts.repos && opts.repos.length > 0) {
|
|
@@ -10279,7 +10445,7 @@ ${opts.task}`;
|
|
|
10279
10445
|
throw new WorkspaceNotFoundError(opts.workspace);
|
|
10280
10446
|
return workspaceToRepoConfigs(ws);
|
|
10281
10447
|
}
|
|
10282
|
-
|
|
10448
|
+
throw new RepoSelectionRequiredError(this.config.repos.map((r) => r.name));
|
|
10283
10449
|
}
|
|
10284
10450
|
resolveRepos(repoNames) {
|
|
10285
10451
|
if (!repoNames || repoNames.length === 0) {
|
|
@@ -10297,14 +10463,14 @@ ${opts.task}`;
|
|
|
10297
10463
|
return names.map((name) => this.config.repos.find((r) => r.name === name)).filter((r) => r !== void 0);
|
|
10298
10464
|
}
|
|
10299
10465
|
transportPlanFile(planFilePath, workspacePath, repoNames) {
|
|
10300
|
-
const planContent =
|
|
10301
|
-
const planFileName =
|
|
10466
|
+
const planContent = fs17.readFileSync(planFilePath, "utf-8");
|
|
10467
|
+
const planFileName = path19.basename(planFilePath);
|
|
10302
10468
|
const targetRepo = repoNames[0];
|
|
10303
10469
|
if (!targetRepo)
|
|
10304
10470
|
return;
|
|
10305
|
-
const plansDir =
|
|
10306
|
-
|
|
10307
|
-
|
|
10471
|
+
const plansDir = path19.join(workspacePath, targetRepo, "docs", "plans");
|
|
10472
|
+
fs17.mkdirSync(plansDir, { recursive: true });
|
|
10473
|
+
fs17.writeFileSync(path19.join(plansDir, planFileName), planContent);
|
|
10308
10474
|
}
|
|
10309
10475
|
resolveServices(repos) {
|
|
10310
10476
|
const services = [];
|
|
@@ -10397,9 +10563,9 @@ var init_tracker = __esm({
|
|
|
10397
10563
|
});
|
|
10398
10564
|
|
|
10399
10565
|
// ../core/dist/world-paths.js
|
|
10400
|
-
import * as
|
|
10566
|
+
import * as path20 from "node:path";
|
|
10401
10567
|
function getWorldDbPath(workspacePath) {
|
|
10402
|
-
return
|
|
10568
|
+
return path20.join(workspacePath, WORLD_DB_FILENAME);
|
|
10403
10569
|
}
|
|
10404
10570
|
var WORLD_DB_FILENAME;
|
|
10405
10571
|
var init_world_paths = __esm({
|
|
@@ -11017,8 +11183,8 @@ var init_session_aggregator = __esm({
|
|
|
11017
11183
|
|
|
11018
11184
|
// ../core/dist/dashboard/server.js
|
|
11019
11185
|
import * as http from "node:http";
|
|
11020
|
-
import * as
|
|
11021
|
-
import * as
|
|
11186
|
+
import * as fs18 from "node:fs";
|
|
11187
|
+
import * as path21 from "node:path";
|
|
11022
11188
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
11023
11189
|
function jsonResponse(res, data, status = 200) {
|
|
11024
11190
|
res.writeHead(status, { "Content-Type": "application/json; charset=utf-8" });
|
|
@@ -11029,7 +11195,7 @@ function notFound(res) {
|
|
|
11029
11195
|
}
|
|
11030
11196
|
function openThoughtStore(workspacePath) {
|
|
11031
11197
|
const dbPath = getWorldDbPath(workspacePath);
|
|
11032
|
-
if (!
|
|
11198
|
+
if (!fs18.existsSync(dbPath))
|
|
11033
11199
|
return null;
|
|
11034
11200
|
return new ThoughtLocalStore(dbPath);
|
|
11035
11201
|
}
|
|
@@ -11200,13 +11366,13 @@ function findSessionInWorld(registry, sessionId) {
|
|
|
11200
11366
|
}
|
|
11201
11367
|
function createDashboardServer(opts) {
|
|
11202
11368
|
const { port, registry } = opts;
|
|
11203
|
-
const thisDir =
|
|
11204
|
-
const defaultPublicDir =
|
|
11369
|
+
const thisDir = path21.dirname(fileURLToPath2(import.meta.url));
|
|
11370
|
+
const defaultPublicDir = path21.resolve(thisDir, "../../../control-plane/public");
|
|
11205
11371
|
const publicDir = opts.publicDir ?? defaultPublicDir;
|
|
11206
|
-
let hasPublicDir =
|
|
11372
|
+
let hasPublicDir = fs18.existsSync(publicDir);
|
|
11207
11373
|
const server = http.createServer((req, res) => {
|
|
11208
11374
|
if (!hasPublicDir) {
|
|
11209
|
-
hasPublicDir =
|
|
11375
|
+
hasPublicDir = fs18.existsSync(publicDir);
|
|
11210
11376
|
}
|
|
11211
11377
|
const host = req.headers.host ?? `localhost:${port}`;
|
|
11212
11378
|
const url = new URL(req.url ?? "/", `http://${host}`);
|
|
@@ -11480,22 +11646,22 @@ function createDashboardServer(opts) {
|
|
|
11480
11646
|
res.end(`<html><body style="font-family:system-ui;padding:2rem"><h1>Olam Dashboard</h1><p>The React app has not been built yet.</p><p>Run <code>npm run build:app</code> in <code>packages/control-plane</code> to build it.</p><p>API routes are available at <code>/api/*</code>.</p></body></html>`);
|
|
11481
11647
|
return;
|
|
11482
11648
|
}
|
|
11483
|
-
let filePath =
|
|
11649
|
+
let filePath = path21.join(publicDir, pathname === "/" ? "index.html" : pathname);
|
|
11484
11650
|
if (!filePath.startsWith(publicDir)) {
|
|
11485
11651
|
notFound(res);
|
|
11486
11652
|
return;
|
|
11487
11653
|
}
|
|
11488
|
-
if (
|
|
11489
|
-
const ext2 =
|
|
11654
|
+
if (fs18.existsSync(filePath) && fs18.statSync(filePath).isFile()) {
|
|
11655
|
+
const ext2 = path21.extname(filePath);
|
|
11490
11656
|
const contentType = MIME[ext2] ?? "application/octet-stream";
|
|
11491
11657
|
res.writeHead(200, { "Content-Type": contentType });
|
|
11492
|
-
|
|
11658
|
+
fs18.createReadStream(filePath).pipe(res);
|
|
11493
11659
|
return;
|
|
11494
11660
|
}
|
|
11495
|
-
filePath =
|
|
11496
|
-
if (
|
|
11661
|
+
filePath = path21.join(publicDir, "index.html");
|
|
11662
|
+
if (fs18.existsSync(filePath)) {
|
|
11497
11663
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
11498
|
-
|
|
11664
|
+
fs18.createReadStream(filePath).pipe(res);
|
|
11499
11665
|
return;
|
|
11500
11666
|
}
|
|
11501
11667
|
notFound(res);
|
|
@@ -11526,16 +11692,16 @@ var init_server = __esm({
|
|
|
11526
11692
|
});
|
|
11527
11693
|
|
|
11528
11694
|
// ../core/dist/dashboard/state.js
|
|
11529
|
-
import * as
|
|
11695
|
+
import * as fs19 from "node:fs";
|
|
11530
11696
|
import * as os11 from "node:os";
|
|
11531
|
-
import * as
|
|
11697
|
+
import * as path22 from "node:path";
|
|
11532
11698
|
function saveDashboardState(state) {
|
|
11533
|
-
|
|
11534
|
-
|
|
11699
|
+
fs19.mkdirSync(path22.dirname(STATE_PATH), { recursive: true });
|
|
11700
|
+
fs19.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
|
|
11535
11701
|
}
|
|
11536
11702
|
function loadDashboardState() {
|
|
11537
11703
|
try {
|
|
11538
|
-
const raw =
|
|
11704
|
+
const raw = fs19.readFileSync(STATE_PATH, "utf-8");
|
|
11539
11705
|
return JSON.parse(raw);
|
|
11540
11706
|
} catch {
|
|
11541
11707
|
return null;
|
|
@@ -11543,7 +11709,7 @@ function loadDashboardState() {
|
|
|
11543
11709
|
}
|
|
11544
11710
|
function clearDashboardState() {
|
|
11545
11711
|
try {
|
|
11546
|
-
|
|
11712
|
+
fs19.unlinkSync(STATE_PATH);
|
|
11547
11713
|
} catch {
|
|
11548
11714
|
}
|
|
11549
11715
|
}
|
|
@@ -11563,7 +11729,7 @@ var STATE_PATH;
|
|
|
11563
11729
|
var init_state2 = __esm({
|
|
11564
11730
|
"../core/dist/dashboard/state.js"() {
|
|
11565
11731
|
"use strict";
|
|
11566
|
-
STATE_PATH =
|
|
11732
|
+
STATE_PATH = path22.join(os11.homedir(), ".olam", "dashboard.json");
|
|
11567
11733
|
}
|
|
11568
11734
|
});
|
|
11569
11735
|
|
|
@@ -11957,51 +12123,51 @@ __export(host_cp_exports, {
|
|
|
11957
12123
|
writePid: () => writePid,
|
|
11958
12124
|
writeToken: () => writeToken
|
|
11959
12125
|
});
|
|
11960
|
-
import * as
|
|
11961
|
-
import * as
|
|
12126
|
+
import * as crypto6 from "node:crypto";
|
|
12127
|
+
import * as fs20 from "node:fs";
|
|
11962
12128
|
import * as os12 from "node:os";
|
|
11963
|
-
import * as
|
|
12129
|
+
import * as path23 from "node:path";
|
|
11964
12130
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
11965
12131
|
import Dockerode2 from "dockerode";
|
|
11966
12132
|
function findComposeFile() {
|
|
11967
12133
|
const candidates = [
|
|
11968
12134
|
// Bundled path: dist/index.js lives at <pkg>/dist/; host-cp/ is a sibling of dist/
|
|
11969
|
-
|
|
12135
|
+
path23.resolve(path23.dirname(new URL(import.meta.url).pathname), "../host-cp/compose.yaml"),
|
|
11970
12136
|
// Source-mode: cwd is monorepo root
|
|
11971
|
-
|
|
12137
|
+
path23.resolve(process.cwd(), "packages/host-cp/compose.yaml"),
|
|
11972
12138
|
// Source-mode: cwd is one level inside the monorepo
|
|
11973
|
-
|
|
12139
|
+
path23.resolve(process.cwd(), "../packages/host-cp/compose.yaml")
|
|
11974
12140
|
];
|
|
11975
12141
|
for (const c of candidates) {
|
|
11976
|
-
if (
|
|
12142
|
+
if (fs20.existsSync(c)) return c;
|
|
11977
12143
|
}
|
|
11978
|
-
return
|
|
12144
|
+
return path23.resolve(process.cwd(), "packages/host-cp/compose.yaml");
|
|
11979
12145
|
}
|
|
11980
12146
|
function olamHome() {
|
|
11981
|
-
return process.env.OLAM_HOME ??
|
|
12147
|
+
return process.env.OLAM_HOME ?? path23.join(os12.homedir(), ".olam");
|
|
11982
12148
|
}
|
|
11983
12149
|
function tokenPath() {
|
|
11984
|
-
return
|
|
12150
|
+
return path23.join(olamHome(), "host-cp.token");
|
|
11985
12151
|
}
|
|
11986
12152
|
function pidPath() {
|
|
11987
|
-
return
|
|
12153
|
+
return path23.join(olamHome(), "host-cp.pid");
|
|
11988
12154
|
}
|
|
11989
12155
|
function authSecretPath() {
|
|
11990
|
-
return
|
|
12156
|
+
return path23.join(olamHome(), "auth-secret");
|
|
11991
12157
|
}
|
|
11992
12158
|
function readAuthSecret2() {
|
|
11993
12159
|
const filePath = authSecretPath();
|
|
11994
|
-
if (!
|
|
11995
|
-
const raw =
|
|
12160
|
+
if (!fs20.existsSync(filePath)) return null;
|
|
12161
|
+
const raw = fs20.readFileSync(filePath, "utf-8").trim();
|
|
11996
12162
|
return raw.length > 0 ? raw : null;
|
|
11997
12163
|
}
|
|
11998
12164
|
function r2CredentialsPath() {
|
|
11999
|
-
return
|
|
12165
|
+
return path23.join(olamHome(), "r2-credentials.json");
|
|
12000
12166
|
}
|
|
12001
12167
|
function readR2Credentials() {
|
|
12002
12168
|
const filePath = r2CredentialsPath();
|
|
12003
|
-
if (!
|
|
12004
|
-
const raw =
|
|
12169
|
+
if (!fs20.existsSync(filePath)) return null;
|
|
12170
|
+
const raw = fs20.readFileSync(filePath, "utf-8").trim();
|
|
12005
12171
|
if (raw.length === 0) return null;
|
|
12006
12172
|
try {
|
|
12007
12173
|
const parsed = JSON.parse(raw);
|
|
@@ -12022,39 +12188,39 @@ function readR2Credentials() {
|
|
|
12022
12188
|
}
|
|
12023
12189
|
}
|
|
12024
12190
|
function writeToken() {
|
|
12025
|
-
const token =
|
|
12191
|
+
const token = crypto6.randomBytes(32).toString("hex");
|
|
12026
12192
|
const filePath = tokenPath();
|
|
12027
|
-
|
|
12028
|
-
|
|
12193
|
+
fs20.mkdirSync(path23.dirname(filePath), { recursive: true });
|
|
12194
|
+
fs20.writeFileSync(filePath, token, { mode: 384 });
|
|
12029
12195
|
return token;
|
|
12030
12196
|
}
|
|
12031
12197
|
function readToken() {
|
|
12032
12198
|
const filePath = tokenPath();
|
|
12033
|
-
if (!
|
|
12034
|
-
return
|
|
12199
|
+
if (!fs20.existsSync(filePath)) return null;
|
|
12200
|
+
return fs20.readFileSync(filePath, "utf-8").trim();
|
|
12035
12201
|
}
|
|
12036
12202
|
function removeToken() {
|
|
12037
12203
|
const filePath = tokenPath();
|
|
12038
|
-
if (!
|
|
12039
|
-
|
|
12204
|
+
if (!fs20.existsSync(filePath)) return false;
|
|
12205
|
+
fs20.unlinkSync(filePath);
|
|
12040
12206
|
return true;
|
|
12041
12207
|
}
|
|
12042
12208
|
function writePid(pid) {
|
|
12043
12209
|
const filePath = pidPath();
|
|
12044
|
-
|
|
12045
|
-
|
|
12210
|
+
fs20.mkdirSync(path23.dirname(filePath), { recursive: true });
|
|
12211
|
+
fs20.writeFileSync(filePath, String(pid), { mode: 420 });
|
|
12046
12212
|
}
|
|
12047
12213
|
function readPid() {
|
|
12048
12214
|
const filePath = pidPath();
|
|
12049
|
-
if (!
|
|
12050
|
-
const raw =
|
|
12215
|
+
if (!fs20.existsSync(filePath)) return null;
|
|
12216
|
+
const raw = fs20.readFileSync(filePath, "utf-8").trim();
|
|
12051
12217
|
const n = parseInt(raw, 10);
|
|
12052
12218
|
return Number.isFinite(n) ? n : null;
|
|
12053
12219
|
}
|
|
12054
12220
|
function removePid() {
|
|
12055
12221
|
const filePath = pidPath();
|
|
12056
|
-
if (!
|
|
12057
|
-
|
|
12222
|
+
if (!fs20.existsSync(filePath)) return false;
|
|
12223
|
+
fs20.unlinkSync(filePath);
|
|
12058
12224
|
return true;
|
|
12059
12225
|
}
|
|
12060
12226
|
async function findHostCpContainer() {
|
|
@@ -12213,7 +12379,7 @@ async function handleStart(opts) {
|
|
|
12213
12379
|
}
|
|
12214
12380
|
const token = writeToken();
|
|
12215
12381
|
const composeFile = findComposeFile();
|
|
12216
|
-
if (!
|
|
12382
|
+
if (!fs20.existsSync(composeFile)) {
|
|
12217
12383
|
printError(`compose.yaml not found at ${composeFile}. Run from the olam project root.`);
|
|
12218
12384
|
removeToken();
|
|
12219
12385
|
process.exitCode = 1;
|
|
@@ -12295,7 +12461,7 @@ async function stopHostCp() {
|
|
|
12295
12461
|
}
|
|
12296
12462
|
async function handleStop() {
|
|
12297
12463
|
const composeFile = findComposeFile();
|
|
12298
|
-
if (!
|
|
12464
|
+
if (!fs20.existsSync(composeFile)) {
|
|
12299
12465
|
printWarning(`compose.yaml not found at ${composeFile}. Cleaning up token + PID anyway.`);
|
|
12300
12466
|
removeToken();
|
|
12301
12467
|
removePid();
|
|
@@ -12323,13 +12489,13 @@ async function buildStatusReport() {
|
|
|
12323
12489
|
const container = await findHostCpContainer();
|
|
12324
12490
|
const health = await probeHealth();
|
|
12325
12491
|
const tokenFile = tokenPath();
|
|
12326
|
-
const tokenPresent =
|
|
12492
|
+
const tokenPresent = fs20.existsSync(tokenFile);
|
|
12327
12493
|
let tokenModeOk = false;
|
|
12328
12494
|
if (tokenPresent) {
|
|
12329
|
-
const mode =
|
|
12495
|
+
const mode = fs20.statSync(tokenFile).mode & 511;
|
|
12330
12496
|
tokenModeOk = mode === 384;
|
|
12331
12497
|
}
|
|
12332
|
-
const pidPresent =
|
|
12498
|
+
const pidPresent = fs20.existsSync(pidPath());
|
|
12333
12499
|
let stack;
|
|
12334
12500
|
if (!container) {
|
|
12335
12501
|
stack = "not_started";
|
|
@@ -12417,13 +12583,13 @@ async function discoverWorldPort(worldId) {
|
|
|
12417
12583
|
}
|
|
12418
12584
|
async function readHostCpToken2() {
|
|
12419
12585
|
const tp = tokenPath();
|
|
12420
|
-
if (!
|
|
12421
|
-
return
|
|
12586
|
+
if (!fs20.existsSync(tp)) return null;
|
|
12587
|
+
return fs20.readFileSync(tp, "utf-8").trim();
|
|
12422
12588
|
}
|
|
12423
|
-
async function callHostCpProxy(method, worldId,
|
|
12589
|
+
async function callHostCpProxy(method, worldId, path45, body) {
|
|
12424
12590
|
const token = await readHostCpToken2();
|
|
12425
12591
|
if (!token) return { ok: false, status: 0, error: "no token (host CP not started)" };
|
|
12426
|
-
const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${
|
|
12592
|
+
const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path45}`;
|
|
12427
12593
|
try {
|
|
12428
12594
|
const headers = {
|
|
12429
12595
|
Authorization: `Bearer ${token}`
|
|
@@ -12548,17 +12714,17 @@ __export(install_root_exports, {
|
|
|
12548
12714
|
isDevMode: () => isDevMode,
|
|
12549
12715
|
resolveBuildScript: () => resolveBuildScript
|
|
12550
12716
|
});
|
|
12551
|
-
import { existsSync as
|
|
12552
|
-
import { dirname as
|
|
12717
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
12718
|
+
import { dirname as dirname14, join as join24, resolve as resolve6 } from "node:path";
|
|
12553
12719
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
12554
12720
|
function installRoot(metaUrl = import.meta.url) {
|
|
12555
12721
|
const here = fileURLToPath3(metaUrl);
|
|
12556
|
-
return resolve6(
|
|
12722
|
+
return resolve6(dirname14(here), "..");
|
|
12557
12723
|
}
|
|
12558
12724
|
function isDevMode(env = process.env, installRootDir = installRoot()) {
|
|
12559
12725
|
if (env.OLAM_DEV !== "1") return false;
|
|
12560
12726
|
const repoRoot = resolve6(installRootDir, "..", "..");
|
|
12561
|
-
return
|
|
12727
|
+
return existsSync19(join24(repoRoot, "packages")) && existsSync19(join24(repoRoot, "package.json"));
|
|
12562
12728
|
}
|
|
12563
12729
|
function resolveBuildScript(input) {
|
|
12564
12730
|
const { scriptRelPath, env = process.env, installRootDir = installRoot() } = input;
|
|
@@ -12737,20 +12903,20 @@ var init_registry_allowlist = __esm({
|
|
|
12737
12903
|
});
|
|
12738
12904
|
|
|
12739
12905
|
// ../core/dist/world/world-yaml.js
|
|
12740
|
-
import * as
|
|
12741
|
-
import * as
|
|
12906
|
+
import * as fs22 from "node:fs";
|
|
12907
|
+
import * as path25 from "node:path";
|
|
12742
12908
|
import { parse as parseYaml4, stringify as stringifyYaml4 } from "yaml";
|
|
12743
12909
|
function writeWorldYaml(worldPath, data) {
|
|
12744
|
-
const olamDir =
|
|
12745
|
-
|
|
12746
|
-
|
|
12910
|
+
const olamDir = path25.join(worldPath, ".olam");
|
|
12911
|
+
fs22.mkdirSync(olamDir, { recursive: true });
|
|
12912
|
+
fs22.writeFileSync(path25.join(olamDir, "world.yaml"), stringifyYaml4(data), "utf-8");
|
|
12747
12913
|
}
|
|
12748
12914
|
function readWorldYaml(worldPath) {
|
|
12749
|
-
const yamlPath =
|
|
12750
|
-
if (!
|
|
12915
|
+
const yamlPath = path25.join(worldPath, ".olam", "world.yaml");
|
|
12916
|
+
if (!fs22.existsSync(yamlPath))
|
|
12751
12917
|
return null;
|
|
12752
12918
|
try {
|
|
12753
|
-
const raw =
|
|
12919
|
+
const raw = fs22.readFileSync(yamlPath, "utf-8");
|
|
12754
12920
|
const parsed = parseYaml4(raw);
|
|
12755
12921
|
return WorldYamlSchema.parse(parsed);
|
|
12756
12922
|
} catch {
|
|
@@ -12881,16 +13047,16 @@ __export(machine_schema_exports, {
|
|
|
12881
13047
|
readMachineConfig: () => readMachineConfig,
|
|
12882
13048
|
writeMachineConfig: () => writeMachineConfig
|
|
12883
13049
|
});
|
|
12884
|
-
import * as
|
|
12885
|
-
import * as
|
|
13050
|
+
import * as fs36 from "node:fs";
|
|
13051
|
+
import * as path40 from "node:path";
|
|
12886
13052
|
import * as os21 from "node:os";
|
|
12887
13053
|
import { parse as parseYaml5, stringify as stringifyYaml5 } from "yaml";
|
|
12888
13054
|
function readMachineConfig(configPath) {
|
|
12889
13055
|
const p = configPath ?? DEFAULT_CONFIG_PATH;
|
|
12890
|
-
if (!
|
|
13056
|
+
if (!fs36.existsSync(p))
|
|
12891
13057
|
return null;
|
|
12892
13058
|
try {
|
|
12893
|
-
const raw =
|
|
13059
|
+
const raw = fs36.readFileSync(p, "utf-8");
|
|
12894
13060
|
const parsed = parseYaml5(raw);
|
|
12895
13061
|
return MachineConfigSchema.parse(parsed);
|
|
12896
13062
|
} catch {
|
|
@@ -12899,8 +13065,8 @@ function readMachineConfig(configPath) {
|
|
|
12899
13065
|
}
|
|
12900
13066
|
function writeMachineConfig(config, configPath) {
|
|
12901
13067
|
const p = configPath ?? DEFAULT_CONFIG_PATH;
|
|
12902
|
-
|
|
12903
|
-
|
|
13068
|
+
fs36.mkdirSync(path40.dirname(p), { recursive: true });
|
|
13069
|
+
fs36.writeFileSync(p, stringifyYaml5({ ...config }), { mode: 420 });
|
|
12904
13070
|
}
|
|
12905
13071
|
function initMachineConfig(opts = {}) {
|
|
12906
13072
|
const configPath = opts.configPath ?? DEFAULT_CONFIG_PATH;
|
|
@@ -12923,16 +13089,16 @@ var init_machine_schema = __esm({
|
|
|
12923
13089
|
channel: external_exports.enum(["stable", "beta", "edge"]).default("stable"),
|
|
12924
13090
|
auto_update: external_exports.boolean().default(true),
|
|
12925
13091
|
telemetry: external_exports.boolean().default(true),
|
|
12926
|
-
worlds_dir: external_exports.string().default(() =>
|
|
13092
|
+
worlds_dir: external_exports.string().default(() => path40.join(os21.homedir(), ".olam", "worlds"))
|
|
12927
13093
|
});
|
|
12928
|
-
DEFAULT_CONFIG_PATH =
|
|
13094
|
+
DEFAULT_CONFIG_PATH = path40.join(os21.homedir(), ".olam", "config.yaml");
|
|
12929
13095
|
}
|
|
12930
13096
|
});
|
|
12931
13097
|
|
|
12932
13098
|
// src/index.ts
|
|
12933
13099
|
import { Command } from "commander";
|
|
12934
|
-
import * as
|
|
12935
|
-
import * as
|
|
13100
|
+
import * as fs40 from "node:fs";
|
|
13101
|
+
import * as path44 from "node:path";
|
|
12936
13102
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
12937
13103
|
|
|
12938
13104
|
// src/commands/init.ts
|
|
@@ -13309,9 +13475,9 @@ var UnknownArchetypeError = class extends Error {
|
|
|
13309
13475
|
};
|
|
13310
13476
|
var ArchetypeCycleError = class extends Error {
|
|
13311
13477
|
path;
|
|
13312
|
-
constructor(
|
|
13313
|
-
super(`Archetype inheritance cycle detected: ${
|
|
13314
|
-
this.path =
|
|
13478
|
+
constructor(path45) {
|
|
13479
|
+
super(`Archetype inheritance cycle detected: ${path45.join(" \u2192 ")} \u2192 ${path45[0] ?? "?"}`);
|
|
13480
|
+
this.path = path45;
|
|
13315
13481
|
this.name = "ArchetypeCycleError";
|
|
13316
13482
|
}
|
|
13317
13483
|
};
|
|
@@ -13680,8 +13846,8 @@ async function runAuthStatus(getStatus) {
|
|
|
13680
13846
|
init_output();
|
|
13681
13847
|
init_host_cp();
|
|
13682
13848
|
init_auth();
|
|
13683
|
-
import * as
|
|
13684
|
-
import * as
|
|
13849
|
+
import * as fs21 from "node:fs";
|
|
13850
|
+
import * as path24 from "node:path";
|
|
13685
13851
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
13686
13852
|
import ora2 from "ora";
|
|
13687
13853
|
import pc7 from "picocolors";
|
|
@@ -13692,20 +13858,20 @@ init_exit_codes();
|
|
|
13692
13858
|
init_protocol_version();
|
|
13693
13859
|
init_output();
|
|
13694
13860
|
import { spawn as spawn2, spawnSync as spawnSync6 } from "node:child_process";
|
|
13695
|
-
import { existsSync as
|
|
13861
|
+
import { existsSync as existsSync20, readFileSync as readFileSync16 } from "node:fs";
|
|
13696
13862
|
import { join as join25 } from "node:path";
|
|
13697
13863
|
import ora from "ora";
|
|
13698
13864
|
import pc6 from "picocolors";
|
|
13699
13865
|
function loadImageDigests(installRootDir = installRoot()) {
|
|
13700
13866
|
const digestsPath = join25(installRootDir, "dist", "image-digests.json");
|
|
13701
|
-
if (!
|
|
13867
|
+
if (!existsSync20(digestsPath)) {
|
|
13702
13868
|
throw new Error(
|
|
13703
13869
|
`image-digests.json missing at ${digestsPath}. Re-run \`npm install -g @pleri/olam-cli@<version>\` to refresh the tarball.`
|
|
13704
13870
|
);
|
|
13705
13871
|
}
|
|
13706
13872
|
let parsed;
|
|
13707
13873
|
try {
|
|
13708
|
-
parsed = JSON.parse(
|
|
13874
|
+
parsed = JSON.parse(readFileSync16(digestsPath, "utf8"));
|
|
13709
13875
|
} catch (err) {
|
|
13710
13876
|
throw new Error(`image-digests.json is not valid JSON: ${err.message}`);
|
|
13711
13877
|
}
|
|
@@ -14005,8 +14171,8 @@ function parseAuthUpgradeOpts(raw) {
|
|
|
14005
14171
|
};
|
|
14006
14172
|
}
|
|
14007
14173
|
function validateAuthRepoRoot(cwd) {
|
|
14008
|
-
const marker =
|
|
14009
|
-
if (!
|
|
14174
|
+
const marker = path24.join(cwd, "packages/auth-service/Dockerfile");
|
|
14175
|
+
if (!fs21.existsSync(marker)) {
|
|
14010
14176
|
return {
|
|
14011
14177
|
ok: false,
|
|
14012
14178
|
error: `Not an olam repo root (expected ${marker}).
|
|
@@ -14579,14 +14745,14 @@ ${pc8.dim("Next: olam create --name my-world")}`);
|
|
|
14579
14745
|
// src/commands/create.ts
|
|
14580
14746
|
init_manager();
|
|
14581
14747
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
14582
|
-
import { existsSync as
|
|
14583
|
-
import { dirname as
|
|
14748
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
14749
|
+
import { dirname as dirname15, resolve as resolve7 } from "node:path";
|
|
14584
14750
|
import ora3 from "ora";
|
|
14585
14751
|
import pc9 from "picocolors";
|
|
14586
14752
|
|
|
14587
14753
|
// ../core/dist/world/devbox-freshness.js
|
|
14588
14754
|
import { execSync as execSync6 } from "node:child_process";
|
|
14589
|
-
import { existsSync as
|
|
14755
|
+
import { existsSync as existsSync22, statSync as statSync5 } from "node:fs";
|
|
14590
14756
|
import { join as join27 } from "node:path";
|
|
14591
14757
|
var DEFAULT_DEVBOX_IMAGE = "olam-devbox:latest";
|
|
14592
14758
|
var DEVBOX_BAKED_SOURCES = [
|
|
@@ -14595,6 +14761,7 @@ var DEVBOX_BAKED_SOURCES = [
|
|
|
14595
14761
|
"packages/control-plane/standalone/intelligence-bridge.mjs",
|
|
14596
14762
|
"packages/control-plane/standalone/d1-sqlite-adapter.mjs",
|
|
14597
14763
|
"packages/adapters/src/docker/scripts/fetch-creds.mjs",
|
|
14764
|
+
"packages/adapters/src/docker/scripts/mcp-status-hint.mjs",
|
|
14598
14765
|
"packages/adapters/src/docker/scripts/pr-gate-hook.mjs",
|
|
14599
14766
|
"packages/adapters/src/docker/scripts/entrypoint.sh"
|
|
14600
14767
|
];
|
|
@@ -14654,9 +14821,9 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
|
|
|
14654
14821
|
"These source files have changed since the image was built; the",
|
|
14655
14822
|
"changes will NOT take effect in fresh worlds until you rebuild:"
|
|
14656
14823
|
];
|
|
14657
|
-
for (const { path:
|
|
14824
|
+
for (const { path: path45, mtimeMs } of result.newerSources) {
|
|
14658
14825
|
const when = new Date(mtimeMs).toISOString();
|
|
14659
|
-
lines.push(` \u2022 ${
|
|
14826
|
+
lines.push(` \u2022 ${path45} (modified ${when})`);
|
|
14660
14827
|
}
|
|
14661
14828
|
lines.push("");
|
|
14662
14829
|
lines.push("Rebuild with:");
|
|
@@ -14675,7 +14842,7 @@ function defaultDockerInspect(image) {
|
|
|
14675
14842
|
}
|
|
14676
14843
|
function defaultStatMtime(absPath) {
|
|
14677
14844
|
try {
|
|
14678
|
-
if (!
|
|
14845
|
+
if (!existsSync22(absPath))
|
|
14679
14846
|
return null;
|
|
14680
14847
|
return statSync5(absPath).mtimeMs;
|
|
14681
14848
|
} catch {
|
|
@@ -14815,15 +14982,15 @@ init_host_cp();
|
|
|
14815
14982
|
var HOST_CP_URL = "http://127.0.0.1:19000";
|
|
14816
14983
|
async function readHostCpTokenForCreate() {
|
|
14817
14984
|
try {
|
|
14818
|
-
const { default:
|
|
14985
|
+
const { default: fs41 } = await import("node:fs");
|
|
14819
14986
|
const { default: os24 } = await import("node:os");
|
|
14820
|
-
const { default:
|
|
14821
|
-
const tp =
|
|
14822
|
-
process.env.OLAM_HOME ??
|
|
14987
|
+
const { default: path45 } = await import("node:path");
|
|
14988
|
+
const tp = path45.join(
|
|
14989
|
+
process.env.OLAM_HOME ?? path45.join(os24.homedir(), ".olam"),
|
|
14823
14990
|
"host-cp.token"
|
|
14824
14991
|
);
|
|
14825
|
-
if (!
|
|
14826
|
-
return
|
|
14992
|
+
if (!fs41.existsSync(tp)) return null;
|
|
14993
|
+
return fs41.readFileSync(tp, "utf-8").trim();
|
|
14827
14994
|
} catch {
|
|
14828
14995
|
return null;
|
|
14829
14996
|
}
|
|
@@ -15161,6 +15328,13 @@ ${pc9.cyan("Host CP UI:")} ${worldUrl}`);
|
|
|
15161
15328
|
if (err instanceof AuthPreflightError) {
|
|
15162
15329
|
printError(err.message);
|
|
15163
15330
|
if (err.remedy) console.log(` ${pc9.dim(err.remedy)}`);
|
|
15331
|
+
} else if (err instanceof RepoSelectionRequiredError) {
|
|
15332
|
+
printError(err.message);
|
|
15333
|
+
if (err.availableRepos.length > 0) {
|
|
15334
|
+
const example = err.availableRepos[0];
|
|
15335
|
+
console.log(` ${pc9.dim(`Example: olam create --name <name> --repos ${example} --task "<task>"`)}`);
|
|
15336
|
+
console.log(` ${pc9.dim('Or: olam create --name <name> --workspace <workspace> --task "<task>"')}`);
|
|
15337
|
+
}
|
|
15164
15338
|
} else {
|
|
15165
15339
|
printError(err instanceof Error ? err.message : String(err));
|
|
15166
15340
|
}
|
|
@@ -15171,10 +15345,10 @@ ${pc9.cyan("Host CP UI:")} ${worldUrl}`);
|
|
|
15171
15345
|
function resolveRepoRoot(start) {
|
|
15172
15346
|
let cur = start;
|
|
15173
15347
|
while (true) {
|
|
15174
|
-
if (
|
|
15348
|
+
if (existsSync23(resolve7(cur, "packages")) && existsSync23(resolve7(cur, "package.json"))) {
|
|
15175
15349
|
return cur;
|
|
15176
15350
|
}
|
|
15177
|
-
const parent =
|
|
15351
|
+
const parent = dirname15(cur);
|
|
15178
15352
|
if (parent === cur) return start;
|
|
15179
15353
|
cur = parent;
|
|
15180
15354
|
}
|
|
@@ -15185,12 +15359,12 @@ function defaultNameFromPrompt(prompt) {
|
|
|
15185
15359
|
}
|
|
15186
15360
|
async function readHostCpToken3() {
|
|
15187
15361
|
try {
|
|
15188
|
-
const { default:
|
|
15362
|
+
const { default: fs41 } = await import("node:fs");
|
|
15189
15363
|
const { default: os24 } = await import("node:os");
|
|
15190
|
-
const { default:
|
|
15191
|
-
const tp =
|
|
15192
|
-
if (!
|
|
15193
|
-
const raw =
|
|
15364
|
+
const { default: path45 } = await import("node:path");
|
|
15365
|
+
const tp = path45.join(os24.homedir(), ".olam", "host-cp.token");
|
|
15366
|
+
if (!fs41.existsSync(tp)) return null;
|
|
15367
|
+
const raw = fs41.readFileSync(tp, "utf-8").trim();
|
|
15194
15368
|
return raw.length > 0 ? raw : null;
|
|
15195
15369
|
} catch {
|
|
15196
15370
|
return null;
|
|
@@ -15402,9 +15576,9 @@ function registerList(program2) {
|
|
|
15402
15576
|
|
|
15403
15577
|
// src/commands/status.ts
|
|
15404
15578
|
init_output();
|
|
15405
|
-
import * as
|
|
15579
|
+
import * as fs23 from "node:fs";
|
|
15406
15580
|
import * as os13 from "node:os";
|
|
15407
|
-
import * as
|
|
15581
|
+
import * as path26 from "node:path";
|
|
15408
15582
|
var CLI_VERSION2 = process.env["OLAM_CLI_VERSION"] ?? "0.0.0";
|
|
15409
15583
|
var HOST_CP_PORT2 = 19e3;
|
|
15410
15584
|
async function getMachineStatus(_probe, _loadCtx, _readToken) {
|
|
@@ -15434,14 +15608,14 @@ async function getMachineStatus(_probe, _loadCtx, _readToken) {
|
|
|
15434
15608
|
}
|
|
15435
15609
|
} catch {
|
|
15436
15610
|
}
|
|
15437
|
-
const manifestPath2 =
|
|
15611
|
+
const manifestPath2 = path26.join(os13.homedir(), ".olam", "cache", "manifest.json");
|
|
15438
15612
|
let updateAvailable = null;
|
|
15439
15613
|
let lastUpdateCheck = null;
|
|
15440
|
-
if (
|
|
15441
|
-
const mtime =
|
|
15614
|
+
if (fs23.existsSync(manifestPath2)) {
|
|
15615
|
+
const mtime = fs23.statSync(manifestPath2).mtime;
|
|
15442
15616
|
lastUpdateCheck = mtime.toISOString();
|
|
15443
15617
|
try {
|
|
15444
|
-
const manifest = JSON.parse(
|
|
15618
|
+
const manifest = JSON.parse(fs23.readFileSync(manifestPath2, "utf-8"));
|
|
15445
15619
|
const latest = manifest["version"];
|
|
15446
15620
|
updateAvailable = latest !== void 0 && latest !== CLI_VERSION2;
|
|
15447
15621
|
} catch {
|
|
@@ -15564,9 +15738,9 @@ function registerDestroy(program2) {
|
|
|
15564
15738
|
// src/commands/clean.ts
|
|
15565
15739
|
init_context();
|
|
15566
15740
|
init_output();
|
|
15567
|
-
import
|
|
15741
|
+
import fs24 from "node:fs";
|
|
15568
15742
|
import os14 from "node:os";
|
|
15569
|
-
import
|
|
15743
|
+
import path27 from "node:path";
|
|
15570
15744
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
15571
15745
|
function registerClean(program2) {
|
|
15572
15746
|
program2.command("clean").description("Reap orphan world filesystem state under ~/.olam/worlds/").option("--apply", "Actually delete the orphans (default is dry-run)", false).option(
|
|
@@ -15590,8 +15764,8 @@ async function runClean(opts) {
|
|
|
15590
15764
|
printError(error?.message ?? "Olam is not configured. Run `olam init` first.");
|
|
15591
15765
|
return 1;
|
|
15592
15766
|
}
|
|
15593
|
-
const worldsDir =
|
|
15594
|
-
if (!
|
|
15767
|
+
const worldsDir = path27.join(os14.homedir(), ".olam", "worlds");
|
|
15768
|
+
if (!fs24.existsSync(worldsDir)) {
|
|
15595
15769
|
if (opts.json) {
|
|
15596
15770
|
process.stdout.write(`${JSON.stringify({ worldsDir, entries: [] })}
|
|
15597
15771
|
`);
|
|
@@ -15606,8 +15780,8 @@ async function runClean(opts) {
|
|
|
15606
15780
|
}
|
|
15607
15781
|
const worktreeMap = collectWorktrees(worldsDir);
|
|
15608
15782
|
const entries = [];
|
|
15609
|
-
for (const id of
|
|
15610
|
-
const fullPath =
|
|
15783
|
+
for (const id of fs24.readdirSync(worldsDir).sort()) {
|
|
15784
|
+
const fullPath = path27.join(worldsDir, id);
|
|
15611
15785
|
const stat = safeStat(fullPath);
|
|
15612
15786
|
if (!stat || !stat.isDirectory()) continue;
|
|
15613
15787
|
entries.push(classifyWorld({ id, fullPath, liveIds, worktreeMap }));
|
|
@@ -15673,7 +15847,7 @@ function classifyWorld(args) {
|
|
|
15673
15847
|
if (liveIds.has(id)) {
|
|
15674
15848
|
return { id, path: fullPath, bytes, category: "active", note: "in registry" };
|
|
15675
15849
|
}
|
|
15676
|
-
const worktreeChild =
|
|
15850
|
+
const worktreeChild = path27.join(fullPath, "olam");
|
|
15677
15851
|
const worktreeInfo = worktreeMap.get(worktreeChild);
|
|
15678
15852
|
if (worktreeInfo) {
|
|
15679
15853
|
if (worktreeInfo.dirty > 0 || worktreeInfo.unpushed > 0) {
|
|
@@ -15719,20 +15893,20 @@ function reapEntry(entry) {
|
|
|
15719
15893
|
}
|
|
15720
15894
|
}
|
|
15721
15895
|
try {
|
|
15722
|
-
|
|
15896
|
+
fs24.rmSync(entry.path, { recursive: true, force: true });
|
|
15723
15897
|
} catch (err) {
|
|
15724
15898
|
process.stderr.write(` ! rm ${entry.path}: ${err instanceof Error ? err.message : String(err)}
|
|
15725
15899
|
`);
|
|
15726
15900
|
return false;
|
|
15727
15901
|
}
|
|
15728
|
-
return !
|
|
15902
|
+
return !fs24.existsSync(entry.path);
|
|
15729
15903
|
}
|
|
15730
15904
|
function collectWorktrees(worldsDir) {
|
|
15731
15905
|
const out = /* @__PURE__ */ new Map();
|
|
15732
|
-
for (const id of
|
|
15733
|
-
const child =
|
|
15734
|
-
const gitMarker =
|
|
15735
|
-
if (!
|
|
15906
|
+
for (const id of fs24.readdirSync(worldsDir)) {
|
|
15907
|
+
const child = path27.join(worldsDir, id, "olam");
|
|
15908
|
+
const gitMarker = path27.join(child, ".git");
|
|
15909
|
+
if (!fs24.existsSync(gitMarker)) continue;
|
|
15736
15910
|
const gitDir = resolveGitDirForWorktree(child);
|
|
15737
15911
|
if (!gitDir) continue;
|
|
15738
15912
|
const branch = readBranch(child);
|
|
@@ -15743,7 +15917,7 @@ function collectWorktrees(worldsDir) {
|
|
|
15743
15917
|
return out;
|
|
15744
15918
|
}
|
|
15745
15919
|
function resolveGitDirForWorktree(worktreePath) {
|
|
15746
|
-
const gitMarker =
|
|
15920
|
+
const gitMarker = path27.join(worktreePath, ".git");
|
|
15747
15921
|
try {
|
|
15748
15922
|
const top = execFileSync4("git", ["rev-parse", "--show-toplevel"], {
|
|
15749
15923
|
cwd: worktreePath,
|
|
@@ -15757,7 +15931,7 @@ function resolveGitDirForWorktree(worktreePath) {
|
|
|
15757
15931
|
stdio: "pipe"
|
|
15758
15932
|
}).trim();
|
|
15759
15933
|
if (!common) return top;
|
|
15760
|
-
return
|
|
15934
|
+
return path27.dirname(path27.resolve(worktreePath, common));
|
|
15761
15935
|
} catch {
|
|
15762
15936
|
return null;
|
|
15763
15937
|
}
|
|
@@ -15800,7 +15974,7 @@ function countUnpushed(worktreePath) {
|
|
|
15800
15974
|
}
|
|
15801
15975
|
function safeStat(p) {
|
|
15802
15976
|
try {
|
|
15803
|
-
return
|
|
15977
|
+
return fs24.statSync(p);
|
|
15804
15978
|
} catch {
|
|
15805
15979
|
return null;
|
|
15806
15980
|
}
|
|
@@ -15812,7 +15986,7 @@ function computeBytes(p) {
|
|
|
15812
15986
|
const cur = stack.pop();
|
|
15813
15987
|
let st;
|
|
15814
15988
|
try {
|
|
15815
|
-
st =
|
|
15989
|
+
st = fs24.lstatSync(cur);
|
|
15816
15990
|
} catch {
|
|
15817
15991
|
continue;
|
|
15818
15992
|
}
|
|
@@ -15820,11 +15994,11 @@ function computeBytes(p) {
|
|
|
15820
15994
|
if (st.isDirectory()) {
|
|
15821
15995
|
let entries;
|
|
15822
15996
|
try {
|
|
15823
|
-
entries =
|
|
15997
|
+
entries = fs24.readdirSync(cur);
|
|
15824
15998
|
} catch {
|
|
15825
15999
|
continue;
|
|
15826
16000
|
}
|
|
15827
|
-
for (const name of entries) stack.push(
|
|
16001
|
+
for (const name of entries) stack.push(path27.join(cur, name));
|
|
15828
16002
|
} else {
|
|
15829
16003
|
total += st.size;
|
|
15830
16004
|
}
|
|
@@ -16032,7 +16206,7 @@ init_context();
|
|
|
16032
16206
|
init_output();
|
|
16033
16207
|
init_exit_codes();
|
|
16034
16208
|
init_world_paths();
|
|
16035
|
-
import * as
|
|
16209
|
+
import * as fs25 from "node:fs";
|
|
16036
16210
|
import "node:path";
|
|
16037
16211
|
import ora6 from "ora";
|
|
16038
16212
|
function registerCrystallize(program2, options = {}) {
|
|
@@ -16064,7 +16238,7 @@ function registerCrystallize(program2, options = {}) {
|
|
|
16064
16238
|
return;
|
|
16065
16239
|
}
|
|
16066
16240
|
const thoughtDbPath = getWorldDbPath(world.workspacePath);
|
|
16067
|
-
if (!
|
|
16241
|
+
if (!fs25.existsSync(thoughtDbPath)) {
|
|
16068
16242
|
printError(`No thoughts captured yet for "${worldId}". Run a dispatch first.`);
|
|
16069
16243
|
process.exitCode = EXIT_GENERIC_ERROR;
|
|
16070
16244
|
return;
|
|
@@ -17438,11 +17612,11 @@ var qmarksTestNoExtDot = ([$0]) => {
|
|
|
17438
17612
|
return (f) => f.length === len && f !== "." && f !== "..";
|
|
17439
17613
|
};
|
|
17440
17614
|
var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix";
|
|
17441
|
-
var
|
|
17615
|
+
var path29 = {
|
|
17442
17616
|
win32: { sep: "\\" },
|
|
17443
17617
|
posix: { sep: "/" }
|
|
17444
17618
|
};
|
|
17445
|
-
var sep = defaultPlatform === "win32" ?
|
|
17619
|
+
var sep = defaultPlatform === "win32" ? path29.win32.sep : path29.posix.sep;
|
|
17446
17620
|
minimatch.sep = sep;
|
|
17447
17621
|
var GLOBSTAR = /* @__PURE__ */ Symbol("globstar **");
|
|
17448
17622
|
minimatch.GLOBSTAR = GLOBSTAR;
|
|
@@ -18270,23 +18444,23 @@ function registerPolicyCheck(program2) {
|
|
|
18270
18444
|
// src/commands/upgrade.ts
|
|
18271
18445
|
init_output();
|
|
18272
18446
|
init_host_cp();
|
|
18273
|
-
import * as
|
|
18274
|
-
import * as
|
|
18447
|
+
import * as fs28 from "node:fs";
|
|
18448
|
+
import * as path32 from "node:path";
|
|
18275
18449
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
18276
18450
|
import ora7 from "ora";
|
|
18277
18451
|
import pc16 from "picocolors";
|
|
18278
18452
|
|
|
18279
18453
|
// src/commands/upgrade-lock.ts
|
|
18280
|
-
import * as
|
|
18454
|
+
import * as fs26 from "node:fs";
|
|
18281
18455
|
import * as os15 from "node:os";
|
|
18282
|
-
import * as
|
|
18456
|
+
import * as path30 from "node:path";
|
|
18283
18457
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
18284
|
-
var LOCK_FILE_PATH =
|
|
18458
|
+
var LOCK_FILE_PATH = path30.join(os15.homedir(), ".olam", ".upgrade.lock");
|
|
18285
18459
|
var STALE_LOCK_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
18286
18460
|
function readLockFile(lockPath) {
|
|
18287
18461
|
try {
|
|
18288
|
-
if (!
|
|
18289
|
-
const raw =
|
|
18462
|
+
if (!fs26.existsSync(lockPath)) return null;
|
|
18463
|
+
const raw = fs26.readFileSync(lockPath, "utf-8").trim();
|
|
18290
18464
|
if (raw.length === 0) return null;
|
|
18291
18465
|
const parsed = JSON.parse(raw);
|
|
18292
18466
|
if (typeof parsed.pid !== "number" || typeof parsed.startTs !== "number") return null;
|
|
@@ -18331,16 +18505,16 @@ function isStaleLock(content, nowMs = Date.now()) {
|
|
|
18331
18505
|
return false;
|
|
18332
18506
|
}
|
|
18333
18507
|
function acquireLock(lockPath = LOCK_FILE_PATH, nowMs = Date.now()) {
|
|
18334
|
-
const dir =
|
|
18335
|
-
|
|
18508
|
+
const dir = path30.dirname(lockPath);
|
|
18509
|
+
fs26.mkdirSync(dir, { recursive: true });
|
|
18336
18510
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
18337
18511
|
try {
|
|
18338
|
-
const fd =
|
|
18512
|
+
const fd = fs26.openSync(lockPath, "wx", 420);
|
|
18339
18513
|
try {
|
|
18340
18514
|
const content = { pid: process.pid, startTs: nowMs };
|
|
18341
|
-
|
|
18515
|
+
fs26.writeSync(fd, JSON.stringify(content));
|
|
18342
18516
|
} finally {
|
|
18343
|
-
|
|
18517
|
+
fs26.closeSync(fd);
|
|
18344
18518
|
}
|
|
18345
18519
|
return { acquired: true, lockPath };
|
|
18346
18520
|
} catch (err) {
|
|
@@ -18349,7 +18523,7 @@ function acquireLock(lockPath = LOCK_FILE_PATH, nowMs = Date.now()) {
|
|
|
18349
18523
|
const existing2 = readLockFile(lockPath);
|
|
18350
18524
|
if (isStaleLock(existing2, nowMs)) {
|
|
18351
18525
|
try {
|
|
18352
|
-
|
|
18526
|
+
fs26.unlinkSync(lockPath);
|
|
18353
18527
|
} catch (unlinkErr) {
|
|
18354
18528
|
const ucode = unlinkErr.code;
|
|
18355
18529
|
if (ucode !== "ENOENT") throw unlinkErr;
|
|
@@ -18374,7 +18548,7 @@ function acquireLock(lockPath = LOCK_FILE_PATH, nowMs = Date.now()) {
|
|
|
18374
18548
|
}
|
|
18375
18549
|
function releaseLock(lockPath = LOCK_FILE_PATH) {
|
|
18376
18550
|
try {
|
|
18377
|
-
|
|
18551
|
+
fs26.unlinkSync(lockPath);
|
|
18378
18552
|
} catch (err) {
|
|
18379
18553
|
const code = err.code;
|
|
18380
18554
|
if (code !== "ENOENT") throw err;
|
|
@@ -18392,19 +18566,19 @@ function formatRefusalMessage(result, lockPath = LOCK_FILE_PATH) {
|
|
|
18392
18566
|
}
|
|
18393
18567
|
|
|
18394
18568
|
// src/commands/upgrade-log.ts
|
|
18395
|
-
import * as
|
|
18569
|
+
import * as fs27 from "node:fs";
|
|
18396
18570
|
import * as os16 from "node:os";
|
|
18397
|
-
import * as
|
|
18571
|
+
import * as path31 from "node:path";
|
|
18398
18572
|
function getUpgradeLogPath() {
|
|
18399
18573
|
const home = process.env["HOME"] ?? os16.homedir();
|
|
18400
|
-
return
|
|
18574
|
+
return path31.join(home, ".olam", "upgrade.log");
|
|
18401
18575
|
}
|
|
18402
18576
|
var UPGRADE_LOG_PATH = getUpgradeLogPath();
|
|
18403
18577
|
function appendUpgradeLog(row, logPath = getUpgradeLogPath()) {
|
|
18404
18578
|
try {
|
|
18405
|
-
|
|
18579
|
+
fs27.mkdirSync(path31.dirname(logPath), { recursive: true });
|
|
18406
18580
|
const line = JSON.stringify(row) + "\n";
|
|
18407
|
-
|
|
18581
|
+
fs27.appendFileSync(logPath, line, { mode: 420 });
|
|
18408
18582
|
} catch (err) {
|
|
18409
18583
|
process.stderr.write(
|
|
18410
18584
|
`[upgrade-log] failed to append: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -18413,10 +18587,10 @@ function appendUpgradeLog(row, logPath = getUpgradeLogPath()) {
|
|
|
18413
18587
|
}
|
|
18414
18588
|
}
|
|
18415
18589
|
function readUpgradeLog(limit = 10, logPath = getUpgradeLogPath()) {
|
|
18416
|
-
if (!
|
|
18590
|
+
if (!fs27.existsSync(logPath)) return [];
|
|
18417
18591
|
let raw;
|
|
18418
18592
|
try {
|
|
18419
|
-
raw =
|
|
18593
|
+
raw = fs27.readFileSync(logPath, "utf-8");
|
|
18420
18594
|
} catch (err) {
|
|
18421
18595
|
process.stderr.write(
|
|
18422
18596
|
`[upgrade-log] failed to read: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -18509,12 +18683,12 @@ init_protocol_version();
|
|
|
18509
18683
|
init_install_root();
|
|
18510
18684
|
var AUTH_HEALTH_URL2 = "http://127.0.0.1:9999/health";
|
|
18511
18685
|
function isNodeModulesInSync(cwd) {
|
|
18512
|
-
const lockPath =
|
|
18513
|
-
const markerPath =
|
|
18514
|
-
if (!
|
|
18686
|
+
const lockPath = path32.join(cwd, "package-lock.json");
|
|
18687
|
+
const markerPath = path32.join(cwd, "node_modules", ".package-lock.json");
|
|
18688
|
+
if (!fs28.existsSync(lockPath) || !fs28.existsSync(markerPath)) return false;
|
|
18515
18689
|
try {
|
|
18516
|
-
const lockStat =
|
|
18517
|
-
const markerStat =
|
|
18690
|
+
const lockStat = fs28.statSync(lockPath);
|
|
18691
|
+
const markerStat = fs28.statSync(markerPath);
|
|
18518
18692
|
return markerStat.mtimeMs >= lockStat.mtimeMs;
|
|
18519
18693
|
} catch {
|
|
18520
18694
|
return false;
|
|
@@ -18530,8 +18704,8 @@ function shouldSkipInstall(opts, cwd) {
|
|
|
18530
18704
|
return { skip: false };
|
|
18531
18705
|
}
|
|
18532
18706
|
function validateRepoRoot(cwd) {
|
|
18533
|
-
const marker =
|
|
18534
|
-
if (!
|
|
18707
|
+
const marker = path32.join(cwd, "packages/host-cp/compose.yaml");
|
|
18708
|
+
if (!fs28.existsSync(marker)) {
|
|
18535
18709
|
return {
|
|
18536
18710
|
ok: false,
|
|
18537
18711
|
error: `Not an olam repo root (expected ${marker}).
|
|
@@ -18883,9 +19057,9 @@ async function recreateAuthService() {
|
|
|
18883
19057
|
}
|
|
18884
19058
|
}
|
|
18885
19059
|
function readBundleHash(cwd) {
|
|
18886
|
-
const indexPath =
|
|
18887
|
-
if (!
|
|
18888
|
-
return extractBundleHash(
|
|
19060
|
+
const indexPath = path32.join(cwd, "packages/control-plane/public/index.html");
|
|
19061
|
+
if (!fs28.existsSync(indexPath)) return null;
|
|
19062
|
+
return extractBundleHash(fs28.readFileSync(indexPath, "utf-8"));
|
|
18889
19063
|
}
|
|
18890
19064
|
async function runUpgradePullByDigest(deps = {}) {
|
|
18891
19065
|
const docker2 = deps.docker ?? realDocker;
|
|
@@ -19324,7 +19498,7 @@ ${buildResult.stderr}`);
|
|
|
19324
19498
|
return;
|
|
19325
19499
|
}
|
|
19326
19500
|
const authSecret = readAuthSecret2();
|
|
19327
|
-
const spaDir =
|
|
19501
|
+
const spaDir = path32.join(cwd, "packages/control-plane/app");
|
|
19328
19502
|
const spaResult = runStep2(
|
|
19329
19503
|
"vite build (SPA)",
|
|
19330
19504
|
"npx",
|
|
@@ -19858,20 +20032,20 @@ ${pc18.dim(`world: ${worldId} sort: ${sortKey} refresh: 5s Ctrl-C to exit`)}
|
|
|
19858
20032
|
|
|
19859
20033
|
// src/commands/keys.ts
|
|
19860
20034
|
init_output();
|
|
19861
|
-
import * as
|
|
20035
|
+
import * as fs29 from "node:fs";
|
|
19862
20036
|
import * as os17 from "node:os";
|
|
19863
|
-
import * as
|
|
20037
|
+
import * as path33 from "node:path";
|
|
19864
20038
|
import YAML4 from "yaml";
|
|
19865
20039
|
function olamHome2() {
|
|
19866
|
-
return process.env.OLAM_HOME ??
|
|
20040
|
+
return process.env.OLAM_HOME ?? path33.join(os17.homedir(), ".olam");
|
|
19867
20041
|
}
|
|
19868
20042
|
function keysFilePath() {
|
|
19869
|
-
return
|
|
20043
|
+
return path33.join(olamHome2(), "keys.yaml");
|
|
19870
20044
|
}
|
|
19871
20045
|
function readKeysFile() {
|
|
19872
20046
|
const filePath = keysFilePath();
|
|
19873
|
-
if (!
|
|
19874
|
-
const raw =
|
|
20047
|
+
if (!fs29.existsSync(filePath)) return null;
|
|
20048
|
+
const raw = fs29.readFileSync(filePath, "utf-8").trim();
|
|
19875
20049
|
if (raw.length === 0) return null;
|
|
19876
20050
|
try {
|
|
19877
20051
|
const parsed = YAML4.parse(raw);
|
|
@@ -19887,13 +20061,13 @@ function readKeysFile() {
|
|
|
19887
20061
|
}
|
|
19888
20062
|
function writeKeysFile(keys) {
|
|
19889
20063
|
const dir = olamHome2();
|
|
19890
|
-
if (!
|
|
19891
|
-
|
|
20064
|
+
if (!fs29.existsSync(dir)) {
|
|
20065
|
+
fs29.mkdirSync(dir, { recursive: true });
|
|
19892
20066
|
}
|
|
19893
20067
|
const filePath = keysFilePath();
|
|
19894
20068
|
const content = YAML4.stringify(keys);
|
|
19895
|
-
|
|
19896
|
-
|
|
20069
|
+
fs29.writeFileSync(filePath, content, { encoding: "utf-8", mode: 384 });
|
|
20070
|
+
fs29.chmodSync(filePath, 384);
|
|
19897
20071
|
}
|
|
19898
20072
|
function redact(value) {
|
|
19899
20073
|
if (value.length <= 8) return value + "...";
|
|
@@ -19936,7 +20110,7 @@ function registerKeys(program2) {
|
|
|
19936
20110
|
}
|
|
19937
20111
|
const { [key]: _removed, ...rest } = existing;
|
|
19938
20112
|
if (Object.keys(rest).length === 0) {
|
|
19939
|
-
|
|
20113
|
+
fs29.unlinkSync(keysFilePath());
|
|
19940
20114
|
} else {
|
|
19941
20115
|
writeKeysFile(rest);
|
|
19942
20116
|
}
|
|
@@ -19959,33 +20133,33 @@ function registerKeys(program2) {
|
|
|
19959
20133
|
}
|
|
19960
20134
|
|
|
19961
20135
|
// src/commands/world-snapshot.ts
|
|
19962
|
-
import * as
|
|
19963
|
-
import * as
|
|
20136
|
+
import * as fs31 from "node:fs";
|
|
20137
|
+
import * as path35 from "node:path";
|
|
19964
20138
|
import { execSync as execSync9 } from "node:child_process";
|
|
19965
20139
|
import pc19 from "picocolors";
|
|
19966
20140
|
|
|
19967
20141
|
// ../core/dist/world/snapshot.js
|
|
19968
|
-
import * as
|
|
19969
|
-
import * as
|
|
20142
|
+
import * as crypto7 from "node:crypto";
|
|
20143
|
+
import * as fs30 from "node:fs";
|
|
19970
20144
|
import * as os18 from "node:os";
|
|
19971
|
-
import * as
|
|
20145
|
+
import * as path34 from "node:path";
|
|
19972
20146
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
19973
20147
|
function snapshotsDir() {
|
|
19974
|
-
return process.env["OLAM_SNAPSHOTS_DIR"] ??
|
|
20148
|
+
return process.env["OLAM_SNAPSHOTS_DIR"] ?? path34.join(os18.homedir(), ".olam", "snapshots");
|
|
19975
20149
|
}
|
|
19976
20150
|
function snapshotKindDir(worldId, kind) {
|
|
19977
|
-
return
|
|
20151
|
+
return path34.join(snapshotsDir(), worldId, kind);
|
|
19978
20152
|
}
|
|
19979
20153
|
function snapshotTarPath(worldId, kind, repoName, hash) {
|
|
19980
20154
|
const base = repoName ? `${repoName}-${hash}` : hash;
|
|
19981
|
-
return
|
|
20155
|
+
return path34.join(snapshotKindDir(worldId, kind), `${base}.tar.gz`);
|
|
19982
20156
|
}
|
|
19983
20157
|
function manifestPath(tarPath) {
|
|
19984
20158
|
return tarPath.replace(/\.tar\.gz$/, ".manifest.json");
|
|
19985
20159
|
}
|
|
19986
20160
|
function hashBuffers(entries) {
|
|
19987
20161
|
const sorted = [...entries].sort((a, b) => a.path.localeCompare(b.path));
|
|
19988
|
-
const hash =
|
|
20162
|
+
const hash = crypto7.createHash("sha256");
|
|
19989
20163
|
for (const entry of sorted) {
|
|
19990
20164
|
hash.update(entry.path);
|
|
19991
20165
|
hash.update("\0");
|
|
@@ -19995,17 +20169,17 @@ function hashBuffers(entries) {
|
|
|
19995
20169
|
return hash.digest("hex").slice(0, 12);
|
|
19996
20170
|
}
|
|
19997
20171
|
function computeGemsFingerprint(repoDir) {
|
|
19998
|
-
const lockfile =
|
|
19999
|
-
if (!
|
|
20172
|
+
const lockfile = path34.join(repoDir, "Gemfile.lock");
|
|
20173
|
+
if (!fs30.existsSync(lockfile))
|
|
20000
20174
|
return null;
|
|
20001
|
-
return hashBuffers([{ path: "Gemfile.lock", content:
|
|
20175
|
+
return hashBuffers([{ path: "Gemfile.lock", content: fs30.readFileSync(lockfile) }]);
|
|
20002
20176
|
}
|
|
20003
20177
|
function computeNodeFingerprint(repoDir) {
|
|
20004
20178
|
const candidates = ["yarn.lock", "pnpm-lock.yaml", "package-lock.json"];
|
|
20005
20179
|
for (const name of candidates) {
|
|
20006
|
-
const lockfile =
|
|
20007
|
-
if (
|
|
20008
|
-
return hashBuffers([{ path: name, content:
|
|
20180
|
+
const lockfile = path34.join(repoDir, name);
|
|
20181
|
+
if (fs30.existsSync(lockfile)) {
|
|
20182
|
+
return hashBuffers([{ path: name, content: fs30.readFileSync(lockfile) }]);
|
|
20009
20183
|
}
|
|
20010
20184
|
}
|
|
20011
20185
|
return null;
|
|
@@ -20015,16 +20189,16 @@ function computePgFingerprint(repoDirs) {
|
|
|
20015
20189
|
const entries = [];
|
|
20016
20190
|
for (const repoDir of repoDirs) {
|
|
20017
20191
|
for (const pattern of patterns) {
|
|
20018
|
-
const filePath =
|
|
20019
|
-
if (
|
|
20020
|
-
entries.push({ path: filePath, content:
|
|
20192
|
+
const filePath = path34.join(repoDir, pattern);
|
|
20193
|
+
if (fs30.existsSync(filePath)) {
|
|
20194
|
+
entries.push({ path: filePath, content: fs30.readFileSync(filePath) });
|
|
20021
20195
|
}
|
|
20022
20196
|
}
|
|
20023
20197
|
}
|
|
20024
20198
|
return entries.length > 0 ? hashBuffers(entries) : null;
|
|
20025
20199
|
}
|
|
20026
20200
|
function packTarball(srcDir, destPath, opts = {}) {
|
|
20027
|
-
|
|
20201
|
+
fs30.mkdirSync(path34.dirname(destPath), { recursive: true });
|
|
20028
20202
|
const tmp = `${destPath}.tmp`;
|
|
20029
20203
|
const args = [];
|
|
20030
20204
|
if (opts.followSymlinks)
|
|
@@ -20032,47 +20206,47 @@ function packTarball(srcDir, destPath, opts = {}) {
|
|
|
20032
20206
|
args.push("-czf", tmp, "-C", srcDir, ".");
|
|
20033
20207
|
try {
|
|
20034
20208
|
execFileSync5("tar", args, { stdio: "pipe" });
|
|
20035
|
-
|
|
20209
|
+
fs30.renameSync(tmp, destPath);
|
|
20036
20210
|
} catch (err) {
|
|
20037
20211
|
try {
|
|
20038
|
-
|
|
20212
|
+
fs30.rmSync(tmp, { force: true });
|
|
20039
20213
|
} catch {
|
|
20040
20214
|
}
|
|
20041
20215
|
throw err;
|
|
20042
20216
|
}
|
|
20043
20217
|
}
|
|
20044
20218
|
function writeManifest(manifest, tarPath) {
|
|
20045
|
-
|
|
20219
|
+
fs30.writeFileSync(manifestPath(tarPath), JSON.stringify(manifest, null, 2), "utf-8");
|
|
20046
20220
|
}
|
|
20047
20221
|
function readManifest(tarPath) {
|
|
20048
20222
|
const mPath = manifestPath(tarPath);
|
|
20049
|
-
if (!
|
|
20223
|
+
if (!fs30.existsSync(mPath))
|
|
20050
20224
|
return null;
|
|
20051
20225
|
try {
|
|
20052
|
-
return JSON.parse(
|
|
20226
|
+
return JSON.parse(fs30.readFileSync(mPath, "utf-8"));
|
|
20053
20227
|
} catch {
|
|
20054
20228
|
return null;
|
|
20055
20229
|
}
|
|
20056
20230
|
}
|
|
20057
20231
|
function listSnapshots(worldIdFilter) {
|
|
20058
20232
|
const root = snapshotsDir();
|
|
20059
|
-
if (!
|
|
20233
|
+
if (!fs30.existsSync(root))
|
|
20060
20234
|
return [];
|
|
20061
20235
|
const now = Date.now();
|
|
20062
20236
|
const results = [];
|
|
20063
|
-
const worlds = worldIdFilter ? [worldIdFilter] :
|
|
20237
|
+
const worlds = worldIdFilter ? [worldIdFilter] : fs30.readdirSync(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
20064
20238
|
for (const worldId of worlds) {
|
|
20065
|
-
const worldDir =
|
|
20066
|
-
if (!
|
|
20239
|
+
const worldDir = path34.join(root, worldId);
|
|
20240
|
+
if (!fs30.existsSync(worldDir) || !fs30.statSync(worldDir).isDirectory())
|
|
20067
20241
|
continue;
|
|
20068
20242
|
for (const kind of ["gems", "node", "pg"]) {
|
|
20069
|
-
const kindDir =
|
|
20070
|
-
if (!
|
|
20243
|
+
const kindDir = path34.join(worldDir, kind);
|
|
20244
|
+
if (!fs30.existsSync(kindDir))
|
|
20071
20245
|
continue;
|
|
20072
|
-
const tarballs =
|
|
20246
|
+
const tarballs = fs30.readdirSync(kindDir).filter((f) => f.endsWith(".tar.gz"));
|
|
20073
20247
|
for (const tarFile of tarballs) {
|
|
20074
|
-
const tarPath =
|
|
20075
|
-
const stat =
|
|
20248
|
+
const tarPath = path34.join(kindDir, tarFile);
|
|
20249
|
+
const stat = fs30.statSync(tarPath);
|
|
20076
20250
|
const manifest = readManifest(tarPath);
|
|
20077
20251
|
if (!manifest)
|
|
20078
20252
|
continue;
|
|
@@ -20162,17 +20336,17 @@ function resolveKinds(arg) {
|
|
|
20162
20336
|
return [];
|
|
20163
20337
|
}
|
|
20164
20338
|
async function captureGems(worldId, workspacePath, repo) {
|
|
20165
|
-
const repoDir =
|
|
20339
|
+
const repoDir = path35.join(workspacePath, repo);
|
|
20166
20340
|
const fingerprint = computeGemsFingerprint(repoDir);
|
|
20167
20341
|
if (!fingerprint) {
|
|
20168
20342
|
return { ok: false, tarPath: "", msg: "no Gemfile.lock \u2014 layer does not apply" };
|
|
20169
20343
|
}
|
|
20170
20344
|
const tarPath = snapshotTarPath(worldId, "gems", repo, fingerprint);
|
|
20171
|
-
const vendorBundle =
|
|
20172
|
-
if (
|
|
20345
|
+
const vendorBundle = path35.join(repoDir, "vendor", "bundle");
|
|
20346
|
+
if (fs31.existsSync(vendorBundle)) {
|
|
20173
20347
|
try {
|
|
20174
20348
|
packTarball(vendorBundle, tarPath);
|
|
20175
|
-
const stat =
|
|
20349
|
+
const stat = fs31.statSync(tarPath);
|
|
20176
20350
|
const manifest = {
|
|
20177
20351
|
kind: "gems",
|
|
20178
20352
|
worldId,
|
|
@@ -20205,10 +20379,10 @@ async function captureGems(worldId, workspacePath, repo) {
|
|
|
20205
20379
|
`docker exec ${containerName} sh -c 'mkdir -p "$(dirname ${tmpTar})" && tar -czf ${tmpTar}.tmp -C ${bundlePath} . && mv ${tmpTar}.tmp ${tmpTar}'`,
|
|
20206
20380
|
{ stdio: "pipe", timeout: 12e4 }
|
|
20207
20381
|
);
|
|
20208
|
-
|
|
20382
|
+
fs31.mkdirSync(path35.dirname(tarPath), { recursive: true });
|
|
20209
20383
|
execSync9(`docker cp ${containerName}:${tmpTar} "${tarPath}"`, { stdio: "pipe", timeout: 12e4 });
|
|
20210
20384
|
execSync9(`docker exec ${containerName} rm -f ${tmpTar}`, { stdio: "pipe" });
|
|
20211
|
-
const stat =
|
|
20385
|
+
const stat = fs31.statSync(tarPath);
|
|
20212
20386
|
const manifest = {
|
|
20213
20387
|
kind: "gems",
|
|
20214
20388
|
worldId,
|
|
@@ -20225,19 +20399,19 @@ async function captureGems(worldId, workspacePath, repo) {
|
|
|
20225
20399
|
}
|
|
20226
20400
|
}
|
|
20227
20401
|
async function captureNode(worldId, workspacePath, repo) {
|
|
20228
|
-
const repoDir =
|
|
20402
|
+
const repoDir = path35.join(workspacePath, repo);
|
|
20229
20403
|
const fingerprint = computeNodeFingerprint(repoDir);
|
|
20230
20404
|
if (!fingerprint) {
|
|
20231
20405
|
return { ok: false, tarPath: "", msg: "no lockfile \u2014 layer does not apply" };
|
|
20232
20406
|
}
|
|
20233
|
-
const nodeModules =
|
|
20234
|
-
if (!
|
|
20407
|
+
const nodeModules = path35.join(repoDir, "node_modules");
|
|
20408
|
+
if (!fs31.existsSync(nodeModules)) {
|
|
20235
20409
|
return { ok: false, tarPath: "", msg: "node_modules not installed yet" };
|
|
20236
20410
|
}
|
|
20237
20411
|
const tarPath = snapshotTarPath(worldId, "node", repo, fingerprint);
|
|
20238
20412
|
try {
|
|
20239
20413
|
packTarball(nodeModules, tarPath);
|
|
20240
|
-
const stat =
|
|
20414
|
+
const stat = fs31.statSync(tarPath);
|
|
20241
20415
|
const manifest = {
|
|
20242
20416
|
kind: "node",
|
|
20243
20417
|
worldId,
|
|
@@ -20254,7 +20428,7 @@ async function captureNode(worldId, workspacePath, repo) {
|
|
|
20254
20428
|
}
|
|
20255
20429
|
}
|
|
20256
20430
|
async function capturePg(worldId, workspacePath, repoNames) {
|
|
20257
|
-
const repoDirs = repoNames.map((r) =>
|
|
20431
|
+
const repoDirs = repoNames.map((r) => path35.join(workspacePath, r));
|
|
20258
20432
|
const fingerprint = computePgFingerprint(repoDirs);
|
|
20259
20433
|
if (!fingerprint) {
|
|
20260
20434
|
return { ok: false, tarPath: "", msg: "no Gemfile.lock / schema.rb \u2014 layer does not apply" };
|
|
@@ -20269,13 +20443,13 @@ async function capturePg(worldId, workspacePath, repoNames) {
|
|
|
20269
20443
|
}
|
|
20270
20444
|
try {
|
|
20271
20445
|
execSync9(`docker stop ${containerName}`, { stdio: "pipe", timeout: 3e4 });
|
|
20272
|
-
|
|
20446
|
+
fs31.mkdirSync(path35.dirname(tarPath), { recursive: true });
|
|
20273
20447
|
execSync9(
|
|
20274
|
-
`docker run --rm -v "${volumeName2}:/pgdata:ro" -v "${
|
|
20448
|
+
`docker run --rm -v "${volumeName2}:/pgdata:ro" -v "${path35.dirname(tarPath)}:/dest" alpine sh -c 'tar -czf /dest/${path35.basename(tarPath)}.tmp -C /pgdata . && mv /dest/${path35.basename(tarPath)}.tmp /dest/${path35.basename(tarPath)}'`,
|
|
20275
20449
|
{ stdio: "pipe", timeout: 18e4 }
|
|
20276
20450
|
);
|
|
20277
20451
|
execSync9(`docker start ${containerName}`, { stdio: "pipe", timeout: 3e4 });
|
|
20278
|
-
const stat =
|
|
20452
|
+
const stat = fs31.statSync(tarPath);
|
|
20279
20453
|
const manifest = {
|
|
20280
20454
|
kind: "pg",
|
|
20281
20455
|
worldId,
|
|
@@ -20350,35 +20524,35 @@ function formatAge2(ms) {
|
|
|
20350
20524
|
// src/commands/refresh.ts
|
|
20351
20525
|
init_context();
|
|
20352
20526
|
init_output();
|
|
20353
|
-
import * as
|
|
20527
|
+
import * as fs33 from "node:fs";
|
|
20354
20528
|
import * as os19 from "node:os";
|
|
20355
|
-
import * as
|
|
20529
|
+
import * as path37 from "node:path";
|
|
20356
20530
|
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
20357
20531
|
import ora8 from "ora";
|
|
20358
20532
|
|
|
20359
20533
|
// src/commands/refresh-helpers.ts
|
|
20360
|
-
import * as
|
|
20361
|
-
import * as
|
|
20534
|
+
import * as fs32 from "node:fs";
|
|
20535
|
+
import * as path36 from "node:path";
|
|
20362
20536
|
function collectCpSourceFiles(standaloneDir) {
|
|
20363
|
-
if (!
|
|
20537
|
+
if (!fs32.existsSync(standaloneDir)) {
|
|
20364
20538
|
throw new Error(`CP standalone dir not found: ${standaloneDir}`);
|
|
20365
20539
|
}
|
|
20366
20540
|
const entries = [];
|
|
20367
|
-
const topLevel =
|
|
20368
|
-
const stat =
|
|
20541
|
+
const topLevel = fs32.readdirSync(standaloneDir).filter((f) => {
|
|
20542
|
+
const stat = fs32.statSync(path36.join(standaloneDir, f));
|
|
20369
20543
|
return stat.isFile() && f.endsWith(".mjs") && !f.endsWith(".test.mjs");
|
|
20370
20544
|
}).sort();
|
|
20371
20545
|
for (const f of topLevel) {
|
|
20372
|
-
entries.push({ srcPath:
|
|
20546
|
+
entries.push({ srcPath: path36.join(standaloneDir, f), destRelPath: f });
|
|
20373
20547
|
}
|
|
20374
|
-
const libDir =
|
|
20375
|
-
if (
|
|
20376
|
-
const libFiles =
|
|
20377
|
-
const stat =
|
|
20548
|
+
const libDir = path36.join(standaloneDir, "lib");
|
|
20549
|
+
if (fs32.existsSync(libDir) && fs32.statSync(libDir).isDirectory()) {
|
|
20550
|
+
const libFiles = fs32.readdirSync(libDir).filter((f) => {
|
|
20551
|
+
const stat = fs32.statSync(path36.join(libDir, f));
|
|
20378
20552
|
return stat.isFile() && f.endsWith(".mjs") && !f.endsWith(".test.mjs");
|
|
20379
20553
|
}).sort();
|
|
20380
20554
|
for (const f of libFiles) {
|
|
20381
|
-
entries.push({ srcPath:
|
|
20555
|
+
entries.push({ srcPath: path36.join(libDir, f), destRelPath: `lib/${f}` });
|
|
20382
20556
|
}
|
|
20383
20557
|
}
|
|
20384
20558
|
return entries;
|
|
@@ -20436,16 +20610,16 @@ async function refreshWorld(worldId, portOffset, standaloneDir, opts) {
|
|
|
20436
20610
|
error: err instanceof Error ? err.message : String(err)
|
|
20437
20611
|
};
|
|
20438
20612
|
}
|
|
20439
|
-
const stagingDir =
|
|
20440
|
-
|
|
20613
|
+
const stagingDir = fs33.mkdtempSync(
|
|
20614
|
+
path37.join(os19.tmpdir(), `olam-refresh-${worldId}-`)
|
|
20441
20615
|
);
|
|
20442
20616
|
try {
|
|
20443
20617
|
const hasLib = entries.some((e) => e.destRelPath.startsWith("lib/"));
|
|
20444
20618
|
if (hasLib) {
|
|
20445
|
-
|
|
20619
|
+
fs33.mkdirSync(path37.join(stagingDir, "lib"), { recursive: true });
|
|
20446
20620
|
}
|
|
20447
20621
|
for (const { srcPath, destRelPath } of entries) {
|
|
20448
|
-
|
|
20622
|
+
fs33.copyFileSync(srcPath, path37.join(stagingDir, destRelPath));
|
|
20449
20623
|
}
|
|
20450
20624
|
const cpResult = docker([
|
|
20451
20625
|
"cp",
|
|
@@ -20460,7 +20634,7 @@ async function refreshWorld(worldId, portOffset, standaloneDir, opts) {
|
|
|
20460
20634
|
};
|
|
20461
20635
|
}
|
|
20462
20636
|
} finally {
|
|
20463
|
-
|
|
20637
|
+
fs33.rmSync(stagingDir, { recursive: true, force: true });
|
|
20464
20638
|
}
|
|
20465
20639
|
if (opts.restart) {
|
|
20466
20640
|
const restartResult = docker([
|
|
@@ -20497,11 +20671,11 @@ function registerRefresh(program2) {
|
|
|
20497
20671
|
process.exitCode = 1;
|
|
20498
20672
|
return;
|
|
20499
20673
|
}
|
|
20500
|
-
const standaloneDir =
|
|
20674
|
+
const standaloneDir = path37.join(
|
|
20501
20675
|
process.cwd(),
|
|
20502
20676
|
"packages/control-plane/standalone"
|
|
20503
20677
|
);
|
|
20504
|
-
if (!
|
|
20678
|
+
if (!fs33.existsSync(standaloneDir)) {
|
|
20505
20679
|
printError(
|
|
20506
20680
|
`CP standalone source not found at ${standaloneDir}.
|
|
20507
20681
|
Run \`olam refresh\` from the olam repo root.`
|
|
@@ -20580,9 +20754,9 @@ Run \`olam refresh\` from the olam repo root.`
|
|
|
20580
20754
|
}
|
|
20581
20755
|
|
|
20582
20756
|
// src/commands/diagnose.ts
|
|
20583
|
-
import * as
|
|
20757
|
+
import * as fs34 from "node:fs";
|
|
20584
20758
|
import * as os20 from "node:os";
|
|
20585
|
-
import * as
|
|
20759
|
+
import * as path38 from "node:path";
|
|
20586
20760
|
import { execFileSync as execFileSync6, execSync as execSync10 } from "node:child_process";
|
|
20587
20761
|
import pc20 from "picocolors";
|
|
20588
20762
|
|
|
@@ -20617,9 +20791,9 @@ function stripSecrets(input) {
|
|
|
20617
20791
|
}
|
|
20618
20792
|
|
|
20619
20793
|
// src/commands/diagnose.ts
|
|
20620
|
-
var DIAGNOSTICS_DIR =
|
|
20621
|
-
var LOG_DIR =
|
|
20622
|
-
var CACHE_DIR =
|
|
20794
|
+
var DIAGNOSTICS_DIR = path38.join(os20.homedir(), ".olam", "diagnostics");
|
|
20795
|
+
var LOG_DIR = path38.join(os20.homedir(), ".olam", "log");
|
|
20796
|
+
var CACHE_DIR = path38.join(os20.homedir(), ".olam", "cache");
|
|
20623
20797
|
var LOG_TAIL_LINES = 200;
|
|
20624
20798
|
function safeExec(cmd) {
|
|
20625
20799
|
try {
|
|
@@ -20633,10 +20807,10 @@ function defaultZip(zipPath, files) {
|
|
|
20633
20807
|
}
|
|
20634
20808
|
async function buildDiagnosticsZip(_exec = (cmd) => safeExec(cmd), _outDir = DIAGNOSTICS_DIR, _logDir = LOG_DIR, _zip = defaultZip) {
|
|
20635
20809
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 23);
|
|
20636
|
-
const zipPath =
|
|
20637
|
-
const tmpDir =
|
|
20810
|
+
const zipPath = path38.join(_outDir, `olam-diag-${ts}.zip`);
|
|
20811
|
+
const tmpDir = fs34.mkdtempSync(path38.join(os20.tmpdir(), "olam-diag-"));
|
|
20638
20812
|
try {
|
|
20639
|
-
|
|
20813
|
+
fs34.mkdirSync(_outDir, { recursive: true });
|
|
20640
20814
|
const entries = [];
|
|
20641
20815
|
const version = process.env["OLAM_CLI_VERSION"] ?? "unknown";
|
|
20642
20816
|
const nodeVersion = process.version;
|
|
@@ -20652,14 +20826,14 @@ platform: ${platform}
|
|
|
20652
20826
|
`uptime: ${os20.uptime()}s`
|
|
20653
20827
|
].join("\n") + "\n";
|
|
20654
20828
|
_writeEntry(tmpDir, "os-info.txt", stripSecrets(osContent), entries);
|
|
20655
|
-
const depsFile =
|
|
20656
|
-
if (
|
|
20657
|
-
const deps =
|
|
20829
|
+
const depsFile = path38.join(CACHE_DIR, "deps.json");
|
|
20830
|
+
if (fs34.existsSync(depsFile)) {
|
|
20831
|
+
const deps = fs34.readFileSync(depsFile, "utf-8");
|
|
20658
20832
|
_writeEntry(tmpDir, "deps.json", stripSecrets(deps), entries);
|
|
20659
20833
|
}
|
|
20660
20834
|
const latestLog = _latestLog(_logDir);
|
|
20661
20835
|
if (latestLog) {
|
|
20662
|
-
const lines =
|
|
20836
|
+
const lines = fs34.readFileSync(latestLog, "utf-8").split("\n");
|
|
20663
20837
|
const tail = lines.slice(-LOG_TAIL_LINES).join("\n");
|
|
20664
20838
|
_writeEntry(tmpDir, "log-tail.txt", stripSecrets(tail), entries);
|
|
20665
20839
|
}
|
|
@@ -20671,38 +20845,38 @@ platform: ${platform}
|
|
|
20671
20845
|
if (authAudit) {
|
|
20672
20846
|
_writeEntry(tmpDir, "audit-auth-callers.txt", stripSecrets(authAudit), entries);
|
|
20673
20847
|
}
|
|
20674
|
-
const fileArgs = entries.map((e) =>
|
|
20848
|
+
const fileArgs = entries.map((e) => path38.join(tmpDir, e));
|
|
20675
20849
|
try {
|
|
20676
20850
|
_zip(zipPath, fileArgs);
|
|
20677
20851
|
} catch (err) {
|
|
20678
20852
|
throw new Error(`zip command produced no output file. zip stderr: ${err.message}`);
|
|
20679
20853
|
}
|
|
20680
|
-
if (!
|
|
20854
|
+
if (!fs34.existsSync(zipPath)) {
|
|
20681
20855
|
throw new Error("zip command produced no output file.");
|
|
20682
20856
|
}
|
|
20683
20857
|
return { zipPath, entries };
|
|
20684
20858
|
} finally {
|
|
20685
20859
|
try {
|
|
20686
|
-
|
|
20860
|
+
fs34.rmSync(tmpDir, { recursive: true, force: true });
|
|
20687
20861
|
} catch {
|
|
20688
20862
|
}
|
|
20689
20863
|
}
|
|
20690
20864
|
}
|
|
20691
20865
|
function _writeEntry(dir, name, content, entries) {
|
|
20692
|
-
|
|
20866
|
+
fs34.writeFileSync(path38.join(dir, name), content, { mode: 420 });
|
|
20693
20867
|
entries.push(name);
|
|
20694
20868
|
}
|
|
20695
20869
|
function _latestLog(logDir) {
|
|
20696
|
-
if (!
|
|
20697
|
-
const files =
|
|
20698
|
-
return files.length > 0 ?
|
|
20870
|
+
if (!fs34.existsSync(logDir)) return null;
|
|
20871
|
+
const files = fs34.readdirSync(logDir).filter((f) => f.startsWith("host-")).sort().reverse();
|
|
20872
|
+
return files.length > 0 ? path38.join(logDir, files[0]) : null;
|
|
20699
20873
|
}
|
|
20700
20874
|
async function buildTelemetryPayload() {
|
|
20701
20875
|
const channel = "stable";
|
|
20702
|
-
const manifestFile =
|
|
20876
|
+
const manifestFile = path38.join(CACHE_DIR, "manifest.json");
|
|
20703
20877
|
let manifestAgeHours = null;
|
|
20704
|
-
if (
|
|
20705
|
-
const mtime =
|
|
20878
|
+
if (fs34.existsSync(manifestFile)) {
|
|
20879
|
+
const mtime = fs34.statSync(manifestFile).mtime.getTime();
|
|
20706
20880
|
manifestAgeHours = Math.round((Date.now() - mtime) / 36e5);
|
|
20707
20881
|
}
|
|
20708
20882
|
return {
|
|
@@ -20745,24 +20919,24 @@ function registerDiagnose(program2) {
|
|
|
20745
20919
|
}
|
|
20746
20920
|
|
|
20747
20921
|
// src/commands/update.ts
|
|
20748
|
-
import * as
|
|
20922
|
+
import * as fs37 from "node:fs";
|
|
20749
20923
|
import * as os22 from "node:os";
|
|
20750
|
-
import * as
|
|
20924
|
+
import * as path41 from "node:path";
|
|
20751
20925
|
import { execSync as execSync11 } from "node:child_process";
|
|
20752
20926
|
import pc21 from "picocolors";
|
|
20753
20927
|
|
|
20754
20928
|
// src/lib/symlink-reconcile.ts
|
|
20755
|
-
import * as
|
|
20756
|
-
import * as
|
|
20929
|
+
import * as fs35 from "node:fs";
|
|
20930
|
+
import * as path39 from "node:path";
|
|
20757
20931
|
var realFs = {
|
|
20758
|
-
readdirSync: (p) =>
|
|
20759
|
-
existsSync: (p) =>
|
|
20760
|
-
lstatSync: (p) =>
|
|
20761
|
-
readlinkSync: (p) =>
|
|
20762
|
-
symlinkSync: (t, l) =>
|
|
20763
|
-
unlinkSync: (p) =>
|
|
20932
|
+
readdirSync: (p) => fs35.readdirSync(p),
|
|
20933
|
+
existsSync: (p) => fs35.existsSync(p),
|
|
20934
|
+
lstatSync: (p) => fs35.lstatSync(p),
|
|
20935
|
+
readlinkSync: (p) => fs35.readlinkSync(p),
|
|
20936
|
+
symlinkSync: (t, l) => fs35.symlinkSync(t, l),
|
|
20937
|
+
unlinkSync: (p) => fs35.unlinkSync(p),
|
|
20764
20938
|
mkdirSync: (p, o) => {
|
|
20765
|
-
|
|
20939
|
+
fs35.mkdirSync(p, o);
|
|
20766
20940
|
}
|
|
20767
20941
|
};
|
|
20768
20942
|
function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
|
|
@@ -20772,8 +20946,8 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
|
|
|
20772
20946
|
_fs.mkdirSync(claudeSkillsDir, { recursive: true });
|
|
20773
20947
|
const sourceSkills = _fs.existsSync(npmSkillsDir) ? _fs.readdirSync(npmSkillsDir).filter((d) => d.startsWith("olam-")) : [];
|
|
20774
20948
|
for (const skill of sourceSkills) {
|
|
20775
|
-
const linkPath =
|
|
20776
|
-
const target =
|
|
20949
|
+
const linkPath = path39.join(claudeSkillsDir, skill);
|
|
20950
|
+
const target = path39.join(npmSkillsDir, skill);
|
|
20777
20951
|
if (!_fs.existsSync(linkPath)) {
|
|
20778
20952
|
try {
|
|
20779
20953
|
_fs.symlinkSync(target, linkPath);
|
|
@@ -20786,7 +20960,7 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
|
|
|
20786
20960
|
}
|
|
20787
20961
|
const deployedEntries = _fs.existsSync(claudeSkillsDir) ? _fs.readdirSync(claudeSkillsDir).filter((d) => d.startsWith("olam-")) : [];
|
|
20788
20962
|
for (const entry of deployedEntries) {
|
|
20789
|
-
const linkPath =
|
|
20963
|
+
const linkPath = path39.join(claudeSkillsDir, entry);
|
|
20790
20964
|
let isSymlink = false;
|
|
20791
20965
|
try {
|
|
20792
20966
|
isSymlink = _fs.lstatSync(linkPath).isSymbolicLink();
|
|
@@ -20811,9 +20985,9 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
|
|
|
20811
20985
|
|
|
20812
20986
|
// src/commands/update.ts
|
|
20813
20987
|
var PACKAGE_NAME = "@pleri/olam-cli";
|
|
20814
|
-
var CACHE_DIR2 =
|
|
20815
|
-
var LOG_DIR2 =
|
|
20816
|
-
var LAST_STABLE_FILE =
|
|
20988
|
+
var CACHE_DIR2 = path41.join(os22.homedir(), ".olam", "cache");
|
|
20989
|
+
var LOG_DIR2 = path41.join(os22.homedir(), ".olam", "log");
|
|
20990
|
+
var LAST_STABLE_FILE = path41.join(CACHE_DIR2, "last-stable.txt");
|
|
20817
20991
|
function defaultExec(cmd) {
|
|
20818
20992
|
try {
|
|
20819
20993
|
const stdout = execSync11(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -20835,22 +21009,22 @@ function getCurrentVersion(_exec = defaultExec) {
|
|
|
20835
21009
|
}
|
|
20836
21010
|
function readLastStable(file = LAST_STABLE_FILE) {
|
|
20837
21011
|
try {
|
|
20838
|
-
const v =
|
|
21012
|
+
const v = fs37.readFileSync(file, "utf-8").trim();
|
|
20839
21013
|
return v || null;
|
|
20840
21014
|
} catch {
|
|
20841
21015
|
return null;
|
|
20842
21016
|
}
|
|
20843
21017
|
}
|
|
20844
21018
|
function writeLastStable(version, file = LAST_STABLE_FILE) {
|
|
20845
|
-
|
|
20846
|
-
|
|
21019
|
+
fs37.mkdirSync(path41.dirname(file), { recursive: true });
|
|
21020
|
+
fs37.writeFileSync(file, version, { mode: 420 });
|
|
20847
21021
|
}
|
|
20848
21022
|
function logUpdateFailure(stderr) {
|
|
20849
21023
|
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
20850
|
-
const logFile =
|
|
21024
|
+
const logFile = path41.join(LOG_DIR2, `update-${ts}.log`);
|
|
20851
21025
|
try {
|
|
20852
|
-
|
|
20853
|
-
|
|
21026
|
+
fs37.mkdirSync(LOG_DIR2, { recursive: true });
|
|
21027
|
+
fs37.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
20854
21028
|
${stderr}
|
|
20855
21029
|
`, "utf-8");
|
|
20856
21030
|
} catch {
|
|
@@ -20937,8 +21111,8 @@ async function doUpdate(opts, _exec = defaultExec, _reconcile = reconcileSkillSy
|
|
|
20937
21111
|
let symlinkResult = { added: [], removed: [] };
|
|
20938
21112
|
if (npmRootResult.exitCode === 0) {
|
|
20939
21113
|
const npmRoot = npmRootResult.stdout.trim();
|
|
20940
|
-
const npmSkillsDir =
|
|
20941
|
-
const claudeSkillsDir =
|
|
21114
|
+
const npmSkillsDir = path41.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills");
|
|
21115
|
+
const claudeSkillsDir = path41.join(os22.homedir(), ".claude", "skills");
|
|
20942
21116
|
const rec = _reconcile(npmSkillsDir, claudeSkillsDir);
|
|
20943
21117
|
symlinkResult = { added: rec.added, removed: rec.removed };
|
|
20944
21118
|
if (!quiet && (rec.added.length > 0 || rec.removed.length > 0)) {
|
|
@@ -20984,8 +21158,8 @@ async function doRollback(_exec = defaultExec, _reconcile = reconcileSkillSymlin
|
|
|
20984
21158
|
if (npmRootResult.exitCode === 0) {
|
|
20985
21159
|
const npmRoot = npmRootResult.stdout.trim();
|
|
20986
21160
|
_reconcile(
|
|
20987
|
-
|
|
20988
|
-
|
|
21161
|
+
path41.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills"),
|
|
21162
|
+
path41.join(os22.homedir(), ".claude", "skills")
|
|
20989
21163
|
);
|
|
20990
21164
|
}
|
|
20991
21165
|
return { action: "rolled-back", restoredVersion: prev, exitCode: 0 };
|
|
@@ -21146,8 +21320,8 @@ var SECRET = process.env["OLAM_MCP_AUTH_SECRET"] ?? "";
|
|
|
21146
21320
|
function authHeaders() {
|
|
21147
21321
|
return SECRET ? { "X-Olam-Mcp-Secret": SECRET } : {};
|
|
21148
21322
|
}
|
|
21149
|
-
async function apiFetch(
|
|
21150
|
-
const res = await fetch(`${BASE_URL}${
|
|
21323
|
+
async function apiFetch(path45, init = {}) {
|
|
21324
|
+
const res = await fetch(`${BASE_URL}${path45}`, {
|
|
21151
21325
|
...init,
|
|
21152
21326
|
headers: {
|
|
21153
21327
|
"Content-Type": "application/json",
|
|
@@ -21407,12 +21581,12 @@ import * as readline3 from "node:readline";
|
|
|
21407
21581
|
import pc25 from "picocolors";
|
|
21408
21582
|
|
|
21409
21583
|
// src/commands/mcp/import-discovery.ts
|
|
21410
|
-
import * as
|
|
21584
|
+
import * as fs38 from "node:fs";
|
|
21411
21585
|
import * as os23 from "node:os";
|
|
21412
|
-
import * as
|
|
21586
|
+
import * as path42 from "node:path";
|
|
21413
21587
|
function readJsonFile(filePath) {
|
|
21414
21588
|
try {
|
|
21415
|
-
const raw =
|
|
21589
|
+
const raw = fs38.readFileSync(filePath, "utf-8");
|
|
21416
21590
|
return JSON.parse(raw);
|
|
21417
21591
|
} catch {
|
|
21418
21592
|
return null;
|
|
@@ -21441,24 +21615,24 @@ function extractMcpServers(obj, source, sourceLabel) {
|
|
|
21441
21615
|
}
|
|
21442
21616
|
function getClaudeDesktopPath() {
|
|
21443
21617
|
if (process.platform === "darwin") {
|
|
21444
|
-
return
|
|
21618
|
+
return path42.join(os23.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
21445
21619
|
}
|
|
21446
21620
|
if (process.platform === "win32") {
|
|
21447
|
-
const appData = process.env["APPDATA"] ??
|
|
21448
|
-
return
|
|
21621
|
+
const appData = process.env["APPDATA"] ?? path42.join(os23.homedir(), "AppData", "Roaming");
|
|
21622
|
+
return path42.join(appData, "Claude", "claude_desktop_config.json");
|
|
21449
21623
|
}
|
|
21450
|
-
return
|
|
21624
|
+
return path42.join(os23.homedir(), ".config", "Claude", "claude_desktop_config.json");
|
|
21451
21625
|
}
|
|
21452
21626
|
function getOlamRepoPaths() {
|
|
21453
21627
|
const configPaths = [
|
|
21454
|
-
|
|
21455
|
-
|
|
21628
|
+
path42.join(os23.homedir(), ".olam", "config.yaml"),
|
|
21629
|
+
path42.join(process.cwd(), ".olam", "config.yaml")
|
|
21456
21630
|
];
|
|
21457
21631
|
const paths = [];
|
|
21458
21632
|
for (const configPath of configPaths) {
|
|
21459
|
-
if (!
|
|
21633
|
+
if (!fs38.existsSync(configPath)) continue;
|
|
21460
21634
|
try {
|
|
21461
|
-
const raw =
|
|
21635
|
+
const raw = fs38.readFileSync(configPath, "utf-8");
|
|
21462
21636
|
const repoMatches = [...raw.matchAll(/path:\s*["']?([^\s"'\n]+)/g)];
|
|
21463
21637
|
for (const m of repoMatches) {
|
|
21464
21638
|
if (m[1]) paths.push(m[1]);
|
|
@@ -21474,7 +21648,7 @@ async function discoverMcpSources(repoPaths) {
|
|
|
21474
21648
|
const sources = [];
|
|
21475
21649
|
const sourceDefs = [
|
|
21476
21650
|
{
|
|
21477
|
-
path:
|
|
21651
|
+
path: path42.join(os23.homedir(), ".claude.json"),
|
|
21478
21652
|
label: "Claude Code (~/.claude.json)"
|
|
21479
21653
|
},
|
|
21480
21654
|
{
|
|
@@ -21482,19 +21656,19 @@ async function discoverMcpSources(repoPaths) {
|
|
|
21482
21656
|
label: "Claude Desktop"
|
|
21483
21657
|
},
|
|
21484
21658
|
{
|
|
21485
|
-
path:
|
|
21659
|
+
path: path42.join(os23.homedir(), ".cursor", "mcp.json"),
|
|
21486
21660
|
label: "Cursor (~/.cursor/mcp.json)"
|
|
21487
21661
|
},
|
|
21488
21662
|
{
|
|
21489
|
-
path:
|
|
21663
|
+
path: path42.join(os23.homedir(), ".codeium", "windsurf", "mcp_config.json"),
|
|
21490
21664
|
label: "Windsurf (~/.codeium/windsurf/mcp_config.json)"
|
|
21491
21665
|
}
|
|
21492
21666
|
];
|
|
21493
21667
|
const resolvedRepoPaths = repoPaths ?? getOlamRepoPaths();
|
|
21494
21668
|
for (const repoPath of resolvedRepoPaths) {
|
|
21495
21669
|
sourceDefs.push({
|
|
21496
|
-
path:
|
|
21497
|
-
label: `.mcp.json (${
|
|
21670
|
+
path: path42.join(repoPath, ".mcp.json"),
|
|
21671
|
+
label: `.mcp.json (${path42.basename(repoPath)})`
|
|
21498
21672
|
});
|
|
21499
21673
|
}
|
|
21500
21674
|
const reads = await Promise.all(
|
|
@@ -21670,30 +21844,72 @@ Importing ${selected.length} server(s)\u2026`);
|
|
|
21670
21844
|
});
|
|
21671
21845
|
}
|
|
21672
21846
|
|
|
21847
|
+
// src/commands/mcp/revoke.ts
|
|
21848
|
+
init_output();
|
|
21849
|
+
import pc26 from "picocolors";
|
|
21850
|
+
function registerMcpRevoke(cmd) {
|
|
21851
|
+
cmd.command("revoke <user> <world> <service>").description("Revoke a user's MCP service entitlement (multi-tenant mode only)").action(async (user, world, service) => {
|
|
21852
|
+
const multiTenant = (process.env["OLAM_MCP_MULTI_TENANT"] ?? "").toLowerCase() === "true";
|
|
21853
|
+
if (!multiTenant) {
|
|
21854
|
+
console.warn(pc26.yellow("\u26A0 revocation only meaningful in multi_tenant mode \u2014 no-op"));
|
|
21855
|
+
return;
|
|
21856
|
+
}
|
|
21857
|
+
const baseUrl = process.env["OLAM_MCP_AUTH_SERVICE_URL"] ?? "http://127.0.0.1:9998";
|
|
21858
|
+
const secret = process.env["OLAM_MCP_AUTH_SECRET"] ?? "";
|
|
21859
|
+
const headers = { "Content-Type": "application/json" };
|
|
21860
|
+
if (secret) headers["X-Olam-Mcp-Secret"] = secret;
|
|
21861
|
+
let res;
|
|
21862
|
+
try {
|
|
21863
|
+
res = await fetch(
|
|
21864
|
+
`${baseUrl}/entitlement/${encodeURIComponent(user)}/${encodeURIComponent(world)}/${encodeURIComponent(service)}`,
|
|
21865
|
+
{ method: "DELETE", headers }
|
|
21866
|
+
);
|
|
21867
|
+
} catch (err) {
|
|
21868
|
+
printError(`Could not reach mcp-auth service: ${err instanceof Error ? err.message : "unknown"}`);
|
|
21869
|
+
process.exitCode = 1;
|
|
21870
|
+
return;
|
|
21871
|
+
}
|
|
21872
|
+
if (!res.ok) {
|
|
21873
|
+
let msg = `HTTP ${res.status}`;
|
|
21874
|
+
try {
|
|
21875
|
+
const body = await res.json();
|
|
21876
|
+
if (body.error) msg = body.error;
|
|
21877
|
+
} catch {
|
|
21878
|
+
}
|
|
21879
|
+
printError(`Revoke failed: ${msg}`);
|
|
21880
|
+
process.exitCode = 1;
|
|
21881
|
+
return;
|
|
21882
|
+
}
|
|
21883
|
+
console.log(pc26.green(`\u2713 Revoked: ${user} / ${world} / ${service}`));
|
|
21884
|
+
console.log(pc26.dim(" Next fetch-creds call returns 403; token cleared on next merge."));
|
|
21885
|
+
});
|
|
21886
|
+
}
|
|
21887
|
+
|
|
21673
21888
|
// src/commands/mcp/index.ts
|
|
21674
21889
|
function registerMcp(program2) {
|
|
21675
|
-
const mcp = program2.command("mcp").description("Manage MCP server credentials (login, add, list, remove, import)");
|
|
21890
|
+
const mcp = program2.command("mcp").description("Manage MCP server credentials (login, add, list, remove, import, revoke)");
|
|
21676
21891
|
registerMcpLogin(mcp);
|
|
21677
21892
|
registerMcpAdd(mcp);
|
|
21678
21893
|
registerMcpList(mcp);
|
|
21679
21894
|
registerMcpRemove(mcp);
|
|
21680
21895
|
registerMcpStatus(mcp);
|
|
21681
21896
|
registerMcpImport(mcp);
|
|
21897
|
+
registerMcpRevoke(mcp);
|
|
21682
21898
|
}
|
|
21683
21899
|
|
|
21684
21900
|
// src/pleri-config.ts
|
|
21685
|
-
import * as
|
|
21686
|
-
import * as
|
|
21901
|
+
import * as fs39 from "node:fs";
|
|
21902
|
+
import * as path43 from "node:path";
|
|
21687
21903
|
function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
21688
21904
|
if (process.env.PLERI_BASE_URL) {
|
|
21689
21905
|
return true;
|
|
21690
21906
|
}
|
|
21691
|
-
const configPath =
|
|
21692
|
-
if (!
|
|
21907
|
+
const configPath = path43.join(configDir, "config.yaml");
|
|
21908
|
+
if (!fs39.existsSync(configPath)) {
|
|
21693
21909
|
return false;
|
|
21694
21910
|
}
|
|
21695
21911
|
try {
|
|
21696
|
-
const contents =
|
|
21912
|
+
const contents = fs39.readFileSync(configPath, "utf8");
|
|
21697
21913
|
return /^[^#\n]*\bpleri:/m.test(contents);
|
|
21698
21914
|
} catch {
|
|
21699
21915
|
return false;
|
|
@@ -21704,14 +21920,14 @@ function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
|
21704
21920
|
var program = new Command();
|
|
21705
21921
|
function readCliVersion() {
|
|
21706
21922
|
try {
|
|
21707
|
-
const here =
|
|
21923
|
+
const here = path44.dirname(fileURLToPath4(import.meta.url));
|
|
21708
21924
|
for (const candidate of [
|
|
21709
|
-
|
|
21710
|
-
|
|
21711
|
-
|
|
21925
|
+
path44.join(here, "package.json"),
|
|
21926
|
+
path44.join(here, "..", "package.json"),
|
|
21927
|
+
path44.join(here, "..", "..", "package.json")
|
|
21712
21928
|
]) {
|
|
21713
|
-
if (
|
|
21714
|
-
const pkg = JSON.parse(
|
|
21929
|
+
if (fs40.existsSync(candidate)) {
|
|
21930
|
+
const pkg = JSON.parse(fs40.readFileSync(candidate, "utf-8"));
|
|
21715
21931
|
if (typeof pkg.version === "string" && pkg.version.length > 0) return pkg.version;
|
|
21716
21932
|
}
|
|
21717
21933
|
}
|