@pleri/olam-cli 0.1.173 → 0.1.175
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/auth.d.ts +22 -7
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +414 -46
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +45 -1
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/services.d.ts +39 -0
- package/dist/commands/services.d.ts.map +1 -1
- package/dist/commands/services.js +64 -9
- package/dist/commands/services.js.map +1 -1
- package/dist/from-manifest.d.ts +53 -0
- package/dist/from-manifest.d.ts.map +1 -0
- package/dist/from-manifest.js +95 -0
- package/dist/from-manifest.js.map +1 -0
- package/dist/image-digests.json +8 -8
- package/dist/index.js +907 -136
- package/dist/lib/auth-remote.d.ts +130 -0
- package/dist/lib/auth-remote.d.ts.map +1 -0
- package/dist/lib/auth-remote.js +307 -0
- package/dist/lib/auth-remote.js.map +1 -0
- package/dist/mcp-server.js +254 -57
- package/hermes-bundle/version.json +1 -1
- package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
- package/host-cp/src/boot-reconciler.mjs +238 -0
- package/host-cp/src/port-bridge-manager.mjs +116 -10
- package/host-cp/src/server.mjs +32 -0
- package/host-cp/src/world-activity-tracker.mjs +392 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8314,6 +8314,21 @@ CREATE TABLE IF NOT EXISTS meta (
|
|
|
8314
8314
|
const row = this.db.prepare("SELECT * FROM worlds WHERE id = ?").get(worldId);
|
|
8315
8315
|
return row ? rowToMetadata(row) : void 0;
|
|
8316
8316
|
}
|
|
8317
|
+
/**
|
|
8318
|
+
* Find all worlds with a given `name`. Returns rows of every lifecycle
|
|
8319
|
+
* status — callers filter as needed (e.g. active-only for dedup, error-
|
|
8320
|
+
* only for cleanup).
|
|
8321
|
+
*
|
|
8322
|
+
* The schema has UNIQUE on `id` but NOT on `name`, so a single name can
|
|
8323
|
+
* legitimately have multiple rows (e.g. one destroyed + one new). Issue
|
|
8324
|
+
* #962: `olam create <name>` was generating fresh ids without checking
|
|
8325
|
+
* for an existing row, accumulating orphan error rows under the same
|
|
8326
|
+
* name. This is the registry-level primitive the manager's dedup uses.
|
|
8327
|
+
*/
|
|
8328
|
+
findByName(name) {
|
|
8329
|
+
const rows = this.db.prepare("SELECT * FROM worlds WHERE name = ? ORDER BY created_at DESC").all(name);
|
|
8330
|
+
return rows.map(rowToMetadata);
|
|
8331
|
+
}
|
|
8317
8332
|
list(filter2) {
|
|
8318
8333
|
if (filter2?.status) {
|
|
8319
8334
|
const rows2 = this.db.prepare("SELECT * FROM worlds WHERE status = ? ORDER BY created_at DESC").all(filter2.status);
|
|
@@ -8863,8 +8878,8 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
|
|
|
8863
8878
|
}
|
|
8864
8879
|
}
|
|
8865
8880
|
async function copyClaudeConfigIntoContainer(containerName) {
|
|
8866
|
-
const { execSync:
|
|
8867
|
-
const dockerExec = (cmd) =>
|
|
8881
|
+
const { execSync: execSync16 } = await import("node:child_process");
|
|
8882
|
+
const dockerExec = (cmd) => execSync16(`docker exec ${containerName} sh -c '${cmd}'`, { stdio: "pipe" });
|
|
8868
8883
|
dockerExec("mkdir -p $HOME/.claude");
|
|
8869
8884
|
dockerExec("test -f /home/olam/workspace/.claude-host-config/settings.json && cp /home/olam/workspace/.claude-host-config/settings.json $HOME/.claude/settings.json || true");
|
|
8870
8885
|
dockerExec("test -f /home/olam/workspace/.claude-host-config/CLAUDE.md && cp /home/olam/workspace/.claude-host-config/CLAUDE.md $HOME/.claude/CLAUDE.md || true");
|
|
@@ -8880,7 +8895,7 @@ async function copyClaudeConfigIntoContainer(containerName) {
|
|
|
8880
8895
|
await sanitizeContainerClaudeHooks(containerName);
|
|
8881
8896
|
}
|
|
8882
8897
|
async function sanitizeContainerClaudeHooks(containerName) {
|
|
8883
|
-
const { execSync:
|
|
8898
|
+
const { execSync: execSync16 } = await import("node:child_process");
|
|
8884
8899
|
const script = `
|
|
8885
8900
|
const fs = require('fs');
|
|
8886
8901
|
const p = (process.env.HOME || '/home/olam') + '/.claude/settings.json';
|
|
@@ -8924,7 +8939,7 @@ if (changed) {
|
|
|
8924
8939
|
}
|
|
8925
8940
|
`;
|
|
8926
8941
|
try {
|
|
8927
|
-
|
|
8942
|
+
execSync16(`docker exec ${containerName} /usr/local/bin/node -e ${shQuote(script)}`, { stdio: "pipe" });
|
|
8928
8943
|
} catch {
|
|
8929
8944
|
}
|
|
8930
8945
|
}
|
|
@@ -11715,6 +11730,60 @@ var init_bootstrap_hooks = __esm({
|
|
|
11715
11730
|
}
|
|
11716
11731
|
});
|
|
11717
11732
|
|
|
11733
|
+
// ../core/dist/world/create-dedup.js
|
|
11734
|
+
import { execSync as execSync5 } from "node:child_process";
|
|
11735
|
+
function resolveCreateDedup(opts) {
|
|
11736
|
+
const { registry, name } = opts;
|
|
11737
|
+
const probe2 = opts.probeContainer ?? defaultContainerProbe;
|
|
11738
|
+
const containerName = `olam-${name}-devbox`;
|
|
11739
|
+
const existing = registry.findByName(name);
|
|
11740
|
+
const active = existing.find((w) => ACTIVE_STATUSES.has(w.status));
|
|
11741
|
+
if (active) {
|
|
11742
|
+
return { action: "reuse", world: active };
|
|
11743
|
+
}
|
|
11744
|
+
const errorRows = existing.filter((w) => w.status === "error");
|
|
11745
|
+
for (const er of errorRows) {
|
|
11746
|
+
registry.remove(er.id);
|
|
11747
|
+
}
|
|
11748
|
+
if (probe2(containerName)) {
|
|
11749
|
+
return {
|
|
11750
|
+
action: "container-orphan",
|
|
11751
|
+
containerName,
|
|
11752
|
+
remediation: `A container '${containerName}' is running on this host but no worlds.db row exists for it. Either destroy the orphan with 'docker rm -f ${containerName}' and re-run, or wait for the reconciler (issue #963) to insert a row.`
|
|
11753
|
+
};
|
|
11754
|
+
}
|
|
11755
|
+
return { action: "fresh", cleanedErrorRows: errorRows.length };
|
|
11756
|
+
}
|
|
11757
|
+
var ACTIVE_STATUSES, defaultContainerProbe, ContainerOrphanError;
|
|
11758
|
+
var init_create_dedup = __esm({
|
|
11759
|
+
"../core/dist/world/create-dedup.js"() {
|
|
11760
|
+
"use strict";
|
|
11761
|
+
ACTIVE_STATUSES = /* @__PURE__ */ new Set([
|
|
11762
|
+
"creating",
|
|
11763
|
+
"running",
|
|
11764
|
+
"paused",
|
|
11765
|
+
"crystallizing"
|
|
11766
|
+
]);
|
|
11767
|
+
defaultContainerProbe = (containerName) => {
|
|
11768
|
+
try {
|
|
11769
|
+
const out = execSync5(`docker ps --filter name=^/${containerName}$ --format '{{.Names}}'`, { stdio: ["pipe", "pipe", "pipe"], timeout: 5e3 }).toString().trim();
|
|
11770
|
+
return out.length > 0;
|
|
11771
|
+
} catch {
|
|
11772
|
+
return false;
|
|
11773
|
+
}
|
|
11774
|
+
};
|
|
11775
|
+
ContainerOrphanError = class extends Error {
|
|
11776
|
+
containerName;
|
|
11777
|
+
kind = "container-orphan";
|
|
11778
|
+
constructor(message, containerName) {
|
|
11779
|
+
super(message);
|
|
11780
|
+
this.containerName = containerName;
|
|
11781
|
+
this.name = "ContainerOrphanError";
|
|
11782
|
+
}
|
|
11783
|
+
};
|
|
11784
|
+
}
|
|
11785
|
+
});
|
|
11786
|
+
|
|
11718
11787
|
// ../core/dist/world/tmux-supervisor.js
|
|
11719
11788
|
function injectBindAll(start) {
|
|
11720
11789
|
let result = start;
|
|
@@ -11852,6 +11921,7 @@ var manager_exports = {};
|
|
|
11852
11921
|
__export(manager_exports, {
|
|
11853
11922
|
AuthPreflightError: () => AuthPreflightError,
|
|
11854
11923
|
BotIdentityError: () => BotIdentityError,
|
|
11924
|
+
ContainerOrphanError: () => ContainerOrphanError,
|
|
11855
11925
|
TaskDispatchError: () => TaskDispatchError,
|
|
11856
11926
|
WorkspaceNotFoundError: () => WorkspaceNotFoundError,
|
|
11857
11927
|
WorldManager: () => WorldManager,
|
|
@@ -11871,12 +11941,12 @@ __export(manager_exports, {
|
|
|
11871
11941
|
runManifestRuntime: () => runManifestRuntime
|
|
11872
11942
|
});
|
|
11873
11943
|
import * as crypto5 from "node:crypto";
|
|
11874
|
-
import { execSync as
|
|
11944
|
+
import { execSync as execSync6, spawnSync as spawnSync5 } from "node:child_process";
|
|
11875
11945
|
import * as fs23 from "node:fs";
|
|
11876
11946
|
import * as os13 from "node:os";
|
|
11877
11947
|
import * as path25 from "node:path";
|
|
11878
11948
|
import YAML3 from "yaml";
|
|
11879
|
-
function getTokenScopes(ghToken, _exec =
|
|
11949
|
+
function getTokenScopes(ghToken, _exec = execSync6) {
|
|
11880
11950
|
try {
|
|
11881
11951
|
const out = _exec("gh auth status 2>&1", {
|
|
11882
11952
|
encoding: "utf-8",
|
|
@@ -11893,13 +11963,13 @@ function getTokenScopes(ghToken, _exec = execSync5) {
|
|
|
11893
11963
|
}
|
|
11894
11964
|
}
|
|
11895
11965
|
async function setupContainerGit(containerName, repos, branch) {
|
|
11896
|
-
const dockerExec = (cmd) =>
|
|
11966
|
+
const dockerExec = (cmd) => execSync6(`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`, {
|
|
11897
11967
|
stdio: "pipe",
|
|
11898
11968
|
timeout: 6e4
|
|
11899
11969
|
}).toString();
|
|
11900
11970
|
let ghToken = "";
|
|
11901
11971
|
try {
|
|
11902
|
-
ghToken =
|
|
11972
|
+
ghToken = execSync6("gh auth token 2>/dev/null", { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
11903
11973
|
} catch {
|
|
11904
11974
|
}
|
|
11905
11975
|
const actorName = process.env.OLAM_BOT_NAME ?? "Claude Code (olam)";
|
|
@@ -11919,7 +11989,7 @@ async function setupContainerGit(containerName, repos, branch) {
|
|
|
11919
11989
|
continue;
|
|
11920
11990
|
const ownerRepo = ghMatch[1];
|
|
11921
11991
|
try {
|
|
11922
|
-
|
|
11992
|
+
execSync6(`gh api repos/${ownerRepo} --silent`, {
|
|
11923
11993
|
stdio: "pipe",
|
|
11924
11994
|
timeout: 5e3,
|
|
11925
11995
|
env: { ...process.env, GH_TOKEN: ghToken }
|
|
@@ -11967,7 +12037,7 @@ ${stderr.split("\n").slice(0, 3).join(" ")}`);
|
|
|
11967
12037
|
if (!olamUserPresent) {
|
|
11968
12038
|
const imageName = (() => {
|
|
11969
12039
|
try {
|
|
11970
|
-
return
|
|
12040
|
+
return execSync6(`docker inspect ${containerName} --format '{{.Config.Image}}'`, {
|
|
11971
12041
|
encoding: "utf8",
|
|
11972
12042
|
timeout: 5e3
|
|
11973
12043
|
}).trim() || "(unknown)";
|
|
@@ -12010,7 +12080,7 @@ ${stderr.split("\n").slice(0, 3).join(" ")}`);
|
|
|
12010
12080
|
function makeHostExecFn() {
|
|
12011
12081
|
return async (cmd) => {
|
|
12012
12082
|
try {
|
|
12013
|
-
const stdout =
|
|
12083
|
+
const stdout = execSync6(cmd, { encoding: "utf-8", timeout: 5e3 });
|
|
12014
12084
|
return { stdout, stderr: "", exitCode: 0 };
|
|
12015
12085
|
} catch {
|
|
12016
12086
|
return { stdout: "", stderr: "", exitCode: 1 };
|
|
@@ -12020,7 +12090,7 @@ function makeHostExecFn() {
|
|
|
12020
12090
|
function makeContainerExecFn(containerName) {
|
|
12021
12091
|
return async (cmd) => {
|
|
12022
12092
|
try {
|
|
12023
|
-
const result =
|
|
12093
|
+
const result = execSync6(`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`, { stdio: "pipe", timeout: 6e5 });
|
|
12024
12094
|
return { stdout: result.toString(), stderr: "", exitCode: 0 };
|
|
12025
12095
|
} catch (err) {
|
|
12026
12096
|
const execErr = err;
|
|
@@ -12034,7 +12104,7 @@ function makeContainerExecFn(containerName) {
|
|
|
12034
12104
|
}
|
|
12035
12105
|
function defaultDockerExec2() {
|
|
12036
12106
|
return (containerName, cmd) => {
|
|
12037
|
-
const result =
|
|
12107
|
+
const result = execSync6(
|
|
12038
12108
|
`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`,
|
|
12039
12109
|
// Phase E E5 raise: 10min was too tight on cold-boot for atlas-core's
|
|
12040
12110
|
// `rails db:create` chain (Rails 7 boot + initializer load + first
|
|
@@ -12214,7 +12284,7 @@ function buildManifestRuntime(worldId, repos) {
|
|
|
12214
12284
|
}
|
|
12215
12285
|
return { worldId, repos: runtimeRepos };
|
|
12216
12286
|
}
|
|
12217
|
-
function exposeWorldOverTailscale(appPortUrls, worldId, registry, _exec =
|
|
12287
|
+
function exposeWorldOverTailscale(appPortUrls, worldId, registry, _exec = execSync6) {
|
|
12218
12288
|
if (process.env["OLAM_TAILSCALE_SERVE"] !== "true")
|
|
12219
12289
|
return;
|
|
12220
12290
|
if (appPortUrls.length === 0)
|
|
@@ -12242,7 +12312,7 @@ function exposeWorldOverTailscale(appPortUrls, worldId, registry, _exec = execSy
|
|
|
12242
12312
|
registry.storeTailscalePaths(worldId, registeredPaths);
|
|
12243
12313
|
}
|
|
12244
12314
|
}
|
|
12245
|
-
function cleanupWorldTailscale(worldId, registry, _exec =
|
|
12315
|
+
function cleanupWorldTailscale(worldId, registry, _exec = execSync6) {
|
|
12246
12316
|
const paths = registry.loadTailscalePaths(worldId);
|
|
12247
12317
|
if (paths.length === 0)
|
|
12248
12318
|
return;
|
|
@@ -12261,7 +12331,7 @@ function cleanupWorldTailscale(worldId, registry, _exec = execSync5) {
|
|
|
12261
12331
|
}
|
|
12262
12332
|
}
|
|
12263
12333
|
}
|
|
12264
|
-
function resolveTailscaleBin(_exec =
|
|
12334
|
+
function resolveTailscaleBin(_exec = execSync6) {
|
|
12265
12335
|
const candidates2 = [
|
|
12266
12336
|
process.env["TAILSCALE_BIN"],
|
|
12267
12337
|
"/Applications/Tailscale.app/Contents/MacOS/Tailscale",
|
|
@@ -12660,6 +12730,8 @@ var init_manager = __esm({
|
|
|
12660
12730
|
init_runbook_resolver();
|
|
12661
12731
|
init_port_validator();
|
|
12662
12732
|
init_bootstrap_hooks();
|
|
12733
|
+
init_create_dedup();
|
|
12734
|
+
init_create_dedup();
|
|
12663
12735
|
init_tmux_supervisor();
|
|
12664
12736
|
BotIdentityError = class extends Error {
|
|
12665
12737
|
constructor(message) {
|
|
@@ -12694,19 +12766,38 @@ var init_manager = __esm({
|
|
|
12694
12766
|
dashboardManager;
|
|
12695
12767
|
pleriClient;
|
|
12696
12768
|
dockerExec;
|
|
12769
|
+
containerProbe;
|
|
12697
12770
|
manifestRuntimes = /* @__PURE__ */ new Map();
|
|
12698
|
-
constructor(config, provider, registry, dashboardManager, pleriClient, dockerExec) {
|
|
12771
|
+
constructor(config, provider, registry, dashboardManager, pleriClient, dockerExec, containerProbe) {
|
|
12699
12772
|
this.config = config;
|
|
12700
12773
|
this.provider = provider;
|
|
12701
12774
|
this.registry = registry;
|
|
12702
12775
|
this.dashboardManager = dashboardManager;
|
|
12703
12776
|
this.pleriClient = pleriClient;
|
|
12704
12777
|
this.dockerExec = dockerExec ?? defaultDockerExec2();
|
|
12778
|
+
this.containerProbe = containerProbe;
|
|
12705
12779
|
}
|
|
12706
12780
|
// -----------------------------------------------------------------------
|
|
12707
12781
|
// createWorld
|
|
12708
12782
|
// -----------------------------------------------------------------------
|
|
12709
12783
|
async createWorld(opts) {
|
|
12784
|
+
{
|
|
12785
|
+
const dedupOpts = {
|
|
12786
|
+
registry: this.registry,
|
|
12787
|
+
name: opts.name,
|
|
12788
|
+
...this.containerProbe ? { probeContainer: this.containerProbe } : {}
|
|
12789
|
+
};
|
|
12790
|
+
const dedup = resolveCreateDedup(dedupOpts);
|
|
12791
|
+
if (dedup.action === "reuse") {
|
|
12792
|
+
return dedup.world;
|
|
12793
|
+
}
|
|
12794
|
+
if (dedup.action === "container-orphan") {
|
|
12795
|
+
throw new ContainerOrphanError(dedup.remediation, dedup.containerName);
|
|
12796
|
+
}
|
|
12797
|
+
if (dedup.cleanedErrorRows > 0) {
|
|
12798
|
+
console.log(`[manager] removed ${dedup.cleanedErrorRows} stale error row(s) for world name "${opts.name}" before fresh create (issue #962)`);
|
|
12799
|
+
}
|
|
12800
|
+
}
|
|
12710
12801
|
if (!opts.noAuth) {
|
|
12711
12802
|
const preflight2 = await runAuthPreflight({ autoStart: true });
|
|
12712
12803
|
if (preflight2.verdict !== "ok") {
|
|
@@ -13390,7 +13481,7 @@ ${detail}`);
|
|
|
13390
13481
|
const escapedDir = `/home/olam/workspace/${repo.name.replace(/["$`\\]/g, "\\$&")}`;
|
|
13391
13482
|
for (const cmd of repo.setup_commands) {
|
|
13392
13483
|
try {
|
|
13393
|
-
|
|
13484
|
+
execSync6(`docker exec ${containerName} sh -c 'cd "${escapedDir}" && ${cmd.replace(/'/g, "'\\''")}'`, { stdio: "pipe", timeout: 6e5 });
|
|
13394
13485
|
} catch (err) {
|
|
13395
13486
|
const msg = err instanceof Error ? err.message : String(err);
|
|
13396
13487
|
console.warn(`[WorldManager] setup command failed for ${repo.name}: ${msg}`);
|
|
@@ -13411,11 +13502,11 @@ ${detail}`);
|
|
|
13411
13502
|
});
|
|
13412
13503
|
if (allPolicies.length > 0) {
|
|
13413
13504
|
try {
|
|
13414
|
-
|
|
13505
|
+
execSync6(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
|
|
13415
13506
|
for (const repo of repos) {
|
|
13416
13507
|
const policiesDir = path25.join(workspacePath, repo.name, ".olam", "policies");
|
|
13417
13508
|
if (fs23.existsSync(policiesDir)) {
|
|
13418
|
-
|
|
13509
|
+
execSync6(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
|
|
13419
13510
|
}
|
|
13420
13511
|
}
|
|
13421
13512
|
} catch (err) {
|
|
@@ -14903,10 +14994,10 @@ var init_state2 = __esm({
|
|
|
14903
14994
|
});
|
|
14904
14995
|
|
|
14905
14996
|
// ../core/dist/dashboard/tunnel.js
|
|
14906
|
-
import { spawn as spawn3, execSync as
|
|
14997
|
+
import { spawn as spawn3, execSync as execSync7 } from "node:child_process";
|
|
14907
14998
|
function isCloudflaredAvailable() {
|
|
14908
14999
|
try {
|
|
14909
|
-
|
|
15000
|
+
execSync7("which cloudflared", { stdio: "ignore" });
|
|
14910
15001
|
return true;
|
|
14911
15002
|
} catch {
|
|
14912
15003
|
return false;
|
|
@@ -16238,6 +16329,69 @@ var init_registry_allowlist = __esm({
|
|
|
16238
16329
|
}
|
|
16239
16330
|
});
|
|
16240
16331
|
|
|
16332
|
+
// src/from-manifest.ts
|
|
16333
|
+
var from_manifest_exports = {};
|
|
16334
|
+
__export(from_manifest_exports, {
|
|
16335
|
+
defaultNameFromManifest: () => defaultNameFromManifest,
|
|
16336
|
+
parseForkManifest: () => parseForkManifest,
|
|
16337
|
+
provenanceLine: () => provenanceLine
|
|
16338
|
+
});
|
|
16339
|
+
import { readFileSync as readFileSync30 } from "node:fs";
|
|
16340
|
+
function parseForkManifest(path96) {
|
|
16341
|
+
let raw;
|
|
16342
|
+
try {
|
|
16343
|
+
raw = readFileSync30(path96, "utf8");
|
|
16344
|
+
} catch (err) {
|
|
16345
|
+
const reason = err?.code === "ENOENT" ? "file does not exist" : err.message;
|
|
16346
|
+
throw new Error(`--from-manifest: cannot read ${path96} (${reason})`);
|
|
16347
|
+
}
|
|
16348
|
+
let json;
|
|
16349
|
+
try {
|
|
16350
|
+
json = JSON.parse(raw);
|
|
16351
|
+
} catch (err) {
|
|
16352
|
+
throw new Error(`--from-manifest: ${path96} is not valid JSON (${err.message})`);
|
|
16353
|
+
}
|
|
16354
|
+
if (!isPlainObject2(json)) {
|
|
16355
|
+
throw new Error(`--from-manifest: ${path96} root must be a JSON object`);
|
|
16356
|
+
}
|
|
16357
|
+
const originalWorldId = json.originalWorldId;
|
|
16358
|
+
if (typeof originalWorldId !== "string" || originalWorldId.trim().length === 0) {
|
|
16359
|
+
throw new Error(`--from-manifest: ${path96} missing required string "originalWorldId"`);
|
|
16360
|
+
}
|
|
16361
|
+
const newPrompt = json.newPrompt;
|
|
16362
|
+
if (typeof newPrompt !== "string" || newPrompt.trim().length === 0) {
|
|
16363
|
+
throw new Error(
|
|
16364
|
+
`--from-manifest: ${path96} has no "newPrompt" \u2014 re-run trace-replay with --with-prompt "<alternate dispatch>"`
|
|
16365
|
+
);
|
|
16366
|
+
}
|
|
16367
|
+
const fp = isPlainObject2(json.forkPoint) ? json.forkPoint : {};
|
|
16368
|
+
const resolvedPhase = typeof fp.resolvedPhase === "string" ? fp.resolvedPhase : null;
|
|
16369
|
+
const resolvedSpanId = typeof fp.resolvedSpanId === "string" ? fp.resolvedSpanId : null;
|
|
16370
|
+
const resolvedAt = typeof fp.resolvedAt === "number" ? fp.resolvedAt : 0;
|
|
16371
|
+
return {
|
|
16372
|
+
originalWorldId: originalWorldId.trim(),
|
|
16373
|
+
forkPoint: { resolvedPhase, resolvedSpanId, resolvedAt },
|
|
16374
|
+
newPrompt,
|
|
16375
|
+
manifestPath: path96
|
|
16376
|
+
};
|
|
16377
|
+
}
|
|
16378
|
+
function defaultNameFromManifest(manifest) {
|
|
16379
|
+
const base = `fork-${manifest.originalWorldId}`.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
16380
|
+
return (base || "fork").slice(0, 40);
|
|
16381
|
+
}
|
|
16382
|
+
function provenanceLine(manifest) {
|
|
16383
|
+
const phase = manifest.forkPoint.resolvedPhase ?? "end-of-trace";
|
|
16384
|
+
return `Forking from ${manifest.originalWorldId} @ phase=${phase} (manifest: ${manifest.manifestPath})`;
|
|
16385
|
+
}
|
|
16386
|
+
function isPlainObject2(v) {
|
|
16387
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
16388
|
+
}
|
|
16389
|
+
var init_from_manifest = __esm({
|
|
16390
|
+
"src/from-manifest.ts"() {
|
|
16391
|
+
"use strict";
|
|
16392
|
+
}
|
|
16393
|
+
});
|
|
16394
|
+
|
|
16241
16395
|
// src/spawn/home-override.ts
|
|
16242
16396
|
var home_override_exports = {};
|
|
16243
16397
|
__export(home_override_exports, {
|
|
@@ -18149,13 +18303,13 @@ var init_file_lock = __esm({
|
|
|
18149
18303
|
});
|
|
18150
18304
|
|
|
18151
18305
|
// ../core/dist/lib/min-version-filter.js
|
|
18152
|
-
import { existsSync as existsSync73, readFileSync as
|
|
18306
|
+
import { existsSync as existsSync73, readFileSync as readFileSync61 } from "node:fs";
|
|
18153
18307
|
function readOlamMinVersion(filepath) {
|
|
18154
18308
|
if (!existsSync73(filepath))
|
|
18155
18309
|
return void 0;
|
|
18156
18310
|
let text;
|
|
18157
18311
|
try {
|
|
18158
|
-
text =
|
|
18312
|
+
text = readFileSync61(filepath, "utf8");
|
|
18159
18313
|
} catch {
|
|
18160
18314
|
return void 0;
|
|
18161
18315
|
}
|
|
@@ -18803,7 +18957,7 @@ var init_meta_hook_injector = __esm({
|
|
|
18803
18957
|
|
|
18804
18958
|
// ../core/dist/lib/markdown-merger.js
|
|
18805
18959
|
import { createHash as createHash8 } from "node:crypto";
|
|
18806
|
-
import { readFileSync as
|
|
18960
|
+
import { readFileSync as readFileSync65, existsSync as existsSync76, statSync as statSync22 } from "node:fs";
|
|
18807
18961
|
function parseFrontmatter3(text) {
|
|
18808
18962
|
const match2 = FM_RE2.exec(text);
|
|
18809
18963
|
if (match2 === null)
|
|
@@ -18925,7 +19079,7 @@ function mergeMarkdown(upstreamText, overlayText, labelForError, upstreamPath, o
|
|
|
18925
19079
|
function sha256OfPath(p) {
|
|
18926
19080
|
if (!existsSync76(p) || !statSync22(p).isFile())
|
|
18927
19081
|
return "MISSING";
|
|
18928
|
-
return createHash8("sha256").update(
|
|
19082
|
+
return createHash8("sha256").update(readFileSync65(p)).digest("hex");
|
|
18929
19083
|
}
|
|
18930
19084
|
var FM_RE2, H2_RE;
|
|
18931
19085
|
var init_markdown_merger = __esm({
|
|
@@ -19177,7 +19331,7 @@ var init_prefix_deploy = __esm({
|
|
|
19177
19331
|
});
|
|
19178
19332
|
|
|
19179
19333
|
// ../core/dist/skill-sync/resolve-source-config.js
|
|
19180
|
-
import { readFileSync as
|
|
19334
|
+
import { readFileSync as readFileSync67, existsSync as existsSync77 } from "node:fs";
|
|
19181
19335
|
import { join as join76 } from "node:path";
|
|
19182
19336
|
import { parse as parseYaml6 } from "yaml";
|
|
19183
19337
|
function sourceConfigPath(clonePath) {
|
|
@@ -19189,7 +19343,7 @@ function readSourceConfig(clonePath, sourceId) {
|
|
|
19189
19343
|
return void 0;
|
|
19190
19344
|
let raw;
|
|
19191
19345
|
try {
|
|
19192
|
-
raw =
|
|
19346
|
+
raw = readFileSync67(path96, "utf-8");
|
|
19193
19347
|
} catch (err) {
|
|
19194
19348
|
emitMalformedWarning(sourceId, `read failed: ${errToMsg(err)}`);
|
|
19195
19349
|
return void 0;
|
|
@@ -23376,6 +23530,7 @@ var MCP_AUTH_CONTAINER = "olam-mcp-auth";
|
|
|
23376
23530
|
var MCP_AUTH_LOCAL_TAG = "olam-mcp-auth:local";
|
|
23377
23531
|
var MCP_AUTH_PUBLISHED_TAG = "ghcr.io/pleri/olam-mcp-auth:latest";
|
|
23378
23532
|
var MCP_AUTH_HEALTH_URL = `http://127.0.0.1:${MCP_AUTH_PORT}/health`;
|
|
23533
|
+
var SOCAT_IMAGE = "alpine/socat:latest";
|
|
23379
23534
|
var MCP_AUTH_HEALTH_TIMEOUT_MS = 6e4;
|
|
23380
23535
|
var McpAuthContainerController = class {
|
|
23381
23536
|
imageTag = MCP_AUTH_LOCAL_TAG;
|
|
@@ -23599,6 +23754,40 @@ async function servicesRestartKubernetes(name, deps = {}) {
|
|
|
23599
23754
|
printSuccess(`${deploymentName}: rollout restart triggered`);
|
|
23600
23755
|
return { exitCode: 0 };
|
|
23601
23756
|
}
|
|
23757
|
+
function pullSocatImage(deps = {}) {
|
|
23758
|
+
const spawnImpl = deps.spawnImpl ?? ((cmd, args, opts) => {
|
|
23759
|
+
const r = spawnSync16(cmd, [...args], { encoding: "utf-8", ...opts });
|
|
23760
|
+
return {
|
|
23761
|
+
status: r.status,
|
|
23762
|
+
stdout: r.stdout ?? "",
|
|
23763
|
+
stderr: r.stderr ?? ""
|
|
23764
|
+
};
|
|
23765
|
+
});
|
|
23766
|
+
const info = spawnImpl("docker", ["info"], { encoding: "utf-8", timeout: 5e3 });
|
|
23767
|
+
if (info.status !== 0) {
|
|
23768
|
+
return { dockerAvailable: false, alreadyPresent: false, pulled: false };
|
|
23769
|
+
}
|
|
23770
|
+
const inspect = spawnImpl("docker", ["image", "inspect", SOCAT_IMAGE], {
|
|
23771
|
+
encoding: "utf-8",
|
|
23772
|
+
timeout: 5e3
|
|
23773
|
+
});
|
|
23774
|
+
if (inspect.status === 0) {
|
|
23775
|
+
return { dockerAvailable: true, alreadyPresent: true, pulled: false };
|
|
23776
|
+
}
|
|
23777
|
+
const pull = spawnImpl("docker", ["pull", SOCAT_IMAGE], {
|
|
23778
|
+
encoding: "utf-8",
|
|
23779
|
+
timeout: 6e4
|
|
23780
|
+
});
|
|
23781
|
+
if (pull.status === 0) {
|
|
23782
|
+
return { dockerAvailable: true, alreadyPresent: false, pulled: true };
|
|
23783
|
+
}
|
|
23784
|
+
return {
|
|
23785
|
+
dockerAvailable: true,
|
|
23786
|
+
alreadyPresent: false,
|
|
23787
|
+
pulled: false,
|
|
23788
|
+
error: pull.stderr.trim() || pull.stdout.trim() || "docker pull failed"
|
|
23789
|
+
};
|
|
23790
|
+
}
|
|
23602
23791
|
function dumpContainerLogs(container, tail = 40) {
|
|
23603
23792
|
try {
|
|
23604
23793
|
const result = spawnSync16("docker", ["logs", "--tail", String(tail), container], {
|
|
@@ -23623,6 +23812,21 @@ async function servicesUp() {
|
|
|
23623
23812
|
const mcpAuth = new McpAuthContainerController();
|
|
23624
23813
|
const kgService = new KgServiceContainerController();
|
|
23625
23814
|
const memoryService = new MemoryServiceContainerController();
|
|
23815
|
+
const socatResult = pullSocatImage();
|
|
23816
|
+
if (!socatResult.dockerAvailable) {
|
|
23817
|
+
printWarning(
|
|
23818
|
+
"docker daemon not reachable \u2014 skipped alpine/socat:latest preflight; olam_port_expose will fail until docker is available"
|
|
23819
|
+
);
|
|
23820
|
+
} else if (socatResult.error !== void 0) {
|
|
23821
|
+
printWarning(
|
|
23822
|
+
`alpine/socat:latest preflight pull failed: ${socatResult.error}
|
|
23823
|
+
olam_port_expose will attempt a fallback pull on first call`
|
|
23824
|
+
);
|
|
23825
|
+
} else if (socatResult.pulled) {
|
|
23826
|
+
printSuccess("alpine/socat:latest pulled");
|
|
23827
|
+
} else {
|
|
23828
|
+
printInfo("alpine/socat:latest", "already cached");
|
|
23829
|
+
}
|
|
23626
23830
|
const authStatus = auth.status();
|
|
23627
23831
|
if (authStatus.state === "running") {
|
|
23628
23832
|
printSuccess(`olam-auth already running on :${authStatus.port}`);
|
|
@@ -24204,7 +24408,7 @@ function appendAuditEntry(entry, auditLogPath, writeFileSyncImpl) {
|
|
|
24204
24408
|
async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, peripheral) {
|
|
24205
24409
|
const auditLogPath = deps.auditLogPath ?? MANIFEST_REFRESH_AUDIT_LOG;
|
|
24206
24410
|
const readdirSync33 = deps.readdirSync ?? fs31.readdirSync;
|
|
24207
|
-
const
|
|
24411
|
+
const readFileSync96 = deps.readFileSync ?? fs31.readFileSync;
|
|
24208
24412
|
const writeFileSyncImpl = deps.writeFileSync ?? fs31.writeFileSync;
|
|
24209
24413
|
const existsSync113 = deps.existsSync ?? fs31.existsSync;
|
|
24210
24414
|
const now = deps.now ? deps.now() : /* @__PURE__ */ new Date();
|
|
@@ -24230,7 +24434,7 @@ async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, per
|
|
|
24230
24434
|
const filePath = path32.join(targetDir, file);
|
|
24231
24435
|
let content;
|
|
24232
24436
|
try {
|
|
24233
|
-
content =
|
|
24437
|
+
content = readFileSync96(filePath, "utf8");
|
|
24234
24438
|
} catch {
|
|
24235
24439
|
continue;
|
|
24236
24440
|
}
|
|
@@ -24481,11 +24685,11 @@ async function checkSecretPreCondition(context, deps) {
|
|
|
24481
24685
|
}
|
|
24482
24686
|
async function applyConfigMapSubstitution(context, manifestsDir, deps) {
|
|
24483
24687
|
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
24484
|
-
const
|
|
24688
|
+
const readFileSync96 = deps.readFileSyncImpl ?? fs32.readFileSync;
|
|
24485
24689
|
const configMapPath = path33.join(manifestsDir, "30-configmap.yaml");
|
|
24486
24690
|
let rawYaml;
|
|
24487
24691
|
try {
|
|
24488
|
-
rawYaml =
|
|
24692
|
+
rawYaml = readFileSync96(configMapPath, "utf8");
|
|
24489
24693
|
} catch (err) {
|
|
24490
24694
|
return `Failed to read ConfigMap at ${configMapPath}: ${err instanceof Error ? err.message : String(err)}`;
|
|
24491
24695
|
}
|
|
@@ -25037,6 +25241,223 @@ async function applyK8sAuthRefresh(pinnedContext, deps = {}) {
|
|
|
25037
25241
|
return 0;
|
|
25038
25242
|
}
|
|
25039
25243
|
|
|
25244
|
+
// src/lib/auth-remote.ts
|
|
25245
|
+
function normalizeBase(url2) {
|
|
25246
|
+
return url2.replace(/\/+$/, "");
|
|
25247
|
+
}
|
|
25248
|
+
function buildHeaders(cookie) {
|
|
25249
|
+
const headers = {
|
|
25250
|
+
"Content-Type": "application/json",
|
|
25251
|
+
Accept: "application/json"
|
|
25252
|
+
};
|
|
25253
|
+
if (cookie) {
|
|
25254
|
+
headers["Cookie"] = `CF_Authorization=${cookie}`;
|
|
25255
|
+
}
|
|
25256
|
+
return headers;
|
|
25257
|
+
}
|
|
25258
|
+
async function remoteHealth(opts) {
|
|
25259
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
25260
|
+
const url2 = `${normalizeBase(baseUrl)}/v1/health`;
|
|
25261
|
+
const res = await fetchFn(url2, {
|
|
25262
|
+
method: "GET",
|
|
25263
|
+
headers: buildHeaders(cfAuthCookie)
|
|
25264
|
+
});
|
|
25265
|
+
if (!res.ok) {
|
|
25266
|
+
throw new Error(`Health check failed: HTTP ${res.status}`);
|
|
25267
|
+
}
|
|
25268
|
+
return res.json();
|
|
25269
|
+
}
|
|
25270
|
+
async function remoteOAuthStart(opts) {
|
|
25271
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
25272
|
+
const url2 = `${normalizeBase(baseUrl)}/v1/oauth/start`;
|
|
25273
|
+
const res = await fetchFn(url2, {
|
|
25274
|
+
method: "POST",
|
|
25275
|
+
headers: buildHeaders(cfAuthCookie),
|
|
25276
|
+
body: JSON.stringify({})
|
|
25277
|
+
});
|
|
25278
|
+
if (!res.ok) {
|
|
25279
|
+
const body = await res.text().catch(() => "");
|
|
25280
|
+
throw new Error(`OAuth start failed: HTTP ${res.status}${body ? ` \u2014 ${body}` : ""}`);
|
|
25281
|
+
}
|
|
25282
|
+
return res.json();
|
|
25283
|
+
}
|
|
25284
|
+
async function remoteListServiceTokens(opts) {
|
|
25285
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
25286
|
+
const url2 = `${normalizeBase(baseUrl)}/v1/service-tokens`;
|
|
25287
|
+
const res = await fetchFn(url2, {
|
|
25288
|
+
method: "GET",
|
|
25289
|
+
headers: buildHeaders(cfAuthCookie)
|
|
25290
|
+
});
|
|
25291
|
+
if (!res.ok) {
|
|
25292
|
+
throw new Error(`List service-tokens failed: HTTP ${res.status}`);
|
|
25293
|
+
}
|
|
25294
|
+
return res.json();
|
|
25295
|
+
}
|
|
25296
|
+
async function remoteListAccounts(opts) {
|
|
25297
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
25298
|
+
const url2 = `${normalizeBase(baseUrl)}/v1/accounts`;
|
|
25299
|
+
const res = await fetchFn(url2, {
|
|
25300
|
+
method: "GET",
|
|
25301
|
+
headers: buildHeaders(cfAuthCookie)
|
|
25302
|
+
});
|
|
25303
|
+
if (!res.ok) {
|
|
25304
|
+
throw new Error(`List accounts failed: HTTP ${res.status}`);
|
|
25305
|
+
}
|
|
25306
|
+
return res.json();
|
|
25307
|
+
}
|
|
25308
|
+
async function remoteBindServiceToken(opts, payload) {
|
|
25309
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
25310
|
+
const url2 = `${normalizeBase(baseUrl)}/v1/service-tokens/bind`;
|
|
25311
|
+
const res = await fetchFn(url2, {
|
|
25312
|
+
method: "POST",
|
|
25313
|
+
headers: buildHeaders(cfAuthCookie),
|
|
25314
|
+
body: JSON.stringify(payload)
|
|
25315
|
+
});
|
|
25316
|
+
if (!res.ok) {
|
|
25317
|
+
const body = await res.text().catch(() => "");
|
|
25318
|
+
throw new Error(`Bind service-token failed: HTTP ${res.status}${body ? ` \u2014 ${body}` : ""}`);
|
|
25319
|
+
}
|
|
25320
|
+
return { ok: true };
|
|
25321
|
+
}
|
|
25322
|
+
async function remoteDeleteServiceToken(opts, clientId) {
|
|
25323
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
25324
|
+
const url2 = `${normalizeBase(baseUrl)}/v1/service-tokens/${encodeURIComponent(clientId)}`;
|
|
25325
|
+
const res = await fetchFn(url2, {
|
|
25326
|
+
method: "DELETE",
|
|
25327
|
+
headers: buildHeaders(cfAuthCookie)
|
|
25328
|
+
});
|
|
25329
|
+
if (!res.ok) {
|
|
25330
|
+
throw new Error(`Delete service-token failed: HTTP ${res.status}`);
|
|
25331
|
+
}
|
|
25332
|
+
return { ok: true };
|
|
25333
|
+
}
|
|
25334
|
+
async function remoteIssueAnthropicToken(opts, label) {
|
|
25335
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
25336
|
+
const url2 = `${normalizeBase(baseUrl)}/v1/anthropic-tokens/issue`;
|
|
25337
|
+
const res = await fetchFn(url2, {
|
|
25338
|
+
method: "POST",
|
|
25339
|
+
headers: buildHeaders(cfAuthCookie),
|
|
25340
|
+
body: JSON.stringify({ label })
|
|
25341
|
+
});
|
|
25342
|
+
if (!res.ok) {
|
|
25343
|
+
const body = await res.text().catch(() => "");
|
|
25344
|
+
throw new Error(`Issue anthropic-token failed: HTTP ${res.status}${body ? ` \u2014 ${body}` : ""}`);
|
|
25345
|
+
}
|
|
25346
|
+
return res.json();
|
|
25347
|
+
}
|
|
25348
|
+
async function remoteListAnthropicTokens(opts) {
|
|
25349
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
25350
|
+
const url2 = `${normalizeBase(baseUrl)}/v1/anthropic-tokens`;
|
|
25351
|
+
const res = await fetchFn(url2, {
|
|
25352
|
+
method: "GET",
|
|
25353
|
+
headers: buildHeaders(cfAuthCookie)
|
|
25354
|
+
});
|
|
25355
|
+
if (!res.ok) {
|
|
25356
|
+
const body = await res.text().catch(() => "");
|
|
25357
|
+
throw new Error(`List anthropic-tokens failed: HTTP ${res.status}${body ? ` \u2014 ${body}` : ""}`);
|
|
25358
|
+
}
|
|
25359
|
+
return res.json();
|
|
25360
|
+
}
|
|
25361
|
+
async function remoteRevokeAnthropicToken(opts, tokenHash) {
|
|
25362
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
25363
|
+
const url2 = `${normalizeBase(baseUrl)}/v1/anthropic-tokens/${encodeURIComponent(tokenHash)}`;
|
|
25364
|
+
const res = await fetchFn(url2, {
|
|
25365
|
+
method: "DELETE",
|
|
25366
|
+
headers: buildHeaders(cfAuthCookie)
|
|
25367
|
+
});
|
|
25368
|
+
if (res.status === 404) return false;
|
|
25369
|
+
if (!res.ok) {
|
|
25370
|
+
throw new Error(`Revoke anthropic-token failed: HTTP ${res.status}`);
|
|
25371
|
+
}
|
|
25372
|
+
return true;
|
|
25373
|
+
}
|
|
25374
|
+
async function runDoctorChecks(opts) {
|
|
25375
|
+
const results = [];
|
|
25376
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
25377
|
+
const base = normalizeBase(baseUrl);
|
|
25378
|
+
try {
|
|
25379
|
+
const h = await remoteHealth({ baseUrl, cfAuthCookie, fetchFn });
|
|
25380
|
+
results.push({
|
|
25381
|
+
probe: "worker-health",
|
|
25382
|
+
status: "pass",
|
|
25383
|
+
message: `Worker alive${h.version ? ` (version=${h.version})` : ""}`
|
|
25384
|
+
});
|
|
25385
|
+
} catch (err) {
|
|
25386
|
+
results.push({
|
|
25387
|
+
probe: "worker-health",
|
|
25388
|
+
status: "fail",
|
|
25389
|
+
message: err instanceof Error ? err.message : "Health check failed",
|
|
25390
|
+
remedy: `Verify the worker is deployed and reachable at ${base}`
|
|
25391
|
+
});
|
|
25392
|
+
}
|
|
25393
|
+
let jwksUrl;
|
|
25394
|
+
try {
|
|
25395
|
+
const parsed = new URL(baseUrl);
|
|
25396
|
+
const parts = parsed.hostname.split(".");
|
|
25397
|
+
const team = parts.length >= 3 ? parts[parts.length - 3] : parts[0];
|
|
25398
|
+
jwksUrl = `https://${team}.cloudflareaccess.com/cdn-cgi/access/certs`;
|
|
25399
|
+
} catch {
|
|
25400
|
+
jwksUrl = `${base}/.well-known/jwks.json`;
|
|
25401
|
+
}
|
|
25402
|
+
try {
|
|
25403
|
+
const res = await fetchFn(jwksUrl, { method: "GET" });
|
|
25404
|
+
if (res.ok) {
|
|
25405
|
+
results.push({
|
|
25406
|
+
probe: "cf-access-jwks",
|
|
25407
|
+
status: "pass",
|
|
25408
|
+
message: `CF Access JWKS reachable at ${jwksUrl}`
|
|
25409
|
+
});
|
|
25410
|
+
} else {
|
|
25411
|
+
results.push({
|
|
25412
|
+
probe: "cf-access-jwks",
|
|
25413
|
+
status: "warn",
|
|
25414
|
+
message: `CF Access JWKS returned HTTP ${res.status}`,
|
|
25415
|
+
remedy: `Verify Cloudflare Access is configured for your zone. JWKS checked: ${jwksUrl}`
|
|
25416
|
+
});
|
|
25417
|
+
}
|
|
25418
|
+
} catch (err) {
|
|
25419
|
+
results.push({
|
|
25420
|
+
probe: "cf-access-jwks",
|
|
25421
|
+
status: "warn",
|
|
25422
|
+
message: `CF Access JWKS unreachable: ${err instanceof Error ? err.message : String(err)}`,
|
|
25423
|
+
remedy: `Check network access to ${jwksUrl}. CF Access may not be configured for this zone.`
|
|
25424
|
+
});
|
|
25425
|
+
}
|
|
25426
|
+
try {
|
|
25427
|
+
await remoteOAuthStart({ baseUrl, cfAuthCookie, fetchFn });
|
|
25428
|
+
results.push({
|
|
25429
|
+
probe: "oauth-start",
|
|
25430
|
+
status: "pass",
|
|
25431
|
+
message: "OAuth start endpoint is reachable"
|
|
25432
|
+
});
|
|
25433
|
+
} catch (err) {
|
|
25434
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
25435
|
+
const status2 = msg.includes("HTTP 403") ? "warn" : "fail";
|
|
25436
|
+
results.push({
|
|
25437
|
+
probe: "oauth-start",
|
|
25438
|
+
status: status2,
|
|
25439
|
+
message: `OAuth start: ${msg}`,
|
|
25440
|
+
remedy: status2 === "warn" ? "Open the worker URL in a browser to complete CF Access SSO, then re-run with --cookie." : `Check that /v1/oauth/start is deployed at ${base}`
|
|
25441
|
+
});
|
|
25442
|
+
}
|
|
25443
|
+
const clientId = process.env["ANTHROPIC_OAUTH_CLIENT_ID"];
|
|
25444
|
+
if (clientId) {
|
|
25445
|
+
results.push({
|
|
25446
|
+
probe: "env-client-id",
|
|
25447
|
+
status: "pass",
|
|
25448
|
+
message: `ANTHROPIC_OAUTH_CLIENT_ID is set (length=${clientId.length})`
|
|
25449
|
+
});
|
|
25450
|
+
} else {
|
|
25451
|
+
results.push({
|
|
25452
|
+
probe: "env-client-id",
|
|
25453
|
+
status: "warn",
|
|
25454
|
+
message: "ANTHROPIC_OAUTH_CLIENT_ID is not set in the environment",
|
|
25455
|
+
remedy: "Set ANTHROPIC_OAUTH_CLIENT_ID in your shell profile (the Anthropic OAuth app client ID)."
|
|
25456
|
+
});
|
|
25457
|
+
}
|
|
25458
|
+
return results;
|
|
25459
|
+
}
|
|
25460
|
+
|
|
25040
25461
|
// src/commands/auth.ts
|
|
25041
25462
|
function openBrowser(url2) {
|
|
25042
25463
|
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
@@ -25071,36 +25492,6 @@ function registerAuth(program2) {
|
|
|
25071
25492
|
printWarning("`olam auth status` is deprecated. Use `olam services status` instead.");
|
|
25072
25493
|
servicesStatus();
|
|
25073
25494
|
});
|
|
25074
|
-
auth.command("list").description("List all stored credentials with state, usage, and rate-limit status").action(async () => {
|
|
25075
|
-
const client = new AuthClient();
|
|
25076
|
-
const status2 = await client.status();
|
|
25077
|
-
if (!status2.reachable) {
|
|
25078
|
-
printError("Auth container is not reachable. Run `olam auth up` first.");
|
|
25079
|
-
process.exitCode = 1;
|
|
25080
|
-
return;
|
|
25081
|
-
}
|
|
25082
|
-
printHeader(`Credentials (${status2.accounts.length})`);
|
|
25083
|
-
if (status2.accounts.length === 0) {
|
|
25084
|
-
console.log(` ${pc12.dim("No credentials \u2014 run: olam auth login --label primary")}`);
|
|
25085
|
-
return;
|
|
25086
|
-
}
|
|
25087
|
-
const stateColor = (s) => {
|
|
25088
|
-
if (s === "active") return pc12.green("active");
|
|
25089
|
-
if (s === "cooldown") return pc12.yellow("cooldown");
|
|
25090
|
-
if (s === "expired") return pc12.red("expired");
|
|
25091
|
-
if (s === "disabled") return pc12.dim("disabled");
|
|
25092
|
-
return pc12.dim(s ?? "unknown");
|
|
25093
|
-
};
|
|
25094
|
-
for (const a of status2.accounts) {
|
|
25095
|
-
const label = a.accountLabel ?? a.id;
|
|
25096
|
-
const reqs = a.usage?.requestCount5h ?? 0;
|
|
25097
|
-
const last429 = a.usage?.last429At ? `last429=${a.usage.last429At}` : "last429=never";
|
|
25098
|
-
const reset = a.rateLimitResetsAt ? `resets=${a.rateLimitResetsAt}` : "";
|
|
25099
|
-
console.log(
|
|
25100
|
-
` ${pc12.bold(label.padEnd(18))} ${stateColor(a.state).padEnd(18)} ${pc12.dim(`req5h=${reqs}`)} ${pc12.dim(`exp=${a.expiresIn}`)} ${pc12.dim(last429)} ${pc12.yellow(reset)}`
|
|
25101
|
-
);
|
|
25102
|
-
}
|
|
25103
|
-
});
|
|
25104
25495
|
auth.command("disable").description("Take a credential out of rotation (manual cooldown)").argument("<label>", "Credential label or id").action(async (label) => {
|
|
25105
25496
|
const client = new AuthClient();
|
|
25106
25497
|
try {
|
|
@@ -25131,7 +25522,68 @@ function registerAuth(program2) {
|
|
|
25131
25522
|
process.exitCode = 1;
|
|
25132
25523
|
}
|
|
25133
25524
|
});
|
|
25134
|
-
auth.command("login").description("Run the OAuth PKCE flow to store a Claude account in the auth container").option("--label <label>", 'Account label (e.g. primary, burner-1). Defaults to "primary" for the first account, "burner-N" thereafter.').action(async (opts) => {
|
|
25525
|
+
auth.command("login").description("Run the OAuth PKCE flow to store a Claude account in the auth container, or print a remote OAuth URL (--remote)").option("--label <label>", 'Account label (e.g. primary, burner-1). Defaults to "primary" for the first account, "burner-N" thereafter.').option("--remote <url>", "Auth-worker base URL. Prints the OAuth start URL for browser completion (v1 dogfood).").option("--print-url", "Print the OAuth URL without attempting to open a browser (implied by --remote).").option("--service-token <client_id:secret>", "Delegate to bind-service-token flow instead (use with --remote).").action(async (opts) => {
|
|
25526
|
+
if (opts.remote) {
|
|
25527
|
+
const baseUrl = opts.remote;
|
|
25528
|
+
if (opts.serviceToken) {
|
|
25529
|
+
const parts = opts.serviceToken.split(":");
|
|
25530
|
+
if (parts.length < 2) {
|
|
25531
|
+
printError("--service-token must be in format <client_id>:<secret>");
|
|
25532
|
+
process.exitCode = 1;
|
|
25533
|
+
return;
|
|
25534
|
+
}
|
|
25535
|
+
const [clientId] = parts;
|
|
25536
|
+
const label2 = opts.label ?? clientId ?? "service-token";
|
|
25537
|
+
printHeader("Auth worker \u2014 bind service token");
|
|
25538
|
+
console.log(`
|
|
25539
|
+
${pc12.bold("Step 1:")} Open ${pc12.cyan(baseUrl + "/v1/oauth/start")} in a browser.`);
|
|
25540
|
+
console.log(` Complete CF Access SSO. You may see a JSON response or "no credentials" \u2014 that is normal.`);
|
|
25541
|
+
const rawCookie = await promptLine(`
|
|
25542
|
+
${pc12.dim("Paste CF_Authorization cookie value (from DevTools > Application > Cookies):")} `);
|
|
25543
|
+
if (!rawCookie) {
|
|
25544
|
+
printError("No cookie provided. Aborting.");
|
|
25545
|
+
process.exitCode = 1;
|
|
25546
|
+
return;
|
|
25547
|
+
}
|
|
25548
|
+
const clientIdStr = clientId ?? "";
|
|
25549
|
+
try {
|
|
25550
|
+
await remoteBindServiceToken({ baseUrl, cfAuthCookie: rawCookie }, { client_id: clientIdStr, label: label2 });
|
|
25551
|
+
printSuccess(`Service token bound: ${clientIdStr} (label=${label2})`);
|
|
25552
|
+
console.log(`
|
|
25553
|
+
${pc12.dim("Set ANTHROPIC_BASE_URL=" + baseUrl + "/v1/proxy in your shell to route Claude API calls through this worker.")}`);
|
|
25554
|
+
} catch (err) {
|
|
25555
|
+
printError(err instanceof Error ? err.message : "bind failed");
|
|
25556
|
+
process.exitCode = 1;
|
|
25557
|
+
}
|
|
25558
|
+
return;
|
|
25559
|
+
}
|
|
25560
|
+
let startUrl;
|
|
25561
|
+
try {
|
|
25562
|
+
const r = await remoteOAuthStart({ baseUrl });
|
|
25563
|
+
startUrl = r.authorize_url;
|
|
25564
|
+
} catch {
|
|
25565
|
+
startUrl = `${baseUrl.replace(/\/+$/, "")}/v1/oauth/start`;
|
|
25566
|
+
}
|
|
25567
|
+
printHeader("Auth worker \u2014 OAuth login (v1 dogfood)");
|
|
25568
|
+
console.log(`
|
|
25569
|
+
${pc12.bold("1.")} Open this URL in your browser to authenticate via CF Access + Anthropic OAuth:`);
|
|
25570
|
+
console.log(`
|
|
25571
|
+
${pc12.cyan(startUrl)}
|
|
25572
|
+
`);
|
|
25573
|
+
console.log(` ${pc12.bold("2.")} Complete the CF Access SSO and Anthropic OAuth consent.`);
|
|
25574
|
+
console.log(` The worker stores your tokens on callback \u2014 the browser lands on a success page.`);
|
|
25575
|
+
console.log(`
|
|
25576
|
+
${pc12.bold("3.")} Confirm your credentials are stored:
|
|
25577
|
+
`);
|
|
25578
|
+
console.log(` ${pc12.dim("olam auth list --remote " + baseUrl)}
|
|
25579
|
+
`);
|
|
25580
|
+
console.log(` ${pc12.dim("Note: full CLI-orchestrated browser SSO flow is deferred to v2 (cookie-bridging complexity).")}
|
|
25581
|
+
`);
|
|
25582
|
+
if (!opts.printUrl) {
|
|
25583
|
+
openBrowser(startUrl);
|
|
25584
|
+
}
|
|
25585
|
+
return;
|
|
25586
|
+
}
|
|
25135
25587
|
const preflight2 = await runAuthPreflight({ autoStart: true });
|
|
25136
25588
|
if (preflight2.verdict !== "ok" && preflight2.verdict !== "no-accounts") {
|
|
25137
25589
|
printError(preflight2.message);
|
|
@@ -25233,6 +25685,297 @@ ${pc12.dim("Next: olam create --name my-world")}`);
|
|
|
25233
25685
|
}
|
|
25234
25686
|
}
|
|
25235
25687
|
});
|
|
25688
|
+
auth.command("bind-service-token").description("Bind a Cloudflare service token to your CF Access user sub on the remote auth-worker").requiredOption("--remote <url>", "Auth-worker base URL").requiredOption("--token <client_id:secret>", "CF service token in format <client_id>:<secret>").option("--label <name>", "Friendly label for this token (defaults to client_id)").action(async (opts) => {
|
|
25689
|
+
const baseUrl = opts.remote;
|
|
25690
|
+
const parts = opts.token.split(":");
|
|
25691
|
+
if (parts.length < 2) {
|
|
25692
|
+
printError("--token must be in format <client_id>:<secret>");
|
|
25693
|
+
process.exitCode = 1;
|
|
25694
|
+
return;
|
|
25695
|
+
}
|
|
25696
|
+
const [clientId] = parts;
|
|
25697
|
+
const clientIdStr = clientId ?? "";
|
|
25698
|
+
const label = opts.label ?? clientIdStr;
|
|
25699
|
+
printHeader("Auth worker \u2014 bind service token");
|
|
25700
|
+
console.log(`
|
|
25701
|
+
${pc12.bold("Step 1:")} Open the URL below in your browser to authenticate via CF Access SSO:`);
|
|
25702
|
+
console.log(`
|
|
25703
|
+
${pc12.cyan(baseUrl.replace(/\/+$/, "") + "/v1/oauth/start")}
|
|
25704
|
+
`);
|
|
25705
|
+
console.log(` You may see a JSON response or a "no credentials" page \u2014 that is normal.`);
|
|
25706
|
+
console.log(` This establishes the session that associates your user sub with the binding.
|
|
25707
|
+
`);
|
|
25708
|
+
await promptLine(` ${pc12.dim("Press Enter once you have completed the CF Access SSO step...")}`);
|
|
25709
|
+
const rawCookie = await promptLine(
|
|
25710
|
+
`
|
|
25711
|
+
${pc12.dim("Paste your CF_Authorization cookie value (DevTools > Application > Cookies > CF_Authorization):")} `
|
|
25712
|
+
);
|
|
25713
|
+
if (!rawCookie) {
|
|
25714
|
+
printError("No cookie provided. Aborting.");
|
|
25715
|
+
process.exitCode = 1;
|
|
25716
|
+
return;
|
|
25717
|
+
}
|
|
25718
|
+
try {
|
|
25719
|
+
await remoteBindServiceToken(
|
|
25720
|
+
{ baseUrl, cfAuthCookie: rawCookie },
|
|
25721
|
+
{ client_id: clientIdStr, label }
|
|
25722
|
+
);
|
|
25723
|
+
printSuccess(`Service token bound: ${clientIdStr} (label=${label})`);
|
|
25724
|
+
console.log(
|
|
25725
|
+
`
|
|
25726
|
+
${pc12.dim("Tip: set ANTHROPIC_BASE_URL=" + baseUrl.replace(/\/+$/, "") + "/v1/proxy")}`
|
|
25727
|
+
);
|
|
25728
|
+
console.log(`${pc12.dim(" to route Claude API calls through this worker.")}
|
|
25729
|
+
`);
|
|
25730
|
+
} catch (err) {
|
|
25731
|
+
printError(err instanceof Error ? err.message : "bind failed");
|
|
25732
|
+
process.exitCode = 1;
|
|
25733
|
+
}
|
|
25734
|
+
});
|
|
25735
|
+
auth.command("list").description("List credentials (local by default; --remote to query a remote auth-worker)").option("--remote <url>", "Auth-worker base URL").option("--cookie <value>", "CF_Authorization cookie for authenticated requests").action(async (opts) => {
|
|
25736
|
+
if (opts.remote) {
|
|
25737
|
+
const baseUrl = opts.remote;
|
|
25738
|
+
const clientOpts = { baseUrl, cfAuthCookie: opts.cookie };
|
|
25739
|
+
let accounts = [];
|
|
25740
|
+
let tokens = [];
|
|
25741
|
+
try {
|
|
25742
|
+
accounts = await remoteListAccounts(clientOpts);
|
|
25743
|
+
} catch (err) {
|
|
25744
|
+
printWarning(`Could not fetch accounts: ${err instanceof Error ? err.message : String(err)}`);
|
|
25745
|
+
}
|
|
25746
|
+
try {
|
|
25747
|
+
tokens = await remoteListServiceTokens(clientOpts);
|
|
25748
|
+
} catch (err) {
|
|
25749
|
+
printWarning(`Could not fetch service tokens: ${err instanceof Error ? err.message : String(err)}`);
|
|
25750
|
+
}
|
|
25751
|
+
printHeader(`Remote accounts (${accounts.length})`);
|
|
25752
|
+
if (accounts.length === 0) {
|
|
25753
|
+
console.log(` ${pc12.dim("No accounts \u2014 run: olam auth login --remote " + baseUrl)}`);
|
|
25754
|
+
} else {
|
|
25755
|
+
for (const a of accounts) {
|
|
25756
|
+
const label = a.label ?? a.id;
|
|
25757
|
+
const state = a.state ?? "unknown";
|
|
25758
|
+
const exp = a.expiresIn ?? "";
|
|
25759
|
+
console.log(` ${pc12.bold(label.padEnd(20))} ${pc12.green(state).padEnd(16)} ${pc12.dim(exp)}`);
|
|
25760
|
+
}
|
|
25761
|
+
}
|
|
25762
|
+
printHeader(`Remote service tokens (${tokens.length})`);
|
|
25763
|
+
if (tokens.length === 0) {
|
|
25764
|
+
console.log(` ${pc12.dim("No service tokens \u2014 run: olam auth bind-service-token --remote " + baseUrl)}`);
|
|
25765
|
+
} else {
|
|
25766
|
+
for (const t of tokens) {
|
|
25767
|
+
const label = t.label ?? t.client_id;
|
|
25768
|
+
const created = t.created_at ?? "";
|
|
25769
|
+
console.log(` ${pc12.bold(label.padEnd(20))} ${pc12.dim(t.client_id)} ${pc12.dim(created)}`);
|
|
25770
|
+
}
|
|
25771
|
+
}
|
|
25772
|
+
return;
|
|
25773
|
+
}
|
|
25774
|
+
const client = new AuthClient();
|
|
25775
|
+
const status2 = await client.status();
|
|
25776
|
+
if (!status2.reachable) {
|
|
25777
|
+
printError("Auth container is not reachable. Run `olam auth up` first.");
|
|
25778
|
+
process.exitCode = 1;
|
|
25779
|
+
return;
|
|
25780
|
+
}
|
|
25781
|
+
printHeader(`Credentials (${status2.accounts.length})`);
|
|
25782
|
+
if (status2.accounts.length === 0) {
|
|
25783
|
+
console.log(` ${pc12.dim("No credentials \u2014 run: olam auth login --label primary")}`);
|
|
25784
|
+
return;
|
|
25785
|
+
}
|
|
25786
|
+
const stateColor = (s) => {
|
|
25787
|
+
if (s === "active") return pc12.green("active");
|
|
25788
|
+
if (s === "cooldown") return pc12.yellow("cooldown");
|
|
25789
|
+
if (s === "expired") return pc12.red("expired");
|
|
25790
|
+
if (s === "disabled") return pc12.dim("disabled");
|
|
25791
|
+
return pc12.dim(s ?? "unknown");
|
|
25792
|
+
};
|
|
25793
|
+
for (const a of status2.accounts) {
|
|
25794
|
+
const label = a.accountLabel ?? a.id;
|
|
25795
|
+
const reqs = a.usage?.requestCount5h ?? 0;
|
|
25796
|
+
const last429 = a.usage?.last429At ? `last429=${a.usage.last429At}` : "last429=never";
|
|
25797
|
+
const reset = a.rateLimitResetsAt ? `resets=${a.rateLimitResetsAt}` : "";
|
|
25798
|
+
console.log(
|
|
25799
|
+
` ${pc12.bold(label.padEnd(18))} ${stateColor(a.state).padEnd(18)} ${pc12.dim(`req5h=${reqs}`)} ${pc12.dim(`exp=${a.expiresIn}`)} ${pc12.dim(last429)} ${pc12.yellow(reset)}`
|
|
25800
|
+
);
|
|
25801
|
+
}
|
|
25802
|
+
});
|
|
25803
|
+
auth.command("migrate-to-remote").description("Print guidance for re-authenticating local credentials against the remote auth-worker (v1: no auto-migration of secrets)").requiredOption("--url <url>", "Auth-worker base URL").action(async (opts) => {
|
|
25804
|
+
const baseUrl = opts.url;
|
|
25805
|
+
let accountLabels = [];
|
|
25806
|
+
try {
|
|
25807
|
+
const client = new AuthClient();
|
|
25808
|
+
const status2 = await client.status();
|
|
25809
|
+
accountLabels = status2.accounts.map((a) => a.accountLabel ?? a.id);
|
|
25810
|
+
} catch {
|
|
25811
|
+
}
|
|
25812
|
+
printHeader("Migrate local credentials to remote auth-worker");
|
|
25813
|
+
console.log(`
|
|
25814
|
+
Remote URL: ${pc12.cyan(baseUrl)}
|
|
25815
|
+
`);
|
|
25816
|
+
console.log(
|
|
25817
|
+
` ${pc12.dim("V1 note: secrets cannot be migrated automatically. Each account must re-authenticate via OAuth.")}
|
|
25818
|
+
`
|
|
25819
|
+
);
|
|
25820
|
+
if (accountLabels.length === 0) {
|
|
25821
|
+
console.log(` No local accounts found. Run:`);
|
|
25822
|
+
console.log(`
|
|
25823
|
+
${pc12.cyan("olam auth login --remote " + baseUrl)}
|
|
25824
|
+
`);
|
|
25825
|
+
} else {
|
|
25826
|
+
console.log(` Found ${accountLabels.length} local account(s). For each, run:
|
|
25827
|
+
`);
|
|
25828
|
+
for (const label of accountLabels) {
|
|
25829
|
+
console.log(` ${pc12.cyan("olam auth login --remote " + baseUrl + " --label " + label)}`);
|
|
25830
|
+
}
|
|
25831
|
+
console.log();
|
|
25832
|
+
}
|
|
25833
|
+
});
|
|
25834
|
+
auth.command("rotate-service-token").description("Revoke a service token and guide through re-binding a replacement").requiredOption("--url <url>", "Auth-worker base URL").requiredOption("--client-id <id>", "CF service token client_id to revoke").option("--cookie <value>", "CF_Authorization cookie for the DELETE request").action(async (opts) => {
|
|
25835
|
+
const baseUrl = opts.url;
|
|
25836
|
+
const clientId = opts.clientId;
|
|
25837
|
+
printHeader("Auth worker \u2014 rotate service token");
|
|
25838
|
+
console.log(`
|
|
25839
|
+
Revoking service token: ${pc12.yellow(clientId)}
|
|
25840
|
+
`);
|
|
25841
|
+
try {
|
|
25842
|
+
await remoteDeleteServiceToken({ baseUrl, cfAuthCookie: opts.cookie }, clientId);
|
|
25843
|
+
printSuccess(`Revoked: ${clientId}`);
|
|
25844
|
+
} catch (err) {
|
|
25845
|
+
printError(err instanceof Error ? err.message : "revoke failed");
|
|
25846
|
+
process.exitCode = 1;
|
|
25847
|
+
return;
|
|
25848
|
+
}
|
|
25849
|
+
console.log(`
|
|
25850
|
+
${pc12.bold("Next steps:")}`);
|
|
25851
|
+
console.log(` 1. Mint a new service token in the Cloudflare Zero Trust dashboard.`);
|
|
25852
|
+
console.log(` 2. Bind it:
|
|
25853
|
+
`);
|
|
25854
|
+
console.log(` ${pc12.cyan("olam auth bind-service-token --remote " + baseUrl + " --token <new_client_id>:<secret>")}
|
|
25855
|
+
`);
|
|
25856
|
+
});
|
|
25857
|
+
auth.command("doctor").description("Run 4 diagnostic probes against the remote auth-worker").requiredOption("--auth-worker <url>", "Auth-worker base URL").option("--cookie <value>", "CF_Authorization cookie (optional, for authenticated probes)").option("--json", "Emit JSON output").action(async (opts) => {
|
|
25858
|
+
const checks = await runDoctorChecks({
|
|
25859
|
+
baseUrl: opts.authWorker,
|
|
25860
|
+
cfAuthCookie: opts.cookie
|
|
25861
|
+
});
|
|
25862
|
+
if (opts.json) {
|
|
25863
|
+
console.log(JSON.stringify(checks, null, 2));
|
|
25864
|
+
const failed = checks.filter((c) => c.status === "fail").length;
|
|
25865
|
+
if (failed > 0) process.exitCode = 1;
|
|
25866
|
+
return;
|
|
25867
|
+
}
|
|
25868
|
+
printHeader(`Auth-worker diagnostics (${opts.authWorker})`);
|
|
25869
|
+
let hasFailure = false;
|
|
25870
|
+
for (const c of checks) {
|
|
25871
|
+
const icon = c.status === "pass" ? pc12.green("\u2713") : c.status === "warn" ? pc12.yellow("\u26A0") : pc12.red("\u2717");
|
|
25872
|
+
console.log(` ${icon} ${pc12.bold(c.probe.padEnd(20))} ${c.message}`);
|
|
25873
|
+
if (c.remedy) {
|
|
25874
|
+
console.log(` ${pc12.dim("\u21B3 " + c.remedy)}`);
|
|
25875
|
+
}
|
|
25876
|
+
if (c.status === "fail") hasFailure = true;
|
|
25877
|
+
}
|
|
25878
|
+
console.log();
|
|
25879
|
+
if (hasFailure) {
|
|
25880
|
+
printError("One or more probes failed \u2014 see remediation steps above.");
|
|
25881
|
+
process.exitCode = 1;
|
|
25882
|
+
} else {
|
|
25883
|
+
printSuccess("All probes passed (warnings are non-blocking).");
|
|
25884
|
+
}
|
|
25885
|
+
});
|
|
25886
|
+
auth.command("issue-anthropic-token").description("Mint a new Anthropic proxy token via the remote auth-worker (g4)").requiredOption("--remote <url>", "Auth-worker base URL").requiredOption("--label <name>", "Friendly label for this token (e.g. my-laptop)").action(async (opts) => {
|
|
25887
|
+
const baseUrl = opts.remote;
|
|
25888
|
+
printHeader("Auth worker \u2014 issue Anthropic proxy token");
|
|
25889
|
+
console.log(`
|
|
25890
|
+
Open ${pc12.cyan(baseUrl.replace(/\/+$/, "") + "/v1/oauth/start")} in a browser to authenticate via CF Access SSO.`);
|
|
25891
|
+
console.log(` Once you've completed SSO, paste your CF_Authorization cookie below`);
|
|
25892
|
+
console.log(` (from browser DevTools \u2192 Application \u2192 Cookies \u2192 CF_Authorization).
|
|
25893
|
+
`);
|
|
25894
|
+
const rawCookie = await promptLine(` ${pc12.dim("CF_Authorization cookie:")} `);
|
|
25895
|
+
if (!rawCookie) {
|
|
25896
|
+
printError("No cookie provided. Aborting.");
|
|
25897
|
+
process.exitCode = 1;
|
|
25898
|
+
return;
|
|
25899
|
+
}
|
|
25900
|
+
try {
|
|
25901
|
+
const result = await remoteIssueAnthropicToken({ baseUrl, cfAuthCookie: rawCookie }, opts.label);
|
|
25902
|
+
printSuccess(`Anthropic proxy token issued (label: ${result.label})`);
|
|
25903
|
+
console.log(`
|
|
25904
|
+
Set this in your Claude Code environment:`);
|
|
25905
|
+
const exportHint = `export ANTHROPIC_BASE_URL='${result.anthropic_base_url_hint}'`;
|
|
25906
|
+
console.log(` ${pc12.cyan(exportHint)}`);
|
|
25907
|
+
console.log(`
|
|
25908
|
+
${pc12.yellow("WARNING: the secret above is shown ONCE. Save it now \u2014 you cannot retrieve it later.")}`);
|
|
25909
|
+
console.log(` Secret: ${pc12.bold(result.secret)}`);
|
|
25910
|
+
console.log(` Token hash (for revocation): ${pc12.dim(result.token_hash)}
|
|
25911
|
+
`);
|
|
25912
|
+
} catch (err) {
|
|
25913
|
+
printError(err instanceof Error ? err.message : "issue failed");
|
|
25914
|
+
process.exitCode = 1;
|
|
25915
|
+
}
|
|
25916
|
+
});
|
|
25917
|
+
auth.command("list-anthropic-tokens").description("List Anthropic proxy tokens from the remote auth-worker (g4)").requiredOption("--remote <url>", "Auth-worker base URL").action(async (opts) => {
|
|
25918
|
+
const baseUrl = opts.remote;
|
|
25919
|
+
printHeader("Auth worker \u2014 list Anthropic proxy tokens");
|
|
25920
|
+
console.log(`
|
|
25921
|
+
Open ${pc12.cyan(baseUrl.replace(/\/+$/, "") + "/v1/oauth/start")} in a browser to authenticate via CF Access SSO.`);
|
|
25922
|
+
console.log(` Once you've completed SSO, paste your CF_Authorization cookie below.
|
|
25923
|
+
`);
|
|
25924
|
+
const rawCookie = await promptLine(` ${pc12.dim("CF_Authorization cookie:")} `);
|
|
25925
|
+
if (!rawCookie) {
|
|
25926
|
+
printError("No cookie provided. Aborting.");
|
|
25927
|
+
process.exitCode = 1;
|
|
25928
|
+
return;
|
|
25929
|
+
}
|
|
25930
|
+
try {
|
|
25931
|
+
const tokens = await remoteListAnthropicTokens({ baseUrl, cfAuthCookie: rawCookie });
|
|
25932
|
+
if (tokens.length === 0) {
|
|
25933
|
+
console.log(`
|
|
25934
|
+
${pc12.dim("No Anthropic proxy tokens found. Run: olam auth issue-anthropic-token --remote " + baseUrl + " --label <name>")}
|
|
25935
|
+
`);
|
|
25936
|
+
return;
|
|
25937
|
+
}
|
|
25938
|
+
const col = (s, w) => s.padEnd(w);
|
|
25939
|
+
console.log(`
|
|
25940
|
+
${"Label".padEnd(20)} ${"Issued".padEnd(22)} ${"Last Used".padEnd(22)} ${"Token Hash (prefix)"}`);
|
|
25941
|
+
console.log(` ${"-".repeat(20)} ${"-".repeat(22)} ${"-".repeat(22)} ${"-".repeat(10)}`);
|
|
25942
|
+
for (const t of tokens) {
|
|
25943
|
+
const issued = t.issued_at ?? "\u2014";
|
|
25944
|
+
const lastUsed = t.last_used_at ?? "\u2014";
|
|
25945
|
+
const hashPrefix = t.token_hash.slice(0, 8);
|
|
25946
|
+
console.log(` ${col(t.label, 20)} ${col(issued, 22)} ${col(lastUsed, 22)} ${pc12.dim(hashPrefix)}`);
|
|
25947
|
+
}
|
|
25948
|
+
console.log();
|
|
25949
|
+
} catch (err) {
|
|
25950
|
+
printError(err instanceof Error ? err.message : "list failed");
|
|
25951
|
+
process.exitCode = 1;
|
|
25952
|
+
}
|
|
25953
|
+
});
|
|
25954
|
+
auth.command("revoke-anthropic-token").description("Revoke an Anthropic proxy token on the remote auth-worker (g4)").requiredOption("--remote <url>", "Auth-worker base URL").requiredOption("--token-hash <hash>", "Token hash to revoke (from issue or list output)").action(async (opts) => {
|
|
25955
|
+
const baseUrl = opts.remote;
|
|
25956
|
+
printHeader("Auth worker \u2014 revoke Anthropic proxy token");
|
|
25957
|
+
console.log(`
|
|
25958
|
+
Open ${pc12.cyan(baseUrl.replace(/\/+$/, "") + "/v1/oauth/start")} in a browser to authenticate via CF Access SSO.`);
|
|
25959
|
+
console.log(` Once you've completed SSO, paste your CF_Authorization cookie below.
|
|
25960
|
+
`);
|
|
25961
|
+
const rawCookie = await promptLine(` ${pc12.dim("CF_Authorization cookie:")} `);
|
|
25962
|
+
if (!rawCookie) {
|
|
25963
|
+
printError("No cookie provided. Aborting.");
|
|
25964
|
+
process.exitCode = 1;
|
|
25965
|
+
return;
|
|
25966
|
+
}
|
|
25967
|
+
try {
|
|
25968
|
+
const revoked = await remoteRevokeAnthropicToken({ baseUrl, cfAuthCookie: rawCookie }, opts.tokenHash);
|
|
25969
|
+
if (revoked) {
|
|
25970
|
+
printSuccess(`Token ${opts.tokenHash} revoked.`);
|
|
25971
|
+
} else {
|
|
25972
|
+
printWarning(`Token ${opts.tokenHash} not found (may already be revoked).`);
|
|
25973
|
+
}
|
|
25974
|
+
} catch (err) {
|
|
25975
|
+
printError(err instanceof Error ? err.message : "revoke failed");
|
|
25976
|
+
process.exitCode = 1;
|
|
25977
|
+
}
|
|
25978
|
+
});
|
|
25236
25979
|
registerAuthUpgrade(auth);
|
|
25237
25980
|
}
|
|
25238
25981
|
|
|
@@ -25245,7 +25988,7 @@ import ora5 from "ora";
|
|
|
25245
25988
|
import pc13 from "picocolors";
|
|
25246
25989
|
|
|
25247
25990
|
// ../core/dist/world/devbox-freshness.js
|
|
25248
|
-
import { execSync as
|
|
25991
|
+
import { execSync as execSync8 } from "node:child_process";
|
|
25249
25992
|
import { existsSync as existsSync36, statSync as statSync9 } from "node:fs";
|
|
25250
25993
|
import { join as join43 } from "node:path";
|
|
25251
25994
|
var DEFAULT_DEVBOX_IMAGE = "olam-devbox:base";
|
|
@@ -25329,7 +26072,7 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
|
|
|
25329
26072
|
}
|
|
25330
26073
|
function defaultDockerInspect(image) {
|
|
25331
26074
|
try {
|
|
25332
|
-
const out =
|
|
26075
|
+
const out = execSync8(`docker inspect ${image} --format '{{.Created}}'`, { encoding: "utf-8", timeout: 5e3, stdio: ["ignore", "pipe", "pipe"] }).trim();
|
|
25333
26076
|
return out.length > 0 ? out : null;
|
|
25334
26077
|
} catch {
|
|
25335
26078
|
return null;
|
|
@@ -25711,7 +26454,7 @@ async function readHostCpTokenForCreate() {
|
|
|
25711
26454
|
}
|
|
25712
26455
|
}
|
|
25713
26456
|
function registerCreate(program2) {
|
|
25714
|
-
program2.command("create").description("Create a new development world").option("--name <name>", "World name (required unless --from-prompt is set; auto-derived in that case)").option("--repos <repos...>", "Repos to include (names from .olam/config.yaml; wins over --workspace)").option("--workspace <name>", "Named workspace from the host catalog (~/.olam/workspaces/<name>.yaml)").option("--task <task>", "Initial task to dispatch").option("--branch <branch>", "Override default branch name").option("--plan <file>", "Path to a plan file to inject").option("--no-auth", "Skip auto-injecting host credentials").option("--no-host-cp", 'Suppress the host CP "you might want to start it" hint').option("--auto-codex-review", "Spawn a parallel codex-review lane that critiques main as it works").option("--no-open", "Suppress auto-opening the Host CP UI in the browser on success").option("--rebuild-base", "Rebuild olam-devbox:latest before creating (slow)").option("--no-freshness-check", "Skip the devbox image freshness check").option("--from-prompt <prompt>", "NL prompt \u2192 infer workspace + dispatch (CLI parity for olam_create_from_prompt MCP tool)").option("--keep-after-merge", "Disable auto-destroy when the world's PR merges (useful for inspection/debugging)").option("--carry-uncommitted", "Preserve operator's uncommitted edits in the world's worktree").option(
|
|
26457
|
+
program2.command("create").description("Create a new development world").option("--name <name>", "World name (required unless --from-prompt is set; auto-derived in that case)").option("--repos <repos...>", "Repos to include (names from .olam/config.yaml; wins over --workspace)").option("--workspace <name>", "Named workspace from the host catalog (~/.olam/workspaces/<name>.yaml)").option("--task <task>", "Initial task to dispatch").option("--branch <branch>", "Override default branch name").option("--plan <file>", "Path to a plan file to inject").option("--no-auth", "Skip auto-injecting host credentials").option("--no-host-cp", 'Suppress the host CP "you might want to start it" hint').option("--auto-codex-review", "Spawn a parallel codex-review lane that critiques main as it works").option("--no-open", "Suppress auto-opening the Host CP UI in the browser on success").option("--rebuild-base", "Rebuild olam-devbox:latest before creating (slow)").option("--no-freshness-check", "Skip the devbox image freshness check").option("--from-prompt <prompt>", "NL prompt \u2192 infer workspace + dispatch (CLI parity for olam_create_from_prompt MCP tool)").option("--from-manifest <path>", "Spawn a world from a trace-replay fork manifest (ADR 044)").option("--keep-after-merge", "Disable auto-destroy when the world's PR merges (useful for inspection/debugging)").option("--carry-uncommitted", "Preserve operator's uncommitted edits in the world's worktree").option(
|
|
25715
26458
|
"--allow-bootstrap-failure",
|
|
25716
26459
|
"Treat bootstrap step failures as warnings instead of destroying the world (dogfood escape hatch for cross-repo seed coupling)"
|
|
25717
26460
|
).option("--devbox-image <ref>", "Override the default devbox image (full registry/name:tag or @sha256: ref)").option("--allow-custom-registry", "Allow --devbox-image refs outside ghcr.io/pleri/* (logs a warning)").option("--runbook <name>", "Named runbook profile from ~/.olam/config.json").option(
|
|
@@ -25756,6 +26499,32 @@ function registerCreate(program2) {
|
|
|
25756
26499
|
let resolvedWorkspace = opts.workspace;
|
|
25757
26500
|
let resolvedRepos = opts.repos;
|
|
25758
26501
|
let resolvedTask = opts.task;
|
|
26502
|
+
if (opts.fromManifest) {
|
|
26503
|
+
if (opts.task) {
|
|
26504
|
+
printError("--from-manifest and --task are mutually exclusive (the manifest carries the task).");
|
|
26505
|
+
process.exitCode = 1;
|
|
26506
|
+
return;
|
|
26507
|
+
}
|
|
26508
|
+
if (opts.fromPrompt) {
|
|
26509
|
+
printError("--from-manifest and --from-prompt are mutually exclusive.");
|
|
26510
|
+
process.exitCode = 1;
|
|
26511
|
+
return;
|
|
26512
|
+
}
|
|
26513
|
+
const { parseForkManifest: parseForkManifest2, defaultNameFromManifest: defaultNameFromManifest2, provenanceLine: provenanceLine2 } = await Promise.resolve().then(() => (init_from_manifest(), from_manifest_exports));
|
|
26514
|
+
let manifest;
|
|
26515
|
+
try {
|
|
26516
|
+
manifest = parseForkManifest2(opts.fromManifest);
|
|
26517
|
+
} catch (err) {
|
|
26518
|
+
printError(err.message);
|
|
26519
|
+
process.exitCode = 1;
|
|
26520
|
+
return;
|
|
26521
|
+
}
|
|
26522
|
+
resolvedTask = manifest.newPrompt;
|
|
26523
|
+
if (!resolvedName) {
|
|
26524
|
+
resolvedName = defaultNameFromManifest2(manifest);
|
|
26525
|
+
}
|
|
26526
|
+
printInfo("Replay", provenanceLine2(manifest));
|
|
26527
|
+
}
|
|
25759
26528
|
if (opts.fromPrompt) {
|
|
25760
26529
|
if (opts.task) {
|
|
25761
26530
|
printError("--from-prompt and --task are mutually exclusive (the prompt IS the task).");
|
|
@@ -26141,6 +26910,8 @@ ${pc13.cyan("Host CP UI:")} ${worldUrl}`);
|
|
|
26141
26910
|
if (err instanceof AuthPreflightError) {
|
|
26142
26911
|
printError(err.message);
|
|
26143
26912
|
if (err.remedy) console.log(` ${pc13.dim(err.remedy)}`);
|
|
26913
|
+
} else if (err instanceof ContainerOrphanError) {
|
|
26914
|
+
printError(err.message);
|
|
26144
26915
|
} else {
|
|
26145
26916
|
printError(err instanceof Error ? err.message : String(err));
|
|
26146
26917
|
}
|
|
@@ -27302,7 +28073,7 @@ async function runImplode(opts) {
|
|
|
27302
28073
|
// src/commands/enter.ts
|
|
27303
28074
|
init_context();
|
|
27304
28075
|
init_output();
|
|
27305
|
-
import { execSync as
|
|
28076
|
+
import { execSync as execSync9 } from "node:child_process";
|
|
27306
28077
|
import pc18 from "picocolors";
|
|
27307
28078
|
var SAFE_IDENT3 = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
27308
28079
|
function buildStartClaudeCommands(containerName, sessionName, task) {
|
|
@@ -27399,7 +28170,7 @@ function registerEnter(program2) {
|
|
|
27399
28170
|
if (opts.exec) {
|
|
27400
28171
|
for (const step2 of steps) {
|
|
27401
28172
|
try {
|
|
27402
|
-
|
|
28173
|
+
execSync9(step2.command, {
|
|
27403
28174
|
stdio: step2.stdin !== void 0 ? ["pipe", "inherit", "inherit"] : "inherit",
|
|
27404
28175
|
input: step2.stdin
|
|
27405
28176
|
});
|
|
@@ -27439,7 +28210,7 @@ function registerEnter(program2) {
|
|
|
27439
28210
|
}
|
|
27440
28211
|
if (opts.exec) {
|
|
27441
28212
|
try {
|
|
27442
|
-
|
|
28213
|
+
execSync9(result.command, { stdio: "inherit" });
|
|
27443
28214
|
} catch (err) {
|
|
27444
28215
|
printError(
|
|
27445
28216
|
err instanceof Error ? err.message : `Command failed: ${result.command}`
|
|
@@ -28214,7 +28985,7 @@ function registerLanes(program2) {
|
|
|
28214
28985
|
|
|
28215
28986
|
// src/commands/policy-check.ts
|
|
28216
28987
|
init_loader2();
|
|
28217
|
-
import { execSync as
|
|
28988
|
+
import { execSync as execSync10 } from "node:child_process";
|
|
28218
28989
|
import pc20 from "picocolors";
|
|
28219
28990
|
|
|
28220
28991
|
// ../../node_modules/balanced-match/dist/esm/index.js
|
|
@@ -30052,7 +30823,7 @@ function enforcePolicies(policies, diff) {
|
|
|
30052
30823
|
function getDiff(base, cwd) {
|
|
30053
30824
|
for (const range2 of [`${base}...HEAD`, `${base}..HEAD`]) {
|
|
30054
30825
|
try {
|
|
30055
|
-
return
|
|
30826
|
+
return execSync10(`git diff --name-only ${range2}`, {
|
|
30056
30827
|
cwd,
|
|
30057
30828
|
encoding: "utf8",
|
|
30058
30829
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -30061,7 +30832,7 @@ function getDiff(base, cwd) {
|
|
|
30061
30832
|
}
|
|
30062
30833
|
}
|
|
30063
30834
|
try {
|
|
30064
|
-
return
|
|
30835
|
+
return execSync10("git diff --name-only HEAD", {
|
|
30065
30836
|
cwd,
|
|
30066
30837
|
encoding: "utf8",
|
|
30067
30838
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -30099,7 +30870,7 @@ function registerPolicyCheck(program2) {
|
|
|
30099
30870
|
}
|
|
30100
30871
|
|
|
30101
30872
|
// src/commands/worldspec/compile.ts
|
|
30102
|
-
import { existsSync as existsSync44, mkdirSync as mkdirSync28, readFileSync as
|
|
30873
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync28, readFileSync as readFileSync34, writeFileSync as writeFileSync22 } from "node:fs";
|
|
30103
30874
|
import { resolve as resolvePath } from "node:path";
|
|
30104
30875
|
import YAML5 from "yaml";
|
|
30105
30876
|
|
|
@@ -30908,7 +31679,7 @@ function registerWorldspecCompile(parent) {
|
|
|
30908
31679
|
}
|
|
30909
31680
|
let yaml;
|
|
30910
31681
|
try {
|
|
30911
|
-
yaml = YAML5.parse(
|
|
31682
|
+
yaml = YAML5.parse(readFileSync34(abs, "utf8"));
|
|
30912
31683
|
} catch (err) {
|
|
30913
31684
|
printError(
|
|
30914
31685
|
`${p}: YAML parse error: ${err.message}`
|
|
@@ -30993,8 +31764,8 @@ function getPkgVersion() {
|
|
|
30993
31764
|
// src/commands/worldspec/init.ts
|
|
30994
31765
|
init_exit_codes();
|
|
30995
31766
|
init_output();
|
|
30996
|
-
import { existsSync as existsSync45, mkdirSync as mkdirSync29, readFileSync as
|
|
30997
|
-
import { execSync as
|
|
31767
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync29, readFileSync as readFileSync35, writeFileSync as writeFileSync23 } from "node:fs";
|
|
31768
|
+
import { execSync as execSync11 } from "node:child_process";
|
|
30998
31769
|
import { basename as basename3, resolve as resolvePath2 } from "node:path";
|
|
30999
31770
|
function registerWorldspecInit(parent) {
|
|
31000
31771
|
parent.command("init").description(
|
|
@@ -31052,7 +31823,7 @@ function detectProjectShape(root, useAdbYaml) {
|
|
|
31052
31823
|
const rubyVersionPath = resolvePath2(root, ".ruby-version");
|
|
31053
31824
|
if (existsSync45(rubyVersionPath)) {
|
|
31054
31825
|
try {
|
|
31055
|
-
const raw =
|
|
31826
|
+
const raw = readFileSync35(rubyVersionPath, "utf8").trim();
|
|
31056
31827
|
const match2 = raw.match(/(\d+\.\d+\.\d+)/);
|
|
31057
31828
|
if (match2) rubyVersion = match2[1] ?? null;
|
|
31058
31829
|
} catch {
|
|
@@ -31069,7 +31840,7 @@ function detectProjectShape(root, useAdbYaml) {
|
|
|
31069
31840
|
}
|
|
31070
31841
|
function getRepoName2(root) {
|
|
31071
31842
|
try {
|
|
31072
|
-
const url2 =
|
|
31843
|
+
const url2 = execSync11("git remote get-url origin", {
|
|
31073
31844
|
cwd: root,
|
|
31074
31845
|
encoding: "utf-8",
|
|
31075
31846
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -32462,7 +33233,7 @@ function registerWorldspecSchema(parent) {
|
|
|
32462
33233
|
}
|
|
32463
33234
|
|
|
32464
33235
|
// src/commands/worldspec/validate.ts
|
|
32465
|
-
import { existsSync as existsSync46, readFileSync as
|
|
33236
|
+
import { existsSync as existsSync46, readFileSync as readFileSync36 } from "node:fs";
|
|
32466
33237
|
import { resolve as resolvePath4 } from "node:path";
|
|
32467
33238
|
init_exit_codes();
|
|
32468
33239
|
init_output();
|
|
@@ -32485,7 +33256,7 @@ function registerWorldspecValidate(parent) {
|
|
|
32485
33256
|
}
|
|
32486
33257
|
let yamlSource;
|
|
32487
33258
|
try {
|
|
32488
|
-
yamlSource =
|
|
33259
|
+
yamlSource = readFileSync36(absPath, "utf8");
|
|
32489
33260
|
} catch (err) {
|
|
32490
33261
|
printError(
|
|
32491
33262
|
`failed to read ${absPath}: ${err.message}`
|
|
@@ -34404,7 +35175,7 @@ init_snapshot();
|
|
|
34404
35175
|
init_output();
|
|
34405
35176
|
import * as fs45 from "node:fs";
|
|
34406
35177
|
import * as path48 from "node:path";
|
|
34407
|
-
import { execSync as
|
|
35178
|
+
import { execSync as execSync12 } from "node:child_process";
|
|
34408
35179
|
import pc24 from "picocolors";
|
|
34409
35180
|
|
|
34410
35181
|
// src/commands/world.ts
|
|
@@ -34540,7 +35311,7 @@ async function captureGems(worldId, workspacePath, repo) {
|
|
|
34540
35311
|
const containerName = `olam-${worldId}-devbox`;
|
|
34541
35312
|
let bundlePath;
|
|
34542
35313
|
try {
|
|
34543
|
-
bundlePath =
|
|
35314
|
+
bundlePath = execSync12(
|
|
34544
35315
|
`docker exec ${containerName} sh -c 'bundle config get path 2>/dev/null || echo ~/.bundle'`,
|
|
34545
35316
|
{ encoding: "utf-8", timeout: 1e4 }
|
|
34546
35317
|
).trim();
|
|
@@ -34550,13 +35321,13 @@ async function captureGems(worldId, workspacePath, repo) {
|
|
|
34550
35321
|
}
|
|
34551
35322
|
try {
|
|
34552
35323
|
const tmpTar = `/tmp/olam-snap-gems-${repo}-${fingerprint}.tar.gz`;
|
|
34553
|
-
|
|
35324
|
+
execSync12(
|
|
34554
35325
|
`docker exec ${containerName} sh -c 'mkdir -p "$(dirname ${tmpTar})" && tar -czf ${tmpTar}.tmp -C ${bundlePath} . && mv ${tmpTar}.tmp ${tmpTar}'`,
|
|
34555
35326
|
{ stdio: "pipe", timeout: 12e4 }
|
|
34556
35327
|
);
|
|
34557
35328
|
fs45.mkdirSync(path48.dirname(tarPath), { recursive: true });
|
|
34558
|
-
|
|
34559
|
-
|
|
35329
|
+
execSync12(`docker cp ${containerName}:${tmpTar} "${tarPath}"`, { stdio: "pipe", timeout: 12e4 });
|
|
35330
|
+
execSync12(`docker exec ${containerName} rm -f ${tmpTar}`, { stdio: "pipe" });
|
|
34560
35331
|
const stat = fs45.statSync(tarPath);
|
|
34561
35332
|
const manifest = {
|
|
34562
35333
|
kind: "gems",
|
|
@@ -34612,18 +35383,18 @@ async function capturePg(worldId, workspacePath, repoNames) {
|
|
|
34612
35383
|
const containerName = `olam-${worldId}-postgres`;
|
|
34613
35384
|
const volumeName2 = `olam-${worldId}-postgres-data`;
|
|
34614
35385
|
try {
|
|
34615
|
-
|
|
35386
|
+
execSync12(`docker inspect ${containerName}`, { stdio: "pipe", timeout: 5e3 });
|
|
34616
35387
|
} catch {
|
|
34617
35388
|
return { ok: false, tarPath, msg: "postgres container not found; world may not use postgres" };
|
|
34618
35389
|
}
|
|
34619
35390
|
try {
|
|
34620
|
-
|
|
35391
|
+
execSync12(`docker stop ${containerName}`, { stdio: "pipe", timeout: 3e4 });
|
|
34621
35392
|
fs45.mkdirSync(path48.dirname(tarPath), { recursive: true });
|
|
34622
|
-
|
|
35393
|
+
execSync12(
|
|
34623
35394
|
`docker run --rm -v "${volumeName2}:/pgdata:ro" -v "${path48.dirname(tarPath)}:/dest" alpine sh -c 'tar -czf /dest/${path48.basename(tarPath)}.tmp -C /pgdata . && mv /dest/${path48.basename(tarPath)}.tmp /dest/${path48.basename(tarPath)}'`,
|
|
34624
35395
|
{ stdio: "pipe", timeout: 18e4 }
|
|
34625
35396
|
);
|
|
34626
|
-
|
|
35397
|
+
execSync12(`docker start ${containerName}`, { stdio: "pipe", timeout: 3e4 });
|
|
34627
35398
|
const stat = fs45.statSync(tarPath);
|
|
34628
35399
|
const manifest = {
|
|
34629
35400
|
kind: "pg",
|
|
@@ -34637,7 +35408,7 @@ async function capturePg(worldId, workspacePath, repoNames) {
|
|
|
34637
35408
|
return { ok: true, tarPath };
|
|
34638
35409
|
} catch (err) {
|
|
34639
35410
|
try {
|
|
34640
|
-
|
|
35411
|
+
execSync12(`docker start ${containerName}`, { stdio: "pipe", timeout: 1e4 });
|
|
34641
35412
|
} catch {
|
|
34642
35413
|
}
|
|
34643
35414
|
return { ok: false, tarPath, msg: `pg capture failed: ${String(err)}` };
|
|
@@ -35068,7 +35839,7 @@ function registerRestart(program2) {
|
|
|
35068
35839
|
import * as fs48 from "node:fs";
|
|
35069
35840
|
import * as os26 from "node:os";
|
|
35070
35841
|
import * as path51 from "node:path";
|
|
35071
|
-
import { execFileSync as execFileSync13, execSync as
|
|
35842
|
+
import { execFileSync as execFileSync13, execSync as execSync13 } from "node:child_process";
|
|
35072
35843
|
import pc25 from "picocolors";
|
|
35073
35844
|
|
|
35074
35845
|
// ../core/dist/diagnose/secret-stripper.js
|
|
@@ -35108,7 +35879,7 @@ var CACHE_DIR = path51.join(os26.homedir(), ".olam", "cache");
|
|
|
35108
35879
|
var LOG_TAIL_LINES = 200;
|
|
35109
35880
|
function safeExec(cmd) {
|
|
35110
35881
|
try {
|
|
35111
|
-
return
|
|
35882
|
+
return execSync13(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
35112
35883
|
} catch {
|
|
35113
35884
|
return "";
|
|
35114
35885
|
}
|
|
@@ -35234,7 +36005,7 @@ init_health_probes();
|
|
|
35234
36005
|
|
|
35235
36006
|
// src/lib/bundle-freshness.ts
|
|
35236
36007
|
import { createHash as createHash4 } from "node:crypto";
|
|
35237
|
-
import { existsSync as existsSync56, readFileSync as
|
|
36008
|
+
import { existsSync as existsSync56, readFileSync as readFileSync43, statSync as statSync17 } from "node:fs";
|
|
35238
36009
|
import { join as join58, resolve as resolve16 } from "node:path";
|
|
35239
36010
|
var BUNDLE_FILES = [
|
|
35240
36011
|
"driver-runner.js",
|
|
@@ -35279,7 +36050,7 @@ async function probeBundleFreshness(deps = {}) {
|
|
|
35279
36050
|
for (const f of BUNDLE_FILES) {
|
|
35280
36051
|
const p = join58(hostDistDir, f);
|
|
35281
36052
|
if (!existsSync56(p)) continue;
|
|
35282
|
-
const buf =
|
|
36053
|
+
const buf = readFileSync43(p);
|
|
35283
36054
|
const sha = createHash4("sha256").update(buf).digest("hex");
|
|
35284
36055
|
const mtimeMs = statSync17(p).mtimeMs;
|
|
35285
36056
|
hostShas.set(f, { sha, mtimeMs });
|
|
@@ -36188,7 +36959,7 @@ function registerSubstrate(program2) {
|
|
|
36188
36959
|
}
|
|
36189
36960
|
|
|
36190
36961
|
// ../cli-plugin-tasks/dist/client.js
|
|
36191
|
-
import { readFileSync as
|
|
36962
|
+
import { readFileSync as readFileSync47 } from "node:fs";
|
|
36192
36963
|
import { homedir as homedir31 } from "node:os";
|
|
36193
36964
|
import { join as join61 } from "node:path";
|
|
36194
36965
|
var TasksClient = class {
|
|
@@ -36200,7 +36971,7 @@ var TasksClient = class {
|
|
|
36200
36971
|
this.baseUrl = (opts.hostCpUrl ?? process.env.OLAM_HOST_CP_URL ?? "http://localhost:19000").replace(/\/$/, "");
|
|
36201
36972
|
const tokenPath2 = opts.tokenPath ?? join61(homedir31(), ".olam", "host-cp.token");
|
|
36202
36973
|
try {
|
|
36203
|
-
this.token =
|
|
36974
|
+
this.token = readFileSync47(tokenPath2, "utf8").trim();
|
|
36204
36975
|
} catch (e) {
|
|
36205
36976
|
throw new Error(`cli-plugin-tasks: cannot read host-cp token at ${tokenPath2} (${e instanceof Error ? e.message : "unknown"}). Bootstrap host-cp first.`);
|
|
36206
36977
|
}
|
|
@@ -36227,7 +36998,7 @@ var TasksClient = class {
|
|
|
36227
36998
|
};
|
|
36228
36999
|
|
|
36229
37000
|
// ../cli-plugin-tasks/dist/tracker-parser.js
|
|
36230
|
-
import { readFileSync as
|
|
37001
|
+
import { readFileSync as readFileSync48 } from "node:fs";
|
|
36231
37002
|
import { createHash as createHash6 } from "node:crypto";
|
|
36232
37003
|
function contentHash(parts) {
|
|
36233
37004
|
const normalized = parts.map((p) => (p ?? "").trim()).join("|");
|
|
@@ -36261,7 +37032,7 @@ function parseFrontmatter2(raw) {
|
|
|
36261
37032
|
return { frontmatter: fm, body };
|
|
36262
37033
|
}
|
|
36263
37034
|
function parseTracker(path96) {
|
|
36264
|
-
const raw =
|
|
37035
|
+
const raw = readFileSync48(path96, "utf8");
|
|
36265
37036
|
const { frontmatter, body } = parseFrontmatter2(raw);
|
|
36266
37037
|
const lines = body.split("\n");
|
|
36267
37038
|
const tasks = [];
|
|
@@ -36654,7 +37425,7 @@ function registerCompletion(program2) {
|
|
|
36654
37425
|
init_cli_version();
|
|
36655
37426
|
init_health_probes();
|
|
36656
37427
|
import { spawn as spawn7, spawnSync as spawnSync27 } from "node:child_process";
|
|
36657
|
-
import { existsSync as existsSync85, readFileSync as
|
|
37428
|
+
import { existsSync as existsSync85, readFileSync as readFileSync71 } from "node:fs";
|
|
36658
37429
|
import { homedir as homedir45 } from "node:os";
|
|
36659
37430
|
import path77 from "node:path";
|
|
36660
37431
|
import { createInterface as createInterface3 } from "node:readline";
|
|
@@ -36721,14 +37492,14 @@ function discoverOfferableContexts(deps = {}) {
|
|
|
36721
37492
|
}
|
|
36722
37493
|
|
|
36723
37494
|
// src/lib/shell-rc.ts
|
|
36724
|
-
import { copyFileSync as copyFileSync5, existsSync as existsSync60, readFileSync as
|
|
37495
|
+
import { copyFileSync as copyFileSync5, existsSync as existsSync60, readFileSync as readFileSync49, renameSync as renameSync8, writeFileSync as writeFileSync29 } from "node:fs";
|
|
36725
37496
|
import path54 from "node:path";
|
|
36726
37497
|
function appendIdempotent(opts) {
|
|
36727
37498
|
const { rcPath, marker, contentLine, clock = () => /* @__PURE__ */ new Date() } = opts;
|
|
36728
37499
|
if (!existsSync60(rcPath)) {
|
|
36729
37500
|
return { status: "no-rc-file", backupPath: null };
|
|
36730
37501
|
}
|
|
36731
|
-
const content =
|
|
37502
|
+
const content = readFileSync49(rcPath, "utf-8");
|
|
36732
37503
|
if (content.includes(marker)) {
|
|
36733
37504
|
return { status: "already-present", backupPath: null };
|
|
36734
37505
|
}
|
|
@@ -37101,7 +37872,7 @@ function resolveSubstrate(opts, deps) {
|
|
|
37101
37872
|
const configPath = deps.configPath ?? OLAM_CONFIG_PATH;
|
|
37102
37873
|
if (existsSync85(configPath)) {
|
|
37103
37874
|
try {
|
|
37104
|
-
const raw =
|
|
37875
|
+
const raw = readFileSync71(configPath, "utf8");
|
|
37105
37876
|
const parsed = JSON.parse(raw);
|
|
37106
37877
|
const host = parsed.host;
|
|
37107
37878
|
if (host?.substrate === "kubernetes") return "kubernetes";
|
|
@@ -37781,11 +38552,11 @@ function registerSetupMetrics(program2) {
|
|
|
37781
38552
|
|
|
37782
38553
|
// ../core/dist/setup/linux-gate.js
|
|
37783
38554
|
init_trust_audit_log();
|
|
37784
|
-
import { execSync as
|
|
38555
|
+
import { execSync as execSync14 } from "node:child_process";
|
|
37785
38556
|
var GH_LABEL = "linux-platform-request";
|
|
37786
38557
|
var LINUX_INVOCATION_THRESHOLD = 3;
|
|
37787
38558
|
function defaultExecGhIssueList(label) {
|
|
37788
|
-
return
|
|
38559
|
+
return execSync14(`gh issue list --label ${label} --json number,title --state all`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
37789
38560
|
}
|
|
37790
38561
|
function countLinuxInvocations(readLog) {
|
|
37791
38562
|
const { entries } = readLog();
|
|
@@ -37860,7 +38631,7 @@ function registerSetupLinuxGate(program2) {
|
|
|
37860
38631
|
import * as fs78 from "node:fs";
|
|
37861
38632
|
import * as os42 from "node:os";
|
|
37862
38633
|
import * as path80 from "node:path";
|
|
37863
|
-
import { execSync as
|
|
38634
|
+
import { execSync as execSync15 } from "node:child_process";
|
|
37864
38635
|
import pc28 from "picocolors";
|
|
37865
38636
|
|
|
37866
38637
|
// src/lib/symlink-reconcile.ts
|
|
@@ -37928,7 +38699,7 @@ var LOG_DIR2 = path80.join(os42.homedir(), ".olam", "log");
|
|
|
37928
38699
|
var LAST_STABLE_FILE = path80.join(CACHE_DIR2, "last-stable.txt");
|
|
37929
38700
|
function defaultExec(cmd) {
|
|
37930
38701
|
try {
|
|
37931
|
-
const stdout =
|
|
38702
|
+
const stdout = execSync15(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
37932
38703
|
return { exitCode: 0, stdout, stderr: "" };
|
|
37933
38704
|
} catch (err) {
|
|
37934
38705
|
const e = err;
|
|
@@ -38453,7 +39224,7 @@ import * as readline2 from "node:readline";
|
|
|
38453
39224
|
import pc32 from "picocolors";
|
|
38454
39225
|
|
|
38455
39226
|
// src/commands/flywheel/install-shims.ts
|
|
38456
|
-
import { copyFileSync as copyFileSync9, existsSync as existsSync89, mkdirSync as mkdirSync53, readFileSync as
|
|
39227
|
+
import { copyFileSync as copyFileSync9, existsSync as existsSync89, mkdirSync as mkdirSync53, readFileSync as readFileSync75, writeFileSync as writeFileSync44 } from "node:fs";
|
|
38457
39228
|
import { homedir as homedir48 } from "node:os";
|
|
38458
39229
|
import { dirname as dirname48, join as join87 } from "node:path";
|
|
38459
39230
|
|
|
@@ -38557,7 +39328,7 @@ function installOne(spec, targetDir, opts) {
|
|
|
38557
39328
|
}
|
|
38558
39329
|
return { basename: spec.basename, action: "written", targetPath };
|
|
38559
39330
|
}
|
|
38560
|
-
const existing =
|
|
39331
|
+
const existing = readFileSync75(targetPath, "utf8");
|
|
38561
39332
|
if (existing === newContent) {
|
|
38562
39333
|
return { basename: spec.basename, action: "unchanged", targetPath };
|
|
38563
39334
|
}
|
|
@@ -39217,7 +39988,7 @@ import {
|
|
|
39217
39988
|
lstatSync as lstatSync8,
|
|
39218
39989
|
mkdirSync as mkdirSync54,
|
|
39219
39990
|
readdirSync as readdirSync27,
|
|
39220
|
-
readFileSync as
|
|
39991
|
+
readFileSync as readFileSync76,
|
|
39221
39992
|
readlinkSync as readlinkSync4,
|
|
39222
39993
|
rmSync as rmSync9,
|
|
39223
39994
|
statSync as statSync27,
|
|
@@ -39324,8 +40095,8 @@ function postMergeSanitize(mergedText, label) {
|
|
|
39324
40095
|
return { ok: false, reason: `[post-merge-sanitize] ${label} merged output failed sanitizer: ${result.reason}` };
|
|
39325
40096
|
}
|
|
39326
40097
|
function mergeOne(upstreamPath, overlayPath, destPath2, label, dryRun, messages) {
|
|
39327
|
-
const upstreamText =
|
|
39328
|
-
const overlayText =
|
|
40098
|
+
const upstreamText = readFileSync76(upstreamPath, "utf8");
|
|
40099
|
+
const overlayText = readFileSync76(overlayPath, "utf8");
|
|
39329
40100
|
const result = mergeMarkdown(upstreamText, overlayText, label, upstreamPath, overlayPath);
|
|
39330
40101
|
if ("error" in result) {
|
|
39331
40102
|
messages.push(`ERROR ${result.error.reason}`);
|
|
@@ -39345,7 +40116,7 @@ function mergeOne(upstreamPath, overlayPath, destPath2, label, dryRun, messages)
|
|
|
39345
40116
|
}
|
|
39346
40117
|
function isNewAgentOverlay(overlayPath) {
|
|
39347
40118
|
try {
|
|
39348
|
-
const text =
|
|
40119
|
+
const text = readFileSync76(overlayPath, "utf8");
|
|
39349
40120
|
const { fm } = parseFrontmatter3(text);
|
|
39350
40121
|
return fm["overlay-intent"] === "new-agent";
|
|
39351
40122
|
} catch {
|
|
@@ -42123,7 +42894,7 @@ function registerMcp(program2) {
|
|
|
42123
42894
|
init_output();
|
|
42124
42895
|
|
|
42125
42896
|
// src/lib/memory-host-process-migration.ts
|
|
42126
|
-
import { existsSync as existsSync101, readFileSync as
|
|
42897
|
+
import { existsSync as existsSync101, readFileSync as readFileSync84, unlinkSync as unlinkSync23 } from "node:fs";
|
|
42127
42898
|
import { spawnSync as spawnSync30 } from "node:child_process";
|
|
42128
42899
|
|
|
42129
42900
|
// src/commands/memory/_paths.ts
|
|
@@ -42192,7 +42963,7 @@ function migrateFromHostProcess(opts = {}) {
|
|
|
42192
42963
|
}
|
|
42193
42964
|
function readPidFromFile(pidPath2) {
|
|
42194
42965
|
try {
|
|
42195
|
-
const raw =
|
|
42966
|
+
const raw = readFileSync84(pidPath2, "utf8").trim();
|
|
42196
42967
|
const pid = parseInt(raw, 10);
|
|
42197
42968
|
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
42198
42969
|
return pid;
|
|
@@ -42625,7 +43396,7 @@ function registerMemoryUninstall(cmd) {
|
|
|
42625
43396
|
// src/commands/memory/mode.ts
|
|
42626
43397
|
init_schema2();
|
|
42627
43398
|
init_output();
|
|
42628
|
-
import { existsSync as existsSync104, readFileSync as
|
|
43399
|
+
import { existsSync as existsSync104, readFileSync as readFileSync85, writeFileSync as writeFileSync51 } from "node:fs";
|
|
42629
43400
|
import { join as join96 } from "node:path";
|
|
42630
43401
|
import * as readline7 from "node:readline/promises";
|
|
42631
43402
|
import { parse as parseYaml8, stringify as stringifyYaml6 } from "yaml";
|
|
@@ -42640,7 +43411,7 @@ function locateConfig(cwd) {
|
|
|
42640
43411
|
return { absPath };
|
|
42641
43412
|
}
|
|
42642
43413
|
function readConfigYaml(absPath) {
|
|
42643
|
-
const raw =
|
|
43414
|
+
const raw = readFileSync85(absPath, "utf-8");
|
|
42644
43415
|
const parsed = parseYaml8(raw) ?? {};
|
|
42645
43416
|
if (typeof parsed !== "object" || parsed === null) {
|
|
42646
43417
|
throw new Error(`${absPath} is not a YAML object`);
|
|
@@ -43127,7 +43898,7 @@ function registerMemoryStats(cmd) {
|
|
|
43127
43898
|
}
|
|
43128
43899
|
|
|
43129
43900
|
// src/commands/memory/install-hooks.ts
|
|
43130
|
-
import { copyFileSync as copyFileSync12, existsSync as existsSync106, mkdirSync as mkdirSync60, readFileSync as
|
|
43901
|
+
import { copyFileSync as copyFileSync12, existsSync as existsSync106, mkdirSync as mkdirSync60, readFileSync as readFileSync86, writeFileSync as writeFileSync52 } from "node:fs";
|
|
43131
43902
|
import { homedir as homedir54 } from "node:os";
|
|
43132
43903
|
import { dirname as dirname56, join as join98, resolve as resolve25 } from "node:path";
|
|
43133
43904
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
@@ -43150,7 +43921,7 @@ function installOne2(basename16, sourceDir, targetDir, opts) {
|
|
|
43150
43921
|
if (!existsSync106(sourcePath)) {
|
|
43151
43922
|
throw new Error(`canonical hook source missing at ${sourcePath} \u2014 olam install corrupt or sourceDir is wrong`);
|
|
43152
43923
|
}
|
|
43153
|
-
const newContent =
|
|
43924
|
+
const newContent = readFileSync86(sourcePath, "utf8");
|
|
43154
43925
|
if (!existsSync106(targetPath)) {
|
|
43155
43926
|
if (opts.dryRun !== true) {
|
|
43156
43927
|
mkdirSync60(dirname56(targetPath), { recursive: true });
|
|
@@ -43158,7 +43929,7 @@ function installOne2(basename16, sourceDir, targetDir, opts) {
|
|
|
43158
43929
|
}
|
|
43159
43930
|
return { basename: basename16, action: "written", targetPath };
|
|
43160
43931
|
}
|
|
43161
|
-
const existing =
|
|
43932
|
+
const existing = readFileSync86(targetPath, "utf8");
|
|
43162
43933
|
if (existing === newContent) {
|
|
43163
43934
|
return { basename: basename16, action: "unchanged", targetPath };
|
|
43164
43935
|
}
|
|
@@ -44636,7 +45407,7 @@ function registerFlywheelK5Score(parent) {
|
|
|
44636
45407
|
}
|
|
44637
45408
|
|
|
44638
45409
|
// src/commands/flywheel/k5-validate.ts
|
|
44639
|
-
import { readFileSync as
|
|
45410
|
+
import { readFileSync as readFileSync90, statSync as statSync30 } from "node:fs";
|
|
44640
45411
|
import { parse as parseYAML } from "yaml";
|
|
44641
45412
|
var K5_DIMS = ["direction", "approach", "open_questions", "constraints", "reuse"];
|
|
44642
45413
|
var MAX_PLAN_BYTES = 1048576;
|
|
@@ -44706,7 +45477,7 @@ function validatePlan(path96) {
|
|
|
44706
45477
|
}
|
|
44707
45478
|
let text;
|
|
44708
45479
|
try {
|
|
44709
|
-
text =
|
|
45480
|
+
text = readFileSync90(path96, "utf8");
|
|
44710
45481
|
} catch (err) {
|
|
44711
45482
|
return { ok: false, message: `FAIL cannot read ${path96}: ${err instanceof Error ? err.message : "unknown"}` };
|
|
44712
45483
|
}
|
|
@@ -44788,7 +45559,7 @@ function registerFlywheelK5Validate(parent) {
|
|
|
44788
45559
|
}
|
|
44789
45560
|
|
|
44790
45561
|
// src/commands/flywheel/k10-measure.ts
|
|
44791
|
-
import { readFileSync as
|
|
45562
|
+
import { readFileSync as readFileSync91 } from "node:fs";
|
|
44792
45563
|
|
|
44793
45564
|
// ../core/dist/lib/k10-budget.js
|
|
44794
45565
|
var K10_TOKEN_CAP = 5500;
|
|
@@ -44845,7 +45616,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
44845
45616
|
parent.command("k10-measure").description("Measure K10 token budget for upstream + optional overlay; emit PASS/REJECT verdict").requiredOption("--upstream <path>", "path to upstream file (e.g. persona prompt)").option("--overlay <path>", "path to overlay file (omit if none \u2014 PASS without enforcement)").option("--json", "emit verdict as JSON instead of human-readable").action((opts) => {
|
|
44846
45617
|
let upstreamText;
|
|
44847
45618
|
try {
|
|
44848
|
-
upstreamText =
|
|
45619
|
+
upstreamText = readFileSync91(opts.upstream, "utf8");
|
|
44849
45620
|
} catch (err) {
|
|
44850
45621
|
process.stderr.write(
|
|
44851
45622
|
`[k10-measure-error] cannot read upstream ${opts.upstream}: ${err instanceof Error ? err.message : "unknown"}
|
|
@@ -44857,7 +45628,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
44857
45628
|
let overlayTokens = null;
|
|
44858
45629
|
if (opts.overlay !== void 0) {
|
|
44859
45630
|
try {
|
|
44860
|
-
const overlayText =
|
|
45631
|
+
const overlayText = readFileSync91(opts.overlay, "utf8");
|
|
44861
45632
|
overlayTokens = tokensFromText(overlayText);
|
|
44862
45633
|
} catch (err) {
|
|
44863
45634
|
process.stderr.write(
|
|
@@ -44891,7 +45662,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
44891
45662
|
}
|
|
44892
45663
|
|
|
44893
45664
|
// src/commands/flywheel/check-persona-skeleton.ts
|
|
44894
|
-
import { existsSync as existsSync110, readFileSync as
|
|
45665
|
+
import { existsSync as existsSync110, readFileSync as readFileSync92, statSync as statSync31 } from "node:fs";
|
|
44895
45666
|
import { homedir as homedir60 } from "node:os";
|
|
44896
45667
|
import { basename as basename14, join as join103 } from "node:path";
|
|
44897
45668
|
import { parse as parseYAML2 } from "yaml";
|
|
@@ -44940,7 +45711,7 @@ function checkFile(filepath) {
|
|
|
44940
45711
|
if (!existsSync110(filepath) || !statSync31(filepath).isFile()) {
|
|
44941
45712
|
return { passed: false, failures: [`file not found: ${filepath}`], tokens: 0, mergedSkipped: false };
|
|
44942
45713
|
}
|
|
44943
|
-
const text =
|
|
45714
|
+
const text = readFileSync92(filepath, "utf8");
|
|
44944
45715
|
const { fm, body } = parseFile(text);
|
|
44945
45716
|
const failures = [];
|
|
44946
45717
|
for (const key of REQUIRED_FRONTMATTER_KEYS) {
|
|
@@ -45006,7 +45777,7 @@ Results: ${passCount} passed, ${failCount} failed
|
|
|
45006
45777
|
}
|
|
45007
45778
|
|
|
45008
45779
|
// src/commands/flywheel/diversity-check.ts
|
|
45009
|
-
import { readFileSync as
|
|
45780
|
+
import { readFileSync as readFileSync93 } from "node:fs";
|
|
45010
45781
|
import { basename as basename15 } from "node:path";
|
|
45011
45782
|
import { globSync as globSync2 } from "node:fs";
|
|
45012
45783
|
|
|
@@ -45115,7 +45886,7 @@ function registerFlywheelDiversityCheck(parent) {
|
|
|
45115
45886
|
const personas = /* @__PURE__ */ new Map();
|
|
45116
45887
|
for (const filepath of files) {
|
|
45117
45888
|
try {
|
|
45118
|
-
const body =
|
|
45889
|
+
const body = readFileSync93(filepath, "utf8");
|
|
45119
45890
|
if (body.trim().length > 0) {
|
|
45120
45891
|
personas.set(basename15(filepath, ".md"), body);
|
|
45121
45892
|
}
|
|
@@ -45208,7 +45979,7 @@ import {
|
|
|
45208
45979
|
copyFileSync as copyFileSync15,
|
|
45209
45980
|
existsSync as existsSync111,
|
|
45210
45981
|
mkdirSync as mkdirSync65,
|
|
45211
|
-
readFileSync as
|
|
45982
|
+
readFileSync as readFileSync94,
|
|
45212
45983
|
readdirSync as readdirSync32,
|
|
45213
45984
|
statSync as statSync32,
|
|
45214
45985
|
writeFileSync as writeFileSync57
|
|
@@ -45294,7 +46065,7 @@ function resolveAtlasUser2(opts) {
|
|
|
45294
46065
|
const claudeDir2 = opts._testClaudeDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join105(homedir62(), ".claude");
|
|
45295
46066
|
const f = join105(claudeDir2, ".atlas-user");
|
|
45296
46067
|
if (existsSync111(f)) {
|
|
45297
|
-
const v =
|
|
46068
|
+
const v = readFileSync94(f, "utf-8").trim();
|
|
45298
46069
|
if (v.length === 0) return null;
|
|
45299
46070
|
assertValidAtlasUser(v);
|
|
45300
46071
|
return v;
|
|
@@ -45436,7 +46207,7 @@ function pushOverlays(opts) {
|
|
|
45436
46207
|
const basename16 = relPath.split("/").pop() ?? relPath;
|
|
45437
46208
|
let content;
|
|
45438
46209
|
try {
|
|
45439
|
-
content =
|
|
46210
|
+
content = readFileSync94(srcFile);
|
|
45440
46211
|
} catch {
|
|
45441
46212
|
continue;
|
|
45442
46213
|
}
|
|
@@ -45484,12 +46255,12 @@ function pushOverlays(opts) {
|
|
|
45484
46255
|
const targetFile = join105(targetDir, relPath);
|
|
45485
46256
|
let srcBuf;
|
|
45486
46257
|
try {
|
|
45487
|
-
srcBuf =
|
|
46258
|
+
srcBuf = readFileSync94(srcFile);
|
|
45488
46259
|
} catch {
|
|
45489
46260
|
continue;
|
|
45490
46261
|
}
|
|
45491
46262
|
if (existsSync111(targetFile)) {
|
|
45492
|
-
const dstBuf =
|
|
46263
|
+
const dstBuf = readFileSync94(targetFile);
|
|
45493
46264
|
if (srcBuf.equals(dstBuf)) {
|
|
45494
46265
|
wouldUnchange += 1;
|
|
45495
46266
|
process.stdout.write(` [skip] ${overlayKind}.overrides/${relPath} (unchanged)
|
|
@@ -45540,13 +46311,13 @@ function pushOverlays(opts) {
|
|
|
45540
46311
|
const targetFile = join105(membersBase, `${overlayKind}.overrides`, relPath);
|
|
45541
46312
|
let srcBuf;
|
|
45542
46313
|
try {
|
|
45543
|
-
srcBuf =
|
|
46314
|
+
srcBuf = readFileSync94(srcFile);
|
|
45544
46315
|
} catch {
|
|
45545
46316
|
continue;
|
|
45546
46317
|
}
|
|
45547
46318
|
const targetExists = existsSync111(targetFile);
|
|
45548
46319
|
if (targetExists) {
|
|
45549
|
-
const dstBuf =
|
|
46320
|
+
const dstBuf = readFileSync94(targetFile);
|
|
45550
46321
|
if (srcBuf.equals(dstBuf)) {
|
|
45551
46322
|
filesUnchanged += 1;
|
|
45552
46323
|
continue;
|
|
@@ -45755,7 +46526,7 @@ function migrateOverlays(opts = {}) {
|
|
|
45755
46526
|
for (const filePath of allFiles) {
|
|
45756
46527
|
let original;
|
|
45757
46528
|
try {
|
|
45758
|
-
original =
|
|
46529
|
+
original = readFileSync94(filePath, "utf8");
|
|
45759
46530
|
} catch {
|
|
45760
46531
|
continue;
|
|
45761
46532
|
}
|