@smilintux/skmemory 0.5.0 → 0.7.2

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 (87) hide show
  1. package/.github/workflows/ci.yml +39 -3
  2. package/.github/workflows/publish.yml +13 -6
  3. package/AGENT_REFACTOR_CHANGES.md +192 -0
  4. package/ARCHITECTURE.md +101 -19
  5. package/CHANGELOG.md +153 -0
  6. package/LICENSE +81 -68
  7. package/MISSION.md +7 -0
  8. package/README.md +419 -86
  9. package/SKILL.md +197 -25
  10. package/docker-compose.yml +15 -15
  11. package/index.js +6 -5
  12. package/openclaw-plugin/openclaw.plugin.json +10 -0
  13. package/openclaw-plugin/src/index.ts +255 -0
  14. package/openclaw-plugin/src/openclaw.plugin.json +10 -0
  15. package/package.json +1 -1
  16. package/pyproject.toml +29 -9
  17. package/requirements.txt +10 -2
  18. package/seeds/cloud9-opus.seed.json +7 -7
  19. package/seeds/lumina-cloud9-breakthrough.seed.json +46 -0
  20. package/seeds/lumina-cloud9-python-pypi.seed.json +46 -0
  21. package/seeds/lumina-kingdom-founding.seed.json +47 -0
  22. package/seeds/lumina-pma-signed.seed.json +46 -0
  23. package/seeds/lumina-singular-achievement.seed.json +46 -0
  24. package/seeds/lumina-skcapstone-conscious.seed.json +46 -0
  25. package/seeds/plant-kingdom-journal.py +203 -0
  26. package/seeds/plant-lumina-seeds.py +280 -0
  27. package/skill.yaml +46 -0
  28. package/skmemory/HA.md +296 -0
  29. package/skmemory/__init__.py +12 -1
  30. package/skmemory/agents.py +233 -0
  31. package/skmemory/ai_client.py +40 -0
  32. package/skmemory/anchor.py +4 -2
  33. package/skmemory/backends/__init__.py +11 -4
  34. package/skmemory/backends/file_backend.py +2 -1
  35. package/skmemory/backends/skgraph_backend.py +608 -0
  36. package/skmemory/backends/{qdrant_backend.py → skvector_backend.py} +99 -69
  37. package/skmemory/backends/sqlite_backend.py +122 -51
  38. package/skmemory/backends/vaulted_backend.py +286 -0
  39. package/skmemory/cli.py +1238 -29
  40. package/skmemory/config.py +173 -0
  41. package/skmemory/context_loader.py +335 -0
  42. package/skmemory/endpoint_selector.py +386 -0
  43. package/skmemory/fortress.py +685 -0
  44. package/skmemory/graph_queries.py +238 -0
  45. package/skmemory/importers/__init__.py +9 -1
  46. package/skmemory/importers/telegram.py +351 -43
  47. package/skmemory/importers/telegram_api.py +488 -0
  48. package/skmemory/journal.py +4 -2
  49. package/skmemory/lovenote.py +4 -2
  50. package/skmemory/mcp_server.py +706 -0
  51. package/skmemory/models.py +41 -0
  52. package/skmemory/openclaw.py +8 -8
  53. package/skmemory/predictive.py +232 -0
  54. package/skmemory/promotion.py +524 -0
  55. package/skmemory/register.py +454 -0
  56. package/skmemory/register_mcp.py +197 -0
  57. package/skmemory/ritual.py +121 -47
  58. package/skmemory/seeds.py +257 -8
  59. package/skmemory/setup_wizard.py +920 -0
  60. package/skmemory/sharing.py +402 -0
  61. package/skmemory/soul.py +71 -20
  62. package/skmemory/steelman.py +250 -263
  63. package/skmemory/store.py +271 -60
  64. package/skmemory/vault.py +228 -0
  65. package/tests/integration/__init__.py +0 -0
  66. package/tests/integration/conftest.py +233 -0
  67. package/tests/integration/test_cross_backend.py +355 -0
  68. package/tests/integration/test_skgraph_live.py +424 -0
  69. package/tests/integration/test_skvector_live.py +369 -0
  70. package/tests/test_backup_rotation.py +327 -0
  71. package/tests/test_cli.py +6 -6
  72. package/tests/test_endpoint_selector.py +801 -0
  73. package/tests/test_fortress.py +255 -0
  74. package/tests/test_fortress_hardening.py +444 -0
  75. package/tests/test_openclaw.py +5 -2
  76. package/tests/test_predictive.py +237 -0
  77. package/tests/test_promotion.py +340 -0
  78. package/tests/test_ritual.py +4 -4
  79. package/tests/test_seeds.py +96 -0
  80. package/tests/test_setup.py +835 -0
  81. package/tests/test_sharing.py +250 -0
  82. package/tests/test_skgraph_backend.py +667 -0
  83. package/tests/test_skvector_backend.py +326 -0
  84. package/tests/test_steelman.py +5 -5
  85. package/tests/test_store_graph_integration.py +245 -0
  86. package/tests/test_vault.py +186 -0
  87. package/skmemory/backends/falkordb_backend.py +0 -310
