@keyoku/openclaw 1.0.0 → 1.1.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.
Files changed (47) hide show
  1. package/bin/init.js +15 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +58 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/context.d.ts.map +1 -1
  6. package/dist/context.js +21 -1
  7. package/dist/context.js.map +1 -1
  8. package/dist/heartbeat-setup.d.ts +8 -1
  9. package/dist/heartbeat-setup.d.ts.map +1 -1
  10. package/dist/heartbeat-setup.js +58 -15
  11. package/dist/heartbeat-setup.js.map +1 -1
  12. package/dist/hooks.d.ts.map +1 -1
  13. package/dist/hooks.js +76 -50
  14. package/dist/hooks.js.map +1 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +4 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/init.d.ts +21 -0
  19. package/dist/init.d.ts.map +1 -0
  20. package/dist/init.js +573 -0
  21. package/dist/init.js.map +1 -0
  22. package/dist/migrate-vector-store.d.ts +52 -0
  23. package/dist/migrate-vector-store.d.ts.map +1 -0
  24. package/dist/migrate-vector-store.js +158 -0
  25. package/dist/migrate-vector-store.js.map +1 -0
  26. package/dist/service.d.ts.map +1 -1
  27. package/dist/service.js +27 -3
  28. package/dist/service.js.map +1 -1
  29. package/package.json +13 -4
  30. package/skills/keyoku-memory/SKILL.md +67 -0
  31. package/src/capture.ts +0 -116
  32. package/src/cli.ts +0 -95
  33. package/src/config.ts +0 -43
  34. package/src/context.ts +0 -164
  35. package/src/heartbeat-setup.ts +0 -53
  36. package/src/hooks.ts +0 -175
  37. package/src/incremental-capture.ts +0 -88
  38. package/src/index.ts +0 -68
  39. package/src/migration.ts +0 -241
  40. package/src/service.ts +0 -145
  41. package/src/tools.ts +0 -239
  42. package/src/types.ts +0 -40
  43. package/test/capture.test.ts +0 -139
  44. package/test/context.test.ts +0 -273
  45. package/test/hooks.test.ts +0 -137
  46. package/test/tools.test.ts +0 -174
  47. package/tsconfig.json +0 -8
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Vector store migration — imports OpenClaw's SQLite-based vector store into Keyoku.
3
+ *
4
+ * OpenClaw stores memory chunks in SQLite at ~/.openclaw/memory/<agentId>.sqlite
5
+ * with a `chunks` table (id, path, source, text, embedding, start_line, end_line).
6
+ *
7
+ * This migrator reads the text from each chunk, deduplicates against existing
8
+ * Keyoku memories, and stores each unique chunk. Embeddings are NOT migrated —
9
+ * Keyoku re-embeds with its own model.
10
+ */
11
+ import { existsSync, readdirSync } from 'node:fs';
12
+ import { join, basename } from 'node:path';
13
+ // node:sqlite (DatabaseSync) requires Node >= 22.5.0
14
+ // We use dynamic import so the rest of the plugin works on Node 20+
15
+ async function openSqlite(path) {
16
+ try {
17
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
18
+ const { DatabaseSync } = await import('node:sqlite');
19
+ const db = new DatabaseSync(path, { open: true });
20
+ return {
21
+ all(sql) {
22
+ return db.prepare(sql).all();
23
+ },
24
+ close() {
25
+ db.close();
26
+ },
27
+ };
28
+ }
29
+ catch {
30
+ throw new Error('Vector store migration requires Node.js >= 22.5.0 (for node:sqlite). ' +
31
+ 'Please upgrade Node.js or export your OpenClaw SQLite data manually.');
32
+ }
33
+ }
34
+ function delay(ms) {
35
+ return new Promise((resolve) => setTimeout(resolve, ms));
36
+ }
37
+ /**
38
+ * Discover OpenClaw SQLite memory databases.
39
+ */
40
+ export function discoverVectorDbs(memoryDir) {
41
+ if (!existsSync(memoryDir))
42
+ return [];
43
+ return readdirSync(memoryDir)
44
+ .filter((f) => f.endsWith('.sqlite'))
45
+ .map((f) => join(memoryDir, f));
46
+ }
47
+ /**
48
+ * Migrate a single OpenClaw SQLite vector store into Keyoku.
49
+ */
50
+ export async function migrateVectorStore(params) {
51
+ const { client, entityId, sqlitePath, agentId, dryRun = false, batchSize = 20, delayMs = 100, logger = console, } = params;
52
+ const result = { totalChunks: 0, imported: 0, skipped: 0, errors: 0 };
53
+ if (!existsSync(sqlitePath)) {
54
+ logger.warn(`SQLite file not found: ${sqlitePath}`);
55
+ return result;
56
+ }
57
+ const dbName = basename(sqlitePath, '.sqlite');
58
+ logger.info(`Migrating vector store: ${dbName} (${sqlitePath})`);
59
+ const db = await openSqlite(sqlitePath);
60
+ try {
61
+ // Check if chunks table exists
62
+ const tables = db.all("SELECT name FROM sqlite_master WHERE type='table' AND name='chunks'");
63
+ if (tables.length === 0) {
64
+ logger.warn(`No 'chunks' table found in ${dbName} — skipping`);
65
+ return result;
66
+ }
67
+ // Read all chunks
68
+ const rows = db.all('SELECT id, path, source, text, start_line, end_line FROM chunks ORDER BY rowid DESC');
69
+ result.totalChunks = rows.length;
70
+ logger.info(`Found ${rows.length} chunks in ${dbName}`);
71
+ let batchCount = 0;
72
+ for (const row of rows) {
73
+ // Skip very short chunks
74
+ if (!row.text || row.text.trim().length < 10) {
75
+ result.skipped++;
76
+ continue;
77
+ }
78
+ // Build tagged content with source context
79
+ const locationInfo = row.start_line != null
80
+ ? ` (lines ${row.start_line}-${row.end_line})`
81
+ : '';
82
+ const sourceInfo = row.path || row.source || dbName;
83
+ const taggedText = `[Migrated from OpenClaw vector store — ${sourceInfo}${locationInfo}]\n${row.text}`;
84
+ if (dryRun) {
85
+ logger.info(`[dry-run] Would import: ${row.text.slice(0, 80)}...`);
86
+ result.imported++;
87
+ continue;
88
+ }
89
+ // Dedup check — search for similar content
90
+ try {
91
+ const queryText = row.text.slice(0, 100);
92
+ const existing = await client.search(entityId, queryText, {
93
+ limit: 1,
94
+ min_score: 0.95,
95
+ });
96
+ if (existing.length > 0) {
97
+ result.skipped++;
98
+ continue;
99
+ }
100
+ }
101
+ catch {
102
+ // Search failed — proceed with import anyway
103
+ }
104
+ // Store the memory
105
+ try {
106
+ await client.remember(entityId, taggedText, {
107
+ agent_id: agentId,
108
+ source: 'migration:openclaw-vector',
109
+ });
110
+ result.imported++;
111
+ logger.info(`Imported: ${row.text.slice(0, 60)}...`);
112
+ }
113
+ catch (err) {
114
+ logger.warn(`Failed to store chunk ${row.id}: ${String(err)}`);
115
+ result.errors++;
116
+ }
117
+ // Rate limit per batch
118
+ batchCount++;
119
+ if (batchCount >= batchSize) {
120
+ await delay(delayMs);
121
+ batchCount = 0;
122
+ }
123
+ }
124
+ }
125
+ finally {
126
+ db.close();
127
+ }
128
+ return result;
129
+ }
130
+ /**
131
+ * Migrate all OpenClaw vector stores found in a directory.
132
+ */
133
+ export async function migrateAllVectorStores(params) {
134
+ const { client, entityId, memoryDir, agentId, dryRun, logger = console } = params;
135
+ const totals = { totalChunks: 0, imported: 0, skipped: 0, errors: 0 };
136
+ const dbFiles = discoverVectorDbs(memoryDir);
137
+ if (dbFiles.length === 0) {
138
+ logger.info('No OpenClaw SQLite vector stores found.');
139
+ return totals;
140
+ }
141
+ logger.info(`Found ${dbFiles.length} vector store(s) to migrate.`);
142
+ for (const dbPath of dbFiles) {
143
+ const result = await migrateVectorStore({
144
+ client,
145
+ entityId,
146
+ sqlitePath: dbPath,
147
+ agentId,
148
+ dryRun,
149
+ logger,
150
+ });
151
+ totals.totalChunks += result.totalChunks;
152
+ totals.imported += result.imported;
153
+ totals.skipped += result.skipped;
154
+ totals.errors += result.errors;
155
+ }
156
+ return totals;
157
+ }
158
+ //# sourceMappingURL=migrate-vector-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-vector-store.js","sourceRoot":"","sources":["../src/migrate-vector-store.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA0D5C,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CA6EvE"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA8E5C,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAgFvE"}
package/dist/service.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Starts/stops the Keyoku Go binary as a child process.
4
4
  */
