@pleri/olam-cli 0.1.173 → 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/commands/auth.d.ts +22 -7
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +414 -46
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +45 -1
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/services.d.ts +39 -0
- package/dist/commands/services.d.ts.map +1 -1
- package/dist/commands/services.js +64 -9
- package/dist/commands/services.js.map +1 -1
- package/dist/from-manifest.d.ts +53 -0
- package/dist/from-manifest.d.ts.map +1 -0
- package/dist/from-manifest.js +95 -0
- package/dist/from-manifest.js.map +1 -0
- package/dist/image-digests.json +8 -8
- package/dist/index.js +907 -136
- package/dist/lib/auth-remote.d.ts +130 -0
- package/dist/lib/auth-remote.d.ts.map +1 -0
- package/dist/lib/auth-remote.js +307 -0
- package/dist/lib/auth-remote.js.map +1 -0
- package/dist/mcp-server.js +254 -57
- package/hermes-bundle/version.json +1 -1
- package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
- package/host-cp/src/boot-reconciler.mjs +238 -0
- package/host-cp/src/port-bridge-manager.mjs +116 -10
- package/host-cp/src/server.mjs +32 -0
- package/host-cp/src/world-activity-tracker.mjs +392 -0
- package/package.json +1 -1
package/dist/mcp-server.js
CHANGED
|
@@ -12331,10 +12331,10 @@ var init_runbooks = __esm({
|
|
|
12331
12331
|
// ../core/dist/global-config/port-validator.js
|
|
12332
12332
|
import * as net2 from "node:net";
|
|
12333
12333
|
import * as childProcess from "node:child_process";
|
|
12334
|
-
import { createRequire as
|
|
12334
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
12335
12335
|
function getRequire() {
|
|
12336
12336
|
if (!_require3) {
|
|
12337
|
-
_require3 =
|
|
12337
|
+
_require3 = createRequire4(import.meta.url);
|
|
12338
12338
|
}
|
|
12339
12339
|
return _require3;
|
|
12340
12340
|
}
|
|
@@ -14165,9 +14165,9 @@ var init_file_lock = __esm({
|
|
|
14165
14165
|
});
|
|
14166
14166
|
|
|
14167
14167
|
// ../core/dist/lib/min-version-filter.js
|
|
14168
|
-
import { existsSync as
|
|
14168
|
+
import { existsSync as existsSync28, readFileSync as readFileSync23 } from "node:fs";
|
|
14169
14169
|
function readOlamMinVersion(filepath) {
|
|
14170
|
-
if (!
|
|
14170
|
+
if (!existsSync28(filepath))
|
|
14171
14171
|
return void 0;
|
|
14172
14172
|
let text;
|
|
14173
14173
|
try {
|
|
@@ -14790,7 +14790,7 @@ var init_meta_hook_injector = __esm({
|
|
|
14790
14790
|
|
|
14791
14791
|
// ../core/dist/lib/markdown-merger.js
|
|
14792
14792
|
import { createHash as createHash5 } from "node:crypto";
|
|
14793
|
-
import { readFileSync as readFileSync27, existsSync as
|
|
14793
|
+
import { readFileSync as readFileSync27, existsSync as existsSync31, statSync as statSync8 } from "node:fs";
|
|
14794
14794
|
function parseFrontmatter(text) {
|
|
14795
14795
|
const match = FM_RE2.exec(text);
|
|
14796
14796
|
if (match === null)
|
|
@@ -14910,7 +14910,7 @@ function mergeMarkdown(upstreamText, overlayText, labelForError, upstreamPath, o
|
|
|
14910
14910
|
return { merged: fmBlock !== "" ? fmBlock + mergedBody : mergedBody };
|
|
14911
14911
|
}
|
|
14912
14912
|
function sha256OfPath(p) {
|
|
14913
|
-
if (!
|
|
14913
|
+
if (!existsSync31(p) || !statSync8(p).isFile())
|
|
14914
14914
|
return "MISSING";
|
|
14915
14915
|
return createHash5("sha256").update(readFileSync27(p)).digest("hex");
|
|
14916
14916
|
}
|
|
@@ -15123,7 +15123,7 @@ var init_prefix_deploy = __esm({
|
|
|
15123
15123
|
});
|
|
15124
15124
|
|
|
15125
15125
|
// ../core/dist/skill-sync/resolve-source-config.js
|
|
15126
|
-
import { readFileSync as readFileSync29, existsSync as
|
|
15126
|
+
import { readFileSync as readFileSync29, existsSync as existsSync32 } from "node:fs";
|
|
15127
15127
|
import { join as join31 } from "node:path";
|
|
15128
15128
|
import { parse as parseYaml4 } from "yaml";
|
|
15129
15129
|
function sourceConfigPath(clonePath) {
|
|
@@ -15131,7 +15131,7 @@ function sourceConfigPath(clonePath) {
|
|
|
15131
15131
|
}
|
|
15132
15132
|
function readSourceConfig(clonePath, sourceId) {
|
|
15133
15133
|
const path53 = sourceConfigPath(clonePath);
|
|
15134
|
-
if (!
|
|
15134
|
+
if (!existsSync32(path53))
|
|
15135
15135
|
return void 0;
|
|
15136
15136
|
let raw;
|
|
15137
15137
|
try {
|
|
@@ -28718,6 +28718,21 @@ var WorldRegistry = class {
|
|
|
28718
28718
|
const row = this.db.prepare("SELECT * FROM worlds WHERE id = ?").get(worldId);
|
|
28719
28719
|
return row ? rowToMetadata(row) : void 0;
|
|
28720
28720
|
}
|
|
28721
|
+
/**
|
|
28722
|
+
* Find all worlds with a given `name`. Returns rows of every lifecycle
|
|
28723
|
+
* status — callers filter as needed (e.g. active-only for dedup, error-
|
|
28724
|
+
* only for cleanup).
|
|
28725
|
+
*
|
|
28726
|
+
* The schema has UNIQUE on `id` but NOT on `name`, so a single name can
|
|
28727
|
+
* legitimately have multiple rows (e.g. one destroyed + one new). Issue
|
|
28728
|
+
* #962: `olam create <name>` was generating fresh ids without checking
|
|
28729
|
+
* for an existing row, accumulating orphan error rows under the same
|
|
28730
|
+
* name. This is the registry-level primitive the manager's dedup uses.
|
|
28731
|
+
*/
|
|
28732
|
+
findByName(name) {
|
|
28733
|
+
const rows = this.db.prepare("SELECT * FROM worlds WHERE name = ? ORDER BY created_at DESC").all(name);
|
|
28734
|
+
return rows.map(rowToMetadata);
|
|
28735
|
+
}
|
|
28721
28736
|
list(filter) {
|
|
28722
28737
|
if (filter?.status) {
|
|
28723
28738
|
const rows2 = this.db.prepare("SELECT * FROM worlds WHERE status = ? ORDER BY created_at DESC").all(filter.status);
|
|
@@ -32349,8 +32364,8 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
|
|
|
32349
32364
|
}
|
|
32350
32365
|
}
|
|
32351
32366
|
async function copyClaudeConfigIntoContainer(containerName) {
|
|
32352
|
-
const { execSync:
|
|
32353
|
-
const dockerExec = (cmd) =>
|
|
32367
|
+
const { execSync: execSync8 } = await import("node:child_process");
|
|
32368
|
+
const dockerExec = (cmd) => execSync8(`docker exec ${containerName} sh -c '${cmd}'`, { stdio: "pipe" });
|
|
32354
32369
|
dockerExec("mkdir -p $HOME/.claude");
|
|
32355
32370
|
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");
|
|
32356
32371
|
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");
|
|
@@ -32366,7 +32381,7 @@ async function copyClaudeConfigIntoContainer(containerName) {
|
|
|
32366
32381
|
await sanitizeContainerClaudeHooks(containerName);
|
|
32367
32382
|
}
|
|
32368
32383
|
async function sanitizeContainerClaudeHooks(containerName) {
|
|
32369
|
-
const { execSync:
|
|
32384
|
+
const { execSync: execSync8 } = await import("node:child_process");
|
|
32370
32385
|
const script = `
|
|
32371
32386
|
const fs = require('fs');
|
|
32372
32387
|
const p = (process.env.HOME || '/home/olam') + '/.claude/settings.json';
|
|
@@ -32410,7 +32425,7 @@ if (changed) {
|
|
|
32410
32425
|
}
|
|
32411
32426
|
`;
|
|
32412
32427
|
try {
|
|
32413
|
-
|
|
32428
|
+
execSync8(`docker exec ${containerName} /usr/local/bin/node -e ${shQuote(script)}`, { stdio: "pipe" });
|
|
32414
32429
|
} catch {
|
|
32415
32430
|
}
|
|
32416
32431
|
}
|
|
@@ -33039,29 +33054,116 @@ function register9(server, ctx, initError, deps) {
|
|
|
33039
33054
|
// ../mcp-server/src/tools/world-observe.ts
|
|
33040
33055
|
var world_observe_exports = {};
|
|
33041
33056
|
__export(world_observe_exports, {
|
|
33057
|
+
readWorldChunks: () => readWorldChunks,
|
|
33042
33058
|
register: () => register10
|
|
33043
33059
|
});
|
|
33060
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
33061
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
33044
33062
|
|
|
33045
33063
|
// ../skill-runtime/dist/skills/world-observe.js
|
|
33046
33064
|
init_v3();
|
|
33047
33065
|
var worldObserveInputSchema = external_exports.object({
|
|
33048
|
-
worldId: external_exports.string()
|
|
33066
|
+
worldId: external_exports.string(),
|
|
33067
|
+
sessionId: external_exports.string().optional(),
|
|
33068
|
+
sinceChunkId: external_exports.string().optional(),
|
|
33069
|
+
limit: external_exports.number().int().min(1).max(1e3).optional()
|
|
33049
33070
|
});
|
|
33050
33071
|
var worldObserveSkill = defineSkill({
|
|
33051
33072
|
name: "world-observe",
|
|
33052
|
-
description: "
|
|
33073
|
+
description: "Stream a world's reasoning chunks (thought_nodes feed). Returns JSON `{ chunks: [{ chunkId, sessionId, role, content, createdAt, nodeType }], metadata: { pane_state, count } }`, most-recent-last. Supports pagination via `sinceChunkId` (returns only chunks newer than the given id) and `limit` (default 100, max 1000). Use `olam_list` first to discover worldIds.",
|
|
33053
33074
|
inputSchema: worldObserveInputSchema,
|
|
33054
|
-
handler: (_input) => "
|
|
33075
|
+
handler: (_input) => "World observation requires an active OlamContext. Use the MCP tool surface to read a world's chunks."
|
|
33055
33076
|
});
|
|
33056
33077
|
|
|
33057
33078
|
// ../mcp-server/src/tools/world-observe.ts
|
|
33079
|
+
var require2 = createRequire3(import.meta.url);
|
|
33080
|
+
var SYSTEM_NODE_TYPES = /* @__PURE__ */ new Set(["lifecycle", "dispatch_error"]);
|
|
33081
|
+
var DEFAULT_LIMIT = 100;
|
|
33082
|
+
var BUSY_WINDOW_MS = 3e4;
|
|
33083
|
+
function roleFor(nodeType) {
|
|
33084
|
+
return SYSTEM_NODE_TYPES.has(nodeType) ? "system" : "assistant";
|
|
33085
|
+
}
|
|
33086
|
+
function rowToChunk(row) {
|
|
33087
|
+
return {
|
|
33088
|
+
chunkId: row.id,
|
|
33089
|
+
sessionId: row.session_id,
|
|
33090
|
+
role: roleFor(row.node_type),
|
|
33091
|
+
content: row.content,
|
|
33092
|
+
summary: row.summary,
|
|
33093
|
+
createdAt: row.created_at,
|
|
33094
|
+
nodeType: row.node_type,
|
|
33095
|
+
sequenceNum: row.sequence_num
|
|
33096
|
+
};
|
|
33097
|
+
}
|
|
33098
|
+
function readWorldChunks(dbPath, params) {
|
|
33099
|
+
const limit = params.limit ?? DEFAULT_LIMIT;
|
|
33100
|
+
const now = params.now ?? Date.now();
|
|
33101
|
+
const empty = () => ({
|
|
33102
|
+
worldId: params.worldId,
|
|
33103
|
+
chunks: [],
|
|
33104
|
+
metadata: {
|
|
33105
|
+
count: 0,
|
|
33106
|
+
pane_state: "idle",
|
|
33107
|
+
sessionFilter: params.sessionId ?? null,
|
|
33108
|
+
sinceChunkId: params.sinceChunkId ?? null,
|
|
33109
|
+
limit
|
|
33110
|
+
}
|
|
33111
|
+
});
|
|
33112
|
+
if (!existsSync11(dbPath)) return empty();
|
|
33113
|
+
const Sqlite = require2("better-sqlite3");
|
|
33114
|
+
const db = new Sqlite(dbPath, { readonly: true, fileMustExist: true });
|
|
33115
|
+
try {
|
|
33116
|
+
let minSeq = -1;
|
|
33117
|
+
if (params.sinceChunkId) {
|
|
33118
|
+
const seqRow = db.prepare("SELECT sequence_num FROM thought_nodes WHERE id = ?").get(params.sinceChunkId);
|
|
33119
|
+
if (!seqRow) {
|
|
33120
|
+
return empty();
|
|
33121
|
+
}
|
|
33122
|
+
minSeq = seqRow.sequence_num;
|
|
33123
|
+
}
|
|
33124
|
+
const where = ["sequence_num > ?"];
|
|
33125
|
+
const bind = [minSeq];
|
|
33126
|
+
if (params.sessionId !== void 0) {
|
|
33127
|
+
where.push("session_id = ?");
|
|
33128
|
+
bind.push(params.sessionId);
|
|
33129
|
+
}
|
|
33130
|
+
const sql = `SELECT id, node_type, summary, content, source_ref, sequence_num, created_at, session_id, hook_event_name, turn_index, token_usage, duration_ms FROM thought_nodes WHERE ${where.join(" AND ")} ORDER BY sequence_num DESC LIMIT ?`;
|
|
33131
|
+
const rows = db.prepare(sql).all(...bind, limit);
|
|
33132
|
+
rows.reverse();
|
|
33133
|
+
const lastRow = rows[rows.length - 1];
|
|
33134
|
+
let paneState = "idle";
|
|
33135
|
+
if (lastRow) {
|
|
33136
|
+
const ageMs = now - new Date(lastRow.created_at).getTime();
|
|
33137
|
+
paneState = ageMs <= BUSY_WINDOW_MS ? "busy" : "idle";
|
|
33138
|
+
} else {
|
|
33139
|
+
const maxRow = db.prepare("SELECT MAX(created_at) AS max_at FROM thought_nodes").get();
|
|
33140
|
+
if (maxRow?.max_at) {
|
|
33141
|
+
const ageMs = now - new Date(maxRow.max_at).getTime();
|
|
33142
|
+
paneState = ageMs <= BUSY_WINDOW_MS ? "busy" : "idle";
|
|
33143
|
+
}
|
|
33144
|
+
}
|
|
33145
|
+
return {
|
|
33146
|
+
worldId: params.worldId,
|
|
33147
|
+
chunks: rows.map(rowToChunk),
|
|
33148
|
+
metadata: {
|
|
33149
|
+
count: rows.length,
|
|
33150
|
+
pane_state: paneState,
|
|
33151
|
+
sessionFilter: params.sessionId ?? null,
|
|
33152
|
+
sinceChunkId: params.sinceChunkId ?? null,
|
|
33153
|
+
limit
|
|
33154
|
+
}
|
|
33155
|
+
};
|
|
33156
|
+
} finally {
|
|
33157
|
+
db.close();
|
|
33158
|
+
}
|
|
33159
|
+
}
|
|
33058
33160
|
function register10(server, ctx, initError) {
|
|
33059
33161
|
const { description, inputSchema } = worldObserveSkill.asMcpTool();
|
|
33060
33162
|
server.tool(
|
|
33061
33163
|
"olam_observe",
|
|
33062
33164
|
description,
|
|
33063
33165
|
inputSchema,
|
|
33064
|
-
async (
|
|
33166
|
+
async (params) => {
|
|
33065
33167
|
if (!ctx) {
|
|
33066
33168
|
const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
|
|
33067
33169
|
return {
|
|
@@ -33069,10 +33171,34 @@ function register10(server, ctx, initError) {
|
|
|
33069
33171
|
isError: true
|
|
33070
33172
|
};
|
|
33071
33173
|
}
|
|
33072
|
-
|
|
33073
|
-
|
|
33074
|
-
|
|
33075
|
-
|
|
33174
|
+
const { worldId, sessionId, sinceChunkId, limit } = params;
|
|
33175
|
+
const world = ctx.worldManager.getWorld(worldId);
|
|
33176
|
+
if (!world) {
|
|
33177
|
+
return {
|
|
33178
|
+
content: [
|
|
33179
|
+
{
|
|
33180
|
+
type: "text",
|
|
33181
|
+
text: `World "${worldId}" not found. Use olam_list to discover available worlds.`
|
|
33182
|
+
}
|
|
33183
|
+
],
|
|
33184
|
+
isError: true
|
|
33185
|
+
};
|
|
33186
|
+
}
|
|
33187
|
+
try {
|
|
33188
|
+
const dbPath = getWorldDbPath(world.workspacePath);
|
|
33189
|
+
const output = readWorldChunks(dbPath, { worldId, sessionId, sinceChunkId, limit });
|
|
33190
|
+
return {
|
|
33191
|
+
content: [{ type: "text", text: JSON.stringify(output, null, 2) }]
|
|
33192
|
+
};
|
|
33193
|
+
} catch (err) {
|
|
33194
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
33195
|
+
return {
|
|
33196
|
+
content: [
|
|
33197
|
+
{ type: "text", text: `Failed to read chunks for world "${worldId}": ${message}` }
|
|
33198
|
+
],
|
|
33199
|
+
isError: true
|
|
33200
|
+
};
|
|
33201
|
+
}
|
|
33076
33202
|
}
|
|
33077
33203
|
);
|
|
33078
33204
|
}
|
|
@@ -36070,16 +36196,20 @@ function register23(server, _ctx, _initError) {
|
|
|
36070
36196
|
};
|
|
36071
36197
|
}
|
|
36072
36198
|
const data = JSON.parse(body);
|
|
36199
|
+
const payload = {
|
|
36200
|
+
url: `http://localhost:${data.hostPort}`,
|
|
36201
|
+
host_port: data.hostPort,
|
|
36202
|
+
sidecar_container_id: data.containerId,
|
|
36203
|
+
container_port: data.containerPort,
|
|
36204
|
+
container_name: data.containerName
|
|
36205
|
+
};
|
|
36206
|
+
if (data.pulledImage === true) {
|
|
36207
|
+
payload["pulled_image"] = "alpine/socat:latest (first-call fallback)";
|
|
36208
|
+
}
|
|
36073
36209
|
return {
|
|
36074
36210
|
content: [{
|
|
36075
36211
|
type: "text",
|
|
36076
|
-
text: JSON.stringify(
|
|
36077
|
-
url: `http://localhost:${data.hostPort}`,
|
|
36078
|
-
host_port: data.hostPort,
|
|
36079
|
-
sidecar_container_id: data.containerId,
|
|
36080
|
-
container_port: data.containerPort,
|
|
36081
|
-
container_name: data.containerName
|
|
36082
|
-
}, null, 2)
|
|
36212
|
+
text: JSON.stringify(payload, null, 2)
|
|
36083
36213
|
}]
|
|
36084
36214
|
};
|
|
36085
36215
|
} catch (err) {
|
|
@@ -36719,14 +36849,14 @@ import * as path37 from "node:path";
|
|
|
36719
36849
|
import * as os22 from "node:os";
|
|
36720
36850
|
|
|
36721
36851
|
// ../mcp-server/src/lib/skills-index.mjs
|
|
36722
|
-
import { createRequire as
|
|
36852
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
36723
36853
|
import * as fs37 from "node:fs";
|
|
36724
36854
|
import * as path36 from "node:path";
|
|
36725
36855
|
import * as os21 from "node:os";
|
|
36726
36856
|
var VECTOR_DIM = 256;
|
|
36727
36857
|
var SCHEMA_VERSION3 = "1";
|
|
36728
36858
|
var SCHEMA_KEY = "skills_index_schema_version";
|
|
36729
|
-
var _require4 =
|
|
36859
|
+
var _require4 = createRequire5(import.meta.url);
|
|
36730
36860
|
var _Database3 = null;
|
|
36731
36861
|
function getDatabase3() {
|
|
36732
36862
|
if (_Database3 === null) {
|
|
@@ -37738,8 +37868,8 @@ function createServer4(ctx, initError) {
|
|
|
37738
37868
|
}
|
|
37739
37869
|
|
|
37740
37870
|
// ../mcp-server/src/utils/native-probe.ts
|
|
37741
|
-
import { createRequire as
|
|
37742
|
-
var PROBE_REQUIRE =
|
|
37871
|
+
import { createRequire as createRequire6 } from "node:module";
|
|
37872
|
+
var PROBE_REQUIRE = createRequire6(import.meta.url);
|
|
37743
37873
|
function runtimeModuleVersion() {
|
|
37744
37874
|
return Number.parseInt(process.versions.modules, 10);
|
|
37745
37875
|
}
|
|
@@ -37855,7 +37985,7 @@ init_loader();
|
|
|
37855
37985
|
|
|
37856
37986
|
// ../core/dist/world/manager.js
|
|
37857
37987
|
import * as crypto8 from "node:crypto";
|
|
37858
|
-
import { execSync as
|
|
37988
|
+
import { execSync as execSync6, spawnSync as spawnSync4 } from "node:child_process";
|
|
37859
37989
|
import * as fs49 from "node:fs";
|
|
37860
37990
|
import * as os29 from "node:os";
|
|
37861
37991
|
import * as path50 from "node:path";
|
|
@@ -38397,7 +38527,7 @@ function extractStderr(err) {
|
|
|
38397
38527
|
function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
38398
38528
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
|
|
38399
38529
|
const homedir30 = deps.homedir ?? (() => os26.homedir());
|
|
38400
|
-
const
|
|
38530
|
+
const existsSync49 = deps.existsSync ?? ((p) => fs43.existsSync(p));
|
|
38401
38531
|
const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs43.copyFileSync(src, dest));
|
|
38402
38532
|
const mkdirSync30 = deps.mkdirSync ?? ((dirPath, opts) => {
|
|
38403
38533
|
fs43.mkdirSync(dirPath, opts);
|
|
@@ -38408,9 +38538,9 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
|
38408
38538
|
continue;
|
|
38409
38539
|
const repoPath = expandHome2(repo.path, homedir30);
|
|
38410
38540
|
const worktreePath = path43.join(workspacePath, repo.name);
|
|
38411
|
-
if (!
|
|
38541
|
+
if (!existsSync49(repoPath))
|
|
38412
38542
|
continue;
|
|
38413
|
-
if (!
|
|
38543
|
+
if (!existsSync49(worktreePath)) {
|
|
38414
38544
|
console.warn(`[carry] ${repo.name}: world worktree ${worktreePath} missing; skipping carry for this repo`);
|
|
38415
38545
|
continue;
|
|
38416
38546
|
}
|
|
@@ -38470,7 +38600,7 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
|
38470
38600
|
for (const rel of plan.diff.untracked) {
|
|
38471
38601
|
const src = path43.join(plan.repoPath, rel);
|
|
38472
38602
|
const dest = path43.join(plan.worktreePath, rel);
|
|
38473
|
-
if (!
|
|
38603
|
+
if (!existsSync49(src))
|
|
38474
38604
|
continue;
|
|
38475
38605
|
try {
|
|
38476
38606
|
mkdirSync30(path43.dirname(dest), { recursive: true });
|
|
@@ -39989,6 +40119,54 @@ async function runSeedHooks(seeds, containerName, servicePortMap, exec) {
|
|
|
39989
40119
|
}
|
|
39990
40120
|
}
|
|
39991
40121
|
|
|
40122
|
+
// ../core/dist/world/create-dedup.js
|
|
40123
|
+
import { execSync as execSync5 } from "node:child_process";
|
|
40124
|
+
var ACTIVE_STATUSES = /* @__PURE__ */ new Set([
|
|
40125
|
+
"creating",
|
|
40126
|
+
"running",
|
|
40127
|
+
"paused",
|
|
40128
|
+
"crystallizing"
|
|
40129
|
+
]);
|
|
40130
|
+
var defaultContainerProbe = (containerName) => {
|
|
40131
|
+
try {
|
|
40132
|
+
const out = execSync5(`docker ps --filter name=^/${containerName}$ --format '{{.Names}}'`, { stdio: ["pipe", "pipe", "pipe"], timeout: 5e3 }).toString().trim();
|
|
40133
|
+
return out.length > 0;
|
|
40134
|
+
} catch {
|
|
40135
|
+
return false;
|
|
40136
|
+
}
|
|
40137
|
+
};
|
|
40138
|
+
function resolveCreateDedup(opts) {
|
|
40139
|
+
const { registry: registry2, name } = opts;
|
|
40140
|
+
const probe = opts.probeContainer ?? defaultContainerProbe;
|
|
40141
|
+
const containerName = `olam-${name}-devbox`;
|
|
40142
|
+
const existing = registry2.findByName(name);
|
|
40143
|
+
const active = existing.find((w) => ACTIVE_STATUSES.has(w.status));
|
|
40144
|
+
if (active) {
|
|
40145
|
+
return { action: "reuse", world: active };
|
|
40146
|
+
}
|
|
40147
|
+
const errorRows = existing.filter((w) => w.status === "error");
|
|
40148
|
+
for (const er of errorRows) {
|
|
40149
|
+
registry2.remove(er.id);
|
|
40150
|
+
}
|
|
40151
|
+
if (probe(containerName)) {
|
|
40152
|
+
return {
|
|
40153
|
+
action: "container-orphan",
|
|
40154
|
+
containerName,
|
|
40155
|
+
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.`
|
|
40156
|
+
};
|
|
40157
|
+
}
|
|
40158
|
+
return { action: "fresh", cleanedErrorRows: errorRows.length };
|
|
40159
|
+
}
|
|
40160
|
+
var ContainerOrphanError = class extends Error {
|
|
40161
|
+
containerName;
|
|
40162
|
+
kind = "container-orphan";
|
|
40163
|
+
constructor(message, containerName) {
|
|
40164
|
+
super(message);
|
|
40165
|
+
this.containerName = containerName;
|
|
40166
|
+
this.name = "ContainerOrphanError";
|
|
40167
|
+
}
|
|
40168
|
+
};
|
|
40169
|
+
|
|
39992
40170
|
// ../core/dist/world/tmux-supervisor.js
|
|
39993
40171
|
function injectBindAll(start) {
|
|
39994
40172
|
let result = start;
|
|
@@ -40122,7 +40300,7 @@ var BotIdentityError = class extends Error {
|
|
|
40122
40300
|
this.name = "BotIdentityError";
|
|
40123
40301
|
}
|
|
40124
40302
|
};
|
|
40125
|
-
function getTokenScopes(ghToken, _exec =
|
|
40303
|
+
function getTokenScopes(ghToken, _exec = execSync6) {
|
|
40126
40304
|
try {
|
|
40127
40305
|
const out = _exec("gh auth status 2>&1", {
|
|
40128
40306
|
encoding: "utf-8",
|
|
@@ -40139,13 +40317,13 @@ function getTokenScopes(ghToken, _exec = execSync5) {
|
|
|
40139
40317
|
}
|
|
40140
40318
|
}
|
|
40141
40319
|
async function setupContainerGit(containerName, repos, branch) {
|
|
40142
|
-
const dockerExec = (cmd) =>
|
|
40320
|
+
const dockerExec = (cmd) => execSync6(`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`, {
|
|
40143
40321
|
stdio: "pipe",
|
|
40144
40322
|
timeout: 6e4
|
|
40145
40323
|
}).toString();
|
|
40146
40324
|
let ghToken = "";
|
|
40147
40325
|
try {
|
|
40148
|
-
ghToken =
|
|
40326
|
+
ghToken = execSync6("gh auth token 2>/dev/null", { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
40149
40327
|
} catch {
|
|
40150
40328
|
}
|
|
40151
40329
|
const actorName = process.env.OLAM_BOT_NAME ?? "Claude Code (olam)";
|
|
@@ -40165,7 +40343,7 @@ async function setupContainerGit(containerName, repos, branch) {
|
|
|
40165
40343
|
continue;
|
|
40166
40344
|
const ownerRepo = ghMatch[1];
|
|
40167
40345
|
try {
|
|
40168
|
-
|
|
40346
|
+
execSync6(`gh api repos/${ownerRepo} --silent`, {
|
|
40169
40347
|
stdio: "pipe",
|
|
40170
40348
|
timeout: 5e3,
|
|
40171
40349
|
env: { ...process.env, GH_TOKEN: ghToken }
|
|
@@ -40213,7 +40391,7 @@ ${stderr.split("\n").slice(0, 3).join(" ")}`);
|
|
|
40213
40391
|
if (!olamUserPresent) {
|
|
40214
40392
|
const imageName = (() => {
|
|
40215
40393
|
try {
|
|
40216
|
-
return
|
|
40394
|
+
return execSync6(`docker inspect ${containerName} --format '{{.Config.Image}}'`, {
|
|
40217
40395
|
encoding: "utf8",
|
|
40218
40396
|
timeout: 5e3
|
|
40219
40397
|
}).trim() || "(unknown)";
|
|
@@ -40256,7 +40434,7 @@ ${stderr.split("\n").slice(0, 3).join(" ")}`);
|
|
|
40256
40434
|
function makeHostExecFn() {
|
|
40257
40435
|
return async (cmd) => {
|
|
40258
40436
|
try {
|
|
40259
|
-
const stdout =
|
|
40437
|
+
const stdout = execSync6(cmd, { encoding: "utf-8", timeout: 5e3 });
|
|
40260
40438
|
return { stdout, stderr: "", exitCode: 0 };
|
|
40261
40439
|
} catch {
|
|
40262
40440
|
return { stdout: "", stderr: "", exitCode: 1 };
|
|
@@ -40266,7 +40444,7 @@ function makeHostExecFn() {
|
|
|
40266
40444
|
function makeContainerExecFn(containerName) {
|
|
40267
40445
|
return async (cmd) => {
|
|
40268
40446
|
try {
|
|
40269
|
-
const result =
|
|
40447
|
+
const result = execSync6(`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`, { stdio: "pipe", timeout: 6e5 });
|
|
40270
40448
|
return { stdout: result.toString(), stderr: "", exitCode: 0 };
|
|
40271
40449
|
} catch (err) {
|
|
40272
40450
|
const execErr = err;
|
|
@@ -40280,7 +40458,7 @@ function makeContainerExecFn(containerName) {
|
|
|
40280
40458
|
}
|
|
40281
40459
|
function defaultDockerExec() {
|
|
40282
40460
|
return (containerName, cmd) => {
|
|
40283
|
-
const result =
|
|
40461
|
+
const result = execSync6(
|
|
40284
40462
|
`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`,
|
|
40285
40463
|
// Phase E E5 raise: 10min was too tight on cold-boot for atlas-core's
|
|
40286
40464
|
// `rails db:create` chain (Rails 7 boot + initializer load + first
|
|
@@ -40480,7 +40658,7 @@ function buildManifestRuntime(worldId, repos) {
|
|
|
40480
40658
|
}
|
|
40481
40659
|
return { worldId, repos: runtimeRepos };
|
|
40482
40660
|
}
|
|
40483
|
-
function exposeWorldOverTailscale(appPortUrls, worldId, registry2, _exec =
|
|
40661
|
+
function exposeWorldOverTailscale(appPortUrls, worldId, registry2, _exec = execSync6) {
|
|
40484
40662
|
if (process.env["OLAM_TAILSCALE_SERVE"] !== "true")
|
|
40485
40663
|
return;
|
|
40486
40664
|
if (appPortUrls.length === 0)
|
|
@@ -40508,7 +40686,7 @@ function exposeWorldOverTailscale(appPortUrls, worldId, registry2, _exec = execS
|
|
|
40508
40686
|
registry2.storeTailscalePaths(worldId, registeredPaths);
|
|
40509
40687
|
}
|
|
40510
40688
|
}
|
|
40511
|
-
function cleanupWorldTailscale(worldId, registry2, _exec =
|
|
40689
|
+
function cleanupWorldTailscale(worldId, registry2, _exec = execSync6) {
|
|
40512
40690
|
const paths = registry2.loadTailscalePaths(worldId);
|
|
40513
40691
|
if (paths.length === 0)
|
|
40514
40692
|
return;
|
|
@@ -40527,7 +40705,7 @@ function cleanupWorldTailscale(worldId, registry2, _exec = execSync5) {
|
|
|
40527
40705
|
}
|
|
40528
40706
|
}
|
|
40529
40707
|
}
|
|
40530
|
-
function resolveTailscaleBin(_exec =
|
|
40708
|
+
function resolveTailscaleBin(_exec = execSync6) {
|
|
40531
40709
|
const candidates = [
|
|
40532
40710
|
process.env["TAILSCALE_BIN"],
|
|
40533
40711
|
"/Applications/Tailscale.app/Contents/MacOS/Tailscale",
|
|
@@ -40552,19 +40730,38 @@ var WorldManager = class {
|
|
|
40552
40730
|
dashboardManager;
|
|
40553
40731
|
pleriClient;
|
|
40554
40732
|
dockerExec;
|
|
40733
|
+
containerProbe;
|
|
40555
40734
|
manifestRuntimes = /* @__PURE__ */ new Map();
|
|
40556
|
-
constructor(config2, provider, registry2, dashboardManager, pleriClient, dockerExec) {
|
|
40735
|
+
constructor(config2, provider, registry2, dashboardManager, pleriClient, dockerExec, containerProbe) {
|
|
40557
40736
|
this.config = config2;
|
|
40558
40737
|
this.provider = provider;
|
|
40559
40738
|
this.registry = registry2;
|
|
40560
40739
|
this.dashboardManager = dashboardManager;
|
|
40561
40740
|
this.pleriClient = pleriClient;
|
|
40562
40741
|
this.dockerExec = dockerExec ?? defaultDockerExec();
|
|
40742
|
+
this.containerProbe = containerProbe;
|
|
40563
40743
|
}
|
|
40564
40744
|
// -----------------------------------------------------------------------
|
|
40565
40745
|
// createWorld
|
|
40566
40746
|
// -----------------------------------------------------------------------
|
|
40567
40747
|
async createWorld(opts) {
|
|
40748
|
+
{
|
|
40749
|
+
const dedupOpts = {
|
|
40750
|
+
registry: this.registry,
|
|
40751
|
+
name: opts.name,
|
|
40752
|
+
...this.containerProbe ? { probeContainer: this.containerProbe } : {}
|
|
40753
|
+
};
|
|
40754
|
+
const dedup = resolveCreateDedup(dedupOpts);
|
|
40755
|
+
if (dedup.action === "reuse") {
|
|
40756
|
+
return dedup.world;
|
|
40757
|
+
}
|
|
40758
|
+
if (dedup.action === "container-orphan") {
|
|
40759
|
+
throw new ContainerOrphanError(dedup.remediation, dedup.containerName);
|
|
40760
|
+
}
|
|
40761
|
+
if (dedup.cleanedErrorRows > 0) {
|
|
40762
|
+
console.log(`[manager] removed ${dedup.cleanedErrorRows} stale error row(s) for world name "${opts.name}" before fresh create (issue #962)`);
|
|
40763
|
+
}
|
|
40764
|
+
}
|
|
40568
40765
|
if (!opts.noAuth) {
|
|
40569
40766
|
const preflight = await runAuthPreflight({ autoStart: true });
|
|
40570
40767
|
if (preflight.verdict !== "ok") {
|
|
@@ -41248,7 +41445,7 @@ ${detail}`);
|
|
|
41248
41445
|
const escapedDir = `/home/olam/workspace/${repo.name.replace(/["$`\\]/g, "\\$&")}`;
|
|
41249
41446
|
for (const cmd of repo.setup_commands) {
|
|
41250
41447
|
try {
|
|
41251
|
-
|
|
41448
|
+
execSync6(`docker exec ${containerName} sh -c 'cd "${escapedDir}" && ${cmd.replace(/'/g, "'\\''")}'`, { stdio: "pipe", timeout: 6e5 });
|
|
41252
41449
|
} catch (err) {
|
|
41253
41450
|
const msg = err instanceof Error ? err.message : String(err);
|
|
41254
41451
|
console.warn(`[WorldManager] setup command failed for ${repo.name}: ${msg}`);
|
|
@@ -41269,11 +41466,11 @@ ${detail}`);
|
|
|
41269
41466
|
});
|
|
41270
41467
|
if (allPolicies.length > 0) {
|
|
41271
41468
|
try {
|
|
41272
|
-
|
|
41469
|
+
execSync6(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
|
|
41273
41470
|
for (const repo of repos) {
|
|
41274
41471
|
const policiesDir = path50.join(workspacePath, repo.name, ".olam", "policies");
|
|
41275
41472
|
if (fs49.existsSync(policiesDir)) {
|
|
41276
|
-
|
|
41473
|
+
execSync6(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
|
|
41277
41474
|
}
|
|
41278
41475
|
}
|
|
41279
41476
|
} catch (err) {
|
|
@@ -42779,11 +42976,11 @@ function isDashboardRunning() {
|
|
|
42779
42976
|
}
|
|
42780
42977
|
|
|
42781
42978
|
// ../core/dist/dashboard/tunnel.js
|
|
42782
|
-
import { spawn as spawn4, execSync as
|
|
42979
|
+
import { spawn as spawn4, execSync as execSync7 } from "node:child_process";
|
|
42783
42980
|
var tunnelProcess = null;
|
|
42784
42981
|
function isCloudflaredAvailable() {
|
|
42785
42982
|
try {
|
|
42786
|
-
|
|
42983
|
+
execSync7("which cloudflared", { stdio: "ignore" });
|
|
42787
42984
|
return true;
|
|
42788
42985
|
} catch {
|
|
42789
42986
|
return false;
|
|
@@ -43041,7 +43238,7 @@ var PleriClient = class {
|
|
|
43041
43238
|
};
|
|
43042
43239
|
|
|
43043
43240
|
// ../mcp-server/src/env-loader.ts
|
|
43044
|
-
import { readFileSync as readFileSync39, existsSync as
|
|
43241
|
+
import { readFileSync as readFileSync39, existsSync as existsSync48, statSync as statSync14 } from "node:fs";
|
|
43045
43242
|
import { join as join52, dirname as dirname29, resolve as resolve14 } from "node:path";
|
|
43046
43243
|
var PROJECT_MARKERS = [
|
|
43047
43244
|
".olam/config.yaml",
|
|
@@ -43054,10 +43251,10 @@ function findProjectRoot2(startDir) {
|
|
|
43054
43251
|
const root = resolve14("/");
|
|
43055
43252
|
while (true) {
|
|
43056
43253
|
for (const marker of PROJECT_MARKERS) {
|
|
43057
|
-
if (
|
|
43254
|
+
if (existsSync48(join52(dir, marker))) return dir;
|
|
43058
43255
|
}
|
|
43059
43256
|
const pkg = join52(dir, "package.json");
|
|
43060
|
-
if (
|
|
43257
|
+
if (existsSync48(pkg)) {
|
|
43061
43258
|
try {
|
|
43062
43259
|
const json = JSON.parse(readFileSync39(pkg, "utf8"));
|
|
43063
43260
|
const isOlamWorkspace = typeof json.name === "string" && json.name.startsWith("@olam/");
|
|
@@ -43097,7 +43294,7 @@ function loadProjectEnv(startDir = process.cwd()) {
|
|
|
43097
43294
|
const merged = {};
|
|
43098
43295
|
for (const name of [".env", ".env.local"]) {
|
|
43099
43296
|
const p = join52(root, name);
|
|
43100
|
-
if (
|
|
43297
|
+
if (existsSync48(p) && statSync14(p).isFile()) {
|
|
43101
43298
|
Object.assign(merged, parseEnvFile(p));
|
|
43102
43299
|
filesRead.push(p);
|
|
43103
43300
|
}
|
|
@@ -118,7 +118,7 @@ spec:
|
|
|
118
118
|
# k3d), started by `olam upgrade` Step 0.7 — not inside this Pod.
|
|
119
119
|
containers:
|
|
120
120
|
- name: olam-host-cp
|
|
121
|
-
image: ghcr.io/pleri/olam-host-cp@sha256:
|
|
121
|
+
image: ghcr.io/pleri/olam-host-cp@sha256:78ab85611487425028f9843dda1cf48fe32cfaac56e0ba180e37f0b7c327d2fd
|
|
122
122
|
imagePullPolicy: IfNotPresent
|
|
123
123
|
securityContext:
|
|
124
124
|
runAsNonRoot: true
|
|
@@ -70,7 +70,7 @@ spec:
|
|
|
70
70
|
mountPath: /data
|
|
71
71
|
containers:
|
|
72
72
|
- name: olam-auth-service
|
|
73
|
-
image: ghcr.io/pleri/olam-auth@sha256:
|
|
73
|
+
image: ghcr.io/pleri/olam-auth@sha256:b7f79147b521f8e7fc8f962e623334f6ae4ea98e893a3fa8f6c81f3916d01f11
|
|
74
74
|
imagePullPolicy: IfNotPresent
|
|
75
75
|
securityContext:
|
|
76
76
|
runAsNonRoot: true
|
|
@@ -61,7 +61,7 @@ spec:
|
|
|
61
61
|
mountPath: /data
|
|
62
62
|
containers:
|
|
63
63
|
- name: olam-kg-service
|
|
64
|
-
image: ghcr.io/pleri/olam-kg-service@sha256:
|
|
64
|
+
image: ghcr.io/pleri/olam-kg-service@sha256:7ca19574cc018e3ceaef7eb0421d3539aa361e1f1ab95a4df5ad400de45d9c41
|
|
65
65
|
imagePullPolicy: IfNotPresent
|
|
66
66
|
securityContext:
|
|
67
67
|
runAsNonRoot: true
|
|
@@ -68,7 +68,7 @@ spec:
|
|
|
68
68
|
mountPath: /data
|
|
69
69
|
containers:
|
|
70
70
|
- name: olam-mcp-auth-service
|
|
71
|
-
image: ghcr.io/pleri/olam-mcp-auth@sha256:
|
|
71
|
+
image: ghcr.io/pleri/olam-mcp-auth@sha256:223f5aa65736fbf0bc96b86cf01d4acf447856d18e5a5e50467eff714b922ed3
|
|
72
72
|
imagePullPolicy: IfNotPresent
|
|
73
73
|
securityContext:
|
|
74
74
|
runAsNonRoot: true
|
|
@@ -70,7 +70,7 @@ spec:
|
|
|
70
70
|
# bootstrap-placeholder comment + run `npm run refresh:manifest-digests`
|
|
71
71
|
# once ghcr.io/pleri/olam-memory-service has a real published digest.
|
|
72
72
|
# bootstrap-placeholder: pre-publish; refresh after first release
|
|
73
|
-
image: ghcr.io/pleri/olam-memory-service@sha256:
|
|
73
|
+
image: ghcr.io/pleri/olam-memory-service@sha256:5db73eab55738ac6eb79150363d6d98daf26e5bc43e626231de146e40e908015
|
|
74
74
|
imagePullPolicy: IfNotPresent
|
|
75
75
|
securityContext:
|
|
76
76
|
runAsNonRoot: true
|