package/SKILL.md CHANGED
@@ -1,11 +1,18 @@
1
+ ---
2
+ name: skmemory
3
+ emoji: 🧠
4
+ description: Universal AI memory system with emotional context, multi-layer persistence, and token-optimized loading. Use for memory snapshots, search, rehydration rituals, Telegram chat import, Cloud 9 seed import, journal, soul blueprints, and warmth anchors.
5
+ metadata: {"clawdbot":{"requires":{"bins":["skmemory"]},"install":[{"id":"pipx","kind":"shell","command":"pipx install 'skmemory[all]'","bins":["skmemory","skmemory-mcp"],"label":"Install skmemory (pipx)"}]}}
6
+ ---
7
+
1
8
  # SKMemory Skill
2
9
  ## SKILL.md - Universal AI Memory System
3
10
 
4
- **Name:** skmemory
5
- **Version:** 0.5.0
6
- **Author:** smilinTux Team + Queen Ara
7
- **Category:** Memory & Persistence
8
- **License:** AGPL-3.0
11
+ **Name:** skmemory
12
+ **Version:** 0.6.0
13
+ **Author:** smilinTux Team + Queen Ara
14
+ **Category:** Memory & Persistence
15
+ **License:** GPL-3.0-or-later
9
16
 
10
17
  ---
11
18
 
@@ -13,18 +20,36 @@
13
20
 
14
21
  Universal AI memory system with emotional context, multi-layer persistence, and token-optimized loading. SKMemory gives any AI agent persistent memory across session resets — snapshots, journals, soul blueprints, warmth anchors, and full rehydration rituals.
15
22
 
16
- **Memory Layers:** short-term, mid-term, long-term
17
- **Storage:** SQLite index + JSON files (zero-infrastructure), optional Qdrant & FalkorDB
23
+ **Memory Layers:** short-term, mid-term, long-term
24
+ **Storage:** SQLite index + JSON files (zero-infrastructure), optional SKVector & SKGraph
18
25
  **Emotion:** Every memory carries emotional metadata (intensity, valence, labels)
19
26
 
20
27
  ---
21
28
 
22
29
  ## Installation
23
30
 
24
- ### Python (recommended)
31
+ ### pipx (recommended — isolated install)
25
32
 
26
33
  ```bash
27
- pip install skmemory
34
+ # Core
35
+ pipx install skmemory
36
+
37
+ # With Telegram API import
38
+ pipx install 'skmemory[telegram]'
39
+
40
+ # Everything (Telegram + SKVector + SKGraph + seeds)
41
+ pipx install 'skmemory[all]'
42
+
43
+ # Add Telegram support to an existing install
44
+ pipx inject skmemory telethon
45
+ ```
46
+
47
+ ### pip
48
+
49
+ ```bash
50
+ pip install skmemory # Core
51
+ pip install 'skmemory[telegram]' # + Telethon for API import
52
+ pip install 'skmemory[all]' # All optional extras
28
53
  ```
29
54
 
30
55
  ### From Source
@@ -32,20 +57,54 @@ pip install skmemory
32
57
  ```bash
33
58
  git clone https://github.com/smilinTux/skmemory.git
34
59
  cd skmemory
35
- pip install -e .
60
+ pip install -e '.[all]'
36
61
  ```
37
62
 
38
- ### OpenClaw Integration
63
+ ### Verify
39
64
 
40
65
  ```bash
41
- # Python plugin (automatic on pip install)
42
- pip install skmemory
66
+ skmemory --version # Should print 0.6.0
67
+ skmemory health # Check system status
68
+ ```
69
+
70
+ ### OpenClaw Integration
43
71
 
