@pleri/olam-cli 0.1.170 → 0.1.174
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/agent-stream/driver-runner.js +13 -0
- 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 +911 -137
- 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 +1487 -435
- 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/observability/ndjson-span-sink.mjs +52 -0
- package/host-cp/src/boot-reconciler.mjs +238 -0
- package/host-cp/src/linear-sync.mjs +43 -0
- package/host-cp/src/plan-chat-service.mjs +129 -1
- package/host-cp/src/port-bridge-manager.mjs +116 -10
- package/host-cp/src/server.mjs +121 -1
- 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);
|
|
@@ -8769,6 +8784,8 @@ function stripMcpServers(mcpServers) {
|
|
|
8769
8784
|
stripped.type = value;
|
|
8770
8785
|
} else if (key === "url" && typeof value === "string") {
|
|
8771
8786
|
stripped.url = value;
|
|
8787
|
+
} else if (key === "alwaysLoad" && typeof value === "boolean") {
|
|
8788
|
+
stripped.alwaysLoad = value;
|
|
8772
8789
|
}
|
|
8773
8790
|
}
|
|
8774
8791
|
out[svc] = stripped;
|
|
@@ -8861,8 +8878,8 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
|
|
|
8861
8878
|
}
|
|
8862
8879
|
}
|
|
8863
8880
|
async function copyClaudeConfigIntoContainer(containerName) {
|
|
8864
|
-
const { execSync:
|
|
8865
|
-
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" });
|
|
8866
8883
|
dockerExec("mkdir -p $HOME/.claude");
|
|
8867
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");
|
|
8868
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");
|
|
@@ -8878,7 +8895,7 @@ async function copyClaudeConfigIntoContainer(containerName) {
|
|
|
8878
8895
|
await sanitizeContainerClaudeHooks(containerName);
|
|
8879
8896
|
}
|
|
8880
8897
|
async function sanitizeContainerClaudeHooks(containerName) {
|
|
8881
|
-
const { execSync:
|
|
8898
|
+
const { execSync: execSync16 } = await import("node:child_process");
|
|
8882
8899
|
const script = `
|
|
8883
8900
|
const fs = require('fs');
|
|
8884
8901
|
const p = (process.env.HOME || '/home/olam') + '/.claude/settings.json';
|
|
@@ -8922,7 +8939,7 @@ if (changed) {
|
|
|
8922
8939
|
}
|
|
8923
8940
|
`;
|
|
8924
8941
|
try {
|
|
8925
|
-
|
|
8942
|
+
execSync16(`docker exec ${containerName} /usr/local/bin/node -e ${shQuote(script)}`, { stdio: "pipe" });
|
|
8926
8943
|
} catch {
|
|
8927
8944
|
}
|
|
8928
8945
|
}
|
|
@@ -9086,7 +9103,8 @@ var init_env_setup = __esm({
|
|
|
9086
9103
|
"command",
|
|
9087
9104
|
"args",
|
|
9088
9105
|
"type",
|
|
9089
|
-
"url"
|
|
9106
|
+
"url",
|
|
9107
|
+
"alwaysLoad"
|
|
9090
9108
|
]);
|
|
9091
9109
|
SKIP_FILES = /* @__PURE__ */ new Set([
|
|
9092
9110
|
".credentials.json",
|
|
@@ -11712,6 +11730,60 @@ var init_bootstrap_hooks = __esm({
|
|
|
11712
11730
|
}
|
|
11713
11731
|
});
|
|
11714
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
|
+
|
|
11715
11787
|
// ../core/dist/world/tmux-supervisor.js
|
|
11716
11788
|
function injectBindAll(start) {
|
|
11717
11789
|
let result = start;
|
|
@@ -11849,6 +11921,7 @@ var manager_exports = {};
|
|
|
11849
11921
|
__export(manager_exports, {
|
|
11850
11922
|
AuthPreflightError: () => AuthPreflightError,
|
|
11851
11923
|
BotIdentityError: () => BotIdentityError,
|
|
11924
|
+
ContainerOrphanError: () => ContainerOrphanError,
|
|
11852
11925
|
TaskDispatchError: () => TaskDispatchError,
|
|
11853
11926
|
WorkspaceNotFoundError: () => WorkspaceNotFoundError,
|
|
11854
11927
|
WorldManager: () => WorldManager,
|
|
@@ -11868,12 +11941,12 @@ __export(manager_exports, {
|
|
|
11868
11941
|
runManifestRuntime: () => runManifestRuntime
|
|
11869
11942
|
});
|
|
11870
11943
|
import * as crypto5 from "node:crypto";
|
|
11871
|
-
import { execSync as
|
|
11944
|
+
import { execSync as execSync6, spawnSync as spawnSync5 } from "node:child_process";
|
|
11872
11945
|
import * as fs23 from "node:fs";
|
|
11873
11946
|
import * as os13 from "node:os";
|
|
11874
11947
|
import * as path25 from "node:path";
|
|
11875
11948
|
import YAML3 from "yaml";
|
|
11876
|
-
function getTokenScopes(ghToken, _exec =
|
|
11949
|
+
function getTokenScopes(ghToken, _exec = execSync6) {
|
|
11877
11950
|
try {
|
|
11878
11951
|
const out = _exec("gh auth status 2>&1", {
|
|
11879
11952
|
encoding: "utf-8",
|
|
@@ -11890,13 +11963,13 @@ function getTokenScopes(ghToken, _exec = execSync5) {
|
|
|
11890
11963
|
}
|
|
11891
11964
|
}
|
|
11892
11965
|
async function setupContainerGit(containerName, repos, branch) {
|
|
11893
|
-
const dockerExec = (cmd) =>
|
|
11966
|
+
const dockerExec = (cmd) => execSync6(`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`, {
|
|
11894
11967
|
stdio: "pipe",
|
|
11895
11968
|
timeout: 6e4
|
|
11896
11969
|
}).toString();
|
|
11897
11970
|
let ghToken = "";
|
|
11898
11971
|
try {
|
|
11899
|
-
ghToken =
|
|
11972
|
+
ghToken = execSync6("gh auth token 2>/dev/null", { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
11900
11973
|
} catch {
|
|
11901
11974
|
}
|
|
11902
11975
|
const actorName = process.env.OLAM_BOT_NAME ?? "Claude Code (olam)";
|
|
@@ -11916,7 +11989,7 @@ async function setupContainerGit(containerName, repos, branch) {
|
|
|
11916
11989
|
continue;
|
|
11917
11990
|
const ownerRepo = ghMatch[1];
|
|
11918
11991
|
try {
|
|
11919
|
-
|
|
11992
|
+
execSync6(`gh api repos/${ownerRepo} --silent`, {
|
|
11920
11993
|
stdio: "pipe",
|
|
11921
11994
|
timeout: 5e3,
|
|
11922
11995
|
env: { ...process.env, GH_TOKEN: ghToken }
|
|
@@ -11964,7 +12037,7 @@ ${stderr.split("\n").slice(0, 3).join(" ")}`);
|
|
|
11964
12037
|
if (!olamUserPresent) {
|
|
11965
12038
|
const imageName = (() => {
|
|
11966
12039
|
try {
|
|
11967
|
-
return
|
|
12040
|
+
return execSync6(`docker inspect ${containerName} --format '{{.Config.Image}}'`, {
|
|
11968
12041
|
encoding: "utf8",
|
|
11969
12042
|
timeout: 5e3
|
|
11970
12043
|
}).trim() || "(unknown)";
|
|
@@ -12007,7 +12080,7 @@ ${stderr.split("\n").slice(0, 3).join(" ")}`);
|
|
|
12007
12080
|
function makeHostExecFn() {
|
|
12008
12081
|
return async (cmd) => {
|
|
12009
12082
|
try {
|
|
12010
|
-
const stdout =
|
|
12083
|
+
const stdout = execSync6(cmd, { encoding: "utf-8", timeout: 5e3 });
|
|
12011
12084
|
return { stdout, stderr: "", exitCode: 0 };
|
|
12012
12085
|
} catch {
|
|
12013
12086
|
return { stdout: "", stderr: "", exitCode: 1 };
|
|
@@ -12017,7 +12090,7 @@ function makeHostExecFn() {
|
|
|
12017
12090
|
function makeContainerExecFn(containerName) {
|
|
12018
12091
|
return async (cmd) => {
|
|
12019
12092
|
try {
|
|
12020
|
-
const result =
|
|
12093
|
+
const result = execSync6(`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`, { stdio: "pipe", timeout: 6e5 });
|
|
12021
12094
|
return { stdout: result.toString(), stderr: "", exitCode: 0 };
|
|
12022
12095
|
} catch (err) {
|
|
12023
12096
|
const execErr = err;
|
|
@@ -12031,7 +12104,7 @@ function makeContainerExecFn(containerName) {
|
|
|
12031
12104
|
}
|
|
12032
12105
|
function defaultDockerExec2() {
|
|
12033
12106
|
return (containerName, cmd) => {
|
|
12034
|
-
const result =
|
|
12107
|
+
const result = execSync6(
|
|
12035
12108
|
`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`,
|
|
12036
12109
|
// Phase E E5 raise: 10min was too tight on cold-boot for atlas-core's
|
|
12037
12110
|
// `rails db:create` chain (Rails 7 boot + initializer load + first
|
|
@@ -12211,7 +12284,7 @@ function buildManifestRuntime(worldId, repos) {
|
|
|
12211
12284
|
}
|
|
12212
12285
|
return { worldId, repos: runtimeRepos };
|
|
12213
12286
|
}
|
|
12214
|
-
function exposeWorldOverTailscale(appPortUrls, worldId, registry, _exec =
|
|
12287
|
+
function exposeWorldOverTailscale(appPortUrls, worldId, registry, _exec = execSync6) {
|
|
12215
12288
|
if (process.env["OLAM_TAILSCALE_SERVE"] !== "true")
|
|
12216
12289
|
return;
|
|
12217
12290
|
if (appPortUrls.length === 0)
|
|
@@ -12239,7 +12312,7 @@ function exposeWorldOverTailscale(appPortUrls, worldId, registry, _exec = execSy
|
|
|
12239
12312
|
registry.storeTailscalePaths(worldId, registeredPaths);
|
|
12240
12313
|
}
|
|
12241
12314
|
}
|
|
12242
|
-
function cleanupWorldTailscale(worldId, registry, _exec =
|
|
12315
|
+
function cleanupWorldTailscale(worldId, registry, _exec = execSync6) {
|
|
12243
12316
|
const paths = registry.loadTailscalePaths(worldId);
|
|
12244
12317
|
if (paths.length === 0)
|
|
12245
12318
|
return;
|
|
@@ -12258,7 +12331,7 @@ function cleanupWorldTailscale(worldId, registry, _exec = execSync5) {
|
|
|
12258
12331
|
}
|
|
12259
12332
|
}
|
|
12260
12333
|
}
|
|
12261
|
-
function resolveTailscaleBin(_exec =
|
|
12334
|
+
function resolveTailscaleBin(_exec = execSync6) {
|
|
12262
12335
|
const candidates2 = [
|
|
12263
12336
|
process.env["TAILSCALE_BIN"],
|
|
12264
12337
|
"/Applications/Tailscale.app/Contents/MacOS/Tailscale",
|
|
@@ -12657,6 +12730,8 @@ var init_manager = __esm({
|
|
|
12657
12730
|
init_runbook_resolver();
|
|
12658
12731
|
init_port_validator();
|
|
12659
12732
|
init_bootstrap_hooks();
|
|
12733
|
+
init_create_dedup();
|
|
12734
|
+
init_create_dedup();
|
|
12660
12735
|
init_tmux_supervisor();
|
|
12661
12736
|
BotIdentityError = class extends Error {
|
|
12662
12737
|
constructor(message) {
|
|
@@ -12691,19 +12766,38 @@ var init_manager = __esm({
|
|
|
12691
12766
|
dashboardManager;
|
|
12692
12767
|
pleriClient;
|
|
12693
12768
|
dockerExec;
|
|
12769
|
+
containerProbe;
|
|
12694
12770
|
manifestRuntimes = /* @__PURE__ */ new Map();
|
|
12695
|
-
constructor(config, provider, registry, dashboardManager, pleriClient, dockerExec) {
|
|
12771
|
+
constructor(config, provider, registry, dashboardManager, pleriClient, dockerExec, containerProbe) {
|
|
12696
12772
|
this.config = config;
|
|
12697
12773
|
this.provider = provider;
|
|
12698
12774
|
this.registry = registry;
|
|
12699
12775
|
this.dashboardManager = dashboardManager;
|
|
12700
12776
|
this.pleriClient = pleriClient;
|
|
12701
12777
|
this.dockerExec = dockerExec ?? defaultDockerExec2();
|
|
12778
|
+
this.containerProbe = containerProbe;
|
|
12702
12779
|
}
|
|
12703
12780
|
// -----------------------------------------------------------------------
|
|
12704
12781
|
// createWorld
|
|
12705
12782
|
// -----------------------------------------------------------------------
|
|
12706
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
|
+
}
|
|
12707
12801
|
if (!opts.noAuth) {
|
|
12708
12802
|
const preflight2 = await runAuthPreflight({ autoStart: true });
|
|
12709
12803
|
if (preflight2.verdict !== "ok") {
|
|
@@ -13387,7 +13481,7 @@ ${detail}`);
|
|
|
13387
13481
|
const escapedDir = `/home/olam/workspace/${repo.name.replace(/["$`\\]/g, "\\$&")}`;
|
|
13388
13482
|
for (const cmd of repo.setup_commands) {
|
|
13389
13483
|
try {
|
|
13390
|
-
|
|
13484
|
+
execSync6(`docker exec ${containerName} sh -c 'cd "${escapedDir}" && ${cmd.replace(/'/g, "'\\''")}'`, { stdio: "pipe", timeout: 6e5 });
|
|
13391
13485
|
} catch (err) {
|
|
13392
13486
|
const msg = err instanceof Error ? err.message : String(err);
|
|
13393
13487
|
console.warn(`[WorldManager] setup command failed for ${repo.name}: ${msg}`);
|
|
@@ -13408,11 +13502,11 @@ ${detail}`);
|
|
|
13408
13502
|
});
|
|
13409
13503
|
if (allPolicies.length > 0) {
|
|
13410
13504
|
try {
|
|
13411
|
-
|
|
13505
|
+
execSync6(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
|
|
13412
13506
|
for (const repo of repos) {
|
|
13413
13507
|
const policiesDir = path25.join(workspacePath, repo.name, ".olam", "policies");
|
|
13414
13508
|
if (fs23.existsSync(policiesDir)) {
|
|
13415
|
-
|
|
13509
|
+
execSync6(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
|
|
13416
13510
|
}
|
|
13417
13511
|
}
|
|
13418
13512
|
} catch (err) {
|
|
@@ -14900,10 +14994,10 @@ var init_state2 = __esm({
|
|
|
14900
14994
|
});
|
|
14901
14995
|
|
|
14902
14996
|
// ../core/dist/dashboard/tunnel.js
|
|
14903
|
-
import { spawn as spawn3, execSync as
|
|
14997
|
+
import { spawn as spawn3, execSync as execSync7 } from "node:child_process";
|
|
14904
14998
|
function isCloudflaredAvailable() {
|
|
14905
14999
|
try {
|
|
14906
|
-
|
|
15000
|
+
execSync7("which cloudflared", { stdio: "ignore" });
|
|
14907
15001
|
return true;
|
|
14908
15002
|
} catch {
|
|
14909
15003
|
return false;
|
|
@@ -16235,6 +16329,69 @@ var init_registry_allowlist = __esm({
|
|
|
16235
16329
|
}
|
|
16236
16330
|
});
|
|
16237
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
|
+
|
|
16238
16395
|
// src/spawn/home-override.ts
|
|
16239
16396
|
var home_override_exports = {};
|
|
16240
16397
|
__export(home_override_exports, {
|
|
@@ -18146,13 +18303,13 @@ var init_file_lock = __esm({
|
|
|
18146
18303
|
});
|
|
18147
18304
|
|
|
18148
18305
|
// ../core/dist/lib/min-version-filter.js
|
|
18149
|
-
import { existsSync as existsSync73, readFileSync as
|
|
18306
|
+
import { existsSync as existsSync73, readFileSync as readFileSync61 } from "node:fs";
|
|
18150
18307
|
function readOlamMinVersion(filepath) {
|
|
18151
18308
|
if (!existsSync73(filepath))
|
|
18152
18309
|
return void 0;
|
|
18153
18310
|
let text;
|
|
18154
18311
|
try {
|
|
18155
|
-
text =
|
|
18312
|
+
text = readFileSync61(filepath, "utf8");
|
|
18156
18313
|
} catch {
|
|
18157
18314
|
return void 0;
|
|
18158
18315
|
}
|
|
@@ -18800,7 +18957,7 @@ var init_meta_hook_injector = __esm({
|
|
|
18800
18957
|
|
|
18801
18958
|
// ../core/dist/lib/markdown-merger.js
|
|
18802
18959
|
import { createHash as createHash8 } from "node:crypto";
|
|
18803
|
-
import { readFileSync as
|
|
18960
|
+
import { readFileSync as readFileSync65, existsSync as existsSync76, statSync as statSync22 } from "node:fs";
|
|
18804
18961
|
function parseFrontmatter3(text) {
|
|
18805
18962
|
const match2 = FM_RE2.exec(text);
|
|
18806
18963
|
if (match2 === null)
|
|
@@ -18922,7 +19079,7 @@ function mergeMarkdown(upstreamText, overlayText, labelForError, upstreamPath, o
|
|
|
18922
19079
|
function sha256OfPath(p) {
|
|
18923
19080
|
if (!existsSync76(p) || !statSync22(p).isFile())
|
|
18924
19081
|
return "MISSING";
|
|
18925
|
-
return createHash8("sha256").update(
|
|
19082
|
+
return createHash8("sha256").update(readFileSync65(p)).digest("hex");
|
|
18926
19083
|
}
|
|
18927
19084
|
var FM_RE2, H2_RE;
|
|
18928
19085
|
var init_markdown_merger = __esm({
|
|
@@ -19174,7 +19331,7 @@ var init_prefix_deploy = __esm({
|
|
|
19174
19331
|
});
|
|
19175
19332
|
|
|
19176
19333
|
// ../core/dist/skill-sync/resolve-source-config.js
|
|
19177
|
-
import { readFileSync as
|
|
19334
|
+
import { readFileSync as readFileSync67, existsSync as existsSync77 } from "node:fs";
|
|
19178
19335
|
import { join as join76 } from "node:path";
|
|
19179
19336
|
import { parse as parseYaml6 } from "yaml";
|
|
19180
19337
|
function sourceConfigPath(clonePath) {
|
|
@@ -19186,7 +19343,7 @@ function readSourceConfig(clonePath, sourceId) {
|
|
|
19186
19343
|
return void 0;
|
|
19187
19344
|
let raw;
|
|
19188
19345
|
try {
|
|
19189
|
-
raw =
|
|
19346
|
+
raw = readFileSync67(path96, "utf-8");
|
|
19190
19347
|
} catch (err) {
|
|
19191
19348
|
emitMalformedWarning(sourceId, `read failed: ${errToMsg(err)}`);
|
|
19192
19349
|
return void 0;
|
|
@@ -23373,6 +23530,7 @@ var MCP_AUTH_CONTAINER = "olam-mcp-auth";
|
|
|
23373
23530
|
var MCP_AUTH_LOCAL_TAG = "olam-mcp-auth:local";
|
|
23374
23531
|
var MCP_AUTH_PUBLISHED_TAG = "ghcr.io/pleri/olam-mcp-auth:latest";
|
|
23375
23532
|
var MCP_AUTH_HEALTH_URL = `http://127.0.0.1:${MCP_AUTH_PORT}/health`;
|
|
23533
|
+
var SOCAT_IMAGE = "alpine/socat:latest";
|
|
23376
23534
|
var MCP_AUTH_HEALTH_TIMEOUT_MS = 6e4;
|
|
23377
23535
|
var McpAuthContainerController = class {
|
|
23378
23536
|
imageTag = MCP_AUTH_LOCAL_TAG;
|
|
@@ -23596,6 +23754,40 @@ async function servicesRestartKubernetes(name, deps = {}) {
|
|
|
23596
23754
|
printSuccess(`${deploymentName}: rollout restart triggered`);
|
|
23597
23755
|
return { exitCode: 0 };
|
|
23598
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
|
+
}
|
|
23599
23791
|
function dumpContainerLogs(container, tail = 40) {
|
|
23600
23792
|
try {
|
|
23601
23793
|
const result = spawnSync16("docker", ["logs", "--tail", String(tail), container], {
|
|
@@ -23620,6 +23812,21 @@ async function servicesUp() {
|
|
|
23620
23812
|
const mcpAuth = new McpAuthContainerController();
|
|
23621
23813
|
const kgService = new KgServiceContainerController();
|
|
23622
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
|
+
}
|
|
23623
23830
|
const authStatus = auth.status();
|
|
23624
23831
|
if (authStatus.state === "running") {
|
|
23625
23832
|
printSuccess(`olam-auth already running on :${authStatus.port}`);
|
|
@@ -24201,7 +24408,7 @@ function appendAuditEntry(entry, auditLogPath, writeFileSyncImpl) {
|
|
|
24201
24408
|
async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, peripheral) {
|
|
24202
24409
|
const auditLogPath = deps.auditLogPath ?? MANIFEST_REFRESH_AUDIT_LOG;
|
|
24203
24410
|
const readdirSync33 = deps.readdirSync ?? fs31.readdirSync;
|
|
24204
|
-
const
|
|
24411
|
+
const readFileSync96 = deps.readFileSync ?? fs31.readFileSync;
|
|
24205
24412
|
const writeFileSyncImpl = deps.writeFileSync ?? fs31.writeFileSync;
|
|
24206
24413
|
const existsSync113 = deps.existsSync ?? fs31.existsSync;
|
|
24207
24414
|
const now = deps.now ? deps.now() : /* @__PURE__ */ new Date();
|
|
@@ -24227,7 +24434,7 @@ async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, per
|
|
|
24227
24434
|
const filePath = path32.join(targetDir, file);
|
|
24228
24435
|
let content;
|
|
24229
24436
|
try {
|
|
24230
|
-
content =
|
|
24437
|
+
content = readFileSync96(filePath, "utf8");
|
|
24231
24438
|
} catch {
|
|
24232
24439
|
continue;
|
|
24233
24440
|
}
|
|
@@ -24478,11 +24685,11 @@ async function checkSecretPreCondition(context, deps) {
|
|
|
24478
24685
|
}
|
|
24479
24686
|
async function applyConfigMapSubstitution(context, manifestsDir, deps) {
|
|
24480
24687
|
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
24481
|
-
const
|
|
24688
|
+
const readFileSync96 = deps.readFileSyncImpl ?? fs32.readFileSync;
|
|
24482
24689
|
const configMapPath = path33.join(manifestsDir, "30-configmap.yaml");
|
|
24483
24690
|
let rawYaml;
|
|
24484
24691
|
try {
|
|
24485
|
-
rawYaml =
|
|
24692
|
+
rawYaml = readFileSync96(configMapPath, "utf8");
|
|
24486
24693
|
} catch (err) {
|
|
24487
24694
|
return `Failed to read ConfigMap at ${configMapPath}: ${err instanceof Error ? err.message : String(err)}`;
|
|
24488
24695
|
}
|
|
@@ -25034,6 +25241,223 @@ async function applyK8sAuthRefresh(pinnedContext, deps = {}) {
|
|
|
25034
25241
|
return 0;
|
|
25035
25242
|
}
|
|
25036
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
|
+
|
|
25037
25461
|
// src/commands/auth.ts
|
|
25038
25462
|
function openBrowser(url2) {
|
|
25039
25463
|
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
@@ -25068,36 +25492,6 @@ function registerAuth(program2) {
|
|
|
25068
25492
|
printWarning("`olam auth status` is deprecated. Use `olam services status` instead.");
|
|
25069
25493
|
servicesStatus();
|
|
25070
25494
|
});
|
|
25071
|
-
auth.command("list").description("List all stored credentials with state, usage, and rate-limit status").action(async () => {
|
|
25072
|
-
const client = new AuthClient();
|
|
25073
|
-
const status2 = await client.status();
|
|
25074
|
-
if (!status2.reachable) {
|
|
25075
|
-
printError("Auth container is not reachable. Run `olam auth up` first.");
|
|
25076
|
-
process.exitCode = 1;
|
|
25077
|
-
return;
|
|
25078
|
-
}
|
|
25079
|
-
printHeader(`Credentials (${status2.accounts.length})`);
|
|
25080
|
-
if (status2.accounts.length === 0) {
|
|
25081
|
-
console.log(` ${pc12.dim("No credentials \u2014 run: olam auth login --label primary")}`);
|
|
25082
|
-
return;
|
|
25083
|
-
}
|
|
25084
|
-
const stateColor = (s) => {
|
|
25085
|
-
if (s === "active") return pc12.green("active");
|
|
25086
|
-
if (s === "cooldown") return pc12.yellow("cooldown");
|
|
25087
|
-
if (s === "expired") return pc12.red("expired");
|
|
25088
|
-
if (s === "disabled") return pc12.dim("disabled");
|
|
25089
|
-
return pc12.dim(s ?? "unknown");
|
|
25090
|
-
};
|
|
25091
|
-
for (const a of status2.accounts) {
|
|
25092
|
-
const label = a.accountLabel ?? a.id;
|
|
25093
|
-
const reqs = a.usage?.requestCount5h ?? 0;
|
|
25094
|
-
const last429 = a.usage?.last429At ? `last429=${a.usage.last429At}` : "last429=never";
|
|
25095
|
-
const reset = a.rateLimitResetsAt ? `resets=${a.rateLimitResetsAt}` : "";
|
|
25096
|
-
console.log(
|
|
25097
|
-
` ${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)}`
|
|
25098
|
-
);
|
|
25099
|
-
}
|
|
25100
|
-
});
|
|
25101
25495
|
auth.command("disable").description("Take a credential out of rotation (manual cooldown)").argument("<label>", "Credential label or id").action(async (label) => {
|
|
25102
25496
|
const client = new AuthClient();
|
|
25103
25497
|
try {
|
|
@@ -25128,7 +25522,68 @@ function registerAuth(program2) {
|
|
|
25128
25522
|
process.exitCode = 1;
|
|
25129
25523
|
}
|
|
25130
25524
|
});
|
|
25131
|
-
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
|
+
}
|
|
25132
25587
|
const preflight2 = await runAuthPreflight({ autoStart: true });
|
|
25133
25588
|
if (preflight2.verdict !== "ok" && preflight2.verdict !== "no-accounts") {
|
|
25134
25589
|
printError(preflight2.message);
|
|
@@ -25230,6 +25685,297 @@ ${pc12.dim("Next: olam create --name my-world")}`);
|
|
|
25230
25685
|
}
|
|
25231
25686
|
}
|
|
25232
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
|
+
});
|
|
25233
25979
|
registerAuthUpgrade(auth);
|
|
25234
25980
|
}
|
|
25235
25981
|
|
|
@@ -25242,7 +25988,7 @@ import ora5 from "ora";
|
|
|
25242
25988
|
import pc13 from "picocolors";
|
|
25243
25989
|
|
|
25244
25990
|
// ../core/dist/world/devbox-freshness.js
|
|
25245
|
-
import { execSync as
|
|
25991
|
+
import { execSync as execSync8 } from "node:child_process";
|
|
25246
25992
|
import { existsSync as existsSync36, statSync as statSync9 } from "node:fs";
|
|
25247
25993
|
import { join as join43 } from "node:path";
|
|
25248
25994
|
var DEFAULT_DEVBOX_IMAGE = "olam-devbox:base";
|
|
@@ -25326,7 +26072,7 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
|
|
|
25326
26072
|
}
|
|
25327
26073
|
function defaultDockerInspect(image) {
|
|
25328
26074
|
try {
|
|
25329
|
-
const out =
|
|
26075
|
+
const out = execSync8(`docker inspect ${image} --format '{{.Created}}'`, { encoding: "utf-8", timeout: 5e3, stdio: ["ignore", "pipe", "pipe"] }).trim();
|
|
25330
26076
|
return out.length > 0 ? out : null;
|
|
25331
26077
|
} catch {
|
|
25332
26078
|
return null;
|
|
@@ -25708,7 +26454,7 @@ async function readHostCpTokenForCreate() {
|
|
|
25708
26454
|
}
|
|
25709
26455
|
}
|
|
25710
26456
|
function registerCreate(program2) {
|
|
25711
|
-
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(
|
|
25712
26458
|
"--allow-bootstrap-failure",
|
|
25713
26459
|
"Treat bootstrap step failures as warnings instead of destroying the world (dogfood escape hatch for cross-repo seed coupling)"
|
|
25714
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(
|
|
@@ -25753,6 +26499,32 @@ function registerCreate(program2) {
|
|
|
25753
26499
|
let resolvedWorkspace = opts.workspace;
|
|
25754
26500
|
let resolvedRepos = opts.repos;
|
|
25755
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
|
+
}
|
|
25756
26528
|
if (opts.fromPrompt) {
|
|
25757
26529
|
if (opts.task) {
|
|
25758
26530
|
printError("--from-prompt and --task are mutually exclusive (the prompt IS the task).");
|
|
@@ -26138,6 +26910,8 @@ ${pc13.cyan("Host CP UI:")} ${worldUrl}`);
|
|
|
26138
26910
|
if (err instanceof AuthPreflightError) {
|
|
26139
26911
|
printError(err.message);
|
|
26140
26912
|
if (err.remedy) console.log(` ${pc13.dim(err.remedy)}`);
|
|
26913
|
+
} else if (err instanceof ContainerOrphanError) {
|
|
26914
|
+
printError(err.message);
|
|
26141
26915
|
} else {
|
|
26142
26916
|
printError(err instanceof Error ? err.message : String(err));
|
|
26143
26917
|
}
|
|
@@ -27299,7 +28073,7 @@ async function runImplode(opts) {
|
|
|
27299
28073
|
// src/commands/enter.ts
|
|
27300
28074
|
init_context();
|
|
27301
28075
|
init_output();
|
|
27302
|
-
import { execSync as
|
|
28076
|
+
import { execSync as execSync9 } from "node:child_process";
|
|
27303
28077
|
import pc18 from "picocolors";
|
|
27304
28078
|
var SAFE_IDENT3 = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
27305
28079
|
function buildStartClaudeCommands(containerName, sessionName, task) {
|
|
@@ -27396,7 +28170,7 @@ function registerEnter(program2) {
|
|
|
27396
28170
|
if (opts.exec) {
|
|
27397
28171
|
for (const step2 of steps) {
|
|
27398
28172
|
try {
|
|
27399
|
-
|
|
28173
|
+
execSync9(step2.command, {
|
|
27400
28174
|
stdio: step2.stdin !== void 0 ? ["pipe", "inherit", "inherit"] : "inherit",
|
|
27401
28175
|
input: step2.stdin
|
|
27402
28176
|
});
|
|
@@ -27436,7 +28210,7 @@ function registerEnter(program2) {
|
|
|
27436
28210
|
}
|
|
27437
28211
|
if (opts.exec) {
|
|
27438
28212
|
try {
|
|
27439
|
-
|
|
28213
|
+
execSync9(result.command, { stdio: "inherit" });
|
|
27440
28214
|
} catch (err) {
|
|
27441
28215
|
printError(
|
|
27442
28216
|
err instanceof Error ? err.message : `Command failed: ${result.command}`
|
|
@@ -28211,7 +28985,7 @@ function registerLanes(program2) {
|
|
|
28211
28985
|
|
|
28212
28986
|
// src/commands/policy-check.ts
|
|
28213
28987
|
init_loader2();
|
|
28214
|
-
import { execSync as
|
|
28988
|
+
import { execSync as execSync10 } from "node:child_process";
|
|
28215
28989
|
import pc20 from "picocolors";
|
|
28216
28990
|
|
|
28217
28991
|
// ../../node_modules/balanced-match/dist/esm/index.js
|
|
@@ -30049,7 +30823,7 @@ function enforcePolicies(policies, diff) {
|
|
|
30049
30823
|
function getDiff(base, cwd) {
|
|
30050
30824
|
for (const range2 of [`${base}...HEAD`, `${base}..HEAD`]) {
|
|
30051
30825
|
try {
|
|
30052
|
-
return
|
|
30826
|
+
return execSync10(`git diff --name-only ${range2}`, {
|
|
30053
30827
|
cwd,
|
|
30054
30828
|
encoding: "utf8",
|
|
30055
30829
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -30058,7 +30832,7 @@ function getDiff(base, cwd) {
|
|
|
30058
30832
|
}
|
|
30059
30833
|
}
|
|
30060
30834
|
try {
|
|
30061
|
-
return
|
|
30835
|
+
return execSync10("git diff --name-only HEAD", {
|
|
30062
30836
|
cwd,
|
|
30063
30837
|
encoding: "utf8",
|
|
30064
30838
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -30096,7 +30870,7 @@ function registerPolicyCheck(program2) {
|
|
|
30096
30870
|
}
|
|
30097
30871
|
|
|
30098
30872
|
// src/commands/worldspec/compile.ts
|
|
30099
|
-
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";
|
|
30100
30874
|
import { resolve as resolvePath } from "node:path";
|
|
30101
30875
|
import YAML5 from "yaml";
|
|
30102
30876
|
|
|
@@ -30905,7 +31679,7 @@ function registerWorldspecCompile(parent) {
|
|
|
30905
31679
|
}
|
|
30906
31680
|
let yaml;
|
|
30907
31681
|
try {
|
|
30908
|
-
yaml = YAML5.parse(
|
|
31682
|
+
yaml = YAML5.parse(readFileSync34(abs, "utf8"));
|
|
30909
31683
|
} catch (err) {
|
|
30910
31684
|
printError(
|
|
30911
31685
|
`${p}: YAML parse error: ${err.message}`
|
|
@@ -30990,8 +31764,8 @@ function getPkgVersion() {
|
|
|
30990
31764
|
// src/commands/worldspec/init.ts
|
|
30991
31765
|
init_exit_codes();
|
|
30992
31766
|
init_output();
|
|
30993
|
-
import { existsSync as existsSync45, mkdirSync as mkdirSync29, readFileSync as
|
|
30994
|
-
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";
|
|
30995
31769
|
import { basename as basename3, resolve as resolvePath2 } from "node:path";
|
|
30996
31770
|
function registerWorldspecInit(parent) {
|
|
30997
31771
|
parent.command("init").description(
|
|
@@ -31049,7 +31823,7 @@ function detectProjectShape(root, useAdbYaml) {
|
|
|
31049
31823
|
const rubyVersionPath = resolvePath2(root, ".ruby-version");
|
|
31050
31824
|
if (existsSync45(rubyVersionPath)) {
|
|
31051
31825
|
try {
|
|
31052
|
-
const raw =
|
|
31826
|
+
const raw = readFileSync35(rubyVersionPath, "utf8").trim();
|
|
31053
31827
|
const match2 = raw.match(/(\d+\.\d+\.\d+)/);
|
|
31054
31828
|
if (match2) rubyVersion = match2[1] ?? null;
|
|
31055
31829
|
} catch {
|
|
@@ -31066,7 +31840,7 @@ function detectProjectShape(root, useAdbYaml) {
|
|
|
31066
31840
|
}
|
|
31067
31841
|
function getRepoName2(root) {
|
|
31068
31842
|
try {
|
|
31069
|
-
const url2 =
|
|
31843
|
+
const url2 = execSync11("git remote get-url origin", {
|
|
31070
31844
|
cwd: root,
|
|
31071
31845
|
encoding: "utf-8",
|
|
31072
31846
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -32459,7 +33233,7 @@ function registerWorldspecSchema(parent) {
|
|
|
32459
33233
|
}
|
|
32460
33234
|
|
|
32461
33235
|
// src/commands/worldspec/validate.ts
|
|
32462
|
-
import { existsSync as existsSync46, readFileSync as
|
|
33236
|
+
import { existsSync as existsSync46, readFileSync as readFileSync36 } from "node:fs";
|
|
32463
33237
|
import { resolve as resolvePath4 } from "node:path";
|
|
32464
33238
|
init_exit_codes();
|
|
32465
33239
|
init_output();
|
|
@@ -32482,7 +33256,7 @@ function registerWorldspecValidate(parent) {
|
|
|
32482
33256
|
}
|
|
32483
33257
|
let yamlSource;
|
|
32484
33258
|
try {
|
|
32485
|
-
yamlSource =
|
|
33259
|
+
yamlSource = readFileSync36(absPath, "utf8");
|
|
32486
33260
|
} catch (err) {
|
|
32487
33261
|
printError(
|
|
32488
33262
|
`failed to read ${absPath}: ${err.message}`
|
|
@@ -34401,7 +35175,7 @@ init_snapshot();
|
|
|
34401
35175
|
init_output();
|
|
34402
35176
|
import * as fs45 from "node:fs";
|
|
34403
35177
|
import * as path48 from "node:path";
|
|
34404
|
-
import { execSync as
|
|
35178
|
+
import { execSync as execSync12 } from "node:child_process";
|
|
34405
35179
|
import pc24 from "picocolors";
|
|
34406
35180
|
|
|
34407
35181
|
// src/commands/world.ts
|
|
@@ -34537,7 +35311,7 @@ async function captureGems(worldId, workspacePath, repo) {
|
|
|
34537
35311
|
const containerName = `olam-${worldId}-devbox`;
|
|
34538
35312
|
let bundlePath;
|
|
34539
35313
|
try {
|
|
34540
|
-
bundlePath =
|
|
35314
|
+
bundlePath = execSync12(
|
|
34541
35315
|
`docker exec ${containerName} sh -c 'bundle config get path 2>/dev/null || echo ~/.bundle'`,
|
|
34542
35316
|
{ encoding: "utf-8", timeout: 1e4 }
|
|
34543
35317
|
).trim();
|
|
@@ -34547,13 +35321,13 @@ async function captureGems(worldId, workspacePath, repo) {
|
|
|
34547
35321
|
}
|
|
34548
35322
|
try {
|
|
34549
35323
|
const tmpTar = `/tmp/olam-snap-gems-${repo}-${fingerprint}.tar.gz`;
|
|
34550
|
-
|
|
35324
|
+
execSync12(
|
|
34551
35325
|
`docker exec ${containerName} sh -c 'mkdir -p "$(dirname ${tmpTar})" && tar -czf ${tmpTar}.tmp -C ${bundlePath} . && mv ${tmpTar}.tmp ${tmpTar}'`,
|
|
34552
35326
|
{ stdio: "pipe", timeout: 12e4 }
|
|
34553
35327
|
);
|
|
34554
35328
|
fs45.mkdirSync(path48.dirname(tarPath), { recursive: true });
|
|
34555
|
-
|
|
34556
|
-
|
|
35329
|
+
execSync12(`docker cp ${containerName}:${tmpTar} "${tarPath}"`, { stdio: "pipe", timeout: 12e4 });
|
|
35330
|
+
execSync12(`docker exec ${containerName} rm -f ${tmpTar}`, { stdio: "pipe" });
|
|
34557
35331
|
const stat = fs45.statSync(tarPath);
|
|
34558
35332
|
const manifest = {
|
|
34559
35333
|
kind: "gems",
|
|
@@ -34609,18 +35383,18 @@ async function capturePg(worldId, workspacePath, repoNames) {
|
|
|
34609
35383
|
const containerName = `olam-${worldId}-postgres`;
|
|
34610
35384
|
const volumeName2 = `olam-${worldId}-postgres-data`;
|
|
34611
35385
|
try {
|
|
34612
|
-
|
|
35386
|
+
execSync12(`docker inspect ${containerName}`, { stdio: "pipe", timeout: 5e3 });
|
|
34613
35387
|
} catch {
|
|
34614
35388
|
return { ok: false, tarPath, msg: "postgres container not found; world may not use postgres" };
|
|
34615
35389
|
}
|
|
34616
35390
|
try {
|
|
34617
|
-
|
|
35391
|
+
execSync12(`docker stop ${containerName}`, { stdio: "pipe", timeout: 3e4 });
|
|
34618
35392
|
fs45.mkdirSync(path48.dirname(tarPath), { recursive: true });
|
|
34619
|
-
|
|
35393
|
+
execSync12(
|
|
34620
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)}'`,
|
|
34621
35395
|
{ stdio: "pipe", timeout: 18e4 }
|
|
34622
35396
|
);
|
|
34623
|
-
|
|
35397
|
+
execSync12(`docker start ${containerName}`, { stdio: "pipe", timeout: 3e4 });
|
|
34624
35398
|
const stat = fs45.statSync(tarPath);
|
|
34625
35399
|
const manifest = {
|
|
34626
35400
|
kind: "pg",
|
|
@@ -34634,7 +35408,7 @@ async function capturePg(worldId, workspacePath, repoNames) {
|
|
|
34634
35408
|
return { ok: true, tarPath };
|
|
34635
35409
|
} catch (err) {
|
|
34636
35410
|
try {
|
|
34637
|
-
|
|
35411
|
+
execSync12(`docker start ${containerName}`, { stdio: "pipe", timeout: 1e4 });
|
|
34638
35412
|
} catch {
|
|
34639
35413
|
}
|
|
34640
35414
|
return { ok: false, tarPath, msg: `pg capture failed: ${String(err)}` };
|
|
@@ -35065,7 +35839,7 @@ function registerRestart(program2) {
|
|
|
35065
35839
|
import * as fs48 from "node:fs";
|
|
35066
35840
|
import * as os26 from "node:os";
|
|
35067
35841
|
import * as path51 from "node:path";
|
|
35068
|
-
import { execFileSync as execFileSync13, execSync as
|
|
35842
|
+
import { execFileSync as execFileSync13, execSync as execSync13 } from "node:child_process";
|
|
35069
35843
|
import pc25 from "picocolors";
|
|
35070
35844
|
|
|
35071
35845
|
// ../core/dist/diagnose/secret-stripper.js
|
|
@@ -35105,7 +35879,7 @@ var CACHE_DIR = path51.join(os26.homedir(), ".olam", "cache");
|
|
|
35105
35879
|
var LOG_TAIL_LINES = 200;
|
|
35106
35880
|
function safeExec(cmd) {
|
|
35107
35881
|
try {
|
|
35108
|
-
return
|
|
35882
|
+
return execSync13(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
35109
35883
|
} catch {
|
|
35110
35884
|
return "";
|
|
35111
35885
|
}
|
|
@@ -35231,7 +36005,7 @@ init_health_probes();
|
|
|
35231
36005
|
|
|
35232
36006
|
// src/lib/bundle-freshness.ts
|
|
35233
36007
|
import { createHash as createHash4 } from "node:crypto";
|
|
35234
|
-
import { existsSync as existsSync56, readFileSync as
|
|
36008
|
+
import { existsSync as existsSync56, readFileSync as readFileSync43, statSync as statSync17 } from "node:fs";
|
|
35235
36009
|
import { join as join58, resolve as resolve16 } from "node:path";
|
|
35236
36010
|
var BUNDLE_FILES = [
|
|
35237
36011
|
"driver-runner.js",
|
|
@@ -35276,7 +36050,7 @@ async function probeBundleFreshness(deps = {}) {
|
|
|
35276
36050
|
for (const f of BUNDLE_FILES) {
|
|
35277
36051
|
const p = join58(hostDistDir, f);
|
|
35278
36052
|
if (!existsSync56(p)) continue;
|
|
35279
|
-
const buf =
|
|
36053
|
+
const buf = readFileSync43(p);
|
|
35280
36054
|
const sha = createHash4("sha256").update(buf).digest("hex");
|
|
35281
36055
|
const mtimeMs = statSync17(p).mtimeMs;
|
|
35282
36056
|
hostShas.set(f, { sha, mtimeMs });
|
|
@@ -36185,7 +36959,7 @@ function registerSubstrate(program2) {
|
|
|
36185
36959
|
}
|
|
36186
36960
|
|
|
36187
36961
|
// ../cli-plugin-tasks/dist/client.js
|
|
36188
|
-
import { readFileSync as
|
|
36962
|
+
import { readFileSync as readFileSync47 } from "node:fs";
|
|
36189
36963
|
import { homedir as homedir31 } from "node:os";
|
|
36190
36964
|
import { join as join61 } from "node:path";
|
|
36191
36965
|
var TasksClient = class {
|
|
@@ -36197,7 +36971,7 @@ var TasksClient = class {
|
|
|
36197
36971
|
this.baseUrl = (opts.hostCpUrl ?? process.env.OLAM_HOST_CP_URL ?? "http://localhost:19000").replace(/\/$/, "");
|
|
36198
36972
|
const tokenPath2 = opts.tokenPath ?? join61(homedir31(), ".olam", "host-cp.token");
|
|
36199
36973
|
try {
|
|
36200
|
-
this.token =
|
|
36974
|
+
this.token = readFileSync47(tokenPath2, "utf8").trim();
|
|
36201
36975
|
} catch (e) {
|
|
36202
36976
|
throw new Error(`cli-plugin-tasks: cannot read host-cp token at ${tokenPath2} (${e instanceof Error ? e.message : "unknown"}). Bootstrap host-cp first.`);
|
|
36203
36977
|
}
|
|
@@ -36224,7 +36998,7 @@ var TasksClient = class {
|
|
|
36224
36998
|
};
|
|
36225
36999
|
|
|
36226
37000
|
// ../cli-plugin-tasks/dist/tracker-parser.js
|
|
36227
|
-
import { readFileSync as
|
|
37001
|
+
import { readFileSync as readFileSync48 } from "node:fs";
|
|
36228
37002
|
import { createHash as createHash6 } from "node:crypto";
|
|
36229
37003
|
function contentHash(parts) {
|
|
36230
37004
|
const normalized = parts.map((p) => (p ?? "").trim()).join("|");
|
|
@@ -36258,7 +37032,7 @@ function parseFrontmatter2(raw) {
|
|
|
36258
37032
|
return { frontmatter: fm, body };
|
|
36259
37033
|
}
|
|
36260
37034
|
function parseTracker(path96) {
|
|
36261
|
-
const raw =
|
|
37035
|
+
const raw = readFileSync48(path96, "utf8");
|
|
36262
37036
|
const { frontmatter, body } = parseFrontmatter2(raw);
|
|
36263
37037
|
const lines = body.split("\n");
|
|
36264
37038
|
const tasks = [];
|
|
@@ -36651,7 +37425,7 @@ function registerCompletion(program2) {
|
|
|
36651
37425
|
init_cli_version();
|
|
36652
37426
|
init_health_probes();
|
|
36653
37427
|
import { spawn as spawn7, spawnSync as spawnSync27 } from "node:child_process";
|
|
36654
|
-
import { existsSync as existsSync85, readFileSync as
|
|
37428
|
+
import { existsSync as existsSync85, readFileSync as readFileSync71 } from "node:fs";
|
|
36655
37429
|
import { homedir as homedir45 } from "node:os";
|
|
36656
37430
|
import path77 from "node:path";
|
|
36657
37431
|
import { createInterface as createInterface3 } from "node:readline";
|
|
@@ -36718,14 +37492,14 @@ function discoverOfferableContexts(deps = {}) {
|
|
|
36718
37492
|
}
|
|
36719
37493
|
|
|
36720
37494
|
// src/lib/shell-rc.ts
|
|
36721
|
-
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";
|
|
36722
37496
|
import path54 from "node:path";
|
|
36723
37497
|
function appendIdempotent(opts) {
|
|
36724
37498
|
const { rcPath, marker, contentLine, clock = () => /* @__PURE__ */ new Date() } = opts;
|
|
36725
37499
|
if (!existsSync60(rcPath)) {
|
|
36726
37500
|
return { status: "no-rc-file", backupPath: null };
|
|
36727
37501
|
}
|
|
36728
|
-
const content =
|
|
37502
|
+
const content = readFileSync49(rcPath, "utf-8");
|
|
36729
37503
|
if (content.includes(marker)) {
|
|
36730
37504
|
return { status: "already-present", backupPath: null };
|
|
36731
37505
|
}
|
|
@@ -37098,7 +37872,7 @@ function resolveSubstrate(opts, deps) {
|
|
|
37098
37872
|
const configPath = deps.configPath ?? OLAM_CONFIG_PATH;
|
|
37099
37873
|
if (existsSync85(configPath)) {
|
|
37100
37874
|
try {
|
|
37101
|
-
const raw =
|
|
37875
|
+
const raw = readFileSync71(configPath, "utf8");
|
|
37102
37876
|
const parsed = JSON.parse(raw);
|
|
37103
37877
|
const host = parsed.host;
|
|
37104
37878
|
if (host?.substrate === "kubernetes") return "kubernetes";
|
|
@@ -37778,11 +38552,11 @@ function registerSetupMetrics(program2) {
|
|
|
37778
38552
|
|
|
37779
38553
|
// ../core/dist/setup/linux-gate.js
|
|
37780
38554
|
init_trust_audit_log();
|
|
37781
|
-
import { execSync as
|
|
38555
|
+
import { execSync as execSync14 } from "node:child_process";
|
|
37782
38556
|
var GH_LABEL = "linux-platform-request";
|
|
37783
38557
|
var LINUX_INVOCATION_THRESHOLD = 3;
|
|
37784
38558
|
function defaultExecGhIssueList(label) {
|
|
37785
|
-
return
|
|
38559
|
+
return execSync14(`gh issue list --label ${label} --json number,title --state all`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
37786
38560
|
}
|
|
37787
38561
|
function countLinuxInvocations(readLog) {
|
|
37788
38562
|
const { entries } = readLog();
|
|
@@ -37857,7 +38631,7 @@ function registerSetupLinuxGate(program2) {
|
|
|
37857
38631
|
import * as fs78 from "node:fs";
|
|
37858
38632
|
import * as os42 from "node:os";
|
|
37859
38633
|
import * as path80 from "node:path";
|
|
37860
|
-
import { execSync as
|
|
38634
|
+
import { execSync as execSync15 } from "node:child_process";
|
|
37861
38635
|
import pc28 from "picocolors";
|
|
37862
38636
|
|
|
37863
38637
|
// src/lib/symlink-reconcile.ts
|
|
@@ -37925,7 +38699,7 @@ var LOG_DIR2 = path80.join(os42.homedir(), ".olam", "log");
|
|
|
37925
38699
|
var LAST_STABLE_FILE = path80.join(CACHE_DIR2, "last-stable.txt");
|
|
37926
38700
|
function defaultExec(cmd) {
|
|
37927
38701
|
try {
|
|
37928
|
-
const stdout =
|
|
38702
|
+
const stdout = execSync15(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
37929
38703
|
return { exitCode: 0, stdout, stderr: "" };
|
|
37930
38704
|
} catch (err) {
|
|
37931
38705
|
const e = err;
|
|
@@ -38450,7 +39224,7 @@ import * as readline2 from "node:readline";
|
|
|
38450
39224
|
import pc32 from "picocolors";
|
|
38451
39225
|
|
|
38452
39226
|
// src/commands/flywheel/install-shims.ts
|
|
38453
|
-
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";
|
|
38454
39228
|
import { homedir as homedir48 } from "node:os";
|
|
38455
39229
|
import { dirname as dirname48, join as join87 } from "node:path";
|
|
38456
39230
|
|
|
@@ -38554,7 +39328,7 @@ function installOne(spec, targetDir, opts) {
|
|
|
38554
39328
|
}
|
|
38555
39329
|
return { basename: spec.basename, action: "written", targetPath };
|
|
38556
39330
|
}
|
|
38557
|
-
const existing =
|
|
39331
|
+
const existing = readFileSync75(targetPath, "utf8");
|
|
38558
39332
|
if (existing === newContent) {
|
|
38559
39333
|
return { basename: spec.basename, action: "unchanged", targetPath };
|
|
38560
39334
|
}
|
|
@@ -39214,7 +39988,7 @@ import {
|
|
|
39214
39988
|
lstatSync as lstatSync8,
|
|
39215
39989
|
mkdirSync as mkdirSync54,
|
|
39216
39990
|
readdirSync as readdirSync27,
|
|
39217
|
-
readFileSync as
|
|
39991
|
+
readFileSync as readFileSync76,
|
|
39218
39992
|
readlinkSync as readlinkSync4,
|
|
39219
39993
|
rmSync as rmSync9,
|
|
39220
39994
|
statSync as statSync27,
|
|
@@ -39321,8 +40095,8 @@ function postMergeSanitize(mergedText, label) {
|
|
|
39321
40095
|
return { ok: false, reason: `[post-merge-sanitize] ${label} merged output failed sanitizer: ${result.reason}` };
|
|
39322
40096
|
}
|
|
39323
40097
|
function mergeOne(upstreamPath, overlayPath, destPath2, label, dryRun, messages) {
|
|
39324
|
-
const upstreamText =
|
|
39325
|
-
const overlayText =
|
|
40098
|
+
const upstreamText = readFileSync76(upstreamPath, "utf8");
|
|
40099
|
+
const overlayText = readFileSync76(overlayPath, "utf8");
|
|
39326
40100
|
const result = mergeMarkdown(upstreamText, overlayText, label, upstreamPath, overlayPath);
|
|
39327
40101
|
if ("error" in result) {
|
|
39328
40102
|
messages.push(`ERROR ${result.error.reason}`);
|
|
@@ -39342,7 +40116,7 @@ function mergeOne(upstreamPath, overlayPath, destPath2, label, dryRun, messages)
|
|
|
39342
40116
|
}
|
|
39343
40117
|
function isNewAgentOverlay(overlayPath) {
|
|
39344
40118
|
try {
|
|
39345
|
-
const text =
|
|
40119
|
+
const text = readFileSync76(overlayPath, "utf8");
|
|
39346
40120
|
const { fm } = parseFrontmatter3(text);
|
|
39347
40121
|
return fm["overlay-intent"] === "new-agent";
|
|
39348
40122
|
} catch {
|
|
@@ -42120,7 +42894,7 @@ function registerMcp(program2) {
|
|
|
42120
42894
|
init_output();
|
|
42121
42895
|
|
|
42122
42896
|
// src/lib/memory-host-process-migration.ts
|
|
42123
|
-
import { existsSync as existsSync101, readFileSync as
|
|
42897
|
+
import { existsSync as existsSync101, readFileSync as readFileSync84, unlinkSync as unlinkSync23 } from "node:fs";
|
|
42124
42898
|
import { spawnSync as spawnSync30 } from "node:child_process";
|
|
42125
42899
|
|
|
42126
42900
|
// src/commands/memory/_paths.ts
|
|
@@ -42189,7 +42963,7 @@ function migrateFromHostProcess(opts = {}) {
|
|
|
42189
42963
|
}
|
|
42190
42964
|
function readPidFromFile(pidPath2) {
|
|
42191
42965
|
try {
|
|
42192
|
-
const raw =
|
|
42966
|
+
const raw = readFileSync84(pidPath2, "utf8").trim();
|
|
42193
42967
|
const pid = parseInt(raw, 10);
|
|
42194
42968
|
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
42195
42969
|
return pid;
|
|
@@ -42622,7 +43396,7 @@ function registerMemoryUninstall(cmd) {
|
|
|
42622
43396
|
// src/commands/memory/mode.ts
|
|
42623
43397
|
init_schema2();
|
|
42624
43398
|
init_output();
|
|
42625
|
-
import { existsSync as existsSync104, readFileSync as
|
|
43399
|
+
import { existsSync as existsSync104, readFileSync as readFileSync85, writeFileSync as writeFileSync51 } from "node:fs";
|
|
42626
43400
|
import { join as join96 } from "node:path";
|
|
42627
43401
|
import * as readline7 from "node:readline/promises";
|
|
42628
43402
|
import { parse as parseYaml8, stringify as stringifyYaml6 } from "yaml";
|
|
@@ -42637,7 +43411,7 @@ function locateConfig(cwd) {
|
|
|
42637
43411
|
return { absPath };
|
|
42638
43412
|
}
|
|
42639
43413
|
function readConfigYaml(absPath) {
|
|
42640
|
-
const raw =
|
|
43414
|
+
const raw = readFileSync85(absPath, "utf-8");
|
|
42641
43415
|
const parsed = parseYaml8(raw) ?? {};
|
|
42642
43416
|
if (typeof parsed !== "object" || parsed === null) {
|
|
42643
43417
|
throw new Error(`${absPath} is not a YAML object`);
|
|
@@ -43124,7 +43898,7 @@ function registerMemoryStats(cmd) {
|
|
|
43124
43898
|
}
|
|
43125
43899
|
|
|
43126
43900
|
// src/commands/memory/install-hooks.ts
|
|
43127
|
-
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";
|
|
43128
43902
|
import { homedir as homedir54 } from "node:os";
|
|
43129
43903
|
import { dirname as dirname56, join as join98, resolve as resolve25 } from "node:path";
|
|
43130
43904
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
@@ -43147,7 +43921,7 @@ function installOne2(basename16, sourceDir, targetDir, opts) {
|
|
|
43147
43921
|
if (!existsSync106(sourcePath)) {
|
|
43148
43922
|
throw new Error(`canonical hook source missing at ${sourcePath} \u2014 olam install corrupt or sourceDir is wrong`);
|
|
43149
43923
|
}
|
|
43150
|
-
const newContent =
|
|
43924
|
+
const newContent = readFileSync86(sourcePath, "utf8");
|
|
43151
43925
|
if (!existsSync106(targetPath)) {
|
|
43152
43926
|
if (opts.dryRun !== true) {
|
|
43153
43927
|
mkdirSync60(dirname56(targetPath), { recursive: true });
|
|
@@ -43155,7 +43929,7 @@ function installOne2(basename16, sourceDir, targetDir, opts) {
|
|
|
43155
43929
|
}
|
|
43156
43930
|
return { basename: basename16, action: "written", targetPath };
|
|
43157
43931
|
}
|
|
43158
|
-
const existing =
|
|
43932
|
+
const existing = readFileSync86(targetPath, "utf8");
|
|
43159
43933
|
if (existing === newContent) {
|
|
43160
43934
|
return { basename: basename16, action: "unchanged", targetPath };
|
|
43161
43935
|
}
|
|
@@ -44633,7 +45407,7 @@ function registerFlywheelK5Score(parent) {
|
|
|
44633
45407
|
}
|
|
44634
45408
|
|
|
44635
45409
|
// src/commands/flywheel/k5-validate.ts
|
|
44636
|
-
import { readFileSync as
|
|
45410
|
+
import { readFileSync as readFileSync90, statSync as statSync30 } from "node:fs";
|
|
44637
45411
|
import { parse as parseYAML } from "yaml";
|
|
44638
45412
|
var K5_DIMS = ["direction", "approach", "open_questions", "constraints", "reuse"];
|
|
44639
45413
|
var MAX_PLAN_BYTES = 1048576;
|
|
@@ -44703,7 +45477,7 @@ function validatePlan(path96) {
|
|
|
44703
45477
|
}
|
|
44704
45478
|
let text;
|
|
44705
45479
|
try {
|
|
44706
|
-
text =
|
|
45480
|
+
text = readFileSync90(path96, "utf8");
|
|
44707
45481
|
} catch (err) {
|
|
44708
45482
|
return { ok: false, message: `FAIL cannot read ${path96}: ${err instanceof Error ? err.message : "unknown"}` };
|
|
44709
45483
|
}
|
|
@@ -44785,7 +45559,7 @@ function registerFlywheelK5Validate(parent) {
|
|
|
44785
45559
|
}
|
|
44786
45560
|
|
|
44787
45561
|
// src/commands/flywheel/k10-measure.ts
|
|
44788
|
-
import { readFileSync as
|
|
45562
|
+
import { readFileSync as readFileSync91 } from "node:fs";
|
|
44789
45563
|
|
|
44790
45564
|
// ../core/dist/lib/k10-budget.js
|
|
44791
45565
|
var K10_TOKEN_CAP = 5500;
|
|
@@ -44842,7 +45616,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
44842
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) => {
|
|
44843
45617
|
let upstreamText;
|
|
44844
45618
|
try {
|
|
44845
|
-
upstreamText =
|
|
45619
|
+
upstreamText = readFileSync91(opts.upstream, "utf8");
|
|
44846
45620
|
} catch (err) {
|
|
44847
45621
|
process.stderr.write(
|
|
44848
45622
|
`[k10-measure-error] cannot read upstream ${opts.upstream}: ${err instanceof Error ? err.message : "unknown"}
|
|
@@ -44854,7 +45628,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
44854
45628
|
let overlayTokens = null;
|
|
44855
45629
|
if (opts.overlay !== void 0) {
|
|
44856
45630
|
try {
|
|
44857
|
-
const overlayText =
|
|
45631
|
+
const overlayText = readFileSync91(opts.overlay, "utf8");
|
|
44858
45632
|
overlayTokens = tokensFromText(overlayText);
|
|
44859
45633
|
} catch (err) {
|
|
44860
45634
|
process.stderr.write(
|
|
@@ -44888,7 +45662,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
44888
45662
|
}
|
|
44889
45663
|
|
|
44890
45664
|
// src/commands/flywheel/check-persona-skeleton.ts
|
|
44891
|
-
import { existsSync as existsSync110, readFileSync as
|
|
45665
|
+
import { existsSync as existsSync110, readFileSync as readFileSync92, statSync as statSync31 } from "node:fs";
|
|
44892
45666
|
import { homedir as homedir60 } from "node:os";
|
|
44893
45667
|
import { basename as basename14, join as join103 } from "node:path";
|
|
44894
45668
|
import { parse as parseYAML2 } from "yaml";
|
|
@@ -44937,7 +45711,7 @@ function checkFile(filepath) {
|
|
|
44937
45711
|
if (!existsSync110(filepath) || !statSync31(filepath).isFile()) {
|
|
44938
45712
|
return { passed: false, failures: [`file not found: ${filepath}`], tokens: 0, mergedSkipped: false };
|
|
44939
45713
|
}
|
|
44940
|
-
const text =
|
|
45714
|
+
const text = readFileSync92(filepath, "utf8");
|
|
44941
45715
|
const { fm, body } = parseFile(text);
|
|
44942
45716
|
const failures = [];
|
|
44943
45717
|
for (const key of REQUIRED_FRONTMATTER_KEYS) {
|
|
@@ -45003,7 +45777,7 @@ Results: ${passCount} passed, ${failCount} failed
|
|
|
45003
45777
|
}
|
|
45004
45778
|
|
|
45005
45779
|
// src/commands/flywheel/diversity-check.ts
|
|
45006
|
-
import { readFileSync as
|
|
45780
|
+
import { readFileSync as readFileSync93 } from "node:fs";
|
|
45007
45781
|
import { basename as basename15 } from "node:path";
|
|
45008
45782
|
import { globSync as globSync2 } from "node:fs";
|
|
45009
45783
|
|
|
@@ -45112,7 +45886,7 @@ function registerFlywheelDiversityCheck(parent) {
|
|
|
45112
45886
|
const personas = /* @__PURE__ */ new Map();
|
|
45113
45887
|
for (const filepath of files) {
|
|
45114
45888
|
try {
|
|
45115
|
-
const body =
|
|
45889
|
+
const body = readFileSync93(filepath, "utf8");
|
|
45116
45890
|
if (body.trim().length > 0) {
|
|
45117
45891
|
personas.set(basename15(filepath, ".md"), body);
|
|
45118
45892
|
}
|
|
@@ -45205,7 +45979,7 @@ import {
|
|
|
45205
45979
|
copyFileSync as copyFileSync15,
|
|
45206
45980
|
existsSync as existsSync111,
|
|
45207
45981
|
mkdirSync as mkdirSync65,
|
|
45208
|
-
readFileSync as
|
|
45982
|
+
readFileSync as readFileSync94,
|
|
45209
45983
|
readdirSync as readdirSync32,
|
|
45210
45984
|
statSync as statSync32,
|
|
45211
45985
|
writeFileSync as writeFileSync57
|
|
@@ -45291,7 +46065,7 @@ function resolveAtlasUser2(opts) {
|
|
|
45291
46065
|
const claudeDir2 = opts._testClaudeDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join105(homedir62(), ".claude");
|
|
45292
46066
|
const f = join105(claudeDir2, ".atlas-user");
|
|
45293
46067
|
if (existsSync111(f)) {
|
|
45294
|
-
const v =
|
|
46068
|
+
const v = readFileSync94(f, "utf-8").trim();
|
|
45295
46069
|
if (v.length === 0) return null;
|
|
45296
46070
|
assertValidAtlasUser(v);
|
|
45297
46071
|
return v;
|
|
@@ -45433,7 +46207,7 @@ function pushOverlays(opts) {
|
|
|
45433
46207
|
const basename16 = relPath.split("/").pop() ?? relPath;
|
|
45434
46208
|
let content;
|
|
45435
46209
|
try {
|
|
45436
|
-
content =
|
|
46210
|
+
content = readFileSync94(srcFile);
|
|
45437
46211
|
} catch {
|
|
45438
46212
|
continue;
|
|
45439
46213
|
}
|
|
@@ -45481,12 +46255,12 @@ function pushOverlays(opts) {
|
|
|
45481
46255
|
const targetFile = join105(targetDir, relPath);
|
|
45482
46256
|
let srcBuf;
|
|
45483
46257
|
try {
|
|
45484
|
-
srcBuf =
|
|
46258
|
+
srcBuf = readFileSync94(srcFile);
|
|
45485
46259
|
} catch {
|
|
45486
46260
|
continue;
|
|
45487
46261
|
}
|
|
45488
46262
|
if (existsSync111(targetFile)) {
|
|
45489
|
-
const dstBuf =
|
|
46263
|
+
const dstBuf = readFileSync94(targetFile);
|
|
45490
46264
|
if (srcBuf.equals(dstBuf)) {
|
|
45491
46265
|
wouldUnchange += 1;
|
|
45492
46266
|
process.stdout.write(` [skip] ${overlayKind}.overrides/${relPath} (unchanged)
|
|
@@ -45537,13 +46311,13 @@ function pushOverlays(opts) {
|
|
|
45537
46311
|
const targetFile = join105(membersBase, `${overlayKind}.overrides`, relPath);
|
|
45538
46312
|
let srcBuf;
|
|
45539
46313
|
try {
|
|
45540
|
-
srcBuf =
|
|
46314
|
+
srcBuf = readFileSync94(srcFile);
|
|
45541
46315
|
} catch {
|
|
45542
46316
|
continue;
|
|
45543
46317
|
}
|
|
45544
46318
|
const targetExists = existsSync111(targetFile);
|
|
45545
46319
|
if (targetExists) {
|
|
45546
|
-
const dstBuf =
|
|
46320
|
+
const dstBuf = readFileSync94(targetFile);
|
|
45547
46321
|
if (srcBuf.equals(dstBuf)) {
|
|
45548
46322
|
filesUnchanged += 1;
|
|
45549
46323
|
continue;
|
|
@@ -45752,7 +46526,7 @@ function migrateOverlays(opts = {}) {
|
|
|
45752
46526
|
for (const filePath of allFiles) {
|
|
45753
46527
|
let original;
|
|
45754
46528
|
try {
|
|
45755
|
-
original =
|
|
46529
|
+
original = readFileSync94(filePath, "utf8");
|
|
45756
46530
|
} catch {
|
|
45757
46531
|
continue;
|
|
45758
46532
|
}
|