@mnemom/mnemom 0.7.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.
Files changed (47) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +123 -0
  3. package/dist/commands/agents.d.ts +15 -0
  4. package/dist/commands/agents.js +303 -0
  5. package/dist/commands/auth.d.ts +5 -0
  6. package/dist/commands/auth.js +60 -0
  7. package/dist/commands/card.d.ts +23 -0
  8. package/dist/commands/card.js +460 -0
  9. package/dist/commands/claim.d.ts +1 -0
  10. package/dist/commands/claim.js +72 -0
  11. package/dist/commands/init.d.ts +7 -0
  12. package/dist/commands/init.js +763 -0
  13. package/dist/commands/integrity.d.ts +1 -0
  14. package/dist/commands/integrity.js +49 -0
  15. package/dist/commands/license.d.ts +3 -0
  16. package/dist/commands/license.js +163 -0
  17. package/dist/commands/logs.d.ts +5 -0
  18. package/dist/commands/logs.js +73 -0
  19. package/dist/commands/migrate-config.d.ts +2 -0
  20. package/dist/commands/migrate-config.js +72 -0
  21. package/dist/commands/policy.d.ts +31 -0
  22. package/dist/commands/policy.js +543 -0
  23. package/dist/commands/register.d.ts +6 -0
  24. package/dist/commands/register.js +362 -0
  25. package/dist/commands/status.d.ts +1 -0
  26. package/dist/commands/status.js +383 -0
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.js +381 -0
  29. package/dist/lib/api.d.ts +133 -0
  30. package/dist/lib/api.js +207 -0
  31. package/dist/lib/auth.d.ts +60 -0
  32. package/dist/lib/auth.js +281 -0
  33. package/dist/lib/config.d.ts +105 -0
  34. package/dist/lib/config.js +253 -0
  35. package/dist/lib/format.d.ts +35 -0
  36. package/dist/lib/format.js +60 -0
  37. package/dist/lib/model-cache.d.ts +16 -0
  38. package/dist/lib/model-cache.js +138 -0
  39. package/dist/lib/models.d.ts +41 -0
  40. package/dist/lib/models.js +357 -0
  41. package/dist/lib/openclaw.d.ts +221 -0
  42. package/dist/lib/openclaw.js +474 -0
  43. package/dist/lib/prompt.d.ts +26 -0
  44. package/dist/lib/prompt.js +150 -0
  45. package/dist/smoltbot-shim.d.ts +2 -0
  46. package/dist/smoltbot-shim.js +7 -0
  47. package/package.json +61 -0