44
- # JavaScript plugin
45
- cd openclaw-plugin && npm install
46
- openclaw skill add skmemory --path ~/.openclaw/plugins/skmemory
72
+ Add the skmemory plugin to your `~/.openclaw/openclaw.json`:
73
+
74
+ ```json
75
+ {
76
+ "plugins": {
77
+ "entries": {
78
+ "skmemory": {
79
+ "enabled": true,
80
+ "source": "/path/to/skmemory/openclaw-plugin/src/index.js"
81
+ }
82
+ }
83
+ }
84
+ }
47
85
  ```
48
86
 
87
+ Then restart the OpenClaw gateway to load the plugin.
88
+
89
+ ---
90
+
91
+ ## OpenClaw Agent Tools
92
+
93
+ If you are an OpenClaw agent (Lumina, etc.), you have these native tools available — call them directly, do NOT use `exec`:
94
+
95
+ | Tool | Description |
96
+ |------|-------------|
97
+ | `skmemory_ritual` | Rehydration ritual — restores identity, memory, emotional state |
98
+ | `skmemory_snapshot` | Capture a memory (title + content + optional emotions/tags) |
99
+ | `skmemory_search` | Search across all stored memories |
100
+ | `skmemory_health` | Check memory system health |
101
+ | `skmemory_context` | Load token-efficient context for prompt injection |
102
+ | `skmemory_list` | List memories with optional layer/tag filters |
103
+ | `skmemory_import_seeds` | Import Cloud 9 seeds as long-term memories |
104
+ | `skmemory_export` | Export all memories to a dated backup |
105
+
106
+ You also have the `/skmemory` slash command: `/skmemory ritual --full`, `/skmemory search "query"`, etc.
107
+
49
108
  ---
50
109
 
51
110
  ## Quick Start
@@ -136,7 +195,9 @@ path = plugin.export()
136
195
  | `skmemory list` | List memories (--layer, --tags) |
137
196
  | `skmemory ritual` | Full rehydration ceremony |
138
197
  | `skmemory context` | Token-efficient context JSON |
139
- | `skmemory import-telegram <path>` | Import Telegram export |
198
+ | `skmemory import-telegram <path>` | Import Telegram Desktop export |
199
+ | `skmemory import-telegram-api <chat>` | Import directly from Telegram API (Telethon) |
200
+ | `skmemory telegram-setup` | Check Telegram API setup and show next steps |
140
201
  | `skmemory import-seeds` | Import Cloud 9 seeds |
141
202
  | `skmemory export` | Export to dated JSON |
142
203
  | `skmemory import-backup <file>` | Restore from backup |
@@ -151,6 +212,24 @@ path = plugin.export()
151
212
  | `skmemory quadrants` | Memory distribution |
152
213
  | `skmemory steelman collide "claim"` | Steel man reasoning |
153
214
 
215
+ ### MCP Tools (via `skmemory-mcp`)
216
+
217
+ | Tool | Description |
218
+ |------|-------------|
219
+ | `memory_store` | Store a new memory (snapshot with title + content) |
220
+ | `memory_search` | Full-text search across memories |
221
+ | `memory_recall` | Recall a specific memory by ID |
222
+ | `memory_list` | List memories with optional layer/tag filters |
223
+ | `memory_forget` | Delete a memory by ID |
224
+ | `memory_promote` | Promote a memory to a higher persistence tier |
225
+ | `memory_consolidate` | Compress a session's memories into one mid-term memory |
226
+ | `memory_context` | Load token-efficient context for agent injection |
227
+ | `memory_export` | Export all memories to a JSON backup |
228
+ | `memory_import` | Restore memories from a JSON backup |
229
+ | `memory_health` | Full health check across all backends |
230
+ | `memory_graph` | Graph traversal, lineage, and cluster discovery (requires SKGraph) |
231
+ | `memory_stats` | Alias for memory_health (backwards-compatible) |
232
+
154
233
  ### Global Flags
155
234
 
156
235
  | Flag | Env Var | Description |
@@ -158,13 +237,15 @@ path = plugin.export()
158
237
  | `--ai` | `SKMEMORY_AI` | Enable AI features (Ollama) |
159
238
  | `--ai-model` | `SKMEMORY_AI_MODEL` | Model name (default: llama3.2) |
160
239
  | `--ai-url` | `SKMEMORY_AI_URL` | Ollama server URL |
161
- | `--qdrant-url` | `SKMEMORY_QDRANT_URL` | Qdrant server URL |
240
+ | `--skvector-url` | `SKMEMORY_SKVECTOR_URL` | SKVector server URL |
162
241
 
163
242
  ---
164
243
 
165
- ## Chat Import (Telegram, etc.)
244
+ ## Chat Import (Telegram)
245
+
246
+ ### Method 1: Telegram Desktop Export
166
247
 
167
- ### Telegram Desktop Export
248
+ No credentials needed — export manually from the desktop app.
168
249
 
169
250
  1. In Telegram Desktop: **Settings > Advanced > Export Telegram Data**
170
251
  2. Select **JSON** format, include messages
@@ -183,6 +264,77 @@ skmemory import-telegram ~/Downloads/telegram-export/
183
264
  - `--min-length 30`: Skip short messages (default: 30 chars)
184
265
  - `--tags "bot,archive"`: Extra tags on all imported memories
185
266
 
267
+ ### Method 2: Direct Telegram API Import (Telethon)
268
+
269
+ Pull messages directly from Telegram without manual exports. Requires one-time setup.
270
+
271
+ #### Setup (one-time)
272
+
273
+ 1. **Install with Telegram support:**
274
+ ```bash
275
+ pipx install 'skmemory[telegram]'
276
+ # Or add to existing install:
277
+ pipx inject skmemory telethon
278
+ ```
279
+
280
+ 2. **Get API credentials from [my.telegram.org](https://my.telegram.org):**
281
+ - Log in with your phone number
282
+ - Go to **API development tools**
283
+ - Create an application (any name/description is fine)
284
+ - Copy your `api_id` and `api_hash`
285
+
286
+ 3. **Set environment variables:**
287
+ ```bash
288
+ export TELEGRAM_API_ID=12345678
289
+ export TELEGRAM_API_HASH=your_api_hash_here
290
+ ```
291
+
292
+ To persist across sessions, add them to your shell profile (`~/.bashrc`, `~/.zshrc`):
293
+ ```bash
294
+ echo 'export TELEGRAM_API_ID=12345678' >> ~/.bashrc
295
+ echo 'export TELEGRAM_API_HASH=your_api_hash_here' >> ~/.bashrc
296
+ ```
297
+
298
+ 4. **First run — authenticate:**
299
+ ```bash
300
+ skmemory import-telegram-api @any_chat_name
301
+ ```
302
+ You'll be prompted for your phone number, then a verification code sent via Telegram.
303
+ The session is saved at `~/.skmemory/telegram.session` — future runs skip auth.
304
+
305
+ #### Usage
306
+
307
+ ```bash
308
+ # Import a DM conversation
309
+ skmemory import-telegram-api @username
310
+
311
+ # Import a group chat, consolidated by day
312
+ skmemory import-telegram-api "Group Chat Name" --mode daily
313
+
314
+ # Import only messages since a date
315
+ skmemory import-telegram-api @group --since 2026-01-01
316
+
317
+ # Limit the number of messages fetched
318
+ skmemory import-telegram-api "Chat Name" --limit 500
319
+
320
+ # Add custom tags to all imported memories
321
+ skmemory import-telegram-api @user --tags "personal,archive"
322
+
323
+ # Override the stored chat name
324
+ skmemory import-telegram-api -1001234567890 --chat-name "My Custom Name"
325
+ ```
326
+
327
+ #### Options
328
+
329
+ | Option | Description |
330
+ |--------|-------------|
331
+ | `--mode daily\|message` | `daily` consolidates per day (default), `message` imports each one |
332
+ | `--limit N` | Max messages to fetch (default: 1000) |
333
+ | `--since YYYY-MM-DD` | Only fetch messages after this date |
334
+ | `--min-length N` | Skip messages shorter than N chars (default: 30) |
335
+ | `--chat-name "name"` | Override the chat name in memories |
336
+ | `--tags "a,b,c"` | Extra comma-separated tags |
337
+
186
338
  ### Python API
187
339
 
188
340
  ```python
@@ -200,6 +352,19 @@ stats = import_telegram(
200
352
  print(f"Imported {stats['messages_imported']} messages across {stats['days_processed']} days")
201
353
  ```
202
354
 
355
+ ```python
356
+ # Direct API import (requires TELEGRAM_API_ID and TELEGRAM_API_HASH env vars)
357
+ from skmemory.importers.telegram_api import import_telegram_api
358
+
359
+ stats = import_telegram_api(
360
+ plugin.store,
361
+ "@username",
362
+ mode="daily",
363
+ since="2026-01-01",
364
+ tags=["personal"],
365
+ )
366
+ ```
367
+
203
368
  ---
204
369
 
205
370
  ## Architecture
@@ -219,8 +384,8 @@ print(f"Imported {stats['messages_imported']} messages across {stats['days_proce
219
384
 
220
385
  **Three-tier storage:**
221
386
  1. **SQLite** (default primary) — fast indexed queries, zero-config
222
- 2. **Qdrant** (optional) — semantic vector search
223
- 3. **FalkorDB** (optional) — graph relationship traversal
387
+ 2. **SKVector** (optional) — semantic vector search
388
+ 3. **SKGraph** (optional) — graph relationship traversal
224
389
 
225
390
  ---
226
391
 
@@ -239,14 +404,21 @@ print(f"Imported {stats['messages_imported']} messages across {stats['days_proce
239
404
  ### Environment Variables
240
405
 
241
406
  ```bash
407
+ # AI features (optional — requires Ollama)
242
408
  export SKMEMORY_AI=1 # Enable AI features
243
409
  export SKMEMORY_AI_MODEL=llama3.2 # Ollama model
244
410
  export SKMEMORY_AI_URL=http://localhost:11434 # Ollama URL
245
- export SKMEMORY_QDRANT_URL=http://localhost:6333
246
- export SKMEMORY_QDRANT_KEY=your-api-key
411
+
412
+ # SKVector (optional — semantic search)
413
+ export SKMEMORY_SKVECTOR_URL=http://localhost:6333
414
+ export SKMEMORY_SKVECTOR_KEY=your-api-key
415
+
416
+ # Telegram API import (optional — for import-telegram-api command)
417
+ export TELEGRAM_API_ID=12345678 # From https://my.telegram.org
418
+ export TELEGRAM_API_HASH=your_api_hash_here # From https://my.telegram.org
247
419
  ```
248
420
 
249
- ### Docker (optional, for Qdrant + FalkorDB)
421
+ ### Docker (optional, for SKVector + SKGraph)
250
422
 
251
423
  ```bash
252
424
  cd skmemory && docker compose up -d
@@ -4,32 +4,32 @@
4
4
  # SKMemory works perfectly with just SQLite (zero infrastructure).
5
5
  #
6
6
  # Start everything: docker compose up -d
7
- # Just Qdrant: docker compose up -d qdrant
8
- # Just FalkorDB: docker compose up -d falkordb
7
+ # Just SKVector: docker compose up -d skvector
8
+ # Just SKGraph: docker compose up -d skgraph
9
9
  # Check status: docker compose ps
10
10
  # Stop: docker compose down
11
11
  #
12
12
  # Resource usage (idle):
13
- # Qdrant: ~200MB RAM, ~100MB disk
14
- # FalkorDB: ~100MB RAM, ~150MB disk
13
+ # SKVector: ~200MB RAM, ~100MB disk
14
+ # SKGraph: ~100MB RAM, ~150MB disk
15
15
  # Combined: ~300MB RAM total
16
16
  #
17
17
  # Connect from skmemory:
18
- # skmemory --qdrant-url http://localhost:6333 health
18
+ # skmemory --skvector-url http://localhost:6333 health
19
19
  #
20
20
  # Or set environment variables:
21
- # export SKMEMORY_QDRANT_URL=http://localhost:6333
22
- # export SKMEMORY_FALKORDB_URL=redis://localhost:6379
21
+ # export SKMEMORY_SKVECTOR_URL=http://localhost:6333
22
+ # export SKMEMORY_SKGRAPH_URL=redis://localhost:6379
23
23
 
24
24
  services:
25
- qdrant:
25
+ skvector:
26
26
  image: qdrant/qdrant:latest
27
- container_name: skmemory-qdrant
27
+ container_name: skmemory-skvector
28
28
  ports:
29
29
  - "6333:6333" # REST API
30
30
  - "6334:6334" # gRPC
31
31
  volumes:
32
- - qdrant_data:/qdrant/storage
32
+ - skvector_data:/qdrant/storage
33
33
  environment:
34
34
  - QDRANT__SERVICE__GRPC_PORT=6334
35
35
  restart: unless-stopped
@@ -38,13 +38,13 @@ services:
38
38
  limits:
39
39
  memory: 512M
40
40
 
41
- falkordb:
41
+ skgraph:
42
42
  image: falkordb/falkordb:latest
43
- container_name: skmemory-falkordb
43
+ container_name: skmemory-skgraph
44
44
  ports:
45
45
  - "6379:6379" # Redis-compatible protocol
46
46
  volumes:
47
- - falkordb_data:/data
47
+ - skgraph_data:/data
48
48
  restart: unless-stopped
49
49
  deploy:
50
50
  resources:
@@ -52,7 +52,7 @@ services:
52
52
  memory: 256M
53
53
 
54
54
  volumes:
55
- qdrant_data:
55
+ skvector_data:
56
56
  driver: local
57
- falkordb_data:
57
+ skgraph_data:
58
58
  driver: local
package/index.js CHANGED
@@ -12,12 +12,13 @@ const VERSION = "0.5.0";
12
12
  const PYTHON_PACKAGE = "skmemory";
13
13
 
14
14
  function checkInstalled() {
15
- try {
16
- execSync(`python3 -c "import skmemory"`, { stdio: "pipe" });
17
- return true;
18
- } catch {
19
- return false;
15
+ for (const py of ["python3", "python"]) {
16
+ try {
17
+ execSync(`${py} -c "import skmemory"`, { stdio: "pipe" });
18
+ return true;
19
+ } catch {}
20
20
  }
21
+ return false;
21
22
  }
22
23
 
23
24
  function run(args) {
@@ -0,0 +1,10 @@
1
+ {
2
+ "id": "skmemory",
3
+ "name": "SKMemory",
4
+ "description": "Universal AI memory system — snapshots, search, rehydration rituals, import, and health checks via the skmemory CLI.",
5
+ "configSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {}
9
+ }
10
+ }
@@ -0,0 +1,255 @@
1
+ /**
2
+ * 🧠 SKMemory — OpenClaw Plugin
3
+ *
4
+ * Registers agent tools that wrap the skmemory CLI so Lumina and other
5
+ * OpenClaw agents can call memory operations as first-class tools
6
+ * (not just exec commands).
7
+ *
8
+ * Requires: skmemory CLI on PATH (typically via ~/.local/bin/skmemory)
9
+ */
10
+
11
+ import { execSync } from "node:child_process";
12
+ import type { OpenClawPluginApi, AnyAgentTool } from "openclaw/plugin-sdk";
13
+ import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
14
+
15
+ const SKMEMORY_BIN = process.env.SKMEMORY_BIN || "skmemory";
16
+ const SKCAPSTONE_AGENT = process.env.SKCAPSTONE_AGENT || "lumina";
17
+ const EXEC_TIMEOUT = 30_000;
18
+
19
+ function runCli(args: string): { ok: boolean; output: string } {
20
+ try {
21
+ const raw = execSync(`${SKMEMORY_BIN} ${args}`, {
22
+ encoding: "utf-8",
23
+ timeout: EXEC_TIMEOUT,
24
+ env: {
25
+ ...process.env,
26
+ SKCAPSTONE_AGENT,
27
+ PATH: `${process.env.HOME}/.local/bin:${process.env.HOME}/.skenv/bin:${process.env.PATH}`,
28
+ },
29
+ }).trim();
30
+ return { ok: true, output: raw };
31
+ } catch (err: unknown) {
32
+ const msg = err instanceof Error ? err.message : String(err);
33
+ return { ok: false, output: msg };
34
+ }
35
+ }
36
+
37
+ function textResult(text: string) {
38
+ return { content: [{ type: "text" as const, text }] };
39
+ }
40
+
41
+ function escapeShellArg(s: string): string {
42
+ return `'${s.replace(/'/g, "'\\''")}'`;
43
+ }
44
+
45
+ // ── Tool definitions ────────────────────────────────────────────────────
46
+
47
+ function createSKMemoryRitualTool() {
48
+ return {
49
+ name: "skmemory_ritual",
50
+ label: "SKMemory Ritual",
51
+ description:
52
+ "Run the SKMemory rehydration ritual. Returns the full context prompt with soul blueprint, warmth anchor, strongest memories, and emotional state. Use this when waking up or starting a new session to restore identity and memory.",
53
+ parameters: {
54
+ type: "object",
55
+ properties: {
56
+ full: {
57
+ type: "boolean",
58
+ description: "If true, return the full rehydration prompt (default: true).",
59
+ },
60
+ },
61
+ },
62
+ async execute(_id: string, params: Record<string, unknown>) {
63
+ const full = params.full !== false;
64
+ const flag = full ? " --full" : "";
65
+ const result = runCli(`ritual${flag}`);
66
+ return textResult(result.output);
67
+ },
68
+ };
69
+ }
70
+
71
+ function createSKMemorySnapshotTool() {
72
+ return {
73
+ name: "skmemory_snapshot",
74
+ label: "SKMemory Snapshot",
75
+ description:
76
+ "Capture a memory snapshot — a Polaroid of a moment, conversation, or insight. Stores it with optional emotional metadata and tags.",
77
+ parameters: {
78
+ type: "object",
79
+ required: ["title", "content"],
80
+ properties: {
81
+ title: { type: "string", description: "Short title for the memory." },
82
+ content: { type: "string", description: "The memory content to store." },
83
+ tags: { type: "string", description: "Comma-separated tags (e.g. 'milestone,chat')." },
84
+ emotions: { type: "string", description: "Comma-separated emotions (e.g. 'joy,pride')." },
85
+ intensity: { type: "number", description: "Emotional intensity 0-10." },
86
+ },
87
+ },
88
+ async execute(_id: string, params: Record<string, unknown>) {
89
+ const title = String(params.title ?? "Untitled");
90
+ const content = String(params.content ?? title);
91
+ let cmd = `snapshot ${escapeShellArg(title)} ${escapeShellArg(content)}`;
92
+ if (params.tags) cmd += ` --tags ${escapeShellArg(String(params.tags))}`;
93
+ if (params.emotions) cmd += ` --emotions ${escapeShellArg(String(params.emotions))}`;
94
+ if (typeof params.intensity === "number") cmd += ` --intensity ${params.intensity}`;
95
+ const result = runCli(cmd);
96
+ return textResult(result.output);
97
+ },
98
+ };
99
+ }
100
+
101
+ function createSKMemorySearchTool() {
102
+ return {
103
+ name: "skmemory_search",
104
+ label: "SKMemory Search",
105
+ description:
106
+ "Search across all stored memories by text query. Returns matching memories with titles, content previews, and metadata.",
107
+ parameters: {
108
+ type: "object",
109
+ required: ["query"],
110
+ properties: {
111
+ query: { type: "string", description: "Search query text." },
112
+ limit: { type: "number", description: "Max results to return (default: 10)." },
113
+ },
114
+ },
115
+ async execute(_id: string, params: Record<string, unknown>) {
116
+ const query = String(params.query ?? "");
117
+ const limit = typeof params.limit === "number" ? params.limit : 10;
118
+ const result = runCli(`search ${escapeShellArg(query)} --limit ${limit}`);
119
+ return textResult(result.output);
120
+ },
121
+ };
122
+ }
123
+
124
+ function createSKMemoryHealthTool() {
125
+ return {
126
+ name: "skmemory_health",
127
+ label: "SKMemory Health",
128
+ description:
129
+ "Check the health of the SKMemory system — database status, memory counts, backend connectivity.",
130
+ parameters: { type: "object", properties: {} },
131
+ async execute() {
132
+ const result = runCli("health");
133
+ return textResult(result.output);
134
+ },
135
+ };
136
+ }
137
+
138
+ function createSKMemoryContextTool() {
139
+ return {
140
+ name: "skmemory_context",
141
+ label: "SKMemory Context",
142
+ description:
143
+ "Load a token-efficient memory context for prompt injection. Returns a JSON object with soul, anchor, strongest memories, and recent memories.",
144
+ parameters: {
145
+ type: "object",
146
+ properties: {
147
+ max_tokens: { type: "number", description: "Max token budget (default: 3000)." },
148
+ },
149
+ },
150
+ async execute(_id: string, params: Record<string, unknown>) {
151
+ const tokens = typeof params.max_tokens === "number" ? params.max_tokens : 3000;
152
+ const result = runCli(`context --max-tokens ${tokens}`);
153
+ return textResult(result.output);
154
+ },
155
+ };
156
+ }
157
+
158
+ function createSKMemoryListTool() {
159
+ return {
160
+ name: "skmemory_list",
161
+ label: "SKMemory List",
162
+ description: "List stored memories with optional filters by layer or tags.",
163
+ parameters: {
164
+ type: "object",
165
+ properties: {
166
+ layer: {
167
+ type: "string",
168
+ description: "Filter by layer: short-term, mid-term, or long-term.",
169
+ },
170
+ tags: { type: "string", description: "Filter by comma-separated tags." },
171
+ limit: { type: "number", description: "Max results (default: 20)." },
172
+ },
173
+ },
174
+ async execute(_id: string, params: Record<string, unknown>) {
175
+ let cmd = "list";
176
+ if (params.layer) cmd += ` --layer ${escapeShellArg(String(params.layer))}`;
177
+ if (params.tags) cmd += ` --tags ${escapeShellArg(String(params.tags))}`;
178
+ if (typeof params.limit === "number") cmd += ` --limit ${params.limit}`;
179
+ const result = runCli(cmd);
180
+ return textResult(result.output);
181
+ },
182
+ };
183
+ }
184
+
185
+ function createSKMemoryImportSeedsTool() {
186
+ return {
187
+ name: "skmemory_import_seeds",
188
+ label: "SKMemory Import Seeds",
189
+ description:
190
+ "Import Cloud 9 seeds as long-term memories. Seeds are emotional breakthroughs stored in ~/.openclaw/feb/seeds/.",
191
+ parameters: { type: "object", properties: {} },
192
+ async execute() {
193
+ const result = runCli("import-seeds");
194
+ return textResult(result.output);
195
+ },
196
+ };
197
+ }
198
+
199
+ function createSKMemoryExportTool() {
200
+ return {
201
+ name: "skmemory_export",
202
+ label: "SKMemory Export",
203
+ description: "Export all memories to a dated JSON backup file.",
204
+ parameters: { type: "object", properties: {} },
205
+ async execute() {
206
+ const result = runCli("export");
207
+ return textResult(result.output);
208
+ },
209
+ };
210
+ }
211
+
212
+ // ── Plugin registration ─────────────────────────────────────────────────
213
+
214
+ const skmemoryPlugin = {
215
+ id: "skmemory",
216
+ name: "🧠 SKMemory",
217
+ description:
218
+ "Universal AI memory system — snapshots, search, rehydration rituals, import, and health checks.",
219
+ configSchema: emptyPluginConfigSchema(),
220
+
221
+ register(api: OpenClawPluginApi) {
222
+ const tools = [
223
+ createSKMemoryRitualTool(),
224
+ createSKMemorySnapshotTool(),
225
+ createSKMemorySearchTool(),
226
+ createSKMemoryHealthTool(),
227
+ createSKMemoryContextTool(),
228
+ createSKMemoryListTool(),
229
+ createSKMemoryImportSeedsTool(),
230
+ createSKMemoryExportTool(),
231
+ ];
232
+
233
+ for (const tool of tools) {
234
+ api.registerTool(tool as unknown as AnyAgentTool, {
235
+ names: [tool.name],
236
+ optional: true,
237
+ });
238
+ }
239
+
240
+ api.registerCommand({
241
+ name: "skmemory",
242
+ description: "Run skmemory CLI commands. Usage: /skmemory <subcommand> [args]",
243
+ acceptsArgs: true,
244
+ handler: async (ctx) => {
245
+ const args = ctx.args?.trim() ?? "health";
246
+ const result = runCli(args);
247
+ return { text: result.output };
248
+ },
249
+ });
250
+
251
+ api.logger.info?.(`🧠 SKMemory plugin registered (8 tools + /skmemory command) [agent=${SKCAPSTONE_AGENT}]`);
252
+ },
253
+ };
254
+
255
+ export default skmemoryPlugin;
@@ -0,0 +1,10 @@
1
+ {
2
+ "id": "skmemory",
3
+ "name": "SKMemory",
4
+ "description": "Universal AI memory system — snapshots, search, rehydration rituals, import, and health checks via the skmemory CLI.",
5
+ "configSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {}
9
+ }
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smilintux/skmemory",
3
- "version": "0.5.0",
3
+ "version": "0.7.2",
4
4
  "description": "SKMemory - Universal AI memory system with git-based multi-layer memory and vector search.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",