@memorystack/clawdbot-memorystack 1.1.0 ā 1.2.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/commands/cli.ts +161 -0
- package/commands/slash.ts +130 -0
- package/index.ts +8 -0
- package/package.json +1 -1
package/commands/cli.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
|
2
|
+
import { MemoryStackClient } from "@memorystack/sdk";
|
|
3
|
+
import type { MemorystackConfig } from "../config.ts";
|
|
4
|
+
import { log } from "../logger.ts";
|
|
5
|
+
|
|
6
|
+
export function registerCliCommands(
|
|
7
|
+
api: ClawdbotPluginApi,
|
|
8
|
+
cfg: MemorystackConfig,
|
|
9
|
+
): void {
|
|
10
|
+
api.registerCli(
|
|
11
|
+
// biome-ignore lint/suspicious/noExplicitAny: clawdbot SDK does not ship types
|
|
12
|
+
({ program }: { program: any }) => {
|
|
13
|
+
const cmd = program
|
|
14
|
+
.command("memorystack")
|
|
15
|
+
.description("MemoryStack long-term memory commands");
|
|
16
|
+
|
|
17
|
+
// clawdbot memorystack search <query>
|
|
18
|
+
cmd
|
|
19
|
+
.command("search")
|
|
20
|
+
.argument("<query>", "Search query")
|
|
21
|
+
.option("--limit <n>", "Max results", "5")
|
|
22
|
+
.option("--type <type>", "Filter by memory type (fact, preference, episode)")
|
|
23
|
+
.action(async (query: string, opts: { limit: string; type?: string }) => {
|
|
24
|
+
const limit = Number.parseInt(opts.limit, 10) || 5;
|
|
25
|
+
log.debug(`cli search: query="${query}" limit=${limit}`);
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const client = new MemoryStackClient({
|
|
29
|
+
apiKey: cfg.apiKey,
|
|
30
|
+
baseUrl: cfg.baseUrl,
|
|
31
|
+
enableLogging: cfg.debug,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const results = await client.search(query, {
|
|
35
|
+
limit,
|
|
36
|
+
memory_type: opts.type,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (results.count === 0) {
|
|
40
|
+
console.log("No memories found.");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log(`Found ${results.count} memories:\n`);
|
|
45
|
+
for (const r of results.results) {
|
|
46
|
+
const conf = r.confidence
|
|
47
|
+
? ` (${(r.confidence * 100).toFixed(0)}%)`
|
|
48
|
+
: "";
|
|
49
|
+
const type = r.memory_type ? ` [${r.memory_type}]` : "";
|
|
50
|
+
console.log(`- ${r.content}${type}${conf}`);
|
|
51
|
+
}
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.error("Search failed:", err);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// clawdbot memorystack stats
|
|
58
|
+
cmd
|
|
59
|
+
.command("stats")
|
|
60
|
+
.description("View usage statistics")
|
|
61
|
+
.action(async () => {
|
|
62
|
+
log.debug("cli stats");
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
const client = new MemoryStackClient({
|
|
66
|
+
apiKey: cfg.apiKey,
|
|
67
|
+
baseUrl: cfg.baseUrl,
|
|
68
|
+
enableLogging: cfg.debug,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const stats = await client.getStats();
|
|
72
|
+
|
|
73
|
+
console.log("\nš MemoryStack Statistics\n");
|
|
74
|
+
console.log(`Total Memories: ${stats.totals.total_memories}`);
|
|
75
|
+
console.log(`Total API Calls: ${stats.totals.total_api_calls}`);
|
|
76
|
+
console.log(`This Month's Calls: ${stats.usage.current_month_api_calls}/${stats.usage.monthly_api_limit}`);
|
|
77
|
+
console.log(`Plan: ${stats.plan_tier || "Free"}`);
|
|
78
|
+
} catch (err) {
|
|
79
|
+
console.error("Failed to get stats:", err);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// clawdbot memorystack add <text>
|
|
84
|
+
cmd
|
|
85
|
+
.command("add")
|
|
86
|
+
.argument("<text>", "Text to save as memory")
|
|
87
|
+
.option("--type <type>", "Memory type (fact, preference, episode)")
|
|
88
|
+
.action(async (text: string, opts: { type?: string }) => {
|
|
89
|
+
log.debug(`cli add: "${text.slice(0, 50)}"`);
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
const client = new MemoryStackClient({
|
|
93
|
+
apiKey: cfg.apiKey,
|
|
94
|
+
baseUrl: cfg.baseUrl,
|
|
95
|
+
enableLogging: cfg.debug,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
await client.add(text, {
|
|
99
|
+
metadata: {
|
|
100
|
+
source: "clawdbot_cli",
|
|
101
|
+
memory_type: opts.type,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
console.log(`ā Saved: "${text.length > 60 ? text.slice(0, 60) + "ā¦" : text}"`);
|
|
106
|
+
} catch (err) {
|
|
107
|
+
console.error("Failed to add memory:", err);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// clawdbot memorystack deleteall (destructive!)
|
|
112
|
+
cmd
|
|
113
|
+
.command("deleteall")
|
|
114
|
+
.description("Delete ALL your memories (destructive, requires confirmation)")
|
|
115
|
+
.action(async () => {
|
|
116
|
+
const readline = await import("node:readline");
|
|
117
|
+
const rl = readline.createInterface({
|
|
118
|
+
input: process.stdin,
|
|
119
|
+
output: process.stdout,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const answer = await new Promise<string>((resolve) => {
|
|
123
|
+
rl.question(
|
|
124
|
+
"ā ļø This will permanently delete ALL your memories. Type 'yes' to confirm: ",
|
|
125
|
+
resolve,
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
rl.close();
|
|
129
|
+
|
|
130
|
+
if (answer.trim().toLowerCase() !== "yes") {
|
|
131
|
+
console.log("Aborted.");
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
log.debug("cli wipe: confirmed");
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
const client = new MemoryStackClient({
|
|
139
|
+
apiKey: cfg.apiKey,
|
|
140
|
+
baseUrl: cfg.baseUrl,
|
|
141
|
+
enableLogging: cfg.debug,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// List all memories first, then delete them
|
|
145
|
+
const memories = await client.listMemories({ limit: 1000 });
|
|
146
|
+
if (memories.count === 0) {
|
|
147
|
+
console.log("No memories to delete.");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const memoryIds = memories.results.map(m => m.id);
|
|
152
|
+
const result = await client.deleteMemories(memoryIds, true);
|
|
153
|
+
console.log(`Wiped ${result.deleted_count} memories.`);
|
|
154
|
+
} catch (err) {
|
|
155
|
+
console.error("Failed to wipe memories:", err);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
},
|
|
159
|
+
{ commands: ["memorystack"] },
|
|
160
|
+
);
|
|
161
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
|
2
|
+
import { MemoryStackClient } from "@memorystack/sdk";
|
|
3
|
+
import type { MemorystackConfig } from "../config.ts";
|
|
4
|
+
import { log } from "../logger.ts";
|
|
5
|
+
|
|
6
|
+
export function registerSlashCommands(
|
|
7
|
+
api: ClawdbotPluginApi,
|
|
8
|
+
cfg: MemorystackConfig,
|
|
9
|
+
getSessionKey: () => string | undefined,
|
|
10
|
+
getContext: () => Record<string, any>,
|
|
11
|
+
): void {
|
|
12
|
+
// /add <text> - Save something to memory
|
|
13
|
+
api.registerCommand({
|
|
14
|
+
name: "add",
|
|
15
|
+
description: "Save something to long-term memory",
|
|
16
|
+
acceptsArgs: true,
|
|
17
|
+
requireAuth: true,
|
|
18
|
+
handler: async (ctx: { args?: string }) => {
|
|
19
|
+
const text = ctx.args?.trim();
|
|
20
|
+
if (!text) {
|
|
21
|
+
return { text: "Usage: /add <text to remember>" };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
log.debug(`/add command: "${text.slice(0, 50)}"`);
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const client = new MemoryStackClient({
|
|
28
|
+
apiKey: cfg.apiKey,
|
|
29
|
+
baseUrl: cfg.baseUrl,
|
|
30
|
+
enableLogging: cfg.debug,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const context = getContext();
|
|
34
|
+
const sessionKey = getSessionKey();
|
|
35
|
+
const effectiveAgentId = context.subagentId || context.agentId || "main";
|
|
36
|
+
|
|
37
|
+
await client.add(text, {
|
|
38
|
+
agentId: effectiveAgentId,
|
|
39
|
+
sessionId: sessionKey,
|
|
40
|
+
metadata: {
|
|
41
|
+
source: "clawdbot_command",
|
|
42
|
+
session_key: sessionKey,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const preview = text.length > 60 ? `${text.slice(0, 60)}ā¦` : text;
|
|
47
|
+
return { text: `ā Saved to memory: "${preview}"` };
|
|
48
|
+
} catch (err) {
|
|
49
|
+
log.error("/add failed", err);
|
|
50
|
+
return { text: "Failed to save memory. Check logs for details." };
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// /search <query> - Search memories
|
|
56
|
+
api.registerCommand({
|
|
57
|
+
name: "search",
|
|
58
|
+
description: "Search your long-term memories",
|
|
59
|
+
acceptsArgs: true,
|
|
60
|
+
requireAuth: true,
|
|
61
|
+
handler: async (ctx: { args?: string }) => {
|
|
62
|
+
const query = ctx.args?.trim();
|
|
63
|
+
if (!query) {
|
|
64
|
+
return { text: "Usage: /search <search query>" };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
log.debug(`/search command: "${query}"`);
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const client = new MemoryStackClient({
|
|
71
|
+
apiKey: cfg.apiKey,
|
|
72
|
+
baseUrl: cfg.baseUrl,
|
|
73
|
+
enableLogging: cfg.debug,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const results = await client.search(query, { limit: 5 });
|
|
77
|
+
|
|
78
|
+
if (results.count === 0) {
|
|
79
|
+
return { text: `No memories found for: "${query}"` };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const lines = results.results.map((r, i) => {
|
|
83
|
+
const conf = r.confidence
|
|
84
|
+
? ` (${(r.confidence * 100).toFixed(0)}%)`
|
|
85
|
+
: "";
|
|
86
|
+
const type = r.memory_type ? ` [${r.memory_type}]` : "";
|
|
87
|
+
return `${i + 1}. ${r.content}${type}${conf}`;
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
text: `Found ${results.count} memories:\n\n${lines.join("\n")}`,
|
|
92
|
+
};
|
|
93
|
+
} catch (err) {
|
|
94
|
+
log.error("/search failed", err);
|
|
95
|
+
return { text: "Failed to search memories. Check logs for details." };
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// /stats - View memory usage statistics
|
|
101
|
+
api.registerCommand({
|
|
102
|
+
name: "stats",
|
|
103
|
+
description: "View your memory usage statistics",
|
|
104
|
+
acceptsArgs: false,
|
|
105
|
+
requireAuth: true,
|
|
106
|
+
handler: async () => {
|
|
107
|
+
log.debug("/stats command");
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
const client = new MemoryStackClient({
|
|
111
|
+
apiKey: cfg.apiKey,
|
|
112
|
+
baseUrl: cfg.baseUrl,
|
|
113
|
+
enableLogging: cfg.debug,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const stats = await client.getStats();
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
text: `š Memory Statistics\n\n` +
|
|
120
|
+
`Total Memories: ${stats.totals.total_memories}\n` +
|
|
121
|
+
`API Calls (this month): ${stats.usage.current_month_api_calls}/${stats.usage.monthly_api_limit}\n` +
|
|
122
|
+
`Plan: ${stats.plan_tier || "Free"}`,
|
|
123
|
+
};
|
|
124
|
+
} catch (err) {
|
|
125
|
+
log.error("/stats failed", err);
|
|
126
|
+
return { text: "Failed to get stats. Check logs for details." };
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
}
|
package/index.ts
CHANGED
|
@@ -9,6 +9,8 @@ import { registerReflectTool } from "./tools/reflect.ts";
|
|
|
9
9
|
import { registerConsolidateTool } from "./tools/consolidate.ts";
|
|
10
10
|
import { buildRecallHandler } from "./hooks/recall.ts";
|
|
11
11
|
import { buildCaptureHandler } from "./hooks/capture.ts";
|
|
12
|
+
import { registerSlashCommands } from "./commands/slash.ts";
|
|
13
|
+
import { registerCliCommands } from "./commands/cli.ts";
|
|
12
14
|
|
|
13
15
|
// Helper to properly parse Moltbot session keys
|
|
14
16
|
// Format: "agent:{agentId}:{rest}" where rest may be "subagent:{uuid}" or "main" etc.
|
|
@@ -115,6 +117,12 @@ export default {
|
|
|
115
117
|
});
|
|
116
118
|
}
|
|
117
119
|
|
|
120
|
+
// Register slash commands (/add, /search, /stats)
|
|
121
|
+
registerSlashCommands(api, cfg, getSessionKey, getContext);
|
|
122
|
+
|
|
123
|
+
// Register CLI commands (memorystack search, stats, add, wipe)
|
|
124
|
+
registerCliCommands(api, cfg);
|
|
125
|
+
|
|
118
126
|
// Register service
|
|
119
127
|
api.registerService({
|
|
120
128
|
id: "clawdbot-memorystack",
|