@mnemom/smoltbot 2.0.1
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/LICENSE +191 -0
- package/README.md +119 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.js +235 -0
- package/dist/commands/integrity.d.ts +1 -0
- package/dist/commands/integrity.js +63 -0
- package/dist/commands/logs.d.ts +4 -0
- package/dist/commands/logs.js +86 -0
- package/dist/commands/status.d.ts +1 -0
- package/dist/commands/status.js +299 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +63 -0
- package/dist/lib/api.d.ts +34 -0
- package/dist/lib/api.js +22 -0
- package/dist/lib/config.d.ts +18 -0
- package/dist/lib/config.js +40 -0
- package/dist/lib/models.d.ts +32 -0
- package/dist/lib/models.js +189 -0
- package/dist/lib/openclaw.d.ts +131 -0
- package/dist/lib/openclaw.js +219 -0
- package/dist/lib/prompt.d.ts +11 -0
- package/dist/lib/prompt.js +40 -0
- package/package.json +38 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { configExists, loadConfig } from "../lib/config.js";
|
|
2
|
+
import { getTraces } from "../lib/api.js";
|
|
3
|
+
export async function logsCommand(options = {}) {
|
|
4
|
+
if (!configExists()) {
|
|
5
|
+
console.log("\nā smoltbot is not initialized\n");
|
|
6
|
+
console.log("Run `smoltbot init` to get started.\n");
|
|
7
|
+
process.exit(1);
|
|
8
|
+
}
|
|
9
|
+
const config = loadConfig();
|
|
10
|
+
if (!config) {
|
|
11
|
+
console.log("\nā Failed to load configuration\n");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
const limit = options.limit || 10;
|
|
15
|
+
console.log("\nš Fetching traces...\n");
|
|
16
|
+
try {
|
|
17
|
+
const traces = await getTraces(config.agentId, limit);
|
|
18
|
+
if (traces.length === 0) {
|
|
19
|
+
console.log("ā".repeat(60));
|
|
20
|
+
console.log("No traces found");
|
|
21
|
+
console.log("ā".repeat(60));
|
|
22
|
+
console.log("\nš” Start using Claude to generate traces.\n");
|
|
23
|
+
console.log("Make sure ANTHROPIC_BASE_URL is set correctly:\n");
|
|
24
|
+
console.log(` export ANTHROPIC_BASE_URL="${config.gateway || "https://gateway.mnemon.ai"}/v1/proxy/${config.agentId}"\n`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
console.log("ā".repeat(60));
|
|
28
|
+
console.log(`Recent Traces (${traces.length})`);
|
|
29
|
+
console.log("ā".repeat(60));
|
|
30
|
+
for (const trace of traces) {
|
|
31
|
+
displayTrace(trace);
|
|
32
|
+
}
|
|
33
|
+
console.log("ā".repeat(60));
|
|
34
|
+
console.log(`\nš” View more: smoltbot logs --limit ${limit + 10}\n`);
|
|
35
|
+
console.log(`š Dashboard: https://mnemon.ai/dashboard/${config.agentId}\n`);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
39
|
+
if (message.includes("404") || message.includes("not found")) {
|
|
40
|
+
console.log("ā".repeat(60));
|
|
41
|
+
console.log("No traces found");
|
|
42
|
+
console.log("ā".repeat(60));
|
|
43
|
+
console.log("\nš” Start using Claude to generate traces.\n");
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
console.log(`\nā Failed to fetch traces: ${message}\n`);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function displayTrace(trace) {
|
|
52
|
+
const timestamp = formatTimestamp(trace.timestamp);
|
|
53
|
+
const status = trace.verified ? "ā" : "ā";
|
|
54
|
+
const statusColor = trace.verified ? "" : " [VIOLATION]";
|
|
55
|
+
console.log(`\n ${timestamp} ${status}${statusColor}`);
|
|
56
|
+
console.log(` Action: ${trace.action}`);
|
|
57
|
+
if (trace.tool_name) {
|
|
58
|
+
console.log(` Tool: ${trace.tool_name}`);
|
|
59
|
+
}
|
|
60
|
+
if (trace.reasoning) {
|
|
61
|
+
const preview = truncate(trace.reasoning, 60);
|
|
62
|
+
console.log(` Reason: ${preview}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function formatTimestamp(iso) {
|
|
66
|
+
try {
|
|
67
|
+
const date = new Date(iso);
|
|
68
|
+
return date.toLocaleString("en-US", {
|
|
69
|
+
month: "short",
|
|
70
|
+
day: "numeric",
|
|
71
|
+
hour: "2-digit",
|
|
72
|
+
minute: "2-digit",
|
|
73
|
+
hour12: false,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return iso;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function truncate(text, maxLength) {
|
|
81
|
+
const cleaned = text.replace(/\n/g, " ").trim();
|
|
82
|
+
if (cleaned.length <= maxLength) {
|
|
83
|
+
return cleaned;
|
|
84
|
+
}
|
|
85
|
+
return cleaned.slice(0, maxLength - 3) + "...";
|
|
86
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function statusCommand(): Promise<void>;
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { configExists, loadConfig } from "../lib/config.js";
|
|
2
|
+
import { getAgent, getIntegrity, getTraces } from "../lib/api.js";
|
|
3
|
+
import { detectOpenClaw, getCurrentModel, } from "../lib/openclaw.js";
|
|
4
|
+
import { formatModelName } from "../lib/models.js";
|
|
5
|
+
const GATEWAY_URL = "https://gateway.mnemom.ai";
|
|
6
|
+
const DASHBOARD_URL = "https://mnemom.ai";
|
|
7
|
+
export async function statusCommand() {
|
|
8
|
+
console.log("\n" + "=".repeat(60));
|
|
9
|
+
console.log(" smoltbot status");
|
|
10
|
+
console.log("=".repeat(60) + "\n");
|
|
11
|
+
const checks = [];
|
|
12
|
+
// 1. Check smoltbot config
|
|
13
|
+
const configCheck = checkSmoltbotConfig();
|
|
14
|
+
checks.push(configCheck);
|
|
15
|
+
if (configCheck.status === "error") {
|
|
16
|
+
printChecks(checks);
|
|
17
|
+
console.log("\nRun `smoltbot init` to get started.\n");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const config = loadConfig();
|
|
21
|
+
// 2. Check OpenClaw configuration
|
|
22
|
+
const openclawCheck = checkOpenClawConfig();
|
|
23
|
+
checks.push(openclawCheck);
|
|
24
|
+
// 3. Check current model
|
|
25
|
+
const modelCheck = checkCurrentModel();
|
|
26
|
+
checks.push(modelCheck);
|
|
27
|
+
// 4. Test gateway connectivity
|
|
28
|
+
const gatewayCheck = await checkGatewayConnectivity();
|
|
29
|
+
checks.push(gatewayCheck);
|
|
30
|
+
// 5. Test API connectivity
|
|
31
|
+
const apiCheck = await checkApiConnectivity(config.agentId);
|
|
32
|
+
checks.push(apiCheck);
|
|
33
|
+
// Print all checks
|
|
34
|
+
printChecks(checks);
|
|
35
|
+
// Show configuration details
|
|
36
|
+
console.log("\n" + "ā".repeat(50));
|
|
37
|
+
console.log("Configuration");
|
|
38
|
+
console.log("ā".repeat(50) + "\n");
|
|
39
|
+
console.log(`Agent ID: ${config.agentId}`);
|
|
40
|
+
console.log(`Gateway: ${config.gateway || GATEWAY_URL}`);
|
|
41
|
+
console.log(`Dashboard: ${DASHBOARD_URL}/agents/${config.agentId}`);
|
|
42
|
+
if (config.openclawConfigured) {
|
|
43
|
+
console.log(`Configured: ${config.configuredAt || "yes"}`);
|
|
44
|
+
}
|
|
45
|
+
// Show current model info
|
|
46
|
+
const { fullPath, provider, modelId } = getCurrentModel();
|
|
47
|
+
if (fullPath) {
|
|
48
|
+
console.log(`\nCurrent Model: ${fullPath}`);
|
|
49
|
+
if (modelId) {
|
|
50
|
+
console.log(` (${formatModelName(modelId)})`);
|
|
51
|
+
}
|
|
52
|
+
if (provider === "smoltbot") {
|
|
53
|
+
console.log(" Status: Traced mode ACTIVE");
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
console.log(" Status: Traced mode NOT ACTIVE");
|
|
57
|
+
console.log(`\n To enable: openclaw models set smoltbot/${modelId}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Show trace summary if available
|
|
61
|
+
if (apiCheck.status === "ok") {
|
|
62
|
+
await showTraceSummary(config.agentId);
|
|
63
|
+
}
|
|
64
|
+
// Show overall status
|
|
65
|
+
const hasErrors = checks.some((c) => c.status === "error");
|
|
66
|
+
const hasWarnings = checks.some((c) => c.status === "warning");
|
|
67
|
+
console.log("\n" + "=".repeat(60));
|
|
68
|
+
if (hasErrors) {
|
|
69
|
+
console.log(" Status: ISSUES DETECTED");
|
|
70
|
+
console.log("\n Fix the errors above to ensure tracing works correctly.");
|
|
71
|
+
}
|
|
72
|
+
else if (hasWarnings) {
|
|
73
|
+
console.log(" Status: OK (with warnings)");
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
console.log(" Status: ALL SYSTEMS GO");
|
|
77
|
+
}
|
|
78
|
+
console.log("=".repeat(60) + "\n");
|
|
79
|
+
}
|
|
80
|
+
function checkSmoltbotConfig() {
|
|
81
|
+
if (!configExists()) {
|
|
82
|
+
return {
|
|
83
|
+
name: "Smoltbot Config",
|
|
84
|
+
status: "error",
|
|
85
|
+
message: "Not initialized",
|
|
86
|
+
details: "Run `smoltbot init` to configure",
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const config = loadConfig();
|
|
90
|
+
if (!config) {
|
|
91
|
+
return {
|
|
92
|
+
name: "Smoltbot Config",
|
|
93
|
+
status: "error",
|
|
94
|
+
message: "Config file corrupted",
|
|
95
|
+
details: "Delete ~/.smoltbot/config.json and run `smoltbot init`",
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
name: "Smoltbot Config",
|
|
100
|
+
status: "ok",
|
|
101
|
+
message: `Agent ID: ${config.agentId}`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function checkOpenClawConfig() {
|
|
105
|
+
const detection = detectOpenClaw();
|
|
106
|
+
if (!detection.installed) {
|
|
107
|
+
return {
|
|
108
|
+
name: "OpenClaw",
|
|
109
|
+
status: "error",
|
|
110
|
+
message: "Not installed",
|
|
111
|
+
details: "Install from https://openclaw.ai",
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (!detection.hasApiKey) {
|
|
115
|
+
if (detection.isOAuth) {
|
|
116
|
+
return {
|
|
117
|
+
name: "OpenClaw",
|
|
118
|
+
status: "error",
|
|
119
|
+
message: "OAuth auth (not supported)",
|
|
120
|
+
details: "smoltbot requires API key authentication",
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
name: "OpenClaw",
|
|
125
|
+
status: "error",
|
|
126
|
+
message: "No API key configured",
|
|
127
|
+
details: "Run `openclaw auth` to add your API key",
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if (!detection.smoltbotAlreadyConfigured) {
|
|
131
|
+
return {
|
|
132
|
+
name: "OpenClaw",
|
|
133
|
+
status: "warning",
|
|
134
|
+
message: "smoltbot provider not configured",
|
|
135
|
+
details: "Run `smoltbot init` to configure",
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
name: "OpenClaw",
|
|
140
|
+
status: "ok",
|
|
141
|
+
message: "smoltbot provider configured",
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function checkCurrentModel() {
|
|
145
|
+
const { fullPath, provider, modelId } = getCurrentModel();
|
|
146
|
+
if (!fullPath) {
|
|
147
|
+
return {
|
|
148
|
+
name: "Current Model",
|
|
149
|
+
status: "warning",
|
|
150
|
+
message: "No default model set",
|
|
151
|
+
details: "Run `openclaw models set smoltbot/<model>`",
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (provider === "smoltbot") {
|
|
155
|
+
return {
|
|
156
|
+
name: "Current Model",
|
|
157
|
+
status: "ok",
|
|
158
|
+
message: `${modelId} (traced)`,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
name: "Current Model",
|
|
163
|
+
status: "warning",
|
|
164
|
+
message: `${fullPath} (not traced)`,
|
|
165
|
+
details: `Switch with: openclaw models set smoltbot/${modelId}`,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
async function checkGatewayConnectivity() {
|
|
169
|
+
try {
|
|
170
|
+
const response = await fetch(`${GATEWAY_URL}/health`, {
|
|
171
|
+
signal: AbortSignal.timeout(5000),
|
|
172
|
+
});
|
|
173
|
+
if (response.ok) {
|
|
174
|
+
const data = (await response.json());
|
|
175
|
+
return {
|
|
176
|
+
name: "Gateway",
|
|
177
|
+
status: "ok",
|
|
178
|
+
message: `Connected (v${data.version || "unknown"})`,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
name: "Gateway",
|
|
183
|
+
status: "error",
|
|
184
|
+
message: `HTTP ${response.status}`,
|
|
185
|
+
details: "Gateway returned an error",
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
190
|
+
if (message.includes("timeout") || message.includes("TIMEOUT")) {
|
|
191
|
+
return {
|
|
192
|
+
name: "Gateway",
|
|
193
|
+
status: "error",
|
|
194
|
+
message: "Connection timeout",
|
|
195
|
+
details: "Check your network connection",
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
name: "Gateway",
|
|
200
|
+
status: "error",
|
|
201
|
+
message: "Connection failed",
|
|
202
|
+
details: message,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
async function checkApiConnectivity(agentId) {
|
|
207
|
+
try {
|
|
208
|
+
const agent = await getAgent(agentId);
|
|
209
|
+
if (agent) {
|
|
210
|
+
return {
|
|
211
|
+
name: "API",
|
|
212
|
+
status: "ok",
|
|
213
|
+
message: "Agent registered",
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
name: "API",
|
|
218
|
+
status: "warning",
|
|
219
|
+
message: "Agent not yet registered",
|
|
220
|
+
details: "Will register on first traced API call",
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
225
|
+
if (message.includes("404") || message.includes("not found")) {
|
|
226
|
+
return {
|
|
227
|
+
name: "API",
|
|
228
|
+
status: "warning",
|
|
229
|
+
message: "Agent not yet registered",
|
|
230
|
+
details: "Will register on first traced API call",
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
if (message.includes("timeout") || message.includes("TIMEOUT")) {
|
|
234
|
+
return {
|
|
235
|
+
name: "API",
|
|
236
|
+
status: "error",
|
|
237
|
+
message: "Connection timeout",
|
|
238
|
+
details: "Check your network connection",
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
name: "API",
|
|
243
|
+
status: "error",
|
|
244
|
+
message: "Connection failed",
|
|
245
|
+
details: message,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async function showTraceSummary(agentId) {
|
|
250
|
+
try {
|
|
251
|
+
const [integrityResult, tracesResult] = await Promise.allSettled([
|
|
252
|
+
getIntegrity(agentId),
|
|
253
|
+
getTraces(agentId, 1),
|
|
254
|
+
]);
|
|
255
|
+
console.log("\n" + "ā".repeat(50));
|
|
256
|
+
console.log("Trace Summary");
|
|
257
|
+
console.log("ā".repeat(50) + "\n");
|
|
258
|
+
if (integrityResult.status === "fulfilled") {
|
|
259
|
+
const integrity = integrityResult.value;
|
|
260
|
+
const score = (integrity.score * 100).toFixed(1);
|
|
261
|
+
console.log(`Integrity Score: ${score}%`);
|
|
262
|
+
console.log(`Total Traces: ${integrity.total_traces}`);
|
|
263
|
+
console.log(`Verified: ${integrity.verified}`);
|
|
264
|
+
if (integrity.violations > 0) {
|
|
265
|
+
console.log(`Violations: ${integrity.violations}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
console.log("Integrity: No data yet");
|
|
270
|
+
}
|
|
271
|
+
if (tracesResult.status === "fulfilled" && tracesResult.value.length > 0) {
|
|
272
|
+
const lastTrace = tracesResult.value[0];
|
|
273
|
+
const lastTime = new Date(lastTrace.timestamp).toLocaleString();
|
|
274
|
+
console.log(`\nLast Activity: ${lastTime}`);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
console.log("\nLast Activity: None");
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
// Silently skip if we can't get trace info
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
function printChecks(checks) {
|
|
285
|
+
console.log("System Checks");
|
|
286
|
+
console.log("ā".repeat(50) + "\n");
|
|
287
|
+
for (const check of checks) {
|
|
288
|
+
const icon = check.status === "ok" ? "ā" : check.status === "warning" ? "ā " : "ā";
|
|
289
|
+
const color = check.status === "ok"
|
|
290
|
+
? ""
|
|
291
|
+
: check.status === "warning"
|
|
292
|
+
? ""
|
|
293
|
+
: "";
|
|
294
|
+
console.log(`${icon} ${check.name}: ${check.message}`);
|
|
295
|
+
if (check.details) {
|
|
296
|
+
console.log(` ${check.details}`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from "commander";
|
|
3
|
+
import { initCommand } from "./commands/init.js";
|
|
4
|
+
import { statusCommand } from "./commands/status.js";
|
|
5
|
+
import { integrityCommand } from "./commands/integrity.js";
|
|
6
|
+
import { logsCommand } from "./commands/logs.js";
|
|
7
|
+
program
|
|
8
|
+
.name("smoltbot")
|
|
9
|
+
.description("Transparent AI agent tracing - AAP compliant")
|
|
10
|
+
.version("2.0.0");
|
|
11
|
+
program
|
|
12
|
+
.command("init")
|
|
13
|
+
.description("Initialize smoltbot and configure OpenClaw for traced mode")
|
|
14
|
+
.option("-y, --yes", "Skip confirmation prompts (accept defaults)")
|
|
15
|
+
.option("-f, --force", "Force reconfiguration even if already configured")
|
|
16
|
+
.action(async (options) => {
|
|
17
|
+
try {
|
|
18
|
+
await initCommand({ yes: options.yes, force: options.force });
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
program
|
|
26
|
+
.command("status")
|
|
27
|
+
.description("Show agent status and connection info")
|
|
28
|
+
.action(async () => {
|
|
29
|
+
try {
|
|
30
|
+
await statusCommand();
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
program
|
|
38
|
+
.command("integrity")
|
|
39
|
+
.description("Display integrity score and verification stats")
|
|
40
|
+
.action(async () => {
|
|
41
|
+
try {
|
|
42
|
+
await integrityCommand();
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
program
|
|
50
|
+
.command("logs")
|
|
51
|
+
.description("Show recent traces and actions")
|
|
52
|
+
.option("-l, --limit <number>", "Number of traces to show", "10")
|
|
53
|
+
.action(async (options) => {
|
|
54
|
+
try {
|
|
55
|
+
const limit = parseInt(options.limit, 10);
|
|
56
|
+
await logsCommand({ limit: isNaN(limit) ? 10 : limit });
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
program.parse();
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const API_BASE = "https://api.mnemom.ai";
|
|
2
|
+
export interface Agent {
|
|
3
|
+
id: string;
|
|
4
|
+
gateway: string;
|
|
5
|
+
last_seen: string | null;
|
|
6
|
+
claimed: boolean;
|
|
7
|
+
email?: string;
|
|
8
|
+
created_at: string;
|
|
9
|
+
}
|
|
10
|
+
export interface IntegrityScore {
|
|
11
|
+
agent_id: string;
|
|
12
|
+
score: number;
|
|
13
|
+
total_traces: number;
|
|
14
|
+
verified: number;
|
|
15
|
+
violations: number;
|
|
16
|
+
last_updated: string;
|
|
17
|
+
}
|
|
18
|
+
export interface Trace {
|
|
19
|
+
id: string;
|
|
20
|
+
agent_id: string;
|
|
21
|
+
timestamp: string;
|
|
22
|
+
action: string;
|
|
23
|
+
verified: boolean;
|
|
24
|
+
reasoning?: string;
|
|
25
|
+
tool_name?: string;
|
|
26
|
+
tool_input?: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
export interface ApiError {
|
|
29
|
+
error: string;
|
|
30
|
+
message: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function getAgent(id: string): Promise<Agent>;
|
|
33
|
+
export declare function getIntegrity(id: string): Promise<IntegrityScore>;
|
|
34
|
+
export declare function getTraces(id: string, limit?: number): Promise<Trace[]>;
|
package/dist/lib/api.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const API_BASE = "https://api.mnemom.ai";
|
|
2
|
+
async function fetchApi(endpoint) {
|
|
3
|
+
const url = `${API_BASE}${endpoint}`;
|
|
4
|
+
const response = await fetch(url);
|
|
5
|
+
if (!response.ok) {
|
|
6
|
+
const error = (await response.json().catch(() => ({
|
|
7
|
+
error: "unknown",
|
|
8
|
+
message: response.statusText,
|
|
9
|
+
})));
|
|
10
|
+
throw new Error(error.message || `API request failed: ${response.status}`);
|
|
11
|
+
}
|
|
12
|
+
return response.json();
|
|
13
|
+
}
|
|
14
|
+
export async function getAgent(id) {
|
|
15
|
+
return fetchApi(`/v1/agents/${id}`);
|
|
16
|
+
}
|
|
17
|
+
export async function getIntegrity(id) {
|
|
18
|
+
return fetchApi(`/v1/integrity/${id}`);
|
|
19
|
+
}
|
|
20
|
+
export async function getTraces(id, limit = 10) {
|
|
21
|
+
return fetchApi(`/v1/traces?agent_id=${id}&limit=${limit}`);
|
|
22
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const CONFIG_DIR: string;
|
|
2
|
+
export declare const CONFIG_FILE: string;
|
|
3
|
+
export interface Config {
|
|
4
|
+
agentId: string;
|
|
5
|
+
email?: string;
|
|
6
|
+
gateway?: string;
|
|
7
|
+
openclawConfigured?: boolean;
|
|
8
|
+
configuredAt?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function configExists(): boolean;
|
|
11
|
+
export declare function loadConfig(): Config | null;
|
|
12
|
+
export declare function saveConfig(config: Config): void;
|
|
13
|
+
export declare function generateAgentId(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Derive agent ID deterministically from an API key.
|
|
16
|
+
* Uses the same SHA-256 hashing as the gateway so IDs match.
|
|
17
|
+
*/
|
|
18
|
+
export declare function deriveAgentId(apiKey: string): string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as crypto from "node:crypto";
|
|
5
|
+
export const CONFIG_DIR = path.join(os.homedir(), ".smoltbot");
|
|
6
|
+
export const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
7
|
+
export function configExists() {
|
|
8
|
+
return fs.existsSync(CONFIG_FILE);
|
|
9
|
+
}
|
|
10
|
+
export function loadConfig() {
|
|
11
|
+
if (!configExists()) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
const content = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
16
|
+
return JSON.parse(content);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function saveConfig(config) {
|
|
23
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
24
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
27
|
+
}
|
|
28
|
+
export function generateAgentId() {
|
|
29
|
+
const randomHex = crypto.randomBytes(4).toString("hex");
|
|
30
|
+
return `smolt-${randomHex}`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Derive agent ID deterministically from an API key.
|
|
34
|
+
* Uses the same SHA-256 hashing as the gateway so IDs match.
|
|
35
|
+
*/
|
|
36
|
+
export function deriveAgentId(apiKey) {
|
|
37
|
+
const hash = crypto.createHash("sha256").update(apiKey).digest("hex");
|
|
38
|
+
const agentHash = hash.substring(0, 16);
|
|
39
|
+
return `smolt-${agentHash.slice(0, 8)}`;
|
|
40
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ModelDefinition } from "./openclaw.js";
|
|
2
|
+
/**
|
|
3
|
+
* Known Anthropic model definitions with their specifications.
|
|
4
|
+
* These are used when configuring the smoltbot provider.
|
|
5
|
+
*/
|
|
6
|
+
export declare const ANTHROPIC_MODELS: Record<string, ModelDefinition>;
|
|
7
|
+
/**
|
|
8
|
+
* Get model definition by ID
|
|
9
|
+
* Returns the definition if known, or creates a basic one if unknown
|
|
10
|
+
*/
|
|
11
|
+
export declare function getModelDefinition(modelId: string): ModelDefinition;
|
|
12
|
+
/**
|
|
13
|
+
* Check if a model ID is a known Anthropic model
|
|
14
|
+
*/
|
|
15
|
+
export declare function isKnownModel(modelId: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Check if a model ID looks like an Anthropic model
|
|
18
|
+
*/
|
|
19
|
+
export declare function isAnthropicModel(modelId: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Format a model ID into a human-readable name
|
|
22
|
+
* e.g., "claude-opus-4-5-20251101" -> "Claude Opus 4.5"
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatModelName(modelId: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Get all known model IDs
|
|
27
|
+
*/
|
|
28
|
+
export declare function getAllKnownModelIds(): string[];
|
|
29
|
+
/**
|
|
30
|
+
* Get the latest model for each tier
|
|
31
|
+
*/
|
|
32
|
+
export declare function getLatestModels(): ModelDefinition[];
|