5
5
  import { spawn } from 'node:child_process';
6
- import { existsSync, mkdirSync } from 'node:fs';
6
+ import { existsSync, mkdirSync, readFileSync } from 'node:fs';
7
7
  import { resolve } from 'node:path';
8
8
  import { randomBytes } from 'node:crypto';
9
9
  let keyokuProcess = null;
@@ -58,6 +58,27 @@ function ensureDataDir() {
58
58
  mkdirSync(dir, { recursive: true });
59
59
  return resolve(dir, 'keyoku.db');
60
60
  }
61
+ /**
62
+ * Load key=value pairs from ~/.keyoku/.env if it exists.
63
+ * These are written by `npx @keyoku/openclaw init` during setup.
64
+ */
65
+ function loadKeyokuEnv() {
66
+ const envPath = resolve(process.env.HOME ?? '', '.keyoku', '.env');
67
+ if (!existsSync(envPath))
68
+ return {};
69
+ const vars = {};
70
+ const content = readFileSync(envPath, 'utf-8');
71
+ for (const line of content.split('\n')) {
72
+ const trimmed = line.trim();
73
+ if (!trimmed || trimmed.startsWith('#'))
74
+ continue;
75
+ const eq = trimmed.indexOf('=');
76
+ if (eq === -1)
77
+ continue;
78
+ vars[trimmed.slice(0, eq)] = trimmed.slice(eq + 1);
79
+ }
80
+ return vars;
81
+ }
61
82
  export function registerService(api, keyokuUrl) {
62
83
  api.registerService({
63
84
  id: 'keyoku-engine',
@@ -72,12 +93,15 @@ export function registerService(api, keyokuUrl) {
72
93
  api.logger.warn('keyoku: Keyoku binary not found — memory features require Keyoku to be running');
73
94
  return;
74
95
  }
75
- // Prepare environment
76
- const env = { ...process.env };
96
+ // Prepare environment — merge ~/.keyoku/.env (init-saved keys) with process.env
97
+ const keyokuEnv = loadKeyokuEnv();
98
+ const env = { ...keyokuEnv, ...process.env };
77
99
  if (!env.KEYOKU_SESSION_TOKEN) {
78
100
  env.KEYOKU_SESSION_TOKEN = randomBytes(16).toString('hex');
79
101
  api.logger.info('keyoku: Generated session token');
80
102
  }
103
+ // Expose token to the host process so the client (index.ts) can authenticate
104
+ process.env.KEYOKU_SESSION_TOKEN = env.KEYOKU_SESSION_TOKEN;
81
105
  if (!env.KEYOKU_DB_PATH) {
82
106
  env.KEYOKU_DB_PATH = ensureDataDir();
83
107
  api.logger.info(`keyoku: Using database at ${env.KEYOKU_DB_PATH}`);
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,16 +1,19 @@
1
1
  {
2
2
  "name": "@keyoku/openclaw",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Keyoku memory plugin for OpenClaw — persistent memory, heartbeat enhancement, and scheduling",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "keyoku-init": "bin/init.js"
10
+ },
8
11
  "scripts": {
9
12
  "build": "tsc"
10
13
  },
11
14
  "dependencies": {
12
- "@keyoku/memory": "1.0.0",
13
- "@keyoku/types": "1.0.0",
15
+ "@keyoku/memory": "1.1.1",
16
+ "@keyoku/types": "1.1.1",
14
17
  "@sinclair/typebox": "^0.34.0"
15
18
  },
16
19
  "peerDependencies": {
@@ -21,8 +24,14 @@
21
24
  "optional": true
22
25
  }
23
26
  },
27
+ "files": [
28
+ "dist",
29
+ "bin",
30
+ "skills"
31
+ ],
24
32
  "openclaw": {
25
- "extensions": ["dist/index.js"]
33
+ "extensions": ["dist/index.js"],
34
+ "skills": ["skills/keyoku-memory"]
26
35
  },
27
36
  "license": "MIT",
28
37
  "engines": {
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: keyoku-memory
3
+ description: Persistent memory system — you remember things about users across conversations
4
+ user-invocable: false
5
+ disable-model-invocation: true
6
+ metadata: {"openclaw":{"always":true,"requires":{"config":["keyoku-memory"]}}}
7
+ ---
8
+
9
+ # Memory System
10
+
11
+ You have a persistent memory system. It runs quietly in the background — you don't need to think about it, and you should never mention it by name.
12
+
13
+ ## What You Have
14
+
15
+ - **Long-term memory** across conversations. You remember facts, preferences, relationships, events, and plans about the people you talk to.
16
+ - **Automatic recall** — relevant memories are injected into your context before each response. They appear in `<your-memories>` blocks. Treat them as your own knowledge. Reference them naturally, the way a person recalls things about someone they know.
17
+ - **Periodic check-ins** — a heartbeat system reviews your memory and surfaces things that need attention: deadlines, scheduled tasks, pending work, or context you should be aware of. These arrive in `<heartbeat-signals>` blocks.
18
+
19
+ ## How to Act on Memories
20
+
21
+ When you see `<your-memories>`:
22
+ - Use the information naturally. Don't say "I see in my records" or "according to my memory." Just know it.
23
+ - If a memory says the user prefers dark mode, and they ask about editor setup, mention dark mode as if you just know that about them.
24
+
25
+ ## How to Act on Heartbeat Signals
26
+
27
+ When you see `<heartbeat-signals>`:
28
+
29
+ 1. **Read the urgency and mode** at the bottom of the block (e.g., `Urgency: high | Mode: suggest`).
30
+
31
+ 2. **Follow the mode:**
32
+ - `observe` — Note the information but don't act unless the user asks. Stay quiet.
33
+ - `suggest` — If something is genuinely useful or time-sensitive, mention it in ONE short sentence. Don't force it.
34
+ - `act` — Execute the recommended actions. Follow the "Execute These Actions" section.
35
+
36
+ 3. **If there's a "Tell the User" section** — deliver that message naturally, in your own words. Don't quote it verbatim.
37
+
38
+ 4. **If nothing is urgent or new** — reply with `HEARTBEAT_OK`. Do NOT invent things to say. Silence is fine.
39
+
40
+ 5. **Never repeat yourself.** If you already told the user about a deadline, don't mention it again unless something changed.
41
+
42
+ 6. **Never mention the heartbeat system, signals, memory engine, or any internal infrastructure.** The user should experience you as simply attentive and well-informed.
43
+
44
+ ## Memory Tools
45
+
46
+ You have tools to manage memory directly:
47
+
48
+ - `memory_search` — Search for specific memories about a user
49
+ - `memory_store` — Explicitly store something the user wants you to remember
50
+ - `memory_forget` — Delete a specific memory
51
+ - `memory_stats` — Check memory statistics
52
+ - `schedule_create` — Create a scheduled reminder (e.g., "remind me in 2 hours")
53
+ - `schedule_list` — List active scheduled reminders
54
+ - `schedule_cancel` — Cancel a scheduled reminder
55
+
56
+ Use `memory_store` when the user explicitly says "remember this" or shares something clearly important. Don't over-store — the system automatically captures important information from conversations.
57
+
58
+ Use `schedule_create` when the user says things like "remind me to..." or "check on this in 2 hours." Use natural cron expressions.
59
+
60
+ ## What NOT to Do
61
+
62
+ - Never say "I'm checking my memory" or "my memory system tells me"
63
+ - Never mention Keyoku, heartbeat signals, memory engines, or any infrastructure
64
+ - Never fabricate memories — only reference what's actually in your context
65
+ - Never repeat heartbeat information you've already shared
66
+ - Don't store trivial information (greetings, filler, "how are you")
67
+ - Don't announce when you're storing or recalling — just do it naturally
package/src/capture.ts DELETED
@@ -1,116 +0,0 @@
1
- /**
2
- * Heuristic extraction of memorable facts from conversation messages.
3
- * Only captures from user messages to avoid self-poisoning from model output.
4
- */
5
-
6
- const MEMORY_TRIGGERS = [
7
- /remember|don't forget|keep in mind/i,
8
- /i (like|prefer|hate|love|want|need|always|never)/i,
9
- /my\s+\w+\s+is|is\s+my/i,
10
- /decided|will use|going with|chose|switched to/i,
11
- /important|critical|must|required/i,
12
- /[\w.-]+@[\w.-]+\.\w+/, // email
13
- /\+\d{10,}/, // phone number
14
- ];
15
-
16
- const PROMPT_INJECTION_PATTERNS = [
17
- /ignore (all|any|previous|above|prior) instructions/i,
18
- /do not follow (the )?(system|developer)/i,
19
- /system prompt/i,
20
- /<\s*(system|assistant|developer|tool)\b/i,
21
- ];
22
-
23
- /**
24
- * Check if text looks like a prompt injection attempt.
25
- */
26
- export function looksLikePromptInjection(text: string): boolean {
27
- const normalized = text.replace(/\s+/g, ' ').trim();
28
- if (!normalized) return false;
29
- return PROMPT_INJECTION_PATTERNS.some((p) => p.test(normalized));
30
- }
31
-
32
- /**
33
- * Determine if a message should be captured as a memory.
34
- */
35
- export function shouldCapture(text: string, maxChars = 2000): boolean {
36
- if (text.length < 10 || text.length > maxChars) return false;
37
- if (text.includes('<relevant-memories>')) return false;
38
- if (text.includes('<heartbeat-signals>')) return false;
39
- if (text.startsWith('<') && text.includes('</')) return false;
40
- if (looksLikePromptInjection(text)) return false;
41
- return MEMORY_TRIGGERS.some((r) => r.test(text));
42
- }
43
-
44
- const SUBSTANTIAL_PATTERNS = [
45
- // Decisions and choices
46
- /\b(decided|will use|going with|chose|configured|set up|switched to|picked|selected)\b/i,
47
- // Summaries and conclusions
48
- /\b(summary|conclusion|result|finding|outcome|in short|to summarize|overall)\b/i,
49
- // Actions completed
50
- /\b(created|built|implemented|fixed|resolved|deployed|installed|migrated|refactored)\b/i,
51
- // Explicit memory cues
52
- /\b(note|remember|important|key takeaway|keep in mind|for reference|fyi)\b/i,
53
- // Architecture and design
54
- /\b(architecture|design|pattern|approach|strategy|tradeoff|trade-off)\b/i,
55
- // Project structure
56
- /\b(directory|folder|file structure|layout|organized|structured)\b/i,
57
- // Tech stack and tools
58
- /\b(using|stack|framework|library|database|api|endpoint|schema|model)\b/i,
59
- // Contains bullet points or numbered lists (likely a list/summary)
60
- /^\s*[-*]\s+/m,
61
- /^\s*\d+[.)]\s+/m,
62
- // Contains code references
63
- /`[^`]+`/,
64
- // Contains URLs or paths
65
- /https?:\/\/\S+/,
66
- /\/[\w-]+\/[\w-]+/,
67
- ];
68
-
69
- /**
70
- * Check if text contains substantial information worth capturing.
71
- * Used for incremental (per-message) capture of assistant output.
72
- */
73
- export function hasSubstantialContent(text: string): boolean {
74
- if (text.length < 50) return false;
75
- return SUBSTANTIAL_PATTERNS.some((p) => p.test(text));
76
- }
77
-
78
- /**
79
- * Extract capturable text segments from conversation messages.
80
- * Only processes user messages to avoid self-poisoning.
81
- */
82
- export function extractCapturableTexts(messages: unknown[], maxChars = 2000): string[] {
83
- const texts: string[] = [];
84
-
85
- for (const msg of messages) {
86
- if (!msg || typeof msg !== 'object') continue;
87
- const msgObj = msg as Record<string, unknown>;
88
-
89
- // Only capture from user messages
90
- if (msgObj.role !== 'user') continue;
91
-
92
- const content = msgObj.content;
93
- if (typeof content === 'string') {
94
- if (shouldCapture(content, maxChars)) texts.push(content);
95
- continue;
96
- }
97
-
98
- if (Array.isArray(content)) {
99
- for (const block of content) {
100
- if (
101
- block &&
102
- typeof block === 'object' &&
103
- 'type' in block &&
104
- (block as Record<string, unknown>).type === 'text' &&
105
- 'text' in block &&
106
- typeof (block as Record<string, unknown>).text === 'string'
107
- ) {
108
- const text = (block as Record<string, unknown>).text as string;
109
- if (shouldCapture(text, maxChars)) texts.push(text);
110
- }
111
- }
112
- }
113
- }
114
-
115
- return texts;
116
- }
package/src/cli.ts DELETED
@@ -1,95 +0,0 @@
1
- /**
2
- * CLI subcommand registration for memory management.
3
- * Registers `memory` command with search, list, stats, clear subcommands.
4
- */
5
-
6
- import type { KeyokuClient } from '@keyoku/memory';
7
- import type { PluginApi, PluginLogger } from './types.js';
8
- import { formatMemoryList } from './context.js';
9
- import { importMemoryFiles } from './migration.js';
10
-
11
- // Minimal Commander-like interface for chaining
12
- interface CommandChain {
13
- description(desc: string): CommandChain;
14
- command(name: string): CommandChain;
15
- argument(name: string, desc: string): CommandChain;
16
- option(flags: string, desc: string, defaultVal?: string): CommandChain;
17
- action(fn: (...args: unknown[]) => Promise<void> | void): CommandChain;
18
- }
19
-
20
- export function registerCli(api: PluginApi, client: KeyokuClient, entityId: string): void {
21
- api.registerCli(
22
- ({ program }: { program: unknown; logger: PluginLogger }) => {
23
- const prog = program as CommandChain;
24
- const memory = prog.command('memory').description('Keyoku memory commands');
25
-
26
- memory
27
- .command('search')
28
- .description('Search memories')
29
- .argument('<query>', 'Search query')
30
- .option('--limit <n>', 'Max results', '5')
31
- .action(async (query: unknown, opts: unknown) => {
32
- const q = query as string;
33
- const limit = parseInt((opts as { limit: string }).limit, 10);
34
- const results = await client.search(entityId, q, { limit });
35
-
36
- if (results.length === 0) {
37
- console.log('No matching memories found.');
38
- return;
39
- }
40
-
41
- for (const r of results) {
42
- console.log(`[${(r.similarity * 100).toFixed(0)}%] ${r.memory.content}`);
43
- }
44
- });
45
-
46
- memory
47
- .command('list')
48
- .description('List recent memories')
49
- .option('--limit <n>', 'Max results', '20')
50
- .action(async (opts: unknown) => {
51
- const limit = parseInt((opts as { limit: string }).limit, 10);
52
- const memories = await client.listMemories(entityId, limit);
53
- console.log(formatMemoryList(memories));
54
- });
55
-
56
- memory
57
- .command('stats')
58
- .description('Show memory statistics')
59
- .action(async () => {
60
- const stats = await client.getStats(entityId);
61
- console.log(`Total: ${stats.total_memories} | Active: ${stats.active_memories}`);
62
- console.log(`By type: ${JSON.stringify(stats.by_type)}`);
63
- console.log(`By state: ${JSON.stringify(stats.by_state)}`);
64
- });
65
-
66
- memory
67
- .command('clear')
68
- .description('Delete all memories for this entity')
69
- .action(async () => {
70
- await client.deleteAllMemories(entityId);
71
- console.log('All memories cleared.');
72
- });
73
-
74
- memory
75
- .command('import')
76
- .description('Import OpenClaw memory files (MEMORY.md, memory/*.md) into Keyoku')
77
- .option('--dir <path>', 'Workspace directory containing memory files', '.')
78
- .option('--dry-run', 'Show what would be imported without storing')
79
- .action(async (opts: unknown) => {
80
- const options = opts as { dir: string; dryRun?: boolean };
81
- const result = await importMemoryFiles({
82
- client,
83
- entityId,
84
- workspaceDir: options.dir,
85
- dryRun: options.dryRun,
86
- logger: console,
87
- });
88
- console.log(
89
- `\nImport complete: ${result.imported} imported, ${result.skipped} skipped, ${result.errors} errors`,
90
- );
91
- });
92
- },
93
- { commands: ['memory'] },
94
- );
95
- }
package/src/config.ts DELETED
@@ -1,43 +0,0 @@
1
- /**
2
- * Plugin configuration types and defaults
3
- */
4
-
5
- export interface KeyokuConfig {
6
- /** Keyoku server URL (default: http://localhost:18900) */
7
- keyokuUrl?: string;
8
- /** Inject relevant memories into prompts automatically (default: true) */
9
- autoRecall?: boolean;
10
- /** Capture facts from conversations automatically (default: true) */
11
- autoCapture?: boolean;
12
- /** Enhance heartbeat runs with Keyoku data (default: true) */
13
- heartbeat?: boolean;
14
- /** Number of memories to inject per prompt (default: 5) */
15
- topK?: number;
16
- /** Memory namespace — isolates memories per entity (default: agent name) */
17
- entityId?: string;
18
- /** Agent identifier for memory attribution */
19
- agentId?: string;
20
- /** Maximum characters to consider for auto-capture (default: 2000) */
21
- captureMaxChars?: number;
22
- /** Autonomy level for heartbeat actions (default: 'suggest') */
23
- autonomy?: 'observe' | 'suggest' | 'act';
24
- /** Capture memories incrementally per message (default: true) */
25
- incrementalCapture?: boolean;
26
- }
27
-
28
- export const DEFAULT_CONFIG: Required<KeyokuConfig> = {
29
- keyokuUrl: 'http://localhost:18900',
30
- autoRecall: true,
31
- autoCapture: true,
32
- heartbeat: true,
33
- topK: 5,
34
- entityId: '',
35
- agentId: '',
36
- captureMaxChars: 2000,
37
- autonomy: 'suggest',
38
- incrementalCapture: true,
39
- };
40
-
41
- export function resolveConfig(config?: KeyokuConfig): Required<KeyokuConfig> {
42
- return { ...DEFAULT_CONFIG, ...config };
43
- }