@memtensor/memos-local-openclaw-plugin 0.3.20 → 1.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/README.md +239 -22
- package/dist/capture/index.d.ts +1 -1
- package/dist/capture/index.d.ts.map +1 -1
- package/dist/capture/index.js +33 -8
- package/dist/capture/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/ingest/providers/anthropic.d.ts.map +1 -1
- package/dist/ingest/providers/anthropic.js +22 -8
- package/dist/ingest/providers/anthropic.js.map +1 -1
- package/dist/ingest/providers/bedrock.d.ts.map +1 -1
- package/dist/ingest/providers/bedrock.js +22 -8
- package/dist/ingest/providers/bedrock.js.map +1 -1
- package/dist/ingest/providers/gemini.d.ts.map +1 -1
- package/dist/ingest/providers/gemini.js +22 -8
- package/dist/ingest/providers/gemini.js.map +1 -1
- package/dist/ingest/providers/index.d.ts +13 -18
- package/dist/ingest/providers/index.d.ts.map +1 -1
- package/dist/ingest/providers/index.js +213 -139
- package/dist/ingest/providers/index.js.map +1 -1
- package/dist/ingest/providers/openai.d.ts +1 -1
- package/dist/ingest/providers/openai.d.ts.map +1 -1
- package/dist/ingest/providers/openai.js +37 -17
- package/dist/ingest/providers/openai.js.map +1 -1
- package/dist/ingest/task-processor.d.ts +28 -3
- package/dist/ingest/task-processor.d.ts.map +1 -1
- package/dist/ingest/task-processor.js +166 -67
- package/dist/ingest/task-processor.js.map +1 -1
- package/dist/ingest/worker.d.ts.map +1 -1
- package/dist/ingest/worker.js +97 -75
- package/dist/ingest/worker.js.map +1 -1
- package/dist/shared/llm-call.d.ts +26 -0
- package/dist/shared/llm-call.d.ts.map +1 -0
- package/dist/shared/llm-call.js +163 -0
- package/dist/shared/llm-call.js.map +1 -0
- package/dist/skill/evaluator.d.ts +0 -3
- package/dist/skill/evaluator.d.ts.map +1 -1
- package/dist/skill/evaluator.js +34 -59
- package/dist/skill/evaluator.js.map +1 -1
- package/dist/skill/evolver.d.ts +22 -1
- package/dist/skill/evolver.d.ts.map +1 -1
- package/dist/skill/evolver.js +191 -32
- package/dist/skill/evolver.js.map +1 -1
- package/dist/skill/generator.d.ts +0 -3
- package/dist/skill/generator.d.ts.map +1 -1
- package/dist/skill/generator.js +15 -50
- package/dist/skill/generator.js.map +1 -1
- package/dist/skill/upgrader.d.ts +0 -2
- package/dist/skill/upgrader.d.ts.map +1 -1
- package/dist/skill/upgrader.js +4 -39
- package/dist/skill/upgrader.js.map +1 -1
- package/dist/skill/validator.d.ts +0 -2
- package/dist/skill/validator.d.ts.map +1 -1
- package/dist/skill/validator.js +14 -44
- package/dist/skill/validator.js.map +1 -1
- package/dist/storage/sqlite.d.ts +13 -2
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +92 -15
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/tools/memory-get.d.ts.map +1 -1
- package/dist/tools/memory-get.js +5 -1
- package/dist/tools/memory-get.js.map +1 -1
- package/dist/tools/memory-search.d.ts.map +1 -1
- package/dist/tools/memory-search.js +5 -0
- package/dist/tools/memory-search.js.map +1 -1
- package/dist/tools/memory-timeline.d.ts.map +1 -1
- package/dist/tools/memory-timeline.js +11 -2
- package/dist/tools/memory-timeline.js.map +1 -1
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/viewer/html.d.ts +1 -1
- package/dist/viewer/html.d.ts.map +1 -1
- package/dist/viewer/html.js +380 -26
- package/dist/viewer/html.js.map +1 -1
- package/dist/viewer/server.d.ts +9 -0
- package/dist/viewer/server.d.ts.map +1 -1
- package/dist/viewer/server.js +549 -184
- package/dist/viewer/server.js.map +1 -1
- package/index.ts +9 -3
- package/package.json +2 -1
- package/src/capture/index.ts +39 -10
- package/src/index.ts +3 -2
- package/src/ingest/providers/anthropic.ts +22 -8
- package/src/ingest/providers/bedrock.ts +22 -8
- package/src/ingest/providers/gemini.ts +22 -8
- package/src/ingest/providers/index.ts +192 -142
- package/src/ingest/providers/openai.ts +37 -17
- package/src/ingest/task-processor.ts +183 -65
- package/src/ingest/worker.ts +98 -77
- package/src/shared/llm-call.ts +144 -0
- package/src/skill/evaluator.ts +35 -64
- package/src/skill/evolver.ts +201 -33
- package/src/skill/generator.ts +16 -59
- package/src/skill/upgrader.ts +5 -43
- package/src/skill/validator.ts +15 -47
- package/src/storage/sqlite.ts +107 -15
- package/src/tools/memory-get.ts +6 -1
- package/src/tools/memory-search.ts +6 -0
- package/src/tools/memory-timeline.ts +13 -1
- package/src/types.ts +2 -1
- package/src/viewer/html.ts +380 -26
- package/src/viewer/server.ts +535 -197
package/README.md
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
# 🧠 MemOS — OpenClaw Memory Plugin
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@memtensor/memos-local-openclaw-plugin)
|
|
4
|
+
[](https://github.com/MemTensor/MemOS/blob/main/LICENSE)
|
|
5
|
+
[](https://nodejs.org/)
|
|
6
|
+
[](https://github.com/MemTensor/MemOS/tree/main/apps/memos-local-openclaw)
|
|
7
|
+
|
|
3
8
|
Persistent local conversation memory for [OpenClaw](https://github.com/nicepkg/openclaw) AI Agents. Every conversation is automatically captured, semantically indexed, and instantly recallable — with **task summarization & skill evolution**, and **multi-agent collaborative memory**.
|
|
4
9
|
|
|
5
10
|
**Full-write | Hybrid Search | Task Summarization & Skill Evolution | Multi-Agent Collaboration | Memory Viewer**
|
|
6
11
|
|
|
12
|
+
> **Homepage:** [Website](https://memtensor.github.io/MemOS/apps/memos-local-openclaw/www/) · [Documentation](https://memtensor.github.io/MemOS/apps/memos-local-openclaw/docs/) · [NPM](https://www.npmjs.com/package/@memtensor/memos-local-openclaw-plugin) · [GitHub](https://github.com/MemTensor/MemOS/tree/main/apps/memos-local-openclaw)
|
|
13
|
+
|
|
7
14
|
## Why MemOS
|
|
8
15
|
|
|
9
16
|
| Problem | Solution |
|
|
@@ -26,11 +33,12 @@ Persistent local conversation memory for [OpenClaw](https://github.com/nicepkg/o
|
|
|
26
33
|
- **Multi-provider embedding** — OpenAI-compatible, Gemini, Cohere, Voyage, Mistral, or local offline (Xenova/all-MiniLM-L6-v2)
|
|
27
34
|
|
|
28
35
|
### Task Summarization & Skill Evolution
|
|
29
|
-
- **Auto task boundary detection** — LLM topic judgment + 2-hour idle timeout segments conversations into tasks
|
|
36
|
+
- **Auto task boundary detection** — Per-turn LLM topic judgment (warm-up: 1 user turn) + 2-hour idle timeout segments conversations into tasks. Strongly biased toward SAME to avoid over-splitting related topics
|
|
30
37
|
- **Structured summaries** — LLM generates Goal, Key Steps, Result, Key Details for each completed task
|
|
31
38
|
- **Key detail preservation** — Code, commands, URLs, file paths, error messages retained in summaries
|
|
32
39
|
- **Quality filtering** — Tasks with too few chunks, too few turns, or trivial content are auto-skipped
|
|
33
40
|
- **Task status** — `active` (in progress), `completed` (with LLM summary), `skipped` (too brief, excluded from search)
|
|
41
|
+
- **Task/Skill CRUD** — Edit title/summary, delete tasks and skills, retry skill generation from task cards
|
|
34
42
|
- **Automatic evaluation** — After task completion, rule filter + LLM evaluates if the task is worth distilling into a skill
|
|
35
43
|
- **Skill generation** — Multi-step LLM pipeline creates SKILL.md + scripts + references + evals from real execution records
|
|
36
44
|
- **Skill upgrading** — When similar tasks appear, existing skills are auto-upgraded (refine / extend / fix)
|
|
@@ -38,6 +46,7 @@ Persistent local conversation memory for [OpenClaw](https://github.com/nicepkg/o
|
|
|
38
46
|
- **Version management** — Full version history with changelog, change summary, and upgrade type tracking
|
|
39
47
|
- **Auto-install** — Generated skills can be auto-installed into the workspace for immediate use
|
|
40
48
|
- **Dedicated model** — Optional separate LLM model for skill generation (e.g., Claude 4.6 for higher quality)
|
|
49
|
+
- **LLM fallback chain** — `skillSummarizer` → `summarizer` → OpenClaw native model (auto-detected from `openclaw.json`). If all configured models fail, the next in chain is tried automatically
|
|
41
50
|
|
|
42
51
|
### Multi-Agent Collaboration
|
|
43
52
|
- **Memory isolation** — Each agent's memories are tagged with `owner`. During search, agents only see their own private memories and explicitly shared `public` memories
|
|
@@ -51,15 +60,16 @@ Persistent local conversation memory for [OpenClaw](https://github.com/nicepkg/o
|
|
|
51
60
|
- **One-click import** — Seamlessly migrate OpenClaw's native built-in memories (SQLite + JSONL) into the MemOS intelligent memory system
|
|
52
61
|
- **Smart deduplication** — Vector similarity + LLM judgment prevents duplicate imports; similar content auto-merged
|
|
53
62
|
- **Resume anytime** — Pause and resume at any time; refreshing the page auto-restores progress; already processed items are skipped
|
|
54
|
-
- **Post-import processing** — Optionally generate task summaries and evolve skills from imported memories
|
|
63
|
+
- **Post-import processing** — Optionally generate task summaries and evolve skills from imported memories; serial processing within each agent, parallel across agents
|
|
64
|
+
- **Agent parallelism** — Configurable concurrency (1–8) for parallel processing across agents; sessions within each agent are processed serially
|
|
55
65
|
- **Source tagging** — All migrated memories are tagged with 🦐, visually distinguishing them from conversation-generated memories
|
|
56
66
|
- **Real-time progress** — Live progress bar, stats (stored/skipped/merged/errors), and scrolling log via SSE
|
|
57
67
|
|
|
58
68
|
### Memory Viewer
|
|
59
69
|
- **7 management pages** — Memories, Tasks, Skills, Analytics, **Logs**, **Import**, Settings
|
|
60
70
|
- **Full CRUD** — Create, edit, delete, search memories; evolution badges and merge history on memory cards
|
|
61
|
-
- **Task browser** — Status filters, chat-bubble chunk view, structured summaries, skill generation status
|
|
62
|
-
- **Skill browser** — Version history, quality scores, one-click download as ZIP
|
|
71
|
+
- **Task browser** — Status filters, chat-bubble chunk view, structured summaries, skill generation status; edit/delete/retry-skill buttons on cards
|
|
72
|
+
- **Skill browser** — Version history, quality scores, visibility toggle, one-click download as ZIP; edit/delete/publish buttons on cards
|
|
63
73
|
- **Analytics dashboard** — Daily read/write activity, memory breakdown charts
|
|
64
74
|
- **Logs** — Tool call log (memory_search, auto_recall, memory_add, etc.) with input/output and duration; filter by tool, auto-refresh
|
|
65
75
|
- **Online configuration** — Modify embedding, summarizer, skill evolution settings via web UI
|
|
@@ -77,17 +87,38 @@ Persistent local conversation memory for [OpenClaw](https://github.com/nicepkg/o
|
|
|
77
87
|
|
|
78
88
|
### 1. Install
|
|
79
89
|
|
|
80
|
-
**
|
|
90
|
+
**Step 0 — Prepare build environment (macOS / Linux):**
|
|
91
|
+
|
|
92
|
+
This plugin uses `better-sqlite3`, a native C/C++ module. On **macOS** and **Linux**, prebuilt binaries may not be available, so **install C++ build tools first** to ensure a smooth installation:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# macOS
|
|
96
|
+
xcode-select --install
|
|
97
|
+
|
|
98
|
+
# Linux (Ubuntu / Debian)
|
|
99
|
+
sudo apt install build-essential python3
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
> **Windows users:** `better-sqlite3` ships prebuilt binaries for Windows + Node.js LTS, so you can usually skip this step and go directly to Step 1. If installation still fails, install [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) (select "C++ build tools" workload).
|
|
103
|
+
>
|
|
104
|
+
> Already have build tools? Skip to Step 1. Not sure? Run the install command above — it's safe to re-run.
|
|
105
|
+
>
|
|
106
|
+
> **Still having issues?** See the [Troubleshooting](#troubleshooting) section, the [detailed troubleshooting guide](https://memtensor.github.io/MemOS/apps/memos-local-openclaw/docs/troubleshooting.html), or the [official better-sqlite3 troubleshooting docs](https://github.com/WiseLibs/better-sqlite3/blob/master/docs/troubleshooting.md).
|
|
107
|
+
|
|
108
|
+
**Step 1 — Install the plugin:**
|
|
81
109
|
|
|
82
110
|
```bash
|
|
83
111
|
openclaw plugins install @memtensor/memos-local-openclaw-plugin
|
|
84
112
|
```
|
|
85
113
|
|
|
86
|
-
The plugin is installed under `~/.openclaw/extensions/memos-local-openclaw-plugin` and registered as `memos-local-openclaw-plugin`. Dependencies and native
|
|
114
|
+
The plugin is installed under `~/.openclaw/extensions/memos-local-openclaw-plugin` and registered as `memos-local-openclaw-plugin`. Dependencies and `better-sqlite3` native module are built automatically during installation.
|
|
87
115
|
|
|
88
116
|
> **Note:** The Memory Viewer starts only when the **OpenClaw gateway** is running. After install, **configure** `openclaw.json` (step 2) and **start the gateway** (step 3); the viewer will then be available at `http://127.0.0.1:18799`.
|
|
89
117
|
>
|
|
90
|
-
> If better-sqlite3 fails
|
|
118
|
+
> **Installation failed?** If `better-sqlite3` compilation fails during install, manually rebuild after ensuring build tools are installed:
|
|
119
|
+
> ```bash
|
|
120
|
+
> cd ~/.openclaw/extensions/memos-local-openclaw-plugin && npm rebuild better-sqlite3
|
|
121
|
+
> ```
|
|
91
122
|
|
|
92
123
|
**From source (development):**
|
|
93
124
|
|
|
@@ -164,7 +195,7 @@ Add the plugin config to `~/.openclaw/openclaw.json`:
|
|
|
164
195
|
| Gemini | `gemini` | `gemini-1.5-flash` |
|
|
165
196
|
| AWS Bedrock | `bedrock` | `anthropic.claude-3-haiku-20240307-v1:0` |
|
|
166
197
|
|
|
167
|
-
> **No summarizer config?**
|
|
198
|
+
> **No summarizer config?** The plugin automatically falls back to the OpenClaw native model (auto-detected from `~/.openclaw/openclaw.json`). If that is also unavailable, a rule-based fallback generates summaries from the first sentence + key entities. Good enough to start.
|
|
168
199
|
|
|
169
200
|
#### Skill Evolution Configuration (Optional)
|
|
170
201
|
|
|
@@ -188,7 +219,7 @@ You can optionally configure a dedicated model for skill generation (for higher
|
|
|
188
219
|
}
|
|
189
220
|
```
|
|
190
221
|
|
|
191
|
-
If `skillSummarizer` is not configured, the plugin
|
|
222
|
+
**LLM fallback chain:** `skillSummarizer` → `summarizer` → OpenClaw native model (auto-detected from `~/.openclaw/openclaw.json`). If `skillSummarizer` is not configured, the plugin tries the regular `summarizer`, then falls back to the OpenClaw native model. Each step in the chain is tried automatically if the previous one fails.
|
|
192
223
|
|
|
193
224
|
#### Environment Variable Support
|
|
194
225
|
|
|
@@ -269,9 +300,13 @@ Conversation → Capture (filter roles, strip system prompts)
|
|
|
269
300
|
### Pipeline 2: Task Generation (auto after memory write)
|
|
270
301
|
|
|
271
302
|
```
|
|
272
|
-
New chunks →
|
|
273
|
-
→
|
|
274
|
-
|
|
303
|
+
New chunks → Group into user-turns → Process one turn at a time
|
|
304
|
+
→ Warm-up (first user turn): assign directly
|
|
305
|
+
→ Each subsequent user turn: LLM topic judge (context vs new message)
|
|
306
|
+
→ "NEW"? → Finalize current task, create new task
|
|
307
|
+
→ "SAME"? → Assign to current task
|
|
308
|
+
→ Time gap > 2h? → Always split regardless of topic
|
|
309
|
+
→ Finalize: Chunks ≥ 4 & turns ≥ 2? → LLM structured summary → status = "completed"
|
|
275
310
|
→ Otherwise → status = "skipped" (excluded from search)
|
|
276
311
|
```
|
|
277
312
|
|
|
@@ -352,6 +387,8 @@ The plugin provides **12 smart tools** (11 registered tools + auto-recall) and a
|
|
|
352
387
|
| `minScore` | 0.45 | 0.35–1.0 | Minimum relevance score |
|
|
353
388
|
| `role` | — | `user` / `assistant` / `tool` | Filter by message role (e.g. `user` to find what the user said) |
|
|
354
389
|
|
|
390
|
+
> **Viewer search** uses a stricter threshold (`minScore` 0.64) for vector results. When no semantic matches are found, it falls back to FTS5 keyword search and returns the top 20 keyword-based results.
|
|
391
|
+
|
|
355
392
|
## Memory Viewer
|
|
356
393
|
|
|
357
394
|
Open `http://127.0.0.1:18799` in your browser after starting the gateway.
|
|
@@ -498,6 +535,8 @@ openclaw plugins install @memtensor/memos-local-openclaw-plugin
|
|
|
498
535
|
## Troubleshooting
|
|
499
536
|
|
|
500
537
|
> 📖 **详细排查指南 / Detailed troubleshooting guide:** [docs/troubleshooting.html](https://memtensor.github.io/MemOS/apps/memos-local-openclaw/docs/troubleshooting.html) — 包含逐步排查流程、日志查看方法、完全重装步骤等。
|
|
538
|
+
>
|
|
539
|
+
> 📦 **better-sqlite3 official troubleshooting:** [better-sqlite3 Troubleshooting](https://github.com/WiseLibs/better-sqlite3/blob/master/docs/troubleshooting.md) — the upstream guide for native module build issues.
|
|
501
540
|
|
|
502
541
|
### Common Issues
|
|
503
542
|
|
|
@@ -533,19 +572,25 @@ openclaw plugins install @memtensor/memos-local-openclaw-plugin
|
|
|
533
572
|
npm rebuild better-sqlite3
|
|
534
573
|
```
|
|
535
574
|
If rebuild fails, install C++ build tools first:
|
|
536
|
-
- **macOS:** `xcode-select --install`
|
|
575
|
+
- **macOS:** `xcode-select --install` (if you see `xcrun: error: invalid active developer path`, run this first)
|
|
537
576
|
- **Linux:** `sudo apt install build-essential python3`
|
|
538
|
-
- **Windows:**
|
|
577
|
+
- **Windows:** Usually not needed — `better-sqlite3` provides prebuilt binaries for Windows + Node.js LTS. If it still fails, install [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) (select "C++ build tools" workload)
|
|
539
578
|
|
|
540
579
|
Then retry `npm rebuild better-sqlite3` and restart the gateway.
|
|
541
580
|
|
|
581
|
+
> **Still failing?** Check the official [better-sqlite3 troubleshooting guide](https://github.com/WiseLibs/better-sqlite3/blob/master/docs/troubleshooting.md) for platform-specific solutions. For non-LTS Node.js versions (e.g., v25.x), prebuilt binaries may not be available and compilation from source is required.
|
|
582
|
+
|
|
542
583
|
7. **Memory conflict with built-in search** — If the agent calls both the built-in memory search and the plugin's `memory_search`, it means `agents.defaults.memorySearch.enabled` is not set to `false`.
|
|
543
584
|
|
|
544
585
|
8. **Skills not generating** — Check:
|
|
545
586
|
- `skillEvolution.enabled` is `true`
|
|
546
587
|
- Tasks have enough content (default requires >= 6 chunks)
|
|
588
|
+
- LLM model is accessible (check gateway log for `judgeNewTopic failed` or `SkillEvolver` errors)
|
|
589
|
+
- The LLM fallback chain will try: `skillSummarizer` → `summarizer` → OpenClaw native model. If all fail, skill generation is skipped
|
|
547
590
|
- Look for `SkillEvolver` output in the gateway log
|
|
548
591
|
|
|
592
|
+
9. **LLM calls failing** — All LLM-dependent features (summarization, topic detection, skill generation) use a fallback chain. If the configured model returns an error, the next model in the chain is tried automatically. Check the gateway log for messages like `failed (model), trying next`. If all models fail, the operation falls back to rule-based logic or is skipped.
|
|
593
|
+
|
|
549
594
|
## Data Location
|
|
550
595
|
|
|
551
596
|
| File | Path |
|
|
@@ -558,21 +603,193 @@ openclaw plugins install @memtensor/memos-local-openclaw-plugin
|
|
|
558
603
|
| Generated skills | `~/.openclaw/memos-local/skills-store/<skill-name>/` |
|
|
559
604
|
| Installed skills | `~/.openclaw/workspace/skills/<skill-name>/` |
|
|
560
605
|
|
|
561
|
-
##
|
|
606
|
+
## Development Guide
|
|
607
|
+
|
|
608
|
+
This section is for contributors who want to develop, test, or modify the plugin from source.
|
|
609
|
+
|
|
610
|
+
### Prerequisites
|
|
611
|
+
|
|
612
|
+
- **Node.js >= 18** (`node -v`)
|
|
613
|
+
- **npm >= 9** (`npm -v`)
|
|
614
|
+
- **C++ build tools** (for `better-sqlite3` native module):
|
|
615
|
+
- macOS: `xcode-select --install`
|
|
616
|
+
- Linux: `sudo apt install build-essential python3`
|
|
617
|
+
- Windows: usually not needed (prebuilt binaries available for LTS Node.js); if build fails, install [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
|
|
618
|
+
- **OpenClaw CLI** installed and available in PATH (`openclaw --version`)
|
|
562
619
|
|
|
563
|
-
|
|
620
|
+
> **`better-sqlite3` build issues?** This is the most common installation problem on macOS and Linux. If `npm install` fails, first install the C++ build tools above, then run `npm rebuild better-sqlite3`. For detailed platform-specific solutions, see the [official better-sqlite3 troubleshooting guide](https://github.com/WiseLibs/better-sqlite3/blob/master/docs/troubleshooting.md) and our [installation troubleshooting page](https://memtensor.github.io/MemOS/apps/memos-local-openclaw/docs/troubleshooting.html).
|
|
621
|
+
|
|
622
|
+
### Clone & Setup
|
|
564
623
|
|
|
565
624
|
```bash
|
|
625
|
+
git clone https://github.com/MemTensor/MemOS.git
|
|
566
626
|
cd MemOS/apps/memos-local-openclaw
|
|
567
|
-
npm
|
|
627
|
+
npm install
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
> `npm install` triggers the `postinstall` script which automatically rebuilds `better-sqlite3` for your Node.js version.
|
|
631
|
+
|
|
632
|
+
### Project Structure
|
|
633
|
+
|
|
634
|
+
```
|
|
635
|
+
apps/memos-local-openclaw/
|
|
636
|
+
├── index.ts # Plugin entry — hooks, tool registration, lifecycle
|
|
637
|
+
├── plugin-impl.ts # OpenClaw plugin SDK implementation
|
|
638
|
+
├── src/
|
|
639
|
+
│ ├── index.ts # Module re-exports
|
|
640
|
+
│ ├── config.ts # Configuration schema & defaults
|
|
641
|
+
│ ├── types.ts # TypeScript type definitions
|
|
642
|
+
│ ├── capture/index.ts # Message capture & filtering logic
|
|
643
|
+
│ ├── embedding/ # Embedding providers (OpenAI, Gemini, Cohere, etc.)
|
|
644
|
+
│ ├── ingest/
|
|
645
|
+
│ │ ├── chunker.ts # Semantic chunking (code blocks, paragraphs)
|
|
646
|
+
│ │ ├── dedup.ts # Content-hash + vector deduplication
|
|
647
|
+
│ │ ├── worker.ts # Async ingestion pipeline
|
|
648
|
+
│ │ ├── task-processor.ts # Task boundary detection & summarization
|
|
649
|
+
│ │ └── providers/ # LLM providers for summarization
|
|
650
|
+
│ ├── recall/
|
|
651
|
+
│ │ ├── engine.ts # Hybrid retrieval engine (FTS5 + Vector)
|
|
652
|
+
│ │ ├── rrf.ts # Reciprocal Rank Fusion
|
|
653
|
+
│ │ ├── mmr.ts # Maximal Marginal Relevance
|
|
654
|
+
│ │ └── recency.ts # Time-decay scoring
|
|
655
|
+
│ ├── shared/
|
|
656
|
+
│ │ └── llm-call.ts # LLM fallback chain utility (callLLMWithFallback, buildSkillConfigChain)
|
|
657
|
+
│ ├── skill/ # Skill evolution pipeline (evaluator, generator, upgrader)
|
|
658
|
+
│ ├── storage/
|
|
659
|
+
│ │ ├── sqlite.ts # SQLite database layer (chunks, tasks, skills, FTS5)
|
|
660
|
+
│ │ └── vector.ts # Vector similarity search
|
|
661
|
+
│ ├── tools/ # Tool implementations (memory-search, memory-get, etc.)
|
|
662
|
+
│ ├── viewer/ # Memory Viewer web server & HTML templates
|
|
663
|
+
│ └── telemetry.ts # Anonymous usage analytics
|
|
664
|
+
├── tests/ # Test suite (vitest)
|
|
665
|
+
├── scripts/ # Utility scripts (seed data, smoke test, viewer)
|
|
666
|
+
├── skill/ # Bundled skill definitions (SKILL.md files)
|
|
667
|
+
├── openclaw.plugin.json # Plugin metadata for OpenClaw registry
|
|
668
|
+
├── package.json # Dependencies & scripts
|
|
669
|
+
├── tsconfig.json # TypeScript configuration
|
|
670
|
+
└── vitest.config.ts # Test runner configuration
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
**Files NOT in the repository** (generated locally, excluded via `.gitignore`):
|
|
674
|
+
|
|
675
|
+
| Directory / File | Purpose | How to generate |
|
|
676
|
+
|---|---|---|
|
|
677
|
+
| `node_modules/` | npm dependencies | `npm install` |
|
|
678
|
+
| `dist/` | Compiled JavaScript output | `npm run build` |
|
|
679
|
+
| `package-lock.json` | Dependency lock file | `npm install` (auto-generated) |
|
|
680
|
+
| `www/` | Memory Viewer static site (local preview) | Started automatically by the plugin |
|
|
681
|
+
| `docs/` | Documentation HTML pages | Built from source or viewed at the hosted URL |
|
|
682
|
+
| `ppt/` | Presentation files (internal use) | Not needed for development |
|
|
683
|
+
| `.env` | Local environment variables | Copy from `.env.example` |
|
|
684
|
+
|
|
685
|
+
### Build
|
|
686
|
+
|
|
687
|
+
```bash
|
|
688
|
+
npm run build # Compile TypeScript → dist/
|
|
689
|
+
npm run dev # Watch mode — auto-recompile on save
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
The build output goes to `dist/` (CommonJS modules with declarations and source maps).
|
|
693
|
+
|
|
694
|
+
### Configure for Local Development
|
|
695
|
+
|
|
696
|
+
1. **Copy the environment template:**
|
|
697
|
+
|
|
698
|
+
```bash
|
|
699
|
+
cp .env.example .env
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
2. **Edit `.env`** with your API keys (or leave blank for local-only mode):
|
|
703
|
+
|
|
704
|
+
```bash
|
|
705
|
+
# Embedding — leave blank to use local offline model
|
|
706
|
+
EMBEDDING_PROVIDER=openai_compatible
|
|
707
|
+
EMBEDDING_API_KEY=your-key
|
|
708
|
+
EMBEDDING_ENDPOINT=https://your-api.com/v1
|
|
709
|
+
EMBEDDING_MODEL=bge-m3
|
|
710
|
+
|
|
711
|
+
# Summarizer — leave blank for rule-based fallback
|
|
712
|
+
SUMMARIZER_PROVIDER=openai_compatible
|
|
713
|
+
SUMMARIZER_API_KEY=your-key
|
|
714
|
+
SUMMARIZER_ENDPOINT=https://api.openai.com/v1
|
|
715
|
+
SUMMARIZER_MODEL=gpt-4o-mini
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
3. **Install the plugin locally into OpenClaw:**
|
|
719
|
+
|
|
720
|
+
```bash
|
|
721
|
+
npm run build
|
|
722
|
+
openclaw plugins install .
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
4. **Configure OpenClaw** — Add the plugin to `~/.openclaw/openclaw.json` (see [Configure](#2-configure) section above).
|
|
726
|
+
|
|
727
|
+
5. **Start the gateway:**
|
|
728
|
+
|
|
729
|
+
```bash
|
|
730
|
+
openclaw gateway stop # stop existing
|
|
731
|
+
openclaw gateway start # start with new plugin
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
### Testing
|
|
735
|
+
|
|
736
|
+
Run the full test suite:
|
|
737
|
+
|
|
738
|
+
```bash
|
|
739
|
+
npm test # Run all tests once
|
|
740
|
+
npm run test:watch # Watch mode — re-run on file changes
|
|
568
741
|
```
|
|
569
742
|
|
|
570
743
|
Test coverage includes:
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
744
|
+
|
|
745
|
+
| Test File | Coverage |
|
|
746
|
+
|---|---|
|
|
747
|
+
| `tests/policy.test.ts` | Retrieval strategy, search filtering, evidence extraction, instruction stripping |
|
|
748
|
+
| `tests/recall.test.ts` | RRF fusion, recency decay correctness |
|
|
749
|
+
| `tests/capture.test.ts` | Message filtering, evidence block stripping, self-tool exclusion |
|
|
750
|
+
| `tests/storage.test.ts` | SQLite CRUD, FTS5, vector storage, content hash dedup |
|
|
751
|
+
| `tests/chunker.test.ts` | Semantic chunking for code blocks, paragraphs, function bodies |
|
|
752
|
+
| `tests/task-processor.test.ts` | Task boundary detection, skip logic, summary generation |
|
|
753
|
+
| `tests/multi-agent.test.ts` | Multi-agent memory isolation, owner filtering, public sharing |
|
|
754
|
+
| `tests/integration.test.ts` | End-to-end ingestion and retrieval pipeline |
|
|
755
|
+
|
|
756
|
+
> Tests use an **in-memory SQLite database** — no external services or API keys required.
|
|
757
|
+
|
|
758
|
+
### Development Workflow
|
|
759
|
+
|
|
760
|
+
1. **Make changes** to files in `src/` or `index.ts`
|
|
761
|
+
2. **Run tests** to verify: `npm test`
|
|
762
|
+
3. **Build** to check TypeScript compilation: `npm run build`
|
|
763
|
+
4. **Test with OpenClaw** locally:
|
|
764
|
+
```bash
|
|
765
|
+
openclaw plugins install . # re-install from local source
|
|
766
|
+
openclaw gateway stop && openclaw gateway start
|
|
767
|
+
tail -f ~/.openclaw/logs/gateway.log # watch logs
|
|
768
|
+
```
|
|
769
|
+
5. **Open Memory Viewer** at `http://127.0.0.1:18799` to verify UI changes
|
|
770
|
+
|
|
771
|
+
### Publishing to npm
|
|
772
|
+
|
|
773
|
+
```bash
|
|
774
|
+
npm run build # Compile TypeScript
|
|
775
|
+
npm publish --access public # Publish to npm registry
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
After publishing, users can install with:
|
|
779
|
+
```bash
|
|
780
|
+
openclaw plugins install @memtensor/memos-local-openclaw-plugin
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
### Utility Scripts
|
|
784
|
+
|
|
785
|
+
| Script | Command | Purpose |
|
|
786
|
+
|---|---|---|
|
|
787
|
+
| Seed test data | `npx tsx scripts/seed-test-data.ts` | Populate local DB with sample memories, tasks, and skills |
|
|
788
|
+
| Smoke test | `npx tsx scripts/smoke-test.ts` | Quick end-to-end verification of plugin functionality |
|
|
789
|
+
| Start viewer | `npx tsx scripts/start-viewer.ts` | Start Memory Viewer standalone (without gateway) |
|
|
790
|
+
| Refresh skills | `npx tsx scripts/refresh-skill.ts` | Re-evaluate and regenerate skills from existing tasks |
|
|
791
|
+
| Refresh summaries | `npx tsx scripts/refresh-summaries.ts` | Re-generate task summaries for completed tasks |
|
|
792
|
+
| Mock skills | `npx tsx scripts/mock-skills.ts` | Generate mock skill data for testing |
|
|
576
793
|
|
|
577
794
|
## License
|
|
578
795
|
|
package/dist/capture/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export declare function captureMessages(messages: Array<{
|
|
|
10
10
|
role: string;
|
|
11
11
|
content: string;
|
|
12
12
|
toolName?: string;
|
|
13
|
-
}>, sessionKey: string, turnId: string,
|
|
13
|
+
}>, sessionKey: string, turnId: string, evidenceTag: string, log: Logger, owner?: string): ConversationMessage[];
|
|
14
14
|
/**
|
|
15
15
|
* Strip OpenClaw-injected inbound metadata blocks from user messages.
|
|
16
16
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/capture/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAQ,MAAM,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/capture/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAQ,MAAM,EAAE,MAAM,UAAU,CAAC;AAmClE;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACrE,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,MAAM,GACb,mBAAmB,EAAE,CAwCvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA8CzD"}
|
package/dist/capture/index.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.captureMessages = captureMessages;
|
|
4
4
|
exports.stripInboundMetadata = stripInboundMetadata;
|
|
5
5
|
const SKIP_ROLES = new Set(["system"]);
|
|
6
|
+
const SYSTEM_BOILERPLATE_RE = /^A new session was started via \/new or \/reset\b/;
|
|
6
7
|
const SELF_TOOLS = new Set([
|
|
7
8
|
"memory_search",
|
|
8
9
|
"memory_timeline",
|
|
@@ -23,7 +24,8 @@ const INBOUND_META_SENTINELS = [
|
|
|
23
24
|
"Forwarded message context (untrusted metadata):",
|
|
24
25
|
"Chat history since last reply (untrusted, for context):",
|
|
25
26
|
];
|
|
26
|
-
const SENTINEL_FAST_RE = new RegExp(INBOUND_META_SENTINELS.map(s => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"));
|
|
27
|
+
const SENTINEL_FAST_RE = new RegExp(INBOUND_META_SENTINELS.map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"));
|
|
28
|
+
const ENVELOPE_PREFIX_RE = /^\s*\[(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}(?::\d{2})?\s+[A-Z]{3}[+-]\d{1,2}\]\s*/;
|
|
27
29
|
/**
|
|
28
30
|
* Extract writable messages from a conversation turn.
|
|
29
31
|
*
|
|
@@ -31,7 +33,7 @@ const SENTINEL_FAST_RE = new RegExp(INBOUND_META_SENTINELS.map(s => s.replace(/[
|
|
|
31
33
|
* prefixes (Sender info, conversation context, etc.) which are not user content.
|
|
32
34
|
* Only skips: system prompts and our own memory tool results (prevents loop).
|
|
33
35
|
*/
|
|
34
|
-
function captureMessages(messages, sessionKey, turnId,
|
|
36
|
+
function captureMessages(messages, sessionKey, turnId, evidenceTag, log, owner) {
|
|
35
37
|
const now = Date.now();
|
|
36
38
|
const result = [];
|
|
37
39
|
for (const msg of messages) {
|
|
@@ -44,10 +46,17 @@ function captureMessages(messages, sessionKey, turnId, _evidenceTag, log, owner)
|
|
|
44
46
|
log.debug(`Skipping self-tool result: ${msg.toolName}`);
|
|
45
47
|
continue;
|
|
46
48
|
}
|
|
49
|
+
if (role === "user" && SYSTEM_BOILERPLATE_RE.test(msg.content.trim())) {
|
|
50
|
+
log.debug(`Skipping system boilerplate: ${msg.content.slice(0, 60)}...`);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
47
53
|
let content = msg.content;
|
|
48
54
|
if (role === "user") {
|
|
49
55
|
content = stripInboundMetadata(content);
|
|
50
56
|
}
|
|
57
|
+
else {
|
|
58
|
+
content = stripEvidenceWrappers(content, evidenceTag);
|
|
59
|
+
}
|
|
51
60
|
if (!content.trim())
|
|
52
61
|
continue;
|
|
53
62
|
result.push({
|
|
@@ -75,13 +84,13 @@ function captureMessages(messages, sessionKey, turnId, _evidenceTag, log, owner)
|
|
|
75
84
|
* Also strips the envelope timestamp prefix like "[Tue 2026-03-03 21:58 GMT+8] "
|
|
76
85
|
*/
|
|
77
86
|
function stripInboundMetadata(text) {
|
|
78
|
-
|
|
79
|
-
let cleaned = text.replace(/^\[(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}(?::\d{2})?\s+[A-Z]{3}[+-]\d{1,2}\]\s*/, "");
|
|
87
|
+
let cleaned = stripEnvelopePrefix(text);
|
|
80
88
|
// Strip OpenClaw envelope tags: [message_id: ...], [[reply_to_current]], etc.
|
|
81
89
|
cleaned = cleaned.replace(/\[message_id:\s*[a-f0-9-]+\]/gi, "");
|
|
82
90
|
cleaned = cleaned.replace(/\[\[reply_to_current\]\]/gi, "");
|
|
83
|
-
if (!SENTINEL_FAST_RE.test(cleaned))
|
|
84
|
-
return cleaned.trim();
|
|
91
|
+
if (!SENTINEL_FAST_RE.test(cleaned)) {
|
|
92
|
+
return stripEnvelopePrefix(cleaned).trim();
|
|
93
|
+
}
|
|
85
94
|
const lines = cleaned.split("\n");
|
|
86
95
|
const result = [];
|
|
87
96
|
let inMetaBlock = false;
|
|
@@ -89,7 +98,7 @@ function stripInboundMetadata(text) {
|
|
|
89
98
|
for (let i = 0; i < lines.length; i++) {
|
|
90
99
|
const line = lines[i];
|
|
91
100
|
const trimmed = line.trim();
|
|
92
|
-
if (!inMetaBlock && INBOUND_META_SENTINELS.some(s => s === trimmed)) {
|
|
101
|
+
if (!inMetaBlock && INBOUND_META_SENTINELS.some((s) => s === trimmed)) {
|
|
93
102
|
if (lines[i + 1]?.trim() === "```json") {
|
|
94
103
|
inMetaBlock = true;
|
|
95
104
|
inFencedJson = false;
|
|
@@ -111,6 +120,22 @@ function stripInboundMetadata(text) {
|
|
|
111
120
|
}
|
|
112
121
|
result.push(line);
|
|
113
122
|
}
|
|
114
|
-
return result.join("\n").trim();
|
|
123
|
+
return stripEnvelopePrefix(result.join("\n")).trim();
|
|
124
|
+
}
|
|
125
|
+
function stripEnvelopePrefix(text) {
|
|
126
|
+
return text.replace(ENVELOPE_PREFIX_RE, "");
|
|
127
|
+
}
|
|
128
|
+
function stripEvidenceWrappers(text, evidenceTag) {
|
|
129
|
+
const tag = evidenceTag.trim();
|
|
130
|
+
if (!tag)
|
|
131
|
+
return text;
|
|
132
|
+
const escapedTag = tag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
133
|
+
const wrapperRe = new RegExp(`\\[${escapedTag}\\][\\s\\S]*?\\[\\/${escapedTag}\\]`, "g");
|
|
134
|
+
return text
|
|
135
|
+
.replace(wrapperRe, "")
|
|
136
|
+
.replace(/[ \t]{2,}/g, " ")
|
|
137
|
+
.replace(/\s+([,.;:!?])/g, "$1")
|
|
138
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
139
|
+
.trim();
|
|
115
140
|
}
|
|
116
141
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/capture/index.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/capture/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export interface MemosLocalPlugin {
|
|
|
8
8
|
}>, sessionKey?: string, owner?: string) => void;
|
|
9
9
|
/** Wait for all pending ingest operations to complete. */
|
|
10
10
|
flush: () => Promise<void>;
|
|
11
|
-
shutdown: () => void
|
|
11
|
+
shutdown: () => Promise<void>;
|
|
12
12
|
}
|
|
13
13
|
export interface PluginInitOptions {
|
|
14
14
|
stateDir?: string;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAExE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,kBAAkB,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACtH,0DAA0D;IAC1D,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,QAAQ,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAExE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,kBAAkB,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACtH,0DAA0D;IAC1D,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,gBAAgB,CAkDzE;AAQD,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAiDA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAiDA,gCAkDC;AAnGD,+BAAkC;AAClC,qCAAwC;AACxC,6CAA+C;AAC/C,2CAAuC;AACvC,4CAA+C;AAC/C,4CAA+C;AAC/C,uCAA4C;AAC5C,mCAAgG;AAmBhG;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,SAAgB,UAAU,CAAC,OAA0B,EAAE;IACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,eAAe,EAAE,CAAC;IACpD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACxD,MAAM,GAAG,GAAG,IAAA,qBAAY,EAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IAExE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;IAEnD,MAAM,KAAK,GAAG,IAAI,oBAAW,CAAC,GAAG,CAAC,MAAM,CAAC,OAAQ,CAAC,MAAO,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,IAAI,oBAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,IAAI,qBAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,qBAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;IAEtD,MAAM,KAAK,GAAqB;QAC9B,IAAA,8BAAsB,EAAC,MAAM,CAAC;QAC9B,IAAA,gCAAwB,EAAC,KAAK,CAAC;QAC/B,IAAA,2BAAmB,EAAC,KAAK,CAAC;KAC3B,CAAC;IAEF,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,GAAG,CAAC,MAAM,CAAC,OAAQ,CAAC,MAAM,gBAAgB,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEjG,OAAO;QACL,EAAE,EAAE,aAAa;QAEjB,KAAK;QAEL,kBAAkB,CAChB,QAAkD,EAClD,UAAmB,EACnB,KAAc;YAEd,MAAM,OAAO,GAAG,UAAU,IAAI,SAAS,CAAC;YACxC,MAAM,MAAM,GAAG,IAAA,SAAI,GAAE,CAAC;YACtB,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,kBAAkB,IAAI,eAAe,CAAC;YAEtE,MAAM,QAAQ,GAAG,IAAA,yBAAe,EAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACjF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QAED,KAAK,CAAC,QAAQ;YACZ,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;YACpD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,MAAM,CAAC;IACnE,OAAO,GAAG,IAAI,YAAY,CAAC;AAC7B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/ingest/providers/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAyC5D,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CA8BjB;
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/ingest/providers/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAyC5D,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CA8BjB;AA6BD,wBAAsB,sBAAsB,CAC1C,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,OAAO,CAAC,CAkClB;AAwBD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACnE,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,YAAY,CAAC,CAmCvB;AAmBD,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CAgCjB;AAKD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EACtE,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,WAAW,CAAC,CAiCtB"}
|
|
@@ -70,16 +70,30 @@ async function summarizeTaskAnthropic(text, cfg, log) {
|
|
|
70
70
|
const json = (await resp.json());
|
|
71
71
|
return json.content.find((c) => c.type === "text")?.text?.trim() ?? "";
|
|
72
72
|
}
|
|
73
|
-
const TOPIC_JUDGE_PROMPT = `You are a conversation topic boundary detector. Given
|
|
73
|
+
const TOPIC_JUDGE_PROMPT = `You are a conversation topic boundary detector. Given the CURRENT task context (may include opening topic + recent exchanges) and a single NEW user message, decide if the new message belongs to the SAME task or starts a NEW one.
|
|
74
74
|
|
|
75
75
|
Answer ONLY "NEW" or "SAME".
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
77
|
+
SAME — the new message:
|
|
78
|
+
- Continues, follows up on, refines, or corrects the same subject/project/task
|
|
79
|
+
- Asks a clarification or next-step question about what was just discussed
|
|
80
|
+
- Reports a result, error, or feedback about the current task
|
|
81
|
+
- Discusses different tools, methods, or approaches for the SAME goal (e.g., learning English via BBC → via ChatGPT → via AI tools = all SAME "learning English" task)
|
|
82
|
+
- Mentions a related technology or platform in the context of the current goal
|
|
83
|
+
- Is a short acknowledgment (ok, thanks, 好的, 嗯) in direct response to the current flow
|
|
84
|
+
|
|
85
|
+
NEW — the new message:
|
|
86
|
+
- Introduces a clearly UNRELATED subject with NO logical connection to the current task
|
|
87
|
+
- The topic has ZERO overlap with any aspect of the current conversation (e.g., from "learning English" to "what's the weather tomorrow")
|
|
88
|
+
- Starts a request about a completely different domain or life area
|
|
89
|
+
- Begins with a new greeting/reset followed by a different topic
|
|
90
|
+
|
|
91
|
+
Key principles:
|
|
92
|
+
- STRONGLY lean toward SAME — only mark NEW for obvious, unambiguous topic shifts
|
|
93
|
+
- Different aspects, tools, or methods related to the same overall goal are SAME
|
|
94
|
+
- If the new message could reasonably be interpreted as part of the ongoing discussion, choose SAME
|
|
95
|
+
- Only choose NEW when there is absolutely no thematic connection to the current task
|
|
96
|
+
- Examples: "学英语" → "用AI工具学英语" = SAME; "学英语" → "明天天气" = NEW
|
|
83
97
|
|
|
84
98
|
Output exactly one word: NEW or SAME`;
|
|
85
99
|
async function judgeNewTopicAnthropic(currentContext, newMessage, cfg, log) {
|
|
@@ -91,7 +105,7 @@ async function judgeNewTopicAnthropic(currentContext, newMessage, cfg, log) {
|
|
|
91
105
|
"anthropic-version": "2023-06-01",
|
|
92
106
|
...cfg.headers,
|
|
93
107
|
};
|
|
94
|
-
const userContent = `CURRENT
|
|
108
|
+
const userContent = `CURRENT TASK CONTEXT:\n${currentContext}\n\n---\n\nNEW USER MESSAGE:\n${newMessage}`;
|
|
95
109
|
const resp = await fetch(endpoint, {
|
|
96
110
|
method: "POST",
|
|
97
111
|
headers,
|