@pleri/olam-cli 0.1.166 → 0.1.168
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/README.md +4 -2
- package/dist/commands/bootstrap.d.ts +6 -0
- package/dist/commands/bootstrap.d.ts.map +1 -1
- package/dist/commands/bootstrap.js +15 -0
- package/dist/commands/bootstrap.js.map +1 -1
- package/dist/commands/doctor.js +4 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +4 -3
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +103 -81
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/memory-service-container.d.ts +8 -0
- package/dist/commands/memory-service-container.d.ts.map +1 -1
- package/dist/commands/memory-service-container.js +16 -1
- package/dist/commands/memory-service-container.js.map +1 -1
- package/dist/commands/plans.d.ts +3 -0
- package/dist/commands/plans.d.ts.map +1 -0
- package/dist/commands/plans.js +211 -0
- package/dist/commands/plans.js.map +1 -0
- package/dist/commands/setup.d.ts +78 -14
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +430 -42
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/skills-source.d.ts +24 -0
- package/dist/commands/skills-source.d.ts.map +1 -1
- package/dist/commands/skills-source.js +257 -18
- package/dist/commands/skills-source.js.map +1 -1
- package/dist/commands/skills.d.ts +21 -0
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +44 -0
- package/dist/commands/skills.js.map +1 -1
- package/dist/image-digests.json +8 -7
- package/dist/index.js +2494 -1279
- package/dist/index.js.map +1 -1
- package/dist/lib/bootstrap-kubernetes.d.ts.map +1 -1
- package/dist/lib/bootstrap-kubernetes.js +178 -107
- package/dist/lib/bootstrap-kubernetes.js.map +1 -1
- package/dist/lib/health-probes.d.ts +16 -0
- package/dist/lib/health-probes.d.ts.map +1 -1
- package/dist/lib/health-probes.js +49 -0
- package/dist/lib/health-probes.js.map +1 -1
- package/dist/lib/peripheral-registry.d.ts +9 -3
- package/dist/lib/peripheral-registry.d.ts.map +1 -1
- package/dist/lib/peripheral-registry.js +4 -4
- package/dist/lib/peripheral-registry.js.map +1 -1
- package/dist/lib/plans-client.d.ts +69 -0
- package/dist/lib/plans-client.d.ts.map +1 -0
- package/dist/lib/plans-client.js +137 -0
- package/dist/lib/plans-client.js.map +1 -0
- package/dist/lib/port-forward.js +1 -1
- package/dist/lib/port-forward.js.map +1 -1
- package/dist/lib/upgrade-kubernetes.d.ts +1 -1
- package/dist/lib/upgrade-kubernetes.d.ts.map +1 -1
- package/dist/lib/upgrade-kubernetes.js +35 -21
- package/dist/lib/upgrade-kubernetes.js.map +1 -1
- package/dist/mcp-server.js +1239 -343
- 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/halt-detect.mjs +43 -0
- package/host-cp/src/panic-counter.mjs +94 -0
- package/host-cp/src/plan-chat-service.mjs +12 -1
- package/host-cp/src/server.mjs +75 -0
- package/package.json +1 -1
package/dist/commands/init.js
CHANGED
|
@@ -10,35 +10,38 @@
|
|
|
10
10
|
* Multiple matches → stderr error, skip. Zero matches → silent skip.
|
|
11
11
|
* Existing value → never overwrite.
|
|
12
12
|
*/
|
|
13
|
-
import * as fs from
|
|
14
|
-
import * as path from
|
|
15
|
-
import { execSync } from
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
13
|
+
import * as fs from "node:fs";
|
|
14
|
+
import * as path from "node:path";
|
|
15
|
+
import { execSync } from "node:child_process";
|
|
16
|
+
import { randomUUID } from "node:crypto";
|
|
17
|
+
import pc from "picocolors";
|
|
18
|
+
import { printError, printInfo, printHeader } from "../output.js";
|
|
19
|
+
import { ensureProjectWorkspaceFromConfig } from "./workspace.js";
|
|
20
|
+
import { OLAM_CONFIG_PATH } from "../lib/config.js";
|
|
20
21
|
function detectProjectType(root) {
|
|
21
|
-
if (fs.existsSync(path.join(root,
|
|
22
|
-
fs.existsSync(path.join(root,
|
|
23
|
-
return
|
|
24
|
-
if (fs.existsSync(path.join(root,
|
|
25
|
-
return
|
|
26
|
-
if (fs.existsSync(path.join(root,
|
|
27
|
-
fs.existsSync(path.join(root,
|
|
28
|
-
return
|
|
29
|
-
return
|
|
22
|
+
if (fs.existsSync(path.join(root, "Gemfile")) ||
|
|
23
|
+
fs.existsSync(path.join(root, "config", "routes.rb")))
|
|
24
|
+
return "rails";
|
|
25
|
+
if (fs.existsSync(path.join(root, "package.json")))
|
|
26
|
+
return "node";
|
|
27
|
+
if (fs.existsSync(path.join(root, "pyproject.toml")) ||
|
|
28
|
+
fs.existsSync(path.join(root, "requirements.txt")))
|
|
29
|
+
return "python";
|
|
30
|
+
return "generic";
|
|
30
31
|
}
|
|
31
32
|
function getRepoName(root) {
|
|
32
33
|
try {
|
|
33
|
-
const url = execSync(
|
|
34
|
+
const url = execSync("git remote get-url origin", {
|
|
34
35
|
cwd: root,
|
|
35
|
-
encoding:
|
|
36
|
+
encoding: "utf-8",
|
|
36
37
|
}).trim();
|
|
37
38
|
const match = url.match(/\/([^/]+?)(?:\.git)?$/);
|
|
38
39
|
if (match)
|
|
39
40
|
return match[1];
|
|
40
41
|
}
|
|
41
|
-
catch {
|
|
42
|
+
catch {
|
|
43
|
+
/* fallback */
|
|
44
|
+
}
|
|
42
45
|
return path.basename(root);
|
|
43
46
|
}
|
|
44
47
|
/**
|
|
@@ -52,9 +55,11 @@ function getRepoName(root) {
|
|
|
52
55
|
*/
|
|
53
56
|
export function detectK3dOlamContexts(execFn = (cmd, opts) => execSync(cmd, opts)) {
|
|
54
57
|
try {
|
|
55
|
-
const raw = execFn(
|
|
58
|
+
const raw = execFn("kubectl config get-contexts -o name", {
|
|
59
|
+
encoding: "utf-8",
|
|
60
|
+
});
|
|
56
61
|
const contexts = raw
|
|
57
|
-
.split(
|
|
62
|
+
.split("\n")
|
|
58
63
|
.map((l) => l.trim())
|
|
59
64
|
.filter((l) => /^k3d-olam-/.test(l));
|
|
60
65
|
return { contexts };
|
|
@@ -80,36 +85,53 @@ export function applyKubectlContextPin(contexts, opts = {}) {
|
|
|
80
85
|
const configPath = opts.configPath ?? OLAM_CONFIG_PATH;
|
|
81
86
|
const readFn = opts.readFileSyncFn ?? fs.readFileSync;
|
|
82
87
|
const writeFn = opts.writeFileSyncFn ?? fs.writeFileSync;
|
|
88
|
+
const mkdirFn = opts.mkdirSyncFn ?? fs.mkdirSync;
|
|
83
89
|
if (contexts.length === 0) {
|
|
84
|
-
return { skipped:
|
|
90
|
+
return { skipped: "no ^k3d-olam- contexts found" };
|
|
85
91
|
}
|
|
86
92
|
if (contexts.length > 1) {
|
|
87
|
-
return {
|
|
93
|
+
return {
|
|
94
|
+
refused: `multiple ^k3d-olam- contexts found: ${contexts.join(", ")} — set host.kubectl_context_pinned manually`,
|
|
95
|
+
};
|
|
88
96
|
}
|
|
89
97
|
const context = contexts[0];
|
|
90
98
|
// Read existing config raw to preserve unknown fields (kubectl_context_pinned
|
|
91
99
|
// is not in OlamConfig strict type; we patch the JSON directly).
|
|
92
100
|
let parsed = {};
|
|
93
101
|
try {
|
|
94
|
-
const raw = readFn(configPath,
|
|
102
|
+
const raw = readFn(configPath, "utf8");
|
|
95
103
|
parsed = JSON.parse(raw);
|
|
96
104
|
}
|
|
97
105
|
catch {
|
|
98
|
-
// File absent or malformed —
|
|
99
|
-
|
|
106
|
+
// File absent or malformed — seed a schema-valid baseline so readConfig
|
|
107
|
+
// won't overwrite kubectl_context_pinned when it validates the schema later.
|
|
108
|
+
// Mirrors makeDefaultConfig() in config.ts.
|
|
109
|
+
parsed = {
|
|
110
|
+
"config.schema": 1,
|
|
111
|
+
host: { substrate: "kubernetes" },
|
|
112
|
+
install_id: randomUUID(),
|
|
113
|
+
};
|
|
100
114
|
}
|
|
101
|
-
const host =
|
|
115
|
+
const host = typeof parsed.host === "object" && parsed.host !== null
|
|
102
116
|
? parsed.host
|
|
103
117
|
: {};
|
|
104
118
|
// Never overwrite an existing value.
|
|
105
|
-
if (typeof host[
|
|
106
|
-
|
|
119
|
+
if (typeof host["kubectl_context_pinned"] === "string" &&
|
|
120
|
+
host["kubectl_context_pinned"].length > 0) {
|
|
121
|
+
return {
|
|
122
|
+
skipped: `kubectl_context_pinned already set to ${host["kubectl_context_pinned"]}`,
|
|
123
|
+
};
|
|
107
124
|
}
|
|
108
125
|
const next = {
|
|
109
126
|
...parsed,
|
|
110
127
|
host: { ...host, kubectl_context_pinned: context },
|
|
111
128
|
};
|
|
112
|
-
|
|
129
|
+
// Ensure parent dir exists (e.g. ~/.olam/ may not exist on fresh machines
|
|
130
|
+
// where Phase 2.6 runs before any other step that would create it).
|
|
131
|
+
mkdirFn(path.dirname(configPath), { recursive: true });
|
|
132
|
+
writeFn(configPath, JSON.stringify(next, null, 2) + "\n", {
|
|
133
|
+
encoding: "utf8",
|
|
134
|
+
});
|
|
113
135
|
return { pinned: context };
|
|
114
136
|
}
|
|
115
137
|
/**
|
|
@@ -124,7 +146,7 @@ export function applyKubectlContextPin(contexts, opts = {}) {
|
|
|
124
146
|
export function findProjectRoot(startDir) {
|
|
125
147
|
let current = path.resolve(startDir);
|
|
126
148
|
while (true) {
|
|
127
|
-
if (fs.existsSync(path.join(current,
|
|
149
|
+
if (fs.existsSync(path.join(current, ".git")))
|
|
128
150
|
return current;
|
|
129
151
|
const parent = path.dirname(current);
|
|
130
152
|
if (parent === current)
|
|
@@ -134,15 +156,15 @@ export function findProjectRoot(startDir) {
|
|
|
134
156
|
}
|
|
135
157
|
export function registerInit(program) {
|
|
136
158
|
program
|
|
137
|
-
.command(
|
|
138
|
-
.description(
|
|
139
|
-
.option(
|
|
140
|
-
.option(
|
|
159
|
+
.command("init")
|
|
160
|
+
.description("Initialize olam in the current project")
|
|
161
|
+
.option("--path <path>", "Project root path", process.cwd())
|
|
162
|
+
.option("--skip-pleri", "Skip Pleri setup")
|
|
141
163
|
.action(async (opts) => {
|
|
142
164
|
try {
|
|
143
165
|
const projectRoot = findProjectRoot(opts.path);
|
|
144
|
-
const olamDir = path.join(projectRoot,
|
|
145
|
-
if (fs.existsSync(path.join(olamDir,
|
|
166
|
+
const olamDir = path.join(projectRoot, ".olam");
|
|
167
|
+
if (fs.existsSync(path.join(olamDir, "config.yaml"))) {
|
|
146
168
|
printError(`Already initialized at ${olamDir}/config.yaml`);
|
|
147
169
|
process.exitCode = 1;
|
|
148
170
|
return;
|
|
@@ -151,58 +173,58 @@ export function registerInit(program) {
|
|
|
151
173
|
const repoName = getRepoName(projectRoot);
|
|
152
174
|
let remoteUrl;
|
|
153
175
|
try {
|
|
154
|
-
remoteUrl = execSync(
|
|
176
|
+
remoteUrl = execSync("git remote get-url origin", {
|
|
155
177
|
cwd: projectRoot,
|
|
156
|
-
encoding:
|
|
178
|
+
encoding: "utf-8",
|
|
157
179
|
}).trim();
|
|
158
180
|
}
|
|
159
181
|
catch {
|
|
160
182
|
remoteUrl = `git@github.com:your-org/${repoName}.git`;
|
|
161
183
|
}
|
|
162
|
-
fs.mkdirSync(path.join(olamDir,
|
|
163
|
-
fs.mkdirSync(path.join(olamDir,
|
|
184
|
+
fs.mkdirSync(path.join(olamDir, "state"), { recursive: true });
|
|
185
|
+
fs.mkdirSync(path.join(olamDir, "thoughts"), { recursive: true });
|
|
164
186
|
const pleriSection = opts.skipPleri
|
|
165
|
-
?
|
|
166
|
-
:
|
|
187
|
+
? "# pleri:\n# base_url: ${PLERI_BASE_URL}\n# plane_id: ${PLERI_PLANE_ID}\n# api_key: ${PLERI_API_KEY}\n"
|
|
188
|
+
: "pleri:\n base_url: ${PLERI_BASE_URL}\n plane_id: ${PLERI_PLANE_ID}\n api_key: ${PLERI_API_KEY}\n";
|
|
167
189
|
const config = [
|
|
168
|
-
|
|
169
|
-
|
|
190
|
+
"version: 2",
|
|
191
|
+
"",
|
|
170
192
|
pleriSection,
|
|
171
|
-
|
|
193
|
+
"repos:",
|
|
172
194
|
` - name: ${repoName}`,
|
|
173
195
|
` url: ${remoteUrl}`,
|
|
174
196
|
` path: ${projectRoot}`,
|
|
175
197
|
` type: ${projectType}`,
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
].join(
|
|
193
|
-
fs.writeFileSync(path.join(olamDir,
|
|
198
|
+
" services: []",
|
|
199
|
+
"",
|
|
200
|
+
"compute:",
|
|
201
|
+
" default: docker",
|
|
202
|
+
"",
|
|
203
|
+
"cost:",
|
|
204
|
+
" # All values in USD (Anthropic's billing currency).",
|
|
205
|
+
" # Convert from your local currency: USD 25 ≈ SGD 33 / EUR 23 / GBP 20",
|
|
206
|
+
" # at typical 2026 rates. Dashboard display localization is a future feature.",
|
|
207
|
+
" max_per_world_usd: 25",
|
|
208
|
+
" max_daily_usd: 100",
|
|
209
|
+
" warning_threshold: 0.8",
|
|
210
|
+
"",
|
|
211
|
+
"auth:",
|
|
212
|
+
" mode: oauth",
|
|
213
|
+
"",
|
|
214
|
+
].join("\n");
|
|
215
|
+
fs.writeFileSync(path.join(olamDir, "config.yaml"), config);
|
|
194
216
|
const envExample = [
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
].join(
|
|
201
|
-
fs.writeFileSync(path.join(olamDir,
|
|
202
|
-
printHeader(
|
|
203
|
-
printInfo(
|
|
204
|
-
printInfo(
|
|
205
|
-
printInfo(
|
|
217
|
+
"# Pleri credentials",
|
|
218
|
+
"PLERI_BASE_URL=https://pleri.dev/api",
|
|
219
|
+
"PLERI_PLANE_ID=",
|
|
220
|
+
"PLERI_API_KEY=",
|
|
221
|
+
"",
|
|
222
|
+
].join("\n");
|
|
223
|
+
fs.writeFileSync(path.join(olamDir, ".env.example"), envExample);
|
|
224
|
+
printHeader("Olam initialized");
|
|
225
|
+
printInfo("Config", `${olamDir}/config.yaml`);
|
|
226
|
+
printInfo("Project", `${projectType} (detected)`);
|
|
227
|
+
printInfo("Repo", repoName);
|
|
206
228
|
// Auto-register this project as a host-catalog workspace so
|
|
207
229
|
// `olam create --workspace <repo>` works from anywhere. Tolerant
|
|
208
230
|
// of failure — init must not bail just because workspace write
|
|
@@ -210,10 +232,10 @@ export function registerInit(program) {
|
|
|
210
232
|
try {
|
|
211
233
|
const result = ensureProjectWorkspaceFromConfig(projectRoot, repoName);
|
|
212
234
|
if (result.created) {
|
|
213
|
-
printInfo(
|
|
235
|
+
printInfo("Workspace", `${repoName} → ${result.file}`);
|
|
214
236
|
}
|
|
215
237
|
else {
|
|
216
|
-
printInfo(
|
|
238
|
+
printInfo("Workspace", `${repoName} (already registered)`);
|
|
217
239
|
}
|
|
218
240
|
}
|
|
219
241
|
catch (err) {
|
|
@@ -223,11 +245,11 @@ export function registerInit(program) {
|
|
|
223
245
|
const { contexts } = detectK3dOlamContexts();
|
|
224
246
|
if (contexts !== null) {
|
|
225
247
|
const pinResult = applyKubectlContextPin(contexts);
|
|
226
|
-
if (
|
|
227
|
-
printInfo(
|
|
248
|
+
if ("pinned" in pinResult) {
|
|
249
|
+
printInfo("kubectl context", `${pinResult.pinned} (auto-pinned)`);
|
|
228
250
|
}
|
|
229
|
-
else if (
|
|
230
|
-
process.stderr.write(`${pc.yellow(
|
|
251
|
+
else if ("refused" in pinResult) {
|
|
252
|
+
process.stderr.write(`${pc.yellow("warn:")} ${pinResult.refused}\n`);
|
|
231
253
|
}
|
|
232
254
|
// skipped → silent
|
|
233
255
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,6 +38,14 @@ export declare class MemoryServiceContainerController {
|
|
|
38
38
|
private imageExists;
|
|
39
39
|
/**
|
|
40
40
|
* Resolve the first available image tag: local → dev → published.
|
|
41
|
+
*
|
|
42
|
+
* The preferred path is :local (populated by `olam bootstrap` pulling the
|
|
43
|
+
* digest-pinned image and tagging it). The :published fallback is `:latest`
|
|
44
|
+
* which is NOT digest-pinned — Docker will pull whatever tag-head is on
|
|
45
|
+
* the registry at pull time. This is the degraded-mode path for operators
|
|
46
|
+
* whose image-digests.json predates the G1 memory-service digest fix; it
|
|
47
|
+
* is intentionally loud so they know they are not on the pinned path.
|
|
48
|
+
*
|
|
41
49
|
* Throws if none exist (operator should run `olam bootstrap` to pull, or
|
|
42
50
|
* `node packages/cli/scripts/build-memory-service-image.mjs` to build locally).
|
|
43
51
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-service-container.d.ts","sourceRoot":"","sources":["../../src/commands/memory-service-container.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;
|
|
1
|
+
{"version":3,"file":"memory-service-container.d.ts","sourceRoot":"","sources":["../../src/commands/memory-service-container.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AASH,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAC9D,eAAO,MAAM,wBAAwB,8BAA8B,CAAC;AACpE,eAAO,MAAM,4BAA4B,6CAA6C,CAAC;AACvF,eAAO,MAAM,sBAAsB,4BAA4B,CAAC;AAChE,eAAO,MAAM,yBAAyB,4CAA8D,CAAC;AAKrG,eAAO,MAAM,gCAAgC,QAAS,CAAC;AAOvD,KAAK,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAeD,qBAAa,gCAAgC;IAC3C,OAAO,CAAC,QAAQ,CAAoC;IAEpD,MAAM,IAAI,mBAAmB;IAiB7B,OAAO,CAAC,WAAW;IAInB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,YAAY;IAkBpB;;;;;;;;;OASG;IACH,KAAK,IAAI,IAAI;IA6Cb;;;;;OAKG;IACH,sBAAsB,IAAI,OAAO;IAQjC,IAAI,IAAI,IAAI;IAMZ,MAAM,IAAI,IAAI;IAId;;;;;;;;;OASG;IACG,YAAY,CAAC,SAAS,SAAmC,GAAG,OAAO,CAAC,OAAO,CAAC;CAoBnF"}
|
|
@@ -23,6 +23,7 @@ import * as fs from 'node:fs';
|
|
|
23
23
|
import { homedir } from 'node:os';
|
|
24
24
|
import { join } from 'node:path';
|
|
25
25
|
import { ensureMemorySecret } from '../lib/memory-secret.js';
|
|
26
|
+
import { printWarning } from '../output.js';
|
|
26
27
|
export const MEMORY_SERVICE_PORT = 3111;
|
|
27
28
|
export const MEMORY_SERVICE_CONTAINER = 'olam-memory-service';
|
|
28
29
|
export const MEMORY_SERVICE_LOCAL_TAG = 'olam-memory-service:local';
|
|
@@ -68,14 +69,28 @@ export class MemoryServiceContainerController {
|
|
|
68
69
|
}
|
|
69
70
|
/**
|
|
70
71
|
* Resolve the first available image tag: local → dev → published.
|
|
72
|
+
*
|
|
73
|
+
* The preferred path is :local (populated by `olam bootstrap` pulling the
|
|
74
|
+
* digest-pinned image and tagging it). The :published fallback is `:latest`
|
|
75
|
+
* which is NOT digest-pinned — Docker will pull whatever tag-head is on
|
|
76
|
+
* the registry at pull time. This is the degraded-mode path for operators
|
|
77
|
+
* whose image-digests.json predates the G1 memory-service digest fix; it
|
|
78
|
+
* is intentionally loud so they know they are not on the pinned path.
|
|
79
|
+
*
|
|
71
80
|
* Throws if none exist (operator should run `olam bootstrap` to pull, or
|
|
72
81
|
* `node packages/cli/scripts/build-memory-service-image.mjs` to build locally).
|
|
73
82
|
*/
|
|
74
83
|
resolveImage() {
|
|
75
|
-
for (const tag of [MEMORY_SERVICE_LOCAL_TAG, MEMORY_SERVICE_DEV_TAG
|
|
84
|
+
for (const tag of [MEMORY_SERVICE_LOCAL_TAG, MEMORY_SERVICE_DEV_TAG]) {
|
|
76
85
|
if (this.imageExists(tag))
|
|
77
86
|
return tag;
|
|
78
87
|
}
|
|
88
|
+
if (this.imageExists(MEMORY_SERVICE_PUBLISHED_TAG)) {
|
|
89
|
+
printWarning(`memory-service: using tag-pulled fallback image (${MEMORY_SERVICE_PUBLISHED_TAG}). ` +
|
|
90
|
+
'This image was NOT pulled by digest. Run `olam bootstrap` to pull the ' +
|
|
91
|
+
'digest-pinned image and eliminate this warning.');
|
|
92
|
+
return MEMORY_SERVICE_PUBLISHED_TAG;
|
|
93
|
+
}
|
|
79
94
|
throw new Error(`memory-service image not found. Tried: ${MEMORY_SERVICE_LOCAL_TAG}, ${MEMORY_SERVICE_DEV_TAG}, ${MEMORY_SERVICE_PUBLISHED_TAG}. ` +
|
|
80
95
|
'Run `olam bootstrap` to pull the published image, or `node packages/cli/scripts/build-memory-service-image.mjs` to build locally.');
|
|
81
96
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-service-container.js","sourceRoot":"","sources":["../../src/commands/memory-service-container.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"memory-service-container.js","sourceRoot":"","sources":["../../src/commands/memory-service-container.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plans.d.ts","sourceRoot":"","sources":["../../src/commands/plans.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BzC,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsLpD"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
// B5 — `olam plans` subcommand surface.
|
|
2
|
+
//
|
|
3
|
+
// olam plans list # list operator's plans
|
|
4
|
+
// olam plans show <plan-id> # plan metadata + cost
|
|
5
|
+
// olam plans rm <plan-id> # destroy (confirms active)
|
|
6
|
+
// olam plans pin <plan-id> --days <n> # exempt from TTL (queued)
|
|
7
|
+
// olam plans unpin <plan-id> # release pin (queued)
|
|
8
|
+
// olam plans re-register <plan-id> --token <ct> # T6 recovery
|
|
9
|
+
//
|
|
10
|
+
// Operator identity: --operator <id> flag OR $OLAM_OPERATOR_ID env.
|
|
11
|
+
// Defaults to '$OLAM_OPERATOR_ID || "default"' — single-operator dogfood
|
|
12
|
+
// path. Multi-operator support follows the A11 vault-sync flow.
|
|
13
|
+
import { PlansClient, PlansClientError, resolveCloudConfig } from '../lib/plans-client.js';
|
|
14
|
+
import { printError, printSuccess, printHeader, printWarning } from '../output.js';
|
|
15
|
+
function defaultOperatorId() {
|
|
16
|
+
return process.env.OLAM_OPERATOR_ID ?? 'default';
|
|
17
|
+
}
|
|
18
|
+
function makeClient() {
|
|
19
|
+
const cfg = resolveCloudConfig();
|
|
20
|
+
if (!cfg) {
|
|
21
|
+
printError('Olam Cloud not configured. Set OLAM_CLOUD_URL (e.g. https://olam-plan-agent.<account>.workers.dev) ' +
|
|
22
|
+
'and OLAM_SHOWCASE_PASSWORD, OR write them to ~/.olam/cloud-url + ~/.olam/showcase-password.');
|
|
23
|
+
process.exit(2);
|
|
24
|
+
}
|
|
25
|
+
return new PlansClient(cfg);
|
|
26
|
+
}
|
|
27
|
+
function formatPlanRow(plan) {
|
|
28
|
+
const lastActive = plan.last_active_at
|
|
29
|
+
? new Date(plan.last_active_at).toISOString().replace('T', ' ').slice(0, 16)
|
|
30
|
+
: 'never';
|
|
31
|
+
const pinFlag = plan.pinned_until ? ' [pinned]' : '';
|
|
32
|
+
return ` ${plan.plan_id.padEnd(36)} ${plan.status.padEnd(10)} ${plan.mode.padEnd(6)} ${lastActive}${pinFlag}`;
|
|
33
|
+
}
|
|
34
|
+
export function registerPlans(program) {
|
|
35
|
+
const plans = program.command('plans').description('Manage Olam Cloud plans (list / show / rm / re-register)');
|
|
36
|
+
plans
|
|
37
|
+
.command('list')
|
|
38
|
+
.description('List your cloud plans')
|
|
39
|
+
.option('--operator <id>', 'Operator id', defaultOperatorId())
|
|
40
|
+
.action(async (opts) => {
|
|
41
|
+
const client = makeClient();
|
|
42
|
+
try {
|
|
43
|
+
const rows = await client.list(opts.operator);
|
|
44
|
+
if (rows.length === 0) {
|
|
45
|
+
printHeader(`No cloud plans for operator '${opts.operator}'.`);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
printHeader(`${rows.length} plan(s) for operator '${opts.operator}':`);
|
|
49
|
+
// eslint-disable-next-line no-console
|
|
50
|
+
console.log(' ' + 'plan_id'.padEnd(36) + ' ' + 'status'.padEnd(10) +
|
|
51
|
+
' ' + 'mode'.padEnd(6) + ' ' + 'last_active_at');
|
|
52
|
+
for (const row of rows) {
|
|
53
|
+
// eslint-disable-next-line no-console
|
|
54
|
+
console.log(formatPlanRow(row));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
printError(`list failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
plans
|
|
63
|
+
.command('show <plan-id>')
|
|
64
|
+
.description('Show plan details')
|
|
65
|
+
.option('--operator <id>', 'Operator id', defaultOperatorId())
|
|
66
|
+
.action(async (planId, opts) => {
|
|
67
|
+
const client = makeClient();
|
|
68
|
+
try {
|
|
69
|
+
const row = await client.show(planId, opts.operator);
|
|
70
|
+
// eslint-disable-next-line no-console
|
|
71
|
+
console.log(JSON.stringify(row, null, 2));
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
if (err instanceof PlansClientError && err.status === 404) {
|
|
75
|
+
printError(`plan '${planId}' not found (or not yours).`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
printError(`show failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
plans
|
|
83
|
+
.command('rm <plan-id>')
|
|
84
|
+
.description('Destroy a plan (confirms when active)')
|
|
85
|
+
.option('--operator <id>', 'Operator id', defaultOperatorId())
|
|
86
|
+
.option('--force', 'Skip the active-plan confirmation prompt', false)
|
|
87
|
+
.action(async (planId, opts) => {
|
|
88
|
+
const client = makeClient();
|
|
89
|
+
try {
|
|
90
|
+
if (!opts.force) {
|
|
91
|
+
try {
|
|
92
|
+
const row = await client.show(planId, opts.operator);
|
|
93
|
+
if (row.status === 'active') {
|
|
94
|
+
printWarning(`plan '${planId}' is ACTIVE. Re-run with --force to destroy, or wait for halt/destruction.`);
|
|
95
|
+
process.exit(2);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
if (!(err instanceof PlansClientError) || err.status !== 404)
|
|
100
|
+
throw err;
|
|
101
|
+
// 404 = nothing to confirm; remove() will no-op
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
await client.remove(planId, opts.operator);
|
|
105
|
+
printSuccess(`plan '${planId}' destroyed.`);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
printError(`rm failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
plans
|
|
113
|
+
.command('pin <plan-id>')
|
|
114
|
+
.description('Pin a plan to skip TTL pruner (queued — B5+ wires the endpoint)')
|
|
115
|
+
.option('--operator <id>', 'Operator id', defaultOperatorId())
|
|
116
|
+
.option('--days <n>', 'How many days to pin for', '30')
|
|
117
|
+
.action(async (planId, opts) => {
|
|
118
|
+
const client = makeClient();
|
|
119
|
+
const days = Number.parseInt(opts.days, 10);
|
|
120
|
+
if (!Number.isFinite(days) || days <= 0) {
|
|
121
|
+
printError('--days must be a positive integer');
|
|
122
|
+
process.exit(2);
|
|
123
|
+
}
|
|
124
|
+
const pinnedUntil = Date.now() + days * 24 * 60 * 60 * 1000;
|
|
125
|
+
try {
|
|
126
|
+
await client.pin(planId, opts.operator, pinnedUntil);
|
|
127
|
+
printSuccess(`plan '${planId}' pinned until ${new Date(pinnedUntil).toISOString()}`);
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
printError(`pin failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
plans
|
|
135
|
+
.command('unpin <plan-id>')
|
|
136
|
+
.description('Release a plan pin (queued — B5+ wires the endpoint)')
|
|
137
|
+
.option('--operator <id>', 'Operator id', defaultOperatorId())
|
|
138
|
+
.action(async (planId, opts) => {
|
|
139
|
+
const client = makeClient();
|
|
140
|
+
try {
|
|
141
|
+
await client.unpin(planId, opts.operator);
|
|
142
|
+
printSuccess(`plan '${planId}' unpinned.`);
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
printError(`unpin failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
// C6 admin --aggregate subcommand. Requires both showcase Basic
|
|
150
|
+
// auth (relay layer at plan-DO) AND ROTATE_SALT_ADMIN_SECRET
|
|
151
|
+
// (auth-Worker handler layer). Used for gate #3 measurement:
|
|
152
|
+
// ≥3 operators × ≥5 plans each.
|
|
153
|
+
const admin = plans.command('admin').description('Admin operations (require admin secret)');
|
|
154
|
+
admin
|
|
155
|
+
.command('aggregate')
|
|
156
|
+
.description('Aggregate plan stats by operator (gate #3 measurement)')
|
|
157
|
+
.option('--admin-secret <s>', 'ROTATE_SALT_ADMIN_SECRET (or $OLAM_ADMIN_SECRET)')
|
|
158
|
+
.option('--json', 'Output raw JSON instead of the table view', false)
|
|
159
|
+
.action(async (opts) => {
|
|
160
|
+
const client = makeClient();
|
|
161
|
+
const adminSecret = opts.adminSecret ?? process.env.OLAM_ADMIN_SECRET ?? '';
|
|
162
|
+
if (!adminSecret) {
|
|
163
|
+
printError('--admin-secret or $OLAM_ADMIN_SECRET required.');
|
|
164
|
+
process.exit(2);
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
const result = await client.adminAggregate(adminSecret);
|
|
168
|
+
if (opts.json) {
|
|
169
|
+
// eslint-disable-next-line no-console
|
|
170
|
+
console.log(JSON.stringify(result, null, 2));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
printHeader(`${result.count} operator(s):`);
|
|
174
|
+
// eslint-disable-next-line no-console
|
|
175
|
+
console.log(' ' + 'operator_id'.padEnd(22) +
|
|
176
|
+
' ' + 'plans'.padEnd(7) +
|
|
177
|
+
' ' + 'active'.padEnd(7) +
|
|
178
|
+
' ' + 'usd_lifetime'.padEnd(14) +
|
|
179
|
+
' ' + 'days_active');
|
|
180
|
+
for (const op of result.operators) {
|
|
181
|
+
const usd = `$${op.usd_lifetime.toFixed(2)}`;
|
|
182
|
+
// eslint-disable-next-line no-console
|
|
183
|
+
console.log(' ' + op.operator_id.padEnd(22) +
|
|
184
|
+
' ' + String(op.plan_count).padEnd(7) +
|
|
185
|
+
' ' + String(op.active_count).padEnd(7) +
|
|
186
|
+
' ' + usd.padEnd(14) +
|
|
187
|
+
' ' + op.days_active);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
printError(`aggregate failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
plans
|
|
196
|
+
.command('re-register <plan-id>')
|
|
197
|
+
.description('Apply a Decision 15 confirmation_token to re-register a halted plan')
|
|
198
|
+
.requiredOption('--token <ct>', 'confirmation_token from the recovery channel')
|
|
199
|
+
.action(async (planId, opts) => {
|
|
200
|
+
const client = makeClient();
|
|
201
|
+
try {
|
|
202
|
+
await client.reregister(planId, opts.token);
|
|
203
|
+
printSuccess(`plan '${planId}' re-registered; status=active.`);
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
printError(`re-register failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=plans.js.map
|