@mnemom/mnemom 0.7.1 → 0.8.0
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 +35 -31
- package/dist/commands/agents.d.ts +0 -14
- package/dist/commands/agents.js +35 -295
- package/dist/commands/auth.js +2 -7
- package/dist/commands/card.d.ts +21 -8
- package/dist/commands/card.js +328 -275
- package/dist/commands/integrity.js +6 -6
- package/dist/commands/license.js +14 -29
- package/dist/commands/logs.js +8 -8
- package/dist/commands/policy.d.ts +10 -23
- package/dist/commands/policy.js +20 -533
- package/dist/commands/protection.d.ts +14 -0
- package/dist/commands/protection.js +308 -0
- package/dist/commands/status.js +42 -50
- package/dist/index.js +114 -160
- package/dist/lib/api.d.ts +41 -0
- package/dist/lib/api.js +131 -1
- package/dist/lib/auth.d.ts +30 -21
- package/dist/lib/auth.js +95 -49
- package/dist/lib/config.d.ts +11 -98
- package/dist/lib/config.js +12 -220
- package/dist/lib/model-cache.js +5 -6
- package/dist/smoltbot-shim.js +1 -1
- package/package.json +2 -2
- package/dist/commands/init.d.ts +0 -7
- package/dist/commands/init.js +0 -763
- package/dist/commands/migrate-config.d.ts +0 -2
- package/dist/commands/migrate-config.js +0 -72
- package/dist/commands/register.d.ts +0 -6
- package/dist/commands/register.js +0 -362
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
5
|
+
import yaml from "js-yaml";
|
|
6
|
+
import { getProtectionCard, putProtectionCard, resolveAgentId, } from "../lib/api.js";
|
|
7
|
+
import { requireAuth } from "../lib/auth.js";
|
|
8
|
+
import { fmt } from "../lib/format.js";
|
|
9
|
+
import { askYesNo, isInteractive } from "../lib/prompt.js";
|
|
10
|
+
const VALID_MODES = new Set(["observe", "warn", "block"]);
|
|
11
|
+
/**
|
|
12
|
+
* Validate a protection card object.
|
|
13
|
+
* Schema: mode, thresholds, screen_surfaces, trusted_sources
|
|
14
|
+
*/
|
|
15
|
+
export function validateProtectionCard(card) {
|
|
16
|
+
const checks = [];
|
|
17
|
+
// mode: required, must be observe | warn | block
|
|
18
|
+
const mode = card.mode;
|
|
19
|
+
if (typeof mode === "string" && VALID_MODES.has(mode)) {
|
|
20
|
+
checks.push({ name: "mode", passed: true, message: mode });
|
|
21
|
+
}
|
|
22
|
+
else if (mode === undefined) {
|
|
23
|
+
checks.push({ name: "mode", passed: false, message: "Required (observe | warn | block)" });
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
checks.push({ name: "mode", passed: false, message: `Invalid: "${mode}". Must be observe | warn | block` });
|
|
27
|
+
}
|
|
28
|
+
// thresholds: optional, if present must have warn/quarantine/block in ascending order (0-1)
|
|
29
|
+
const thresholds = card.thresholds;
|
|
30
|
+
if (thresholds !== undefined) {
|
|
31
|
+
if (typeof thresholds !== "object" || thresholds === null) {
|
|
32
|
+
checks.push({ name: "thresholds", passed: false, message: "Must be an object" });
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
const w = thresholds.warn;
|
|
36
|
+
const q = thresholds.quarantine;
|
|
37
|
+
const b = thresholds.block;
|
|
38
|
+
if (w === undefined || q === undefined || b === undefined) {
|
|
39
|
+
checks.push({ name: "thresholds", passed: false, message: "Must have warn, quarantine, and block fields" });
|
|
40
|
+
}
|
|
41
|
+
else if (typeof w !== "number" || typeof q !== "number" || typeof b !== "number") {
|
|
42
|
+
checks.push({ name: "thresholds", passed: false, message: "Values must be numbers" });
|
|
43
|
+
}
|
|
44
|
+
else if (w < 0 || w > 1 || q < 0 || q > 1 || b < 0 || b > 1) {
|
|
45
|
+
checks.push({ name: "thresholds", passed: false, message: "Values must be between 0 and 1" });
|
|
46
|
+
}
|
|
47
|
+
else if (!(w <= q && q <= b)) {
|
|
48
|
+
checks.push({ name: "thresholds", passed: false, message: `Must be in ascending order (warn=${w} <= quarantine=${q} <= block=${b})` });
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
checks.push({ name: "thresholds", passed: true, message: `warn=${w}, quarantine=${q}, block=${b}` });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// screen_surfaces: optional, array of strings
|
|
56
|
+
const surfaces = card.screen_surfaces;
|
|
57
|
+
if (surfaces !== undefined) {
|
|
58
|
+
if (!Array.isArray(surfaces)) {
|
|
59
|
+
checks.push({ name: "screen_surfaces", passed: false, message: "Must be an array" });
|
|
60
|
+
}
|
|
61
|
+
else if (surfaces.some((s) => typeof s !== "string")) {
|
|
62
|
+
checks.push({ name: "screen_surfaces", passed: false, message: "All entries must be strings" });
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
checks.push({ name: "screen_surfaces", passed: true, message: `${surfaces.length} surface(s)` });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// trusted_sources: optional, array of objects
|
|
69
|
+
const trusted = card.trusted_sources;
|
|
70
|
+
if (trusted !== undefined) {
|
|
71
|
+
if (!Array.isArray(trusted)) {
|
|
72
|
+
checks.push({ name: "trusted_sources", passed: false, message: "Must be an array" });
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
checks.push({ name: "trusted_sources", passed: true, message: `${trusted.length} source(s)` });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return checks;
|
|
79
|
+
}
|
|
80
|
+
// ============================================================================
|
|
81
|
+
// File parsing
|
|
82
|
+
// ============================================================================
|
|
83
|
+
function parseProtectionFile(filePath) {
|
|
84
|
+
const raw = fs.readFileSync(filePath, "utf-8");
|
|
85
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
86
|
+
const format = (ext === ".yaml" || ext === ".yml") ? "yaml" : "json";
|
|
87
|
+
if (format === "yaml") {
|
|
88
|
+
const parsed = yaml.load(raw);
|
|
89
|
+
if (!parsed || typeof parsed !== "object") {
|
|
90
|
+
throw new Error("YAML did not produce a valid object");
|
|
91
|
+
}
|
|
92
|
+
return { parsed, raw, format };
|
|
93
|
+
}
|
|
94
|
+
return { parsed: JSON.parse(raw), raw, format };
|
|
95
|
+
}
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// Subcommands
|
|
98
|
+
// ============================================================================
|
|
99
|
+
export async function protectionShowCommand(agentName) {
|
|
100
|
+
const agentId = await resolveAgentId(agentName);
|
|
101
|
+
console.log("\nFetching protection card...\n");
|
|
102
|
+
try {
|
|
103
|
+
const { body, contentType } = await getProtectionCard(agentId);
|
|
104
|
+
if (!body) {
|
|
105
|
+
console.log(fmt.warn("No protection card found"));
|
|
106
|
+
console.log("\nPublish one with:\n");
|
|
107
|
+
console.log(" mnemom protection publish <file.yaml>\n");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (contentType.includes("yaml") || contentType.includes("text/yaml")) {
|
|
111
|
+
console.log(fmt.header("Protection Card"));
|
|
112
|
+
console.log();
|
|
113
|
+
console.log(body);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
const parsed = JSON.parse(body);
|
|
117
|
+
console.log(fmt.header("Protection Card"));
|
|
118
|
+
console.log();
|
|
119
|
+
console.log(yaml.dump(parsed, { lineWidth: 120, noRefs: true }));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
124
|
+
console.log("\n" + fmt.error(`Failed to fetch protection card: ${message}`) + "\n");
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export async function protectionPublishCommand(file, agentName) {
|
|
129
|
+
const agentId = await resolveAgentId(agentName);
|
|
130
|
+
const filePath = path.resolve(file);
|
|
131
|
+
if (!fs.existsSync(filePath)) {
|
|
132
|
+
console.log("\n" + fmt.error(`File not found: ${filePath}`) + "\n");
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
let parsed;
|
|
136
|
+
try {
|
|
137
|
+
parsed = parseProtectionFile(filePath);
|
|
138
|
+
}
|
|
139
|
+
catch (e) {
|
|
140
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
141
|
+
console.log("\n" + fmt.error(`Could not parse file: ${msg}`) + "\n");
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
// Validate locally
|
|
145
|
+
const checks = validateProtectionCard(parsed.parsed);
|
|
146
|
+
const allPassed = checks.every((c) => c.passed);
|
|
147
|
+
console.log(fmt.header("Protection Card Validation"));
|
|
148
|
+
console.log(fmt.label(" Format:", ` ${parsed.format.toUpperCase()}`));
|
|
149
|
+
console.log();
|
|
150
|
+
for (const check of checks) {
|
|
151
|
+
if (check.passed) {
|
|
152
|
+
console.log(fmt.success(`${check.name}: ${check.message}`));
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
console.log(fmt.error(`${check.name}: ${check.message}`));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
console.log();
|
|
159
|
+
if (!allPassed) {
|
|
160
|
+
console.log(fmt.error("Validation failed. Fix the errors above before publishing.") + "\n");
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
await requireAuth();
|
|
164
|
+
if (isInteractive()) {
|
|
165
|
+
const confirm = await askYesNo(`Publish this protection card for agent ${agentId}?`, false);
|
|
166
|
+
if (!confirm) {
|
|
167
|
+
console.log("\nPublish cancelled.\n");
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
console.log("\nPublishing protection card...");
|
|
173
|
+
const contentType = parsed.format === "yaml" ? "text/yaml" : "application/json";
|
|
174
|
+
const body = parsed.format === "yaml" ? parsed.raw : JSON.stringify(parsed.parsed);
|
|
175
|
+
const result = await putProtectionCard(agentId, body, contentType);
|
|
176
|
+
console.log(fmt.success("Protection card published!"));
|
|
177
|
+
console.log(fmt.label(" Card ID:", ` ${result.card_id}`));
|
|
178
|
+
if (result.composed) {
|
|
179
|
+
console.log(fmt.success("Canonical protection card recomposed"));
|
|
180
|
+
}
|
|
181
|
+
console.log();
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
185
|
+
console.log("\n" + fmt.error(`Failed to publish protection card: ${message}`) + "\n");
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
export async function protectionValidateCommand(file) {
|
|
190
|
+
const filePath = path.resolve(file);
|
|
191
|
+
if (!fs.existsSync(filePath)) {
|
|
192
|
+
console.log("\n" + fmt.error(`File not found: ${filePath}`) + "\n");
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
let parsed;
|
|
196
|
+
try {
|
|
197
|
+
parsed = parseProtectionFile(filePath);
|
|
198
|
+
}
|
|
199
|
+
catch (e) {
|
|
200
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
201
|
+
console.log("\n" + fmt.error(`Could not parse file: ${msg}`) + "\n");
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
const checks = validateProtectionCard(parsed.parsed);
|
|
205
|
+
const allPassed = checks.every((c) => c.passed);
|
|
206
|
+
const passCount = checks.filter((c) => c.passed).length;
|
|
207
|
+
const failCount = checks.filter((c) => !c.passed).length;
|
|
208
|
+
console.log(fmt.header("Protection Card Validation Report"));
|
|
209
|
+
console.log();
|
|
210
|
+
console.log(fmt.label(" File:", ` ${filePath}`));
|
|
211
|
+
console.log(fmt.label(" Format:", ` ${parsed.format.toUpperCase()}`));
|
|
212
|
+
console.log();
|
|
213
|
+
for (const check of checks) {
|
|
214
|
+
if (check.passed) {
|
|
215
|
+
console.log(fmt.success(`${check.name}: ${check.message}`));
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
console.log(fmt.error(`${check.name}: ${check.message}`));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
console.log();
|
|
222
|
+
if (allPassed) {
|
|
223
|
+
console.log(fmt.success(`All ${passCount} checks passed`) + "\n");
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
console.log(fmt.error(`${failCount} check(s) failed, ${passCount} passed`) + "\n");
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
export async function protectionEditCommand(agentName) {
|
|
231
|
+
const agentId = await resolveAgentId(agentName);
|
|
232
|
+
await requireAuth();
|
|
233
|
+
console.log("\nFetching current protection card...\n");
|
|
234
|
+
const { body: original } = await getProtectionCard(agentId);
|
|
235
|
+
if (!original) {
|
|
236
|
+
console.log(fmt.warn("No protection card found. Creating a template..."));
|
|
237
|
+
}
|
|
238
|
+
const cardYaml = original || yaml.dump({
|
|
239
|
+
mode: "observe",
|
|
240
|
+
thresholds: { warn: 0.3, quarantine: 0.6, block: 0.9 },
|
|
241
|
+
screen_surfaces: ["system_prompt", "tool_input", "tool_output"],
|
|
242
|
+
trusted_sources: [],
|
|
243
|
+
}, { lineWidth: 120, noRefs: true });
|
|
244
|
+
const tmpDir = os.tmpdir();
|
|
245
|
+
const tmpFile = path.join(tmpDir, `mnemom-protection-${agentId}.yaml`);
|
|
246
|
+
fs.writeFileSync(tmpFile, cardYaml);
|
|
247
|
+
const editor = process.env.EDITOR || process.env.VISUAL || "vi";
|
|
248
|
+
console.log(`Opening ${editor}...`);
|
|
249
|
+
const result = spawnSync(editor, [tmpFile], { stdio: "inherit" });
|
|
250
|
+
if (result.status !== 0) {
|
|
251
|
+
console.log("\n" + fmt.error("Editor exited with an error") + "\n");
|
|
252
|
+
try {
|
|
253
|
+
fs.unlinkSync(tmpFile);
|
|
254
|
+
}
|
|
255
|
+
catch { /* ignore */ }
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
const edited = fs.readFileSync(tmpFile, "utf-8");
|
|
259
|
+
try {
|
|
260
|
+
fs.unlinkSync(tmpFile);
|
|
261
|
+
}
|
|
262
|
+
catch { /* ignore */ }
|
|
263
|
+
if (edited === cardYaml) {
|
|
264
|
+
console.log("\nNo changes made.\n");
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
let parsed;
|
|
268
|
+
try {
|
|
269
|
+
parsed = yaml.load(edited);
|
|
270
|
+
if (!parsed || typeof parsed !== "object")
|
|
271
|
+
throw new Error("Invalid YAML");
|
|
272
|
+
}
|
|
273
|
+
catch (e) {
|
|
274
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
275
|
+
console.log("\n" + fmt.error(`Invalid YAML: ${msg}`) + "\n");
|
|
276
|
+
process.exit(1);
|
|
277
|
+
}
|
|
278
|
+
const checks = validateProtectionCard(parsed);
|
|
279
|
+
const allPassed = checks.every((c) => c.passed);
|
|
280
|
+
if (!allPassed) {
|
|
281
|
+
console.log(fmt.header("Validation Errors"));
|
|
282
|
+
console.log();
|
|
283
|
+
for (const check of checks.filter((c) => !c.passed)) {
|
|
284
|
+
console.log(fmt.error(`${check.name}: ${check.message}`));
|
|
285
|
+
}
|
|
286
|
+
console.log();
|
|
287
|
+
console.log(fmt.error("Validation failed. Card not published.") + "\n");
|
|
288
|
+
process.exit(1);
|
|
289
|
+
}
|
|
290
|
+
if (isInteractive()) {
|
|
291
|
+
const confirm = await askYesNo("Publish updated protection card?", true);
|
|
292
|
+
if (!confirm) {
|
|
293
|
+
console.log("\nPublish cancelled.\n");
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
try {
|
|
298
|
+
console.log("\nPublishing protection card...");
|
|
299
|
+
const putResult = await putProtectionCard(agentId, edited, "text/yaml");
|
|
300
|
+
console.log(fmt.success("Protection card published!"));
|
|
301
|
+
console.log(fmt.label(" Card ID:", ` ${putResult.card_id}`) + "\n");
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
305
|
+
console.log("\n" + fmt.error(`Failed to publish protection card: ${message}`) + "\n");
|
|
306
|
+
process.exit(1);
|
|
307
|
+
}
|
|
308
|
+
}
|
package/dist/commands/status.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getAgent, getIntegrity, getTraces } from "../lib/api.js";
|
|
1
|
+
import { getGatewayUrl } from "../lib/config.js";
|
|
2
|
+
import { resolveAgentId, getAgent, getIntegrity, getTraces } from "../lib/api.js";
|
|
3
|
+
import { isLoggedIn, getAuthInfo } from "../lib/auth.js";
|
|
3
4
|
import { detectOpenClaw, detectProviders, getCurrentModel, getSmoltbotConfiguredProviders, PROVIDER_CONFIG_KEYS, } from "../lib/openclaw.js";
|
|
4
5
|
import { formatModelName, detectProvider } from "../lib/models.js";
|
|
5
6
|
import { refreshModelCache } from "../lib/model-cache.js";
|
|
6
7
|
import { fmt } from "../lib/format.js";
|
|
7
|
-
const GATEWAY_URL = "https://gateway.mnemom.ai";
|
|
8
8
|
const DASHBOARD_URL = "https://mnemom.ai";
|
|
9
9
|
const PROVIDER_LABELS = {
|
|
10
10
|
anthropic: "Anthropic",
|
|
@@ -17,19 +17,20 @@ const AIP_SUPPORT = {
|
|
|
17
17
|
gemini: "Full (thought parts)",
|
|
18
18
|
};
|
|
19
19
|
export async function statusCommand(agentName) {
|
|
20
|
-
console.log(fmt.header("
|
|
20
|
+
console.log(fmt.header("mnemom status"));
|
|
21
21
|
console.log();
|
|
22
22
|
const checks = [];
|
|
23
|
-
// 1. Check
|
|
24
|
-
const
|
|
25
|
-
checks.push(
|
|
26
|
-
if (
|
|
23
|
+
// 1. Check auth status
|
|
24
|
+
const authCheck = await checkAuthStatus();
|
|
25
|
+
checks.push(authCheck);
|
|
26
|
+
if (authCheck.status === "error") {
|
|
27
27
|
printChecks(checks);
|
|
28
|
-
console.log("\nRun `
|
|
28
|
+
console.log("\nRun `mnemom login` to authenticate.\n");
|
|
29
29
|
process.exit(1);
|
|
30
30
|
}
|
|
31
|
-
|
|
32
|
-
const
|
|
31
|
+
// Resolve agent ID from server
|
|
32
|
+
const agentId = await resolveAgentId(agentName);
|
|
33
|
+
const gatewayUrl = getGatewayUrl();
|
|
33
34
|
// 2. Check OpenClaw configuration
|
|
34
35
|
const openclawCheck = checkOpenClawConfig();
|
|
35
36
|
checks.push(openclawCheck);
|
|
@@ -40,28 +41,19 @@ export async function statusCommand(agentName) {
|
|
|
40
41
|
const modelCheck = checkCurrentModel();
|
|
41
42
|
checks.push(modelCheck);
|
|
42
43
|
// 5. Test gateway connectivity
|
|
43
|
-
const gatewayCheck = await checkGatewayConnectivity();
|
|
44
|
+
const gatewayCheck = await checkGatewayConnectivity(gatewayUrl);
|
|
44
45
|
checks.push(gatewayCheck);
|
|
45
46
|
// 6. Test API connectivity
|
|
46
|
-
const apiCheck = await checkApiConnectivity(
|
|
47
|
+
const apiCheck = await checkApiConnectivity(agentId);
|
|
47
48
|
checks.push(apiCheck);
|
|
48
49
|
// Print all checks
|
|
49
50
|
printChecks(checks);
|
|
50
51
|
// Show configuration details
|
|
51
52
|
console.log(fmt.section("Configuration"));
|
|
52
53
|
console.log();
|
|
53
|
-
console.log(fmt.label("Agent ID: ",
|
|
54
|
-
console.log(fmt.label("Gateway: ",
|
|
55
|
-
console.log(fmt.label("Dashboard:", ` ${DASHBOARD_URL}/agents/${
|
|
56
|
-
if (config.mnemomApiKey) {
|
|
57
|
-
console.log(`Mnemom Key: [CONFIGURED] (billing enabled)`);
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
console.log(`Mnemom Key: Not configured (free tier)`);
|
|
61
|
-
}
|
|
62
|
-
if (agent.openclawConfigured) {
|
|
63
|
-
console.log(`Configured: ${agent.configuredAt || "yes"}`);
|
|
64
|
-
}
|
|
54
|
+
console.log(fmt.label("Agent ID: ", agentId));
|
|
55
|
+
console.log(fmt.label("Gateway: ", gatewayUrl));
|
|
56
|
+
console.log(fmt.label("Dashboard:", ` ${DASHBOARD_URL}/agents/${agentId}`));
|
|
65
57
|
// Show current model info
|
|
66
58
|
const { fullPath, provider, modelId } = getCurrentModel();
|
|
67
59
|
if (fullPath) {
|
|
@@ -76,7 +68,7 @@ export async function statusCommand(agentName) {
|
|
|
76
68
|
console.log(" Status: Traced mode NOT ACTIVE");
|
|
77
69
|
if (modelId) {
|
|
78
70
|
const detectedProvider = detectProvider(modelId);
|
|
79
|
-
const configKey = detectedProvider ? PROVIDER_CONFIG_KEYS[detectedProvider] : "
|
|
71
|
+
const configKey = detectedProvider ? PROVIDER_CONFIG_KEYS[detectedProvider] : "mnemom";
|
|
80
72
|
console.log(`\n To enable: openclaw models set ${configKey}/${modelId}`);
|
|
81
73
|
}
|
|
82
74
|
}
|
|
@@ -85,7 +77,7 @@ export async function statusCommand(agentName) {
|
|
|
85
77
|
showProviderSummary();
|
|
86
78
|
// Show trace summary if available
|
|
87
79
|
if (apiCheck.status === "ok") {
|
|
88
|
-
await showTraceSummary(
|
|
80
|
+
await showTraceSummary(agentId);
|
|
89
81
|
}
|
|
90
82
|
// Show overall status
|
|
91
83
|
const hasErrors = checks.some((c) => c.status === "error");
|
|
@@ -105,29 +97,29 @@ export async function statusCommand(agentName) {
|
|
|
105
97
|
// Refresh model cache in background (non-blocking)
|
|
106
98
|
refreshModelCache().catch(() => { });
|
|
107
99
|
}
|
|
108
|
-
function
|
|
109
|
-
|
|
100
|
+
async function checkAuthStatus() {
|
|
101
|
+
const loggedIn = await isLoggedIn();
|
|
102
|
+
if (!loggedIn) {
|
|
110
103
|
return {
|
|
111
|
-
name: "
|
|
104
|
+
name: "Authentication",
|
|
112
105
|
status: "error",
|
|
113
|
-
message: "Not
|
|
114
|
-
details: "Run `
|
|
106
|
+
message: "Not authenticated",
|
|
107
|
+
details: "Run `mnemom login` or set MNEMOM_API_KEY",
|
|
115
108
|
};
|
|
116
109
|
}
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
110
|
+
const auth = getAuthInfo();
|
|
111
|
+
if (auth) {
|
|
119
112
|
return {
|
|
120
|
-
name: "
|
|
121
|
-
status: "
|
|
122
|
-
message:
|
|
123
|
-
details: "Delete ~/.smoltbot/config.json and run `smoltbot init`",
|
|
113
|
+
name: "Authentication",
|
|
114
|
+
status: "ok",
|
|
115
|
+
message: `Logged in as ${auth.email}`,
|
|
124
116
|
};
|
|
125
117
|
}
|
|
126
|
-
|
|
118
|
+
// API key auth (no email available)
|
|
127
119
|
return {
|
|
128
|
-
name: "
|
|
120
|
+
name: "Authentication",
|
|
129
121
|
status: "ok",
|
|
130
|
-
message:
|
|
122
|
+
message: "Authenticated via API key",
|
|
131
123
|
};
|
|
132
124
|
}
|
|
133
125
|
function checkOpenClawConfig() {
|
|
@@ -146,7 +138,7 @@ function checkOpenClawConfig() {
|
|
|
146
138
|
name: "OpenClaw",
|
|
147
139
|
status: "error",
|
|
148
140
|
message: "OAuth auth (not supported)",
|
|
149
|
-
details: "
|
|
141
|
+
details: "mnemom requires API key authentication",
|
|
150
142
|
};
|
|
151
143
|
}
|
|
152
144
|
// Check if any provider has a key (not just Anthropic)
|
|
@@ -170,14 +162,14 @@ function checkOpenClawConfig() {
|
|
|
170
162
|
return {
|
|
171
163
|
name: "OpenClaw",
|
|
172
164
|
status: "warning",
|
|
173
|
-
message: "
|
|
174
|
-
details: "Run `
|
|
165
|
+
message: "mnemom provider not configured",
|
|
166
|
+
details: "Run `mnemom register <name>` to configure",
|
|
175
167
|
};
|
|
176
168
|
}
|
|
177
169
|
return {
|
|
178
170
|
name: "OpenClaw",
|
|
179
171
|
status: "ok",
|
|
180
|
-
message: "
|
|
172
|
+
message: "mnemom provider configured",
|
|
181
173
|
};
|
|
182
174
|
}
|
|
183
175
|
function checkConfiguredProviders() {
|
|
@@ -201,7 +193,7 @@ function checkConfiguredProviders() {
|
|
|
201
193
|
name: `${PROVIDER_LABELS[provider]}`,
|
|
202
194
|
status: "warning",
|
|
203
195
|
message: "API key found but not configured",
|
|
204
|
-
details: "Run `
|
|
196
|
+
details: "Run `mnemom register <name>` to configure",
|
|
205
197
|
});
|
|
206
198
|
}
|
|
207
199
|
// Don't show providers without keys (too noisy)
|
|
@@ -215,7 +207,7 @@ function checkCurrentModel() {
|
|
|
215
207
|
name: "Current Model",
|
|
216
208
|
status: "warning",
|
|
217
209
|
message: "No default model set",
|
|
218
|
-
details: "Run `openclaw models set
|
|
210
|
+
details: "Run `openclaw models set mnemom/<model>`",
|
|
219
211
|
};
|
|
220
212
|
}
|
|
221
213
|
if (provider && (provider === "smoltbot" || provider.startsWith("smoltbot"))) {
|
|
@@ -229,7 +221,7 @@ function checkCurrentModel() {
|
|
|
229
221
|
name: "Current Model",
|
|
230
222
|
status: "warning",
|
|
231
223
|
message: `${fullPath} (not traced)`,
|
|
232
|
-
details: `Switch with: openclaw models set
|
|
224
|
+
details: `Switch with: openclaw models set mnemom/${modelId}`,
|
|
233
225
|
};
|
|
234
226
|
}
|
|
235
227
|
function showProviderSummary() {
|
|
@@ -248,9 +240,9 @@ function showProviderSummary() {
|
|
|
248
240
|
console.log(` ${label}: ${configKey}/* (AIP: ${aip})`);
|
|
249
241
|
}
|
|
250
242
|
}
|
|
251
|
-
async function checkGatewayConnectivity() {
|
|
243
|
+
async function checkGatewayConnectivity(gatewayUrl) {
|
|
252
244
|
try {
|
|
253
|
-
const response = await fetch(`${
|
|
245
|
+
const response = await fetch(`${gatewayUrl}/health`, {
|
|
254
246
|
signal: AbortSignal.timeout(5000),
|
|
255
247
|
});
|
|
256
248
|
if (response.ok) {
|