@@ -0,0 +1 @@
1
+ export declare function integrityCommand(agentName?: string): Promise<void>;
@@ -0,0 +1,49 @@
1
+ import { requireAgent } from "../lib/config.js";
2
+ import { getIntegrity } from "../lib/api.js";
3
+ import { fmt } from "../lib/format.js";
4
+ export async function integrityCommand(agentName) {
5
+ const agent = await requireAgent(agentName);
6
+ console.log("\nFetching integrity score...\n");
7
+ try {
8
+ const integrity = await getIntegrity(agent.agentId);
9
+ const scorePercent = (integrity.score * 100).toFixed(1);
10
+ const scoreBar = generateScoreBar(integrity.score);
11
+ console.log(fmt.header("Integrity Score"));
12
+ console.log(` ${fmt.label("Score: ", `${scorePercent}% ${scoreBar}`)}`);
13
+ console.log(` ${fmt.label("Total: ", `${integrity.total_traces} traces`)}`);
14
+ console.log(` ${fmt.label("Verified: ", `${integrity.verified}`)} ${fmt.success("")}`);
15
+ console.log(` ${fmt.label("Violations:", ` ${integrity.violations}`)} ${fmt.error("")}`);
16
+ console.log(` ${fmt.label("Updated: ", integrity.last_updated)}`);
17
+ if (integrity.violations > 0) {
18
+ console.log("\n" + fmt.warn("You have integrity violations. Run `smoltbot logs` to investigate.") + "\n");
19
+ }
20
+ else if (integrity.total_traces === 0) {
21
+ console.log("\nNo traces recorded yet. Start using Claude to build your integrity score.\n");
22
+ }
23
+ else {
24
+ console.log("\n" + fmt.success("Your agent has a clean integrity record!") + "\n");
25
+ }
26
+ }
27
+ catch (error) {
28
+ const message = error instanceof Error ? error.message : String(error);
29
+ if (message.includes("404") || message.includes("not found")) {
30
+ console.log(fmt.header("Integrity Score"));
31
+ console.log(` ${fmt.label("Score: ", "N/A")}`);
32
+ console.log(` ${fmt.label("Total: ", "0 traces")}`);
33
+ console.log(` ${fmt.label("Verified: ", "0")}`);
34
+ console.log(` ${fmt.label("Violations:", " 0")}`);
35
+ console.log("\nNo traces recorded yet. Start using Claude to build your integrity score.\n");
36
+ }
37
+ else {
38
+ console.log("\n" + fmt.error(`Failed to fetch integrity score: ${message}`) + "\n");
39
+ process.exit(1);
40
+ }
41
+ }
42
+ }
43
+ function generateScoreBar(score) {
44
+ const filled = Math.round(score * 10);
45
+ const empty = 10 - filled;
46
+ const filledChar = "█";
47
+ const emptyChar = "░";
48
+ return `[${filledChar.repeat(filled)}${emptyChar.repeat(empty)}]`;
49
+ }
@@ -0,0 +1,3 @@
1
+ export declare function licenseActivateCommand(jwt: string): Promise<void>;
2
+ export declare function licenseStatusCommand(): Promise<void>;
3
+ export declare function licenseDeactivateCommand(): Promise<void>;
@@ -0,0 +1,163 @@
1
+ import { loadConfig, saveConfig, configExists } from "../lib/config.js";
2
+ import { API_BASE } from "../lib/api.js";
3
+ import { fmt } from "../lib/format.js";
4
+ /** Sanitize file-sourced data before use in outbound HTTP requests. */
5
+ function sanitizeForHttp(data) {
6
+ return String(data).trim();
7
+ }
8
+ /**
9
+ * Decode a JWT payload without verifying the signature.
10
+ */
11
+ function decodeJwtPayload(jwt) {
12
+ const parts = jwt.split(".");
13
+ if (parts.length !== 3)
14
+ return null;
15
+ try {
16
+ const padded = parts[1].replace(/-/g, "+").replace(/_/g, "/");
17
+ const padding = padded.length % 4 === 0 ? "" : "=".repeat(4 - (padded.length % 4));
18
+ return JSON.parse(Buffer.from(padded + padding, "base64").toString("utf-8"));
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
24
+ export async function licenseActivateCommand(jwt) {
25
+ if (!jwt || jwt.trim() === "") {
26
+ console.error("Error: License JWT is required");
27
+ console.error("Usage: smoltbot license activate <jwt>");
28
+ process.exit(1);
29
+ }
30
+ // Decode claims
31
+ const claims = decodeJwtPayload(jwt);
32
+ if (!claims) {
33
+ console.error("Error: Invalid JWT format");
34
+ process.exit(1);
35
+ }
36
+ console.log("\nActivating enterprise license...\n");
37
+ // Validate against API (if reachable)
38
+ const hostname = (await import("node:os")).hostname();
39
+ try {
40
+ const licenseUrl = new URL(`${API_BASE}/v1/license/validate`).href;
41
+ const response = await fetch(licenseUrl, {
42
+ method: "POST",
43
+ headers: { "Content-Type": "application/json" },
44
+ body: JSON.stringify({
45
+ license: jwt,
46
+ instance_id: hostname,
47
+ instance_metadata: {
48
+ hostname,
49
+ platform: process.platform,
50
+ cli_version: "2.1.0",
51
+ },
52
+ }),
53
+ });
54
+ if (response.ok) {
55
+ const result = (await response.json());
56
+ console.log(" License validated successfully!\n");
57
+ if (result.warning) {
58
+ console.log(` Warning: ${result.warning}\n`);
59
+ }
60
+ }
61
+ else {
62
+ const err = (await response.json());
63
+ console.log(` Warning: Validation returned ${response.status}: ${err.error || "unknown"}`);
64
+ console.log(" License stored locally (will retry validation).\n");
65
+ }
66
+ }
67
+ catch {
68
+ console.log(" Warning: Could not reach API for validation.");
69
+ console.log(" License stored locally (offline mode).\n");
70
+ }
71
+ // Store in config
72
+ const config = loadConfig();
73
+ if (!config) {
74
+ console.log("No configuration found. Run 'smoltbot init' first.");
75
+ process.exit(1);
76
+ }
77
+ config.licenseJwt = jwt;
78
+ saveConfig(config);
79
+ // Display info
80
+ const expiresAt = claims.exp ? new Date(claims.exp * 1000) : null;
81
+ const daysRemaining = expiresAt ? Math.floor((expiresAt.getTime() - Date.now()) / 86400000) : "unknown";
82
+ console.log(" License ID: " + (claims.license_id || "unknown"));
83
+ console.log(" Plan: " + (claims.plan_id || "unknown"));
84
+ console.log(" Features: " + Object.keys(claims.feature_flags || {}).filter((k) => claims.feature_flags[k]).join(", ") || "none");
85
+ console.log(" Expires: " + (expiresAt ? expiresAt.toISOString() : "unknown"));
86
+ console.log(" Days remaining: " + daysRemaining);
87
+ console.log(" Max activations: " + (claims.max_activations || "unknown"));
88
+ console.log(" Offline mode: " + (claims.is_offline ? "yes" : "no"));
89
+ console.log();
90
+ }
91
+ export async function licenseStatusCommand() {
92
+ if (!configExists()) {
93
+ console.error("Error: No smoltbot configuration found. Run 'smoltbot init' first.");
94
+ process.exit(1);
95
+ }
96
+ const config = loadConfig();
97
+ if (!config?.licenseJwt) {
98
+ console.log("\nNo enterprise license configured.");
99
+ console.log("Use 'smoltbot license activate <jwt>' to activate a license.\n");
100
+ return;
101
+ }
102
+ const claims = decodeJwtPayload(config.licenseJwt);
103
+ if (!claims) {
104
+ console.error("Error: Stored license JWT is invalid");
105
+ process.exit(1);
106
+ }
107
+ const expiresAt = claims.exp ? new Date(claims.exp * 1000) : null;
108
+ const daysRemaining = expiresAt ? Math.floor((expiresAt.getTime() - Date.now()) / 86400000) : null;
109
+ const isExpired = daysRemaining !== null && daysRemaining <= 0;
110
+ console.log(fmt.header("Enterprise License Status"));
111
+ console.log();
112
+ console.log(` ${fmt.label("License ID: ", String(claims.license_id || "unknown"))}`);
113
+ console.log(` ${fmt.label("Account: ", String(claims.account_id || "unknown"))}`);
114
+ console.log(` ${fmt.label("Plan: ", String(claims.plan_id || "unknown"))}`);
115
+ console.log(` ${fmt.label("Features: ", Object.keys(claims.feature_flags || {}).filter((k) => claims.feature_flags[k]).join(", ") || "none")}`);
116
+ console.log(` ${fmt.label("Expires: ", expiresAt ? expiresAt.toISOString() : "unknown")}`);
117
+ console.log(` ${fmt.label("Days remaining: ", String(daysRemaining ?? "unknown"))}`);
118
+ console.log(` ${fmt.label("Status: ", isExpired ? "EXPIRED" : "Active")}`);
119
+ console.log(` ${fmt.label("Max activations:", ` ${claims.max_activations || "unknown"}`)}`);
120
+ console.log(` ${fmt.label("Offline mode: ", claims.is_offline ? "yes" : "no")}`);
121
+ console.log();
122
+ if (isExpired) {
123
+ console.log(" WARNING: License has expired. Contact enterprise@mnemom.ai for renewal.\n");
124
+ }
125
+ else if (daysRemaining !== null && daysRemaining <= 30) {
126
+ console.log(` WARNING: License expires in ${daysRemaining} days.\n`);
127
+ }
128
+ }
129
+ export async function licenseDeactivateCommand() {
130
+ if (!configExists()) {
131
+ console.error("Error: No smoltbot configuration found.");
132
+ process.exit(1);
133
+ }
134
+ const config = loadConfig();
135
+ if (!config?.licenseJwt) {
136
+ console.log("\nNo enterprise license to deactivate.\n");
137
+ return;
138
+ }
139
+ // Try to deactivate via API
140
+ const claims = decodeJwtPayload(config.licenseJwt);
141
+ if (claims) {
142
+ try {
143
+ const hostname = (await import("node:os")).hostname();
144
+ const deactivateUrl = new URL(`${API_BASE}/v1/license/validate`).href;
145
+ await fetch(deactivateUrl, {
146
+ method: "POST",
147
+ headers: { "Content-Type": "application/json" },
148
+ body: sanitizeForHttp(JSON.stringify({
149
+ license: String(config.licenseJwt),
150
+ instance_id: hostname,
151
+ instance_metadata: { deactivating: true },
152
+ })),
153
+ });
154
+ }
155
+ catch {
156
+ // Best-effort
157
+ }
158
+ }
159
+ // Remove from config
160
+ delete config.licenseJwt;
161
+ saveConfig(config);
162
+ console.log("\nLicense deactivated and removed from local configuration.\n");
163
+ }
@@ -0,0 +1,5 @@
1
+ export interface LogsOptions {
2
+ limit?: number;
3
+ agentName?: string;
4
+ }
5
+ export declare function logsCommand(options?: LogsOptions): Promise<void>;
@@ -0,0 +1,73 @@
1
+ import { requireAgent, loadConfig } from "../lib/config.js";
2
+ import { getTraces } from "../lib/api.js";
3
+ import { fmt } from "../lib/format.js";
4
+ export async function logsCommand(options = {}) {
5
+ const agent = await requireAgent(options.agentName);
6
+ const config = loadConfig();
7
+ const limit = options.limit || 10;
8
+ console.log("\nFetching traces...\n");
9
+ try {
10
+ const traces = await getTraces(agent.agentId, limit);
11
+ if (traces.length === 0) {
12
+ console.log(fmt.header("No traces found"));
13
+ console.log("\nStart using Claude to generate traces.\n");
14
+ console.log("Make sure ANTHROPIC_BASE_URL is set correctly:\n");
15
+ console.log(` export ANTHROPIC_BASE_URL="${config.gateway || "https://gateway.mnemon.ai"}/v1/proxy/${agent.agentId}"\n`);
16
+ return;
17
+ }
18
+ console.log(fmt.header(`Recent Traces (${traces.length})`));
19
+ for (const trace of traces) {
20
+ displayTrace(trace);
21
+ }
22
+ console.log(`\nView more: smoltbot logs --limit ${limit + 10}`);
23
+ console.log(`Dashboard: https://mnemon.ai/dashboard/${agent.agentId}\n`);
24
+ }
25
+ catch (error) {
26
+ const message = error instanceof Error ? error.message : String(error);
27
+ if (message.includes("404") || message.includes("not found")) {
28
+ console.log(fmt.header("No traces found"));
29
+ console.log("\nStart using Claude to generate traces.\n");
30
+ }
31
+ else {
32
+ console.log("\n" + fmt.error(`Failed to fetch traces: ${message}`) + "\n");
33
+ process.exit(1);
34
+ }
35
+ }
36
+ }
37
+ function displayTrace(trace) {
38
+ const timestamp = formatTimestamp(trace.timestamp);
39
+ const statusMsg = trace.verified
40
+ ? fmt.success(timestamp)
41
+ : fmt.error(`${timestamp} [VIOLATION]`);
42
+ console.log(`\n ${statusMsg}`);
43
+ console.log(` ${fmt.label("Action:", ` ${trace.action}`)}`);
44
+ if (trace.tool_name) {
45
+ console.log(` ${fmt.label("Tool: ", ` ${trace.tool_name}`)}`);
46
+ }
47
+ if (trace.reasoning) {
48
+ const preview = truncate(trace.reasoning, 60);
49
+ console.log(` ${fmt.label("Reason:", ` ${preview}`)}`);
50
+ }
51
+ }
52
+ function formatTimestamp(iso) {
53
+ try {
54
+ const date = new Date(iso);
55
+ return date.toLocaleString("en-US", {
56
+ month: "short",
57
+ day: "numeric",
58
+ hour: "2-digit",
59
+ minute: "2-digit",
60
+ hour12: false,
61
+ });
62
+ }
63
+ catch {
64
+ return iso;
65
+ }
66
+ }
67
+ function truncate(text, maxLength) {
68
+ const cleaned = text.replace(/\n/g, " ").trim();
69
+ if (cleaned.length <= maxLength) {
70
+ return cleaned;
71
+ }
72
+ return cleaned.slice(0, maxLength - 3) + "...";
73
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function makeMigrateConfigCommand(): Command;
@@ -0,0 +1,72 @@
1
+ import * as fs from "node:fs";
2
+ import * as os from "node:os";
3
+ import * as path from "node:path";
4
+ import { Command } from "commander";
5
+ const OPENCLAW_CONFIG_PATH = path.join(os.homedir(), ".openclaw", "openclaw.json");
6
+ export function makeMigrateConfigCommand() {
7
+ const cmd = new Command("migrate-config");
8
+ cmd
9
+ .description("Migrate ~/.openclaw/openclaw.json provider keys from smoltbot* to mnemom*")
10
+ .action(async () => {
11
+ // 1. Check if OpenClaw config exists
12
+ if (!fs.existsSync(OPENCLAW_CONFIG_PATH)) {
13
+ console.log("OpenClaw not detected at ~/.openclaw/openclaw.json. Nothing to migrate.");
14
+ return;
15
+ }
16
+ // 2. Read and parse the config
17
+ let config = null;
18
+ try {
19
+ const raw = fs.readFileSync(OPENCLAW_CONFIG_PATH, "utf-8");
20
+ config = JSON.parse(raw);
21
+ }
22
+ catch {
23
+ console.error("Error: ~/.openclaw/openclaw.json is malformed JSON.");
24
+ process.exit(1);
25
+ return;
26
+ }
27
+ if (!config)
28
+ return;
29
+ // 3. Get models.providers — must be an object
30
+ const models = config.models;
31
+ const providers = models?.providers;
32
+ if (!providers || typeof providers !== "object" || Object.keys(providers).length === 0) {
33
+ console.log("No providers found.");
34
+ return;
35
+ }
36
+ // 4. Find all keys matching /^smoltbot/
37
+ const keysToMigrate = Object.keys(providers).filter((k) => /^smoltbot/.test(k));
38
+ if (keysToMigrate.length === 0) {
39
+ console.log("No smoltbot* provider keys found. Nothing to migrate.");
40
+ return;
41
+ }
42
+ // 5. Migrate each key
43
+ const migrations = [];
44
+ for (const oldKey of keysToMigrate) {
45
+ const newKey = oldKey.replace(/^smoltbot/, "mnemom");
46
+ const entry = providers[oldKey];
47
+ // Deep-copy the provider entry
48
+ const newEntry = { ...entry };
49
+ // Rename x-smoltbot-agent header if present
50
+ const defaultHeaders = newEntry.defaultHeaders;
51
+ if (defaultHeaders && "x-smoltbot-agent" in defaultHeaders) {
52
+ const headersCopy = { ...defaultHeaders };
53
+ headersCopy["x-mnemom-agent"] = headersCopy["x-smoltbot-agent"];
54
+ delete headersCopy["x-smoltbot-agent"];
55
+ newEntry.defaultHeaders = headersCopy;
56
+ }
57
+ // Remove old key, add new key
58
+ delete providers[oldKey];
59
+ providers[newKey] = newEntry;
60
+ migrations.push({ from: oldKey, to: newKey });
61
+ }
62
+ // 6. Write back
63
+ fs.writeFileSync(OPENCLAW_CONFIG_PATH, JSON.stringify(config, null, 2));
64
+ // 7. Print summary
65
+ console.log(`✓ Migrated ${migrations.length} provider${migrations.length !== 1 ? "s" : ""}:`);
66
+ for (const { from, to } of migrations) {
67
+ console.log(` ${from} → ${to}`);
68
+ }
69
+ console.log("\nYour agent config at ~/.smoltbot/ is unchanged.\n");
70
+ });
71
+ return cmd;
72
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * smoltbot policy init — scaffold a policy.json with commented examples
3
+ */
4
+ export declare function policyInitCommand(): Promise<void>;
5
+ /**
6
+ * smoltbot policy validate <file> — local-only validation
7
+ */
8
+ export declare function policyValidateCommand(file: string): Promise<void>;
9
+ /**
10
+ * smoltbot policy publish <file> — validate + upload to API
11
+ */
12
+ export declare function policyPublishCommand(file: string, agentName?: string): Promise<void>;
13
+ /**
14
+ * smoltbot policy list — list active policies for current agent
15
+ */
16
+ export declare function policyListCommand(agentName?: string): Promise<void>;
17
+ /**
18
+ * smoltbot policy test <file> --against-traces — dry-run against historical traces
19
+ */
20
+ export declare function policyTestCommand(file: string, agentName?: string): Promise<void>;
21
+ /**
22
+ * smoltbot policy evaluate <policy-file> --card <card-file> --tools <tools> — local CI/CD evaluation
23
+ *
24
+ * Runs entirely locally using the embedded policy engine. No API key needed.
25
+ */
26
+ export declare function policyEvaluateCommand(file: string, options: {
27
+ card?: string;
28
+ tools?: string;
29
+ toolManifest?: string;
30
+ strict?: boolean;
31
+ }): Promise<void>;