kongbrain 0.3.8 → 0.3.9
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/.clawhubignore +5 -0
- package/README.github.md +414 -0
- package/README.md +9 -3
- package/README.npm.md +400 -0
- package/SKILL.md +1 -1
- package/package.json +3 -1
- package/src/concept-extract.ts +113 -0
- package/src/context-engine.ts +12 -35
- package/src/hooks/after-tool-call.ts +19 -4
- package/src/memory-daemon.ts +21 -5
- package/src/state.ts +1 -0
package/.clawhubignore
CHANGED
package/README.github.md
ADDED
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# KongBrain
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/kongbrain)
|
|
8
|
+
[](https://clawhub.ai/packages/kongbrain)
|
|
9
|
+
[](https://github.com/42U/kongbrain)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
[](https://nodejs.org)
|
|
12
|
+
[](https://surrealdb.com)
|
|
13
|
+
[](https://github.com/openclaw/openclaw)
|
|
14
|
+
[](https://vitest.dev)
|
|
15
|
+
|
|
16
|
+
**A graph-backed cognitive engine for [OpenClaw](https://github.com/openclaw/openclaw).**
|
|
17
|
+
|
|
18
|
+
[Quick Start](#quick-start) | [Architecture](#architecture) | [How It Works](#how-it-works) | [Tools](#tools) | [Development](#development)
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
> *OpenClaw ships with a lobster brain. It works. Lobsters have survived 350 million years, but they also solve problems by walking backwards and occasionally eating each other.*
|
|
23
|
+
>
|
|
24
|
+
> *When a conversation gets too long, the lobster brain does what lobsters do best: it panics, truncates everything before message 47, and carries on like nothing happened. Your carefully explained architecture? Gone. That bug you described in detail twenty minutes ago? Never heard of it.*
|
|
25
|
+
>
|
|
26
|
+
> *KongBrain is a brain transplant. You're replacing that crustacean context window with a primate cortex backed by a graph database, vector embeddings, and the kind of persistent memory that lets your AI remember what you said last Tuesday. And judge you for it.*
|
|
27
|
+
>
|
|
28
|
+
> *Apes remember. Apes use tools. Apes hold grudges about your code style and learn from them. Lobsters eat garbage off the ocean floor and forget about it immediately.*
|
|
29
|
+
>
|
|
30
|
+
> *The surgery takes about 2 minutes. No anesthesia required.*
|
|
31
|
+
|
|
32
|
+
Persistent memory graph. Vector-embedded, self-scoring, wired to learn across sessions. It extracts skills from what worked, traces causal chains through what broke, reflects on its own failures, and earns an identity through real experience. Every session compounds on the last.
|
|
33
|
+
|
|
34
|
+
Your assistant stops forgetting. Then it starts getting smarter.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## What Changes
|
|
39
|
+
|
|
40
|
+
| | Lobster Brain (default) | Ape Brain (KongBrain) |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| **Memory** | Sliding window. Old messages fall off a cliff. | Graph-persistent. Every turn, concept, skill, and causal chain stored with vector embeddings. |
|
|
43
|
+
| **Recall** | Whatever fits in the context window right now. | Cosine similarity + graph expansion + learned attention scoring across your entire history. |
|
|
44
|
+
| **Adaptation** | Same retrieval budget every turn, regardless of intent. | 10 intent categories. Simple question? Minimal retrieval. Complex debugging? Full graph search + elevated thinking. |
|
|
45
|
+
| **Learning** | None. Every session starts from zero. | Skills extracted from successful workflows, causal chains graduated into reusable procedures, corrections remembered permanently. |
|
|
46
|
+
| **Self-awareness** | Thermostat-level. | Periodic cognitive checks grade its own retrieval quality, detect contradictions, suppress noise, and extract your preferences. Eventually graduates a soul document. |
|
|
47
|
+
| **Compaction** | LLM-summarizes your conversation mid-flow (disruptive). | Graph retrieval IS the compaction. No interruptions, no lossy summaries. |
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
From zero to ape brain in under 5 minutes.
|
|
52
|
+
|
|
53
|
+
### 1. Install OpenClaw (if you haven't already)
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm install -g openclaw
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 2. Start SurrealDB
|
|
60
|
+
|
|
61
|
+
Install SurrealDB via your platform's package manager (see [surrealdb.com/install](https://surrealdb.com/docs/surrealdb/installation)):
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# macOS
|
|
65
|
+
brew install surrealdb/tap/surreal
|
|
66
|
+
|
|
67
|
+
# Linux (Debian/Ubuntu)
|
|
68
|
+
curl -sSf https://install.surrealdb.com | sh
|
|
69
|
+
export PATH="$HOME/.surrealdb:$PATH"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Then start it locally, **change the credentials before use**:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
surreal start --user youruser --pass yourpass --bind 127.0.0.1:8042 surrealkv:~/.kongbrain/surreal.db
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Or with Docker:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
docker run -d --name surrealdb -p 127.0.0.1:8042:8000 \
|
|
82
|
+
-v ~/.kongbrain/surreal-data:/data \
|
|
83
|
+
surrealdb/surrealdb:latest start \
|
|
84
|
+
--user youruser --pass yourpass surrealkv:/data/surreal.db
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
> **Security note:** Always bind to `127.0.0.1` (not `0.0.0.0`) unless you need remote access. Never use default credentials in production.
|
|
88
|
+
|
|
89
|
+
### 3. Install KongBrain
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# From ClawHub (recommended)
|
|
93
|
+
openclaw plugins install clawhub:kongbrain
|
|
94
|
+
|
|
95
|
+
# From npm (fallback)
|
|
96
|
+
openclaw plugins install kongbrain
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
> **Note:** Bare `openclaw plugins install kongbrain` checks ClawHub first, then falls back to npm. Use the `clawhub:` prefix to install from ClawHub explicitly.
|
|
100
|
+
|
|
101
|
+
### 4. Activate
|
|
102
|
+
|
|
103
|
+
Add to your OpenClaw config (`~/.openclaw/openclaw.json`):
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"plugins": {
|
|
108
|
+
"allow": ["kongbrain"],
|
|
109
|
+
"slots": {
|
|
110
|
+
"contextEngine": "kongbrain"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 5. Talk to your ape
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
openclaw tui
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
That's it. KongBrain uses whatever LLM provider and model you already have configured in OpenClaw (Anthropic, OpenAI, Google, Ollama, whatever). No separate API keys needed for the brain itself.
|
|
123
|
+
|
|
124
|
+
The BGE-M3 embedding model (~420MB) downloads automatically on first startup from [Hugging Face](https://huggingface.co/BAAI/bge-m3). All database tables and indexes are created automatically on first run. No manual setup required.
|
|
125
|
+
|
|
126
|
+
<details>
|
|
127
|
+
<summary><strong>Configuration Options</strong></summary>
|
|
128
|
+
|
|
129
|
+
All options have sensible defaults. Override via plugin config or environment variables:
|
|
130
|
+
|
|
131
|
+
| Option | Env Var | Default |
|
|
132
|
+
|--------|---------|---------|
|
|
133
|
+
| `surreal.url` | `SURREAL_URL` | `ws://127.0.0.1:8042/rpc` |
|
|
134
|
+
| `surreal.user` | `SURREAL_USER` | (required) |
|
|
135
|
+
| `surreal.pass` | `SURREAL_PASS` | (required) |
|
|
136
|
+
| `surreal.ns` | `SURREAL_NS` | `kong` |
|
|
137
|
+
| `surreal.db` | `SURREAL_DB` | `memory` |
|
|
138
|
+
| `embedding.modelPath` | `KONGBRAIN_EMBEDDING_MODEL` | Auto-downloaded BGE-M3 Q4_K_M |
|
|
139
|
+
| `embedding.dimensions` | - | `1024` |
|
|
140
|
+
|
|
141
|
+
Full config example:
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"plugins": {
|
|
146
|
+
"allow": ["kongbrain"],
|
|
147
|
+
"slots": {
|
|
148
|
+
"contextEngine": "kongbrain"
|
|
149
|
+
},
|
|
150
|
+
"entries": {
|
|
151
|
+
"kongbrain": {
|
|
152
|
+
"config": {
|
|
153
|
+
"surreal": {
|
|
154
|
+
"url": "ws://127.0.0.1:8042/rpc",
|
|
155
|
+
"user": "youruser",
|
|
156
|
+
"pass": "yourpass",
|
|
157
|
+
"ns": "kong",
|
|
158
|
+
"db": "memory"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
</details>
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Architecture
|
|
172
|
+
|
|
173
|
+
### The IKONG Pillars
|
|
174
|
+
|
|
175
|
+
KongBrain's cognitive architecture follows five functional pillars:
|
|
176
|
+
|
|
177
|
+
| Pillar | Role | What it does |
|
|
178
|
+
|--------|------|-------------|
|
|
179
|
+
| **I**ntelligence | Adaptive reasoning | Intent classification, complexity estimation, thinking depth, orchestrator preflight |
|
|
180
|
+
| **K**nowledge | Persistent memory | Memory graph, concepts, skills, reflections, identity chunks, core memory tiers |
|
|
181
|
+
| **O**peration | Execution | Tool orchestration, skill procedures, causal chain tracking, artifact management |
|
|
182
|
+
| **N**etwork | Graph traversal | Cross-pillar edge following, neighbor expansion, causal path walking |
|
|
183
|
+
| **G**raph | Persistence | SurrealDB storage, BGE-M3 vector search, HNSW indexes, embedding pipeline |
|
|
184
|
+
|
|
185
|
+
A 6th pillar, **Persona**, is unlocked at soul graduation: *"You have a Soul, an identity grounded in real experience. Be unique, be genuine, be yourself."*
|
|
186
|
+
|
|
187
|
+
### Structural Pillars
|
|
188
|
+
|
|
189
|
+
The graph entity model in SurrealDB:
|
|
190
|
+
|
|
191
|
+
| Pillar | Table | What it anchors |
|
|
192
|
+
|--------|-------|-----------------|
|
|
193
|
+
| 1. Agent | `agent` | Who is operating (name, model) |
|
|
194
|
+
| 2. Project | `project` | What we're working on (status, tags) |
|
|
195
|
+
| 3. Task | `task` | Individual sessions as units of work |
|
|
196
|
+
| 4. Artifact | `artifact` | Files and outputs tracked across sessions |
|
|
197
|
+
| 5. Concept | `concept` | Semantic knowledge nodes extracted from sessions |
|
|
198
|
+
|
|
199
|
+
On startup, the agent bootstraps the full chain: `Agent → owns → Project`, `Agent → performed → Task`, `Task → task_part_of → Project`, `Session → session_task → Task`. Graph expansion traverses these edges during retrieval.
|
|
200
|
+
|
|
201
|
+
### The Knowledge Graph
|
|
202
|
+
|
|
203
|
+
SurrealDB with HNSW vector indexes (1024-dim cosine). Everything is embedded and queryable.
|
|
204
|
+
|
|
205
|
+
| Table | What it stores |
|
|
206
|
+
|-------|---------------|
|
|
207
|
+
| `turn` | Every conversation message (role, text, embedding, token count, model, usage) |
|
|
208
|
+
| `memory` | Compacted episodic knowledge (importance 0-10, confidence, access tracking) |
|
|
209
|
+
| `skill` | Learned procedures with steps, preconditions, success/failure counts |
|
|
210
|
+
| `reflection` | Metacognitive lessons (efficiency, failure patterns, approach strategy) |
|
|
211
|
+
| `causal_chain` | Cause-effect patterns (trigger, outcome, chain type, success, confidence) |
|
|
212
|
+
| `identity_chunk` | Agent self-knowledge fragments (source, importance, embedding) |
|
|
213
|
+
| `monologue` | Thinking traces preserved across sessions |
|
|
214
|
+
| `core_memory` | Tier 0 (always loaded) + Tier 1 (session-pinned) directives |
|
|
215
|
+
| `soul` | Emergent identity document, earned through graduation |
|
|
216
|
+
|
|
217
|
+
<details>
|
|
218
|
+
<summary><strong>Adaptive Reasoning</strong>, per-turn intent classification and budget allocation</summary>
|
|
219
|
+
|
|
220
|
+
Every turn gets classified by intent and assigned an adaptive config:
|
|
221
|
+
|
|
222
|
+
| Intent | Thinking | Tool Limit | Token Budget | Retrieval Share |
|
|
223
|
+
|--------|----------|------------|--------------|-----------------|
|
|
224
|
+
| `simple-question` | low | 3 | 4K | 10% |
|
|
225
|
+
| `code-read` | medium | 5 | 6K | 15% |
|
|
226
|
+
| `code-write` | high | 8 | 8K | 20% |
|
|
227
|
+
| `code-debug` | high | 10 | 8K | 20% |
|
|
228
|
+
| `deep-explore` | medium | 15 | 6K | 15% |
|
|
229
|
+
| `reference-prior` | medium | 5 | 10K | 25% |
|
|
230
|
+
| `meta-session` | low | 2 | 3K | 7% (skip retrieval) |
|
|
231
|
+
| `multi-step` | high | 12 | 8K | 20% |
|
|
232
|
+
| `continuation` | low | 8 | 4K | skip retrieval |
|
|
233
|
+
|
|
234
|
+
**Fast path:** Short inputs (<20 chars, no `?`) skip classification entirely.
|
|
235
|
+
**Confidence gate:** Below 0.40 confidence, falls back to conservative config.
|
|
236
|
+
|
|
237
|
+
</details>
|
|
238
|
+
|
|
239
|
+
<details>
|
|
240
|
+
<summary><strong>Context Injection Pipeline</strong></summary>
|
|
241
|
+
|
|
242
|
+
1. **Embed** user input via BGE-M3 (or hit prefetch cache at 0.85 cosine threshold)
|
|
243
|
+
2. **Vector search** across 6 tables (turn, identity_chunk, concept, memory, artifact, monologue)
|
|
244
|
+
3. **Graph expand**: fetch neighbors via structural + semantic edges, compute cosine similarity
|
|
245
|
+
4. **Score** all candidates with WMR (Working Memory Ranker):
|
|
246
|
+
```
|
|
247
|
+
score = W * [similarity, recency, importance, access, neighbor_bonus, utility, reflection_boost]
|
|
248
|
+
```
|
|
249
|
+
5. **Budget trim**: inject Tier 0/1 core memory first (15% of context), then ranked results up to 21% retrieval budget
|
|
250
|
+
6. **Stage** retrieval snapshot for post-hoc quality evaluation
|
|
251
|
+
|
|
252
|
+
</details>
|
|
253
|
+
|
|
254
|
+
<details>
|
|
255
|
+
<summary><strong>ACAN</strong>, learned cross-attention scorer</summary>
|
|
256
|
+
|
|
257
|
+
A ~130K-parameter cross-attention network that replaces the fixed WMR weights once enough data accumulates.
|
|
258
|
+
|
|
259
|
+
- **Activation:** 5,000+ labeled retrieval outcomes
|
|
260
|
+
- **Training:** Pure TypeScript SGD with manual backprop, 80 epochs
|
|
261
|
+
- **Staleness:** Retrains when data grows 50%+ or weights age > 7 days
|
|
262
|
+
|
|
263
|
+
</details>
|
|
264
|
+
|
|
265
|
+
<details>
|
|
266
|
+
<summary><strong>Soul & Graduation</strong>, earned identity, not assigned</summary>
|
|
267
|
+
|
|
268
|
+
The agent earns an identity document through accumulated experience. Graduation requires **all 7 thresholds met** AND a **quality score >= 0.6**:
|
|
269
|
+
|
|
270
|
+
| Signal | Threshold |
|
|
271
|
+
|--------|-----------|
|
|
272
|
+
| Sessions completed | 15 |
|
|
273
|
+
| Reflections stored | 10 |
|
|
274
|
+
| Causal chains traced | 5 |
|
|
275
|
+
| Concepts extracted | 30 |
|
|
276
|
+
| Memory compactions | 5 |
|
|
277
|
+
| Monologue traces | 5 |
|
|
278
|
+
| Time span | 3 days |
|
|
279
|
+
|
|
280
|
+
**Quality scoring** from 4 real performance signals: retrieval utilization (30%), skill success rate (25%), critical reflection rate (25%), tool failure rate (20%).
|
|
281
|
+
|
|
282
|
+
**Maturity stages:** nascent (0-3/7) → developing (4/7) → emerging (5/7) → maturing (6/7) → ready (7/7 + quality gate). The agent and user are notified at each stage transition.
|
|
283
|
+
|
|
284
|
+
**Soul evolution:** Every 10 sessions after graduation, the soul is re-evaluated against new experience and revised if the agent has meaningfully changed.
|
|
285
|
+
|
|
286
|
+
**Soul document structure:** Working style, self-observations, earned values (grounded in specific evidence), revision history. Seeded as Tier 0 core memory, loaded every single turn.
|
|
287
|
+
|
|
288
|
+
</details>
|
|
289
|
+
|
|
290
|
+
<details>
|
|
291
|
+
<summary><strong>Reflection System</strong>, metacognitive self-correction</summary>
|
|
292
|
+
|
|
293
|
+
Triggers at session end when metrics indicate problems:
|
|
294
|
+
|
|
295
|
+
| Condition | Threshold |
|
|
296
|
+
|-----------|-----------|
|
|
297
|
+
| Retrieval utilization | < 20% average |
|
|
298
|
+
| Tool failure rate | > 20% |
|
|
299
|
+
| Steering candidates | any detected |
|
|
300
|
+
| Context waste | > 0.5% of context window |
|
|
301
|
+
|
|
302
|
+
The LLM generates a 2-4 sentence reflection: root cause, error pattern, what to do differently. Stored with importance 7.0, deduped at 0.85 cosine similarity.
|
|
303
|
+
|
|
304
|
+
</details>
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## How It Works
|
|
309
|
+
|
|
310
|
+
### Every Turn
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
User Input
|
|
314
|
+
|
|
|
315
|
+
v
|
|
316
|
+
Preflight ──────── Intent classification (25ms, zero-shot BGE-M3 cosine)
|
|
317
|
+
| 10 categories: simple-question, code-read, code-write,
|
|
318
|
+
| code-debug, deep-explore, reference-prior, meta-session,
|
|
319
|
+
| multi-step, continuation, unknown
|
|
320
|
+
v
|
|
321
|
+
Prefetch ────────── Predictive background vector searches (LRU cache, 5-min TTL)
|
|
322
|
+
|
|
|
323
|
+
v
|
|
324
|
+
Context Injection ─ Vector search -> graph expand -> 6-signal scoring -> budget trim
|
|
325
|
+
| Searches: turns, concepts, memories, artifacts, identity, monologues
|
|
326
|
+
| Scores: similarity, recency, importance, access, neighbor, utility
|
|
327
|
+
| Budget: 21% of context window reserved for retrieval
|
|
328
|
+
v
|
|
329
|
+
Agent Loop ──────── LLM + tool execution
|
|
330
|
+
| Planning gate: announces plan before touching tools
|
|
331
|
+
| Smart truncation: preserves tail of large tool outputs
|
|
332
|
+
v
|
|
333
|
+
Turn Storage ────── Every message embedded + stored + linked via graph edges
|
|
334
|
+
| responds_to, part_of, mentions, produced
|
|
335
|
+
v
|
|
336
|
+
Quality Eval ────── Measures retrieval utilization (text overlap, trigrams, unigrams)
|
|
337
|
+
| Tracks tool success, context waste, feeds ACAN training
|
|
338
|
+
v
|
|
339
|
+
Memory Daemon ───── Worker thread extracts 9 knowledge types via LLM:
|
|
340
|
+
| causal chains, monologues, concepts, corrections,
|
|
341
|
+
| preferences, artifacts, decisions, skills, resolved memories
|
|
342
|
+
v
|
|
343
|
+
Postflight ──────── Records orchestrator metrics (non-blocking)
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Between Sessions
|
|
347
|
+
|
|
348
|
+
At session end, KongBrain runs a combined extraction pass: skill graduation, metacognitive reflection, causal chain consolidation, soul graduation check, and soul evolution. A handoff note is written so the next session wakes up knowing what happened.
|
|
349
|
+
|
|
350
|
+
At session start, a wake-up briefing is synthesized from the handoff, recent monologues, soul content (if graduated), and identity state, then injected as inner speech so the agent knows who it is and what it was doing.
|
|
351
|
+
|
|
352
|
+
<details>
|
|
353
|
+
<summary><strong>Memory Daemon</strong>, background knowledge extraction</summary>
|
|
354
|
+
|
|
355
|
+
A worker thread running throughout the session. Batches turns every ~12K tokens, calls the configured LLM to extract:
|
|
356
|
+
|
|
357
|
+
- **Causal chains**: trigger/outcome sequences with success/confidence
|
|
358
|
+
- **Monologue traces**: thinking blocks that reveal problem-solving approach
|
|
359
|
+
- **Concepts**: semantic nodes (architecture patterns, domain terms)
|
|
360
|
+
- **Corrections**: user-provided fixes (importance: 9)
|
|
361
|
+
- **Preferences**: behavioral rules learned from feedback
|
|
362
|
+
- **Artifacts**: file paths created or modified
|
|
363
|
+
- **Decisions**: important conclusions reached
|
|
364
|
+
- **Skills**: multi-step procedures (if 5+ tool calls in session)
|
|
365
|
+
- **Resolved memories**: completed tasks and confirmed facts
|
|
366
|
+
|
|
367
|
+
</details>
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Tools
|
|
372
|
+
|
|
373
|
+
Three tools are registered for the LLM:
|
|
374
|
+
|
|
375
|
+
- **`recall`** Search graph memory by query
|
|
376
|
+
- **`core_memory`** Read/write persistent core directives (tiered: always-loaded vs session-pinned)
|
|
377
|
+
- **`introspect`** Inspect database state, verify memory counts, run diagnostics, check graduation status, migrate workspace files
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## Development
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
git clone https://github.com/42U/kongbrain.git
|
|
385
|
+
cd kongbrain
|
|
386
|
+
pnpm install
|
|
387
|
+
pnpm build
|
|
388
|
+
pnpm test
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Link your local build to OpenClaw:
|
|
392
|
+
|
|
393
|
+
```bash
|
|
394
|
+
openclaw plugins install . --link
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Then set `plugins.slots.contextEngine` to `"kongbrain"` in `~/.openclaw/openclaw.json` and run `openclaw`.
|
|
398
|
+
|
|
399
|
+
## Contributing
|
|
400
|
+
|
|
401
|
+
1. Clone the repo and install dependencies (`pnpm install`)
|
|
402
|
+
2. Make your changes
|
|
403
|
+
3. Build (`pnpm build`) and run tests (`pnpm test`)
|
|
404
|
+
4. Open a PR against `master`
|
|
405
|
+
|
|
406
|
+
The lobster doesn't accept contributions. The ape does.
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
<div align="center">
|
|
411
|
+
|
|
412
|
+
MIT License | Built by [42U](https://github.com/42U)
|
|
413
|
+
|
|
414
|
+
</div>
|
package/README.md
CHANGED
|
@@ -7,13 +7,19 @@
|
|
|
7
7
|
[](https://nodejs.org)
|
|
8
8
|
[](https://surrealdb.com)
|
|
9
9
|
[](https://github.com/openclaw/openclaw)
|
|
10
|
-
[](https://vitest.dev)
|
|
11
11
|
|
|
12
12
|
**A graph-backed cognitive engine for [OpenClaw](https://github.com/openclaw/openclaw).**
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
> *OpenClaw ships with a lobster brain. It works — lobsters have survived 350 million years — but they also solve problems by walking backwards and occasionally eating each other.*
|
|
15
|
+
>
|
|
16
|
+
> *When a conversation gets too long, the lobster brain does what lobsters do best: it panics, truncates everything before message 47, and carries on like nothing happened. Your carefully explained architecture? Gone. That bug you described in detail twenty minutes ago? Never heard of it.*
|
|
17
|
+
>
|
|
18
|
+
> *KongBrain is a brain transplant. You're replacing that crustacean context window with a primate cortex — backed by a graph database, vector embeddings, and the kind of persistent memory that lets your AI remember what you said last Tuesday — and judge you for it.*
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
Persistent memory graph. Vector-embedded, self-scoring, wired to learn across sessions. It extracts skills from what worked, traces causal chains through what broke, reflects on its own failures, and earns an identity through real experience. Every session compounds on the last.
|
|
21
|
+
|
|
22
|
+
Your assistant stops forgetting. Then it starts getting smarter.
|
|
17
23
|
|
|
18
24
|
[Quick Start](#quick-start) | [Architecture](#architecture) | [How It Works](#how-it-works) | [Tools](#tools) | [Development](#development)
|
|
19
25
|
|
package/README.npm.md
ADDED
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
# KongBrain
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/kongbrain)
|
|
4
|
+
[](https://clawhub.ai/packages/kongbrain)
|
|
5
|
+
[](https://github.com/42U/kongbrain)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://nodejs.org)
|
|
8
|
+
[](https://surrealdb.com)
|
|
9
|
+
[](https://github.com/openclaw/openclaw)
|
|
10
|
+
[](https://vitest.dev)
|
|
11
|
+
|
|
12
|
+
**A graph-backed cognitive engine for [OpenClaw](https://github.com/openclaw/openclaw).**
|
|
13
|
+
|
|
14
|
+
> *OpenClaw ships with a lobster brain. It works — lobsters have survived 350 million years — but they also solve problems by walking backwards and occasionally eating each other.*
|
|
15
|
+
>
|
|
16
|
+
> *When a conversation gets too long, the lobster brain does what lobsters do best: it panics, truncates everything before message 47, and carries on like nothing happened. Your carefully explained architecture? Gone. That bug you described in detail twenty minutes ago? Never heard of it.*
|
|
17
|
+
>
|
|
18
|
+
> *KongBrain is a brain transplant. You're replacing that crustacean context window with a primate cortex — backed by a graph database, vector embeddings, and the kind of persistent memory that lets your AI remember what you said last Tuesday — and judge you for it.*
|
|
19
|
+
|
|
20
|
+
Persistent memory graph. Vector-embedded, self-scoring, wired to learn across sessions. It extracts skills from what worked, traces causal chains through what broke, reflects on its own failures, and earns an identity through real experience. Every session compounds on the last.
|
|
21
|
+
|
|
22
|
+
Your assistant stops forgetting. Then it starts getting smarter.
|
|
23
|
+
|
|
24
|
+
[Quick Start](#quick-start) | [Architecture](#architecture) | [How It Works](#how-it-works) | [Tools](#tools) | [Development](#development)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## What Changes
|
|
29
|
+
|
|
30
|
+
| | Lobster Brain (default) | Ape Brain (KongBrain) |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| **Memory** | Sliding window. Old messages fall off a cliff. | Graph-persistent. Every turn, concept, skill, and causal chain stored with vector embeddings. |
|
|
33
|
+
| **Recall** | Whatever fits in the context window right now. | Cosine similarity + graph expansion + learned attention scoring across your entire history. |
|
|
34
|
+
| **Adaptation** | Same retrieval budget every turn, regardless of intent. | 10 intent categories. Simple question? Minimal retrieval. Complex debugging? Full graph search + elevated thinking. |
|
|
35
|
+
| **Learning** | None. Every session starts from zero. | Skills extracted from successful workflows, causal chains graduated into reusable procedures, corrections remembered permanently. |
|
|
36
|
+
| **Self-awareness** | Thermostat-level. | Periodic cognitive checks grade its own retrieval quality, detect contradictions, suppress noise, and extract your preferences. Eventually graduates a soul document. |
|
|
37
|
+
| **Compaction** | LLM-summarizes your conversation mid-flow (disruptive). | Graph retrieval IS the compaction. No interruptions, no lossy summaries. |
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
From zero to ape brain in under 5 minutes.
|
|
42
|
+
|
|
43
|
+
### 1. Install OpenClaw (if you haven't already)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm install -g openclaw
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 2. Start SurrealDB
|
|
50
|
+
|
|
51
|
+
Install SurrealDB via your platform's package manager (see [surrealdb.com/install](https://surrealdb.com/docs/surrealdb/installation)):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# macOS
|
|
55
|
+
brew install surrealdb/tap/surreal
|
|
56
|
+
|
|
57
|
+
# Linux (Debian/Ubuntu)
|
|
58
|
+
curl -sSf https://install.surrealdb.com | sh
|
|
59
|
+
export PATH="$HOME/.surrealdb:$PATH"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Then start it locally — **change the credentials before use**:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
surreal start --user youruser --pass yourpass --bind 127.0.0.1:8042 surrealkv:~/.kongbrain/surreal.db
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Or with Docker:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
docker run -d --name surrealdb -p 127.0.0.1:8042:8000 \
|
|
72
|
+
-v ~/.kongbrain/surreal-data:/data \
|
|
73
|
+
surrealdb/surrealdb:latest start \
|
|
74
|
+
--user youruser --pass yourpass surrealkv:/data/surreal.db
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
> **Security note:** Always bind to `127.0.0.1` (not `0.0.0.0`) unless you need remote access. Never use default credentials in production.
|
|
78
|
+
|
|
79
|
+
### 3. Install KongBrain
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# From ClawHub (recommended)
|
|
83
|
+
openclaw plugins install clawhub:kongbrain
|
|
84
|
+
|
|
85
|
+
# From npm (fallback)
|
|
86
|
+
openclaw plugins install kongbrain
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
> **Note:** Bare `openclaw plugins install kongbrain` checks ClawHub first, then falls back to npm. Use the `clawhub:` prefix to install from ClawHub explicitly.
|
|
90
|
+
|
|
91
|
+
### 4. Activate
|
|
92
|
+
|
|
93
|
+
Add to your OpenClaw config (`~/.openclaw/openclaw.json`):
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"plugins": {
|
|
98
|
+
"allow": ["kongbrain"],
|
|
99
|
+
"slots": {
|
|
100
|
+
"contextEngine": "kongbrain"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 5. Talk to your ape
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
openclaw tui
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
That's it. KongBrain uses whatever LLM provider and model you already have configured in OpenClaw (Anthropic, OpenAI, Google, Ollama, whatever). No separate API keys needed for the brain itself.
|
|
113
|
+
|
|
114
|
+
The BGE-M3 embedding model (~420MB) downloads automatically on first startup from [Hugging Face](https://huggingface.co/BAAI/bge-m3). All database tables and indexes are created automatically on first run. No manual setup required.
|
|
115
|
+
|
|
116
|
+
<details>
|
|
117
|
+
<summary><strong>Configuration Options</strong></summary>
|
|
118
|
+
|
|
119
|
+
All options have sensible defaults. Override via plugin config or environment variables:
|
|
120
|
+
|
|
121
|
+
| Option | Env Var | Default |
|
|
122
|
+
|--------|---------|---------|
|
|
123
|
+
| `surreal.url` | `SURREAL_URL` | `ws://127.0.0.1:8042/rpc` |
|
|
124
|
+
| `surreal.user` | `SURREAL_USER` | (required) |
|
|
125
|
+
| `surreal.pass` | `SURREAL_PASS` | (required) |
|
|
126
|
+
| `surreal.ns` | `SURREAL_NS` | `kong` |
|
|
127
|
+
| `surreal.db` | `SURREAL_DB` | `memory` |
|
|
128
|
+
| `embedding.modelPath` | `KONGBRAIN_EMBEDDING_MODEL` | Auto-downloaded BGE-M3 Q4_K_M |
|
|
129
|
+
| `embedding.dimensions` | - | `1024` |
|
|
130
|
+
|
|
131
|
+
Full config example:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"plugins": {
|
|
136
|
+
"allow": ["kongbrain"],
|
|
137
|
+
"slots": {
|
|
138
|
+
"contextEngine": "kongbrain"
|
|
139
|
+
},
|
|
140
|
+
"entries": {
|
|
141
|
+
"kongbrain": {
|
|
142
|
+
"config": {
|
|
143
|
+
"surreal": {
|
|
144
|
+
"url": "ws://127.0.0.1:8042/rpc",
|
|
145
|
+
"user": "youruser",
|
|
146
|
+
"pass": "yourpass",
|
|
147
|
+
"ns": "kong",
|
|
148
|
+
"db": "memory"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
</details>
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Architecture
|
|
162
|
+
|
|
163
|
+
### The IKONG Pillars
|
|
164
|
+
|
|
165
|
+
KongBrain's cognitive architecture follows five functional pillars:
|
|
166
|
+
|
|
167
|
+
| Pillar | Role | What it does |
|
|
168
|
+
|--------|------|-------------|
|
|
169
|
+
| **I**ntelligence | Adaptive reasoning | Intent classification, complexity estimation, thinking depth, orchestrator preflight |
|
|
170
|
+
| **K**nowledge | Persistent memory | Memory graph, concepts, skills, reflections, identity chunks, core memory tiers |
|
|
171
|
+
| **O**peration | Execution | Tool orchestration, skill procedures, causal chain tracking, artifact management |
|
|
172
|
+
| **N**etwork | Graph traversal | Cross-pillar edge following, neighbor expansion, causal path walking |
|
|
173
|
+
| **G**raph | Persistence | SurrealDB storage, BGE-M3 vector search, HNSW indexes, embedding pipeline |
|
|
174
|
+
|
|
175
|
+
A 6th pillar, **Persona**, is unlocked at soul graduation: *"You have a Soul, an identity grounded in real experience. Be unique, be genuine, be yourself."*
|
|
176
|
+
|
|
177
|
+
### Structural Pillars
|
|
178
|
+
|
|
179
|
+
The graph entity model in SurrealDB:
|
|
180
|
+
|
|
181
|
+
| Pillar | Table | What it anchors |
|
|
182
|
+
|--------|-------|-----------------|
|
|
183
|
+
| 1. Agent | `agent` | Who is operating (name, model) |
|
|
184
|
+
| 2. Project | `project` | What we're working on (status, tags) |
|
|
185
|
+
| 3. Task | `task` | Individual sessions as units of work |
|
|
186
|
+
| 4. Artifact | `artifact` | Files and outputs tracked across sessions |
|
|
187
|
+
| 5. Concept | `concept` | Semantic knowledge nodes extracted from sessions |
|
|
188
|
+
|
|
189
|
+
On startup, the agent bootstraps the full chain: `Agent → owns → Project`, `Agent → performed → Task`, `Task → task_part_of → Project`, `Session → session_task → Task`. Graph expansion traverses these edges during retrieval.
|
|
190
|
+
|
|
191
|
+
### The Knowledge Graph
|
|
192
|
+
|
|
193
|
+
SurrealDB with HNSW vector indexes (1024-dim cosine). Everything is embedded and queryable.
|
|
194
|
+
|
|
195
|
+
| Table | What it stores |
|
|
196
|
+
|-------|---------------|
|
|
197
|
+
| `turn` | Every conversation message (role, text, embedding, token count, model, usage) |
|
|
198
|
+
| `memory` | Compacted episodic knowledge (importance 0-10, confidence, access tracking) |
|
|
199
|
+
| `skill` | Learned procedures with steps, preconditions, success/failure counts |
|
|
200
|
+
| `reflection` | Metacognitive lessons (efficiency, failure patterns, approach strategy) |
|
|
201
|
+
| `causal_chain` | Cause-effect patterns (trigger, outcome, chain type, success, confidence) |
|
|
202
|
+
| `identity_chunk` | Agent self-knowledge fragments (source, importance, embedding) |
|
|
203
|
+
| `monologue` | Thinking traces preserved across sessions |
|
|
204
|
+
| `core_memory` | Tier 0 (always loaded) + Tier 1 (session-pinned) directives |
|
|
205
|
+
| `soul` | Emergent identity document, earned through graduation |
|
|
206
|
+
|
|
207
|
+
<details>
|
|
208
|
+
<summary><strong>Adaptive Reasoning</strong>: per-turn intent classification and budget allocation</summary>
|
|
209
|
+
|
|
210
|
+
Every turn gets classified by intent and assigned an adaptive config:
|
|
211
|
+
|
|
212
|
+
| Intent | Thinking | Tool Limit | Token Budget | Retrieval Share |
|
|
213
|
+
|--------|----------|------------|--------------|-----------------|
|
|
214
|
+
| `simple-question` | low | 3 | 4K | 10% |
|
|
215
|
+
| `code-read` | medium | 5 | 6K | 15% |
|
|
216
|
+
| `code-write` | high | 8 | 8K | 20% |
|
|
217
|
+
| `code-debug` | high | 10 | 8K | 20% |
|
|
218
|
+
| `deep-explore` | medium | 15 | 6K | 15% |
|
|
219
|
+
| `reference-prior` | medium | 5 | 10K | 25% |
|
|
220
|
+
| `meta-session` | low | 2 | 3K | 7% (skip retrieval) |
|
|
221
|
+
| `multi-step` | high | 12 | 8K | 20% |
|
|
222
|
+
| `continuation` | low | 8 | 4K | skip retrieval |
|
|
223
|
+
|
|
224
|
+
**Fast path:** Short inputs (<20 chars, no `?`) skip classification entirely.
|
|
225
|
+
**Confidence gate:** Below 0.40 confidence, falls back to conservative config.
|
|
226
|
+
|
|
227
|
+
</details>
|
|
228
|
+
|
|
229
|
+
<details>
|
|
230
|
+
<summary><strong>Context Injection Pipeline</strong></summary>
|
|
231
|
+
|
|
232
|
+
1. **Embed** user input via BGE-M3 (or hit prefetch cache at 0.85 cosine threshold)
|
|
233
|
+
2. **Vector search** across 6 tables (turn, identity_chunk, concept, memory, artifact, monologue)
|
|
234
|
+
3. **Graph expand**: fetch neighbors via structural + semantic edges, compute cosine similarity
|
|
235
|
+
4. **Score** all candidates with WMR (Working Memory Ranker):
|
|
236
|
+
```
|
|
237
|
+
score = W * [similarity, recency, importance, access, neighbor_bonus, utility, reflection_boost]
|
|
238
|
+
```
|
|
239
|
+
5. **Budget trim**: inject Tier 0/1 core memory first (15% of context), then ranked results up to 21% retrieval budget
|
|
240
|
+
6. **Stage** retrieval snapshot for post-hoc quality evaluation
|
|
241
|
+
|
|
242
|
+
</details>
|
|
243
|
+
|
|
244
|
+
<details>
|
|
245
|
+
<summary><strong>ACAN</strong>: learned cross-attention scorer</summary>
|
|
246
|
+
|
|
247
|
+
A ~130K-parameter cross-attention network that replaces the fixed WMR weights once enough data accumulates.
|
|
248
|
+
|
|
249
|
+
- **Activation:** 5,000+ labeled retrieval outcomes
|
|
250
|
+
- **Training:** Pure TypeScript SGD with manual backprop, 80 epochs
|
|
251
|
+
- **Staleness:** Retrains when data grows 50%+ or weights age > 7 days
|
|
252
|
+
|
|
253
|
+
</details>
|
|
254
|
+
|
|
255
|
+
<details>
|
|
256
|
+
<summary><strong>Soul & Graduation</strong>: earned identity, not assigned</summary>
|
|
257
|
+
|
|
258
|
+
The agent earns an identity document through accumulated experience. Graduation requires **all 7 thresholds met** AND a **quality score >= 0.6**:
|
|
259
|
+
|
|
260
|
+
| Signal | Threshold |
|
|
261
|
+
|--------|-----------|
|
|
262
|
+
| Sessions completed | 15 |
|
|
263
|
+
| Reflections stored | 10 |
|
|
264
|
+
| Causal chains traced | 5 |
|
|
265
|
+
| Concepts extracted | 30 |
|
|
266
|
+
| Memory compactions | 5 |
|
|
267
|
+
| Monologue traces | 5 |
|
|
268
|
+
| Time span | 3 days |
|
|
269
|
+
|
|
270
|
+
**Quality scoring** from 4 real performance signals: retrieval utilization (30%), skill success rate (25%), critical reflection rate (25%), tool failure rate (20%).
|
|
271
|
+
|
|
272
|
+
**Maturity stages:** nascent (0-3/7) → developing (4/7) → emerging (5/7) → maturing (6/7) → ready (7/7 + quality gate). The agent and user are notified at each stage transition.
|
|
273
|
+
|
|
274
|
+
**Soul evolution:** Every 10 sessions after graduation, the soul is re-evaluated against new experience and revised if the agent has meaningfully changed.
|
|
275
|
+
|
|
276
|
+
**Soul document structure:** Working style, self-observations, earned values (grounded in specific evidence), revision history. Seeded as Tier 0 core memory, loaded every single turn.
|
|
277
|
+
|
|
278
|
+
</details>
|
|
279
|
+
|
|
280
|
+
<details>
|
|
281
|
+
<summary><strong>Reflection System</strong>: metacognitive self-correction</summary>
|
|
282
|
+
|
|
283
|
+
Triggers at session end when metrics indicate problems:
|
|
284
|
+
|
|
285
|
+
| Condition | Threshold |
|
|
286
|
+
|-----------|-----------|
|
|
287
|
+
| Retrieval utilization | < 20% average |
|
|
288
|
+
| Tool failure rate | > 20% |
|
|
289
|
+
| Steering candidates | any detected |
|
|
290
|
+
| Context waste | > 0.5% of context window |
|
|
291
|
+
|
|
292
|
+
The LLM generates a 2-4 sentence reflection: root cause, error pattern, what to do differently. Stored with importance 7.0, deduped at 0.85 cosine similarity.
|
|
293
|
+
|
|
294
|
+
</details>
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## How It Works
|
|
299
|
+
|
|
300
|
+
### Every Turn
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
User Input
|
|
304
|
+
|
|
|
305
|
+
v
|
|
306
|
+
Preflight ──────── Intent classification (25ms, zero-shot BGE-M3 cosine)
|
|
307
|
+
| 10 categories: simple-question, code-read, code-write,
|
|
308
|
+
| code-debug, deep-explore, reference-prior, meta-session,
|
|
309
|
+
| multi-step, continuation, unknown
|
|
310
|
+
v
|
|
311
|
+
Prefetch ────────── Predictive background vector searches (LRU cache, 5-min TTL)
|
|
312
|
+
|
|
|
313
|
+
v
|
|
314
|
+
Context Injection ─ Vector search -> graph expand -> 6-signal scoring -> budget trim
|
|
315
|
+
| Searches: turns, concepts, memories, artifacts, identity, monologues
|
|
316
|
+
| Scores: similarity, recency, importance, access, neighbor, utility
|
|
317
|
+
| Budget: 21% of context window reserved for retrieval
|
|
318
|
+
v
|
|
319
|
+
Agent Loop ──────── LLM + tool execution
|
|
320
|
+
| Planning gate: announces plan before touching tools
|
|
321
|
+
| Smart truncation: preserves tail of large tool outputs
|
|
322
|
+
v
|
|
323
|
+
Turn Storage ────── Every message embedded + stored + linked via graph edges
|
|
324
|
+
| responds_to, part_of, mentions, produced
|
|
325
|
+
v
|
|
326
|
+
Quality Eval ────── Measures retrieval utilization (text overlap, trigrams, unigrams)
|
|
327
|
+
| Tracks tool success, context waste, feeds ACAN training
|
|
328
|
+
v
|
|
329
|
+
Memory Daemon ───── Worker thread extracts 9 knowledge types via LLM:
|
|
330
|
+
| causal chains, monologues, concepts, corrections,
|
|
331
|
+
| preferences, artifacts, decisions, skills, resolved memories
|
|
332
|
+
v
|
|
333
|
+
Postflight ──────── Records orchestrator metrics (non-blocking)
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Between Sessions
|
|
337
|
+
|
|
338
|
+
At session end, KongBrain runs a combined extraction pass: skill graduation, metacognitive reflection, causal chain consolidation, soul graduation check, and soul evolution. A handoff note is written so the next session wakes up knowing what happened.
|
|
339
|
+
|
|
340
|
+
At session start, a wake-up briefing is synthesized from the handoff, recent monologues, soul content (if graduated), and identity state, then injected as inner speech so the agent knows who it is and what it was doing.
|
|
341
|
+
|
|
342
|
+
<details>
|
|
343
|
+
<summary><strong>Memory Daemon</strong>: background knowledge extraction</summary>
|
|
344
|
+
|
|
345
|
+
A worker thread running throughout the session. Batches turns every ~12K tokens, calls the configured LLM to extract:
|
|
346
|
+
|
|
347
|
+
- **Causal chains**: trigger/outcome sequences with success/confidence
|
|
348
|
+
- **Monologue traces**: thinking blocks that reveal problem-solving approach
|
|
349
|
+
- **Concepts**: semantic nodes (architecture patterns, domain terms)
|
|
350
|
+
- **Corrections**: user-provided fixes (importance: 9)
|
|
351
|
+
- **Preferences**: behavioral rules learned from feedback
|
|
352
|
+
- **Artifacts**: file paths created or modified
|
|
353
|
+
- **Decisions**: important conclusions reached
|
|
354
|
+
- **Skills**: multi-step procedures (if 5+ tool calls in session)
|
|
355
|
+
- **Resolved memories**: completed tasks and confirmed facts
|
|
356
|
+
|
|
357
|
+
</details>
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
## Tools
|
|
362
|
+
|
|
363
|
+
Three tools are registered for the LLM:
|
|
364
|
+
|
|
365
|
+
- **`recall`**: Search graph memory by query
|
|
366
|
+
- **`core_memory`**: Read/write persistent core directives (tiered: always-loaded vs session-pinned)
|
|
367
|
+
- **`introspect`**: Inspect database state, verify memory counts, run diagnostics, check graduation status, migrate workspace files
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Development
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
git clone https://github.com/42U/kongbrain.git
|
|
375
|
+
cd kongbrain
|
|
376
|
+
pnpm install
|
|
377
|
+
pnpm build
|
|
378
|
+
pnpm test
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Link your local build to OpenClaw:
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
openclaw plugins install . --link
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
Then set `plugins.slots.contextEngine` to `"kongbrain"` in `~/.openclaw/openclaw.json` and run `openclaw`.
|
|
388
|
+
|
|
389
|
+
## Contributing
|
|
390
|
+
|
|
391
|
+
1. Clone the repo and install dependencies (`pnpm install`)
|
|
392
|
+
2. Make your changes
|
|
393
|
+
3. Build (`pnpm build`) and run tests (`pnpm test`)
|
|
394
|
+
4. Open a PR against `master`
|
|
395
|
+
|
|
396
|
+
The lobster doesn't accept contributions. The ape does.
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
MIT License | Built by [42U](https://github.com/42U)
|
package/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kongbrain
|
|
3
3
|
description: Graph-backed persistent memory engine for OpenClaw. Replaces the default context window with SurrealDB + vector embeddings that learn across sessions.
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.9
|
|
5
5
|
homepage: https://github.com/42U/kongbrain
|
|
6
6
|
metadata:
|
|
7
7
|
openclaw:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kongbrain",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"description": "Graph-backed persistent memory engine for OpenClaw. Replaces the default context window with SurrealDB + vector embeddings that learn across sessions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -41,6 +41,8 @@
|
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
|
+
"prepack": "cp README.md README.github.md && cp README.npm.md README.md",
|
|
45
|
+
"postpack": "cp README.github.md README.md && rm README.github.md",
|
|
44
46
|
"test": "vitest run",
|
|
45
47
|
"test:watch": "vitest",
|
|
46
48
|
"build": "tsc --noEmit",
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared concept-extraction helpers.
|
|
3
|
+
*
|
|
4
|
+
* Regex-based extraction of concept names from text, plus helpers to
|
|
5
|
+
* upsert extracted concepts and link them via arbitrary edge types.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { SurrealStore } from "./surreal.js";
|
|
9
|
+
import type { EmbeddingService } from "./embeddings.js";
|
|
10
|
+
import { swallow } from "./errors.js";
|
|
11
|
+
|
|
12
|
+
// Same regexes used by the original extractAndLinkConcepts in context-engine.
|
|
13
|
+
export const CONCEPT_RE = /\b(?:(?:use|using|implement|create|add|configure|setup|install|import)\s+)([A-Z][a-zA-Z0-9_-]+(?:\s+[A-Z][a-zA-Z0-9_-]+)?)/g;
|
|
14
|
+
export const TECH_TERMS = /\b(api|database|schema|migration|endpoint|middleware|component|service|module|handler|controller|model|interface|type|class|function|method|hook|plugin|extension|config|cache|queue|worker|daemon)\b/gi;
|
|
15
|
+
|
|
16
|
+
/** Extract concept name strings from free text using regex heuristics. */
|
|
17
|
+
export function extractConceptNames(text: string): string[] {
|
|
18
|
+
const concepts = new Set<string>();
|
|
19
|
+
|
|
20
|
+
let match: RegExpExecArray | null;
|
|
21
|
+
const re1 = new RegExp(CONCEPT_RE.source, CONCEPT_RE.flags);
|
|
22
|
+
while ((match = re1.exec(text)) !== null) {
|
|
23
|
+
concepts.add(match[1].trim());
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const re2 = new RegExp(TECH_TERMS.source, TECH_TERMS.flags);
|
|
27
|
+
while ((match = re2.exec(text)) !== null) {
|
|
28
|
+
concepts.add(match[1].toLowerCase());
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return [...concepts].slice(0, 10);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Upsert concepts from text and link them to a source node via the given edge.
|
|
36
|
+
*
|
|
37
|
+
* Used for:
|
|
38
|
+
* - turn → "mentions" → concept (existing behaviour)
|
|
39
|
+
* - memory → "about_concept" → concept (Fix 1)
|
|
40
|
+
* - artifact → "artifact_mentions" → concept (Fix 2)
|
|
41
|
+
*/
|
|
42
|
+
export async function upsertAndLinkConcepts(
|
|
43
|
+
sourceId: string,
|
|
44
|
+
edgeName: string,
|
|
45
|
+
text: string,
|
|
46
|
+
store: SurrealStore,
|
|
47
|
+
embeddings: EmbeddingService,
|
|
48
|
+
logTag: string,
|
|
49
|
+
): Promise<void> {
|
|
50
|
+
const names = extractConceptNames(text);
|
|
51
|
+
if (names.length === 0) return;
|
|
52
|
+
|
|
53
|
+
for (const name of names) {
|
|
54
|
+
try {
|
|
55
|
+
let embedding: number[] | null = null;
|
|
56
|
+
if (embeddings.isAvailable()) {
|
|
57
|
+
try { embedding = await embeddings.embed(name); } catch { /* ok */ }
|
|
58
|
+
}
|
|
59
|
+
const conceptId = await store.upsertConcept(name, embedding);
|
|
60
|
+
if (conceptId) {
|
|
61
|
+
await store.relate(sourceId, edgeName, conceptId)
|
|
62
|
+
.catch(e => swallow(`${logTag}:relate`, e));
|
|
63
|
+
}
|
|
64
|
+
} catch (e) {
|
|
65
|
+
swallow(`${logTag}:upsert`, e);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Link a newly-upserted concept to existing concepts via narrower/broader
|
|
72
|
+
* edges when one concept's name is a substring of the other (indicating a
|
|
73
|
+
* parent-child hierarchy, e.g. "React" → "React hooks").
|
|
74
|
+
*/
|
|
75
|
+
export async function linkConceptHierarchy(
|
|
76
|
+
conceptId: string,
|
|
77
|
+
conceptName: string,
|
|
78
|
+
store: SurrealStore,
|
|
79
|
+
logTag: string,
|
|
80
|
+
): Promise<void> {
|
|
81
|
+
try {
|
|
82
|
+
const existing = await store.queryFirst<{ id: string; content: string }>(
|
|
83
|
+
`SELECT id, content FROM concept WHERE id != $cid LIMIT 50`,
|
|
84
|
+
{ cid: conceptId },
|
|
85
|
+
);
|
|
86
|
+
if (existing.length === 0) return;
|
|
87
|
+
|
|
88
|
+
const lowerName = conceptName.toLowerCase();
|
|
89
|
+
|
|
90
|
+
for (const other of existing) {
|
|
91
|
+
const otherLower = (other.content ?? "").toLowerCase();
|
|
92
|
+
if (!otherLower || otherLower === lowerName) continue;
|
|
93
|
+
|
|
94
|
+
const otherId = String(other.id);
|
|
95
|
+
|
|
96
|
+
if (lowerName.includes(otherLower) && lowerName !== otherLower) {
|
|
97
|
+
// New concept is more specific (e.g. "React hooks" contains "React")
|
|
98
|
+
await store.relate(conceptId, "narrower", otherId)
|
|
99
|
+
.catch(e => swallow(`${logTag}:narrower`, e));
|
|
100
|
+
await store.relate(otherId, "broader", conceptId)
|
|
101
|
+
.catch(e => swallow(`${logTag}:broader`, e));
|
|
102
|
+
} else if (otherLower.includes(lowerName) && otherLower !== lowerName) {
|
|
103
|
+
// New concept is more general (e.g. "React" contained in "React hooks")
|
|
104
|
+
await store.relate(conceptId, "broader", otherId)
|
|
105
|
+
.catch(e => swallow(`${logTag}:broader`, e));
|
|
106
|
+
await store.relate(otherId, "narrower", conceptId)
|
|
107
|
+
.catch(e => swallow(`${logTag}:narrower`, e));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} catch (e) {
|
|
111
|
+
swallow(`${logTag}:hierarchy`, e);
|
|
112
|
+
}
|
|
113
|
+
}
|
package/src/context-engine.ts
CHANGED
|
@@ -51,6 +51,7 @@ import { extractSkill } from "./skills.js";
|
|
|
51
51
|
import { generateReflection } from "./reflection.js";
|
|
52
52
|
import { graduateCausalToSkills } from "./skills.js";
|
|
53
53
|
import { swallow } from "./errors.js";
|
|
54
|
+
import { upsertAndLinkConcepts } from "./concept-extract.js";
|
|
54
55
|
|
|
55
56
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
56
57
|
|
|
@@ -305,6 +306,7 @@ export class KongBrainContextEngine implements ContextEngine {
|
|
|
305
306
|
}
|
|
306
307
|
} else {
|
|
307
308
|
session.lastAssistantText = text;
|
|
309
|
+
if (turnId) session.lastAssistantTurnId = turnId;
|
|
308
310
|
}
|
|
309
311
|
|
|
310
312
|
return { ingested: true };
|
|
@@ -506,7 +508,11 @@ export class KongBrainContextEngine implements ContextEngine {
|
|
|
506
508
|
if (embeddings.isAvailable()) {
|
|
507
509
|
try { embedding = await embeddings.embed(handoffText); } catch { /* ok */ }
|
|
508
510
|
}
|
|
509
|
-
await store.createMemory(handoffText, embedding, 8, "handoff", session.sessionId);
|
|
511
|
+
const handoffMemId = await store.createMemory(handoffText, embedding, 8, "handoff", session.sessionId);
|
|
512
|
+
if (handoffMemId && session.surrealSessionId) {
|
|
513
|
+
await store.relate(handoffMemId, "summarizes", session.surrealSessionId)
|
|
514
|
+
.catch(e => swallow.warn("midCleanup:summarizes", e));
|
|
515
|
+
}
|
|
510
516
|
}
|
|
511
517
|
})().catch(e => swallow.warn("midCleanup:handoff", e)),
|
|
512
518
|
);
|
|
@@ -548,44 +554,15 @@ function hasSemantic(text: string): boolean {
|
|
|
548
554
|
return text.split(/\s+/).filter(w => w.length > 2).length >= 3;
|
|
549
555
|
}
|
|
550
556
|
|
|
551
|
-
// --- Concept extraction (
|
|
552
|
-
|
|
553
|
-
const CONCEPT_RE = /\b(?:(?:use|using|implement|create|add|configure|setup|install|import)\s+)([A-Z][a-zA-Z0-9_-]+(?:\s+[A-Z][a-zA-Z0-9_-]+)?)/g;
|
|
554
|
-
const TECH_TERMS = /\b(api|database|schema|migration|endpoint|middleware|component|service|module|handler|controller|model|interface|type|class|function|method|hook|plugin|extension|config|cache|queue|worker|daemon)\b/gi;
|
|
557
|
+
// --- Concept extraction (delegates to shared helper) ---
|
|
555
558
|
|
|
556
559
|
async function extractAndLinkConcepts(
|
|
557
560
|
turnId: string,
|
|
558
561
|
text: string,
|
|
559
562
|
state: GlobalPluginState,
|
|
560
563
|
): Promise<void> {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
while ((match = re1.exec(text)) !== null) {
|
|
566
|
-
concepts.add(match[1].trim());
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
const re2 = new RegExp(TECH_TERMS.source, TECH_TERMS.flags);
|
|
570
|
-
while ((match = re2.exec(text)) !== null) {
|
|
571
|
-
concepts.add(match[1].toLowerCase());
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
if (concepts.size === 0) return;
|
|
575
|
-
|
|
576
|
-
for (const conceptText of [...concepts].slice(0, 10)) {
|
|
577
|
-
try {
|
|
578
|
-
let embedding: number[] | null = null;
|
|
579
|
-
if (state.embeddings.isAvailable()) {
|
|
580
|
-
try { embedding = await state.embeddings.embed(conceptText); } catch { /* ok */ }
|
|
581
|
-
}
|
|
582
|
-
const conceptId = await state.store.upsertConcept(conceptText, embedding);
|
|
583
|
-
if (conceptId) {
|
|
584
|
-
await state.store.relate(turnId, "mentions", conceptId)
|
|
585
|
-
.catch(e => swallow("concepts:relate", e));
|
|
586
|
-
}
|
|
587
|
-
} catch (e) {
|
|
588
|
-
swallow("concepts:upsert", e);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
564
|
+
await upsertAndLinkConcepts(
|
|
565
|
+
turnId, "mentions", text,
|
|
566
|
+
state.store, state.embeddings, "concepts",
|
|
567
|
+
);
|
|
591
568
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import type { GlobalPluginState } from "../state.js";
|
|
6
6
|
import { recordToolOutcome } from "../retrieval-quality.js";
|
|
7
7
|
import { swallow } from "../errors.js";
|
|
8
|
+
import { upsertAndLinkConcepts } from "../concept-extract.js";
|
|
8
9
|
|
|
9
10
|
export function createAfterToolCallHandler(state: GlobalPluginState) {
|
|
10
11
|
return async (
|
|
@@ -30,13 +31,20 @@ export function createAfterToolCallHandler(state: GlobalPluginState) {
|
|
|
30
31
|
? event.result.slice(0, 500)
|
|
31
32
|
: JSON.stringify(event.result ?? "").slice(0, 500);
|
|
32
33
|
|
|
34
|
+
let toolResultTurnId: string | undefined;
|
|
33
35
|
try {
|
|
34
|
-
await state.store.upsertTurn({
|
|
36
|
+
toolResultTurnId = await state.store.upsertTurn({
|
|
35
37
|
session_id: session.sessionId,
|
|
36
38
|
role: "tool",
|
|
37
39
|
text: `[${event.toolName}] ${resultText}`,
|
|
38
40
|
embedding: null,
|
|
39
41
|
});
|
|
42
|
+
|
|
43
|
+
// Fix 5: Link tool result turn back to the assistant turn that triggered it
|
|
44
|
+
if (toolResultTurnId && session.lastAssistantTurnId) {
|
|
45
|
+
await state.store.relate(toolResultTurnId, "tool_result_of", session.lastAssistantTurnId)
|
|
46
|
+
.catch(e => swallow.warn("hook:afterToolCall:tool_result_of", e));
|
|
47
|
+
}
|
|
40
48
|
} catch (e) {
|
|
41
49
|
swallow("hook:afterToolCall:store", e);
|
|
42
50
|
}
|
|
@@ -92,8 +100,15 @@ async function trackArtifact(
|
|
|
92
100
|
const artifactId = await state.store.createArtifact(
|
|
93
101
|
(args.path as string) ?? "shell", ext, description, emb,
|
|
94
102
|
);
|
|
95
|
-
if (artifactId
|
|
96
|
-
|
|
97
|
-
.
|
|
103
|
+
if (artifactId) {
|
|
104
|
+
if (taskId) {
|
|
105
|
+
await state.store.relate(taskId, "produced", artifactId)
|
|
106
|
+
.catch(e => swallow.warn("artifact:relate", e));
|
|
107
|
+
}
|
|
108
|
+
// Fix 2: Link artifact to concepts it mentions
|
|
109
|
+
await upsertAndLinkConcepts(
|
|
110
|
+
artifactId, "artifact_mentions", description,
|
|
111
|
+
state.store, state.embeddings, "artifact:concepts",
|
|
112
|
+
);
|
|
98
113
|
}
|
|
99
114
|
}
|
package/src/memory-daemon.ts
CHANGED
|
@@ -13,6 +13,7 @@ import type { SurrealStore } from "./surreal.js";
|
|
|
13
13
|
import type { EmbeddingService } from "./embeddings.js";
|
|
14
14
|
import { swallow } from "./errors.js";
|
|
15
15
|
import { assertRecordId } from "./surreal.js";
|
|
16
|
+
import { upsertAndLinkConcepts, linkConceptHierarchy } from "./concept-extract.js";
|
|
16
17
|
|
|
17
18
|
// --- Build the extraction prompt ---
|
|
18
19
|
|
|
@@ -196,7 +197,10 @@ export async function writeExtractionResults(
|
|
|
196
197
|
if (embeddings.isAvailable()) {
|
|
197
198
|
try { emb = await embeddings.embed(c.content); } catch (e) { swallow("daemon:embedConcept", e); }
|
|
198
199
|
}
|
|
199
|
-
await store.upsertConcept(c.content, emb, `daemon:${sessionId}`);
|
|
200
|
+
const conceptId = await store.upsertConcept(c.content, emb, `daemon:${sessionId}`);
|
|
201
|
+
if (conceptId) {
|
|
202
|
+
await linkConceptHierarchy(conceptId, c.name, store, "daemon:concept");
|
|
203
|
+
}
|
|
200
204
|
})());
|
|
201
205
|
}
|
|
202
206
|
}
|
|
@@ -212,7 +216,10 @@ export async function writeExtractionResults(
|
|
|
212
216
|
if (embeddings.isAvailable()) {
|
|
213
217
|
try { emb = await embeddings.embed(text); } catch (e) { swallow("daemon:embedCorrection", e); }
|
|
214
218
|
}
|
|
215
|
-
await store.createMemory(text, emb, 9, "correction", sessionId);
|
|
219
|
+
const memId = await store.createMemory(text, emb, 9, "correction", sessionId);
|
|
220
|
+
if (memId) {
|
|
221
|
+
await upsertAndLinkConcepts(memId, "about_concept", text, store, embeddings, "daemon:correction");
|
|
222
|
+
}
|
|
216
223
|
})());
|
|
217
224
|
}
|
|
218
225
|
}
|
|
@@ -228,7 +235,10 @@ export async function writeExtractionResults(
|
|
|
228
235
|
if (embeddings.isAvailable()) {
|
|
229
236
|
try { emb = await embeddings.embed(text); } catch (e) { swallow("daemon:embedPreference", e); }
|
|
230
237
|
}
|
|
231
|
-
await store.createMemory(text, emb, 7, "preference", sessionId);
|
|
238
|
+
const memId = await store.createMemory(text, emb, 7, "preference", sessionId);
|
|
239
|
+
if (memId) {
|
|
240
|
+
await upsertAndLinkConcepts(memId, "about_concept", text, store, embeddings, "daemon:preference");
|
|
241
|
+
}
|
|
232
242
|
})());
|
|
233
243
|
}
|
|
234
244
|
}
|
|
@@ -246,7 +256,10 @@ export async function writeExtractionResults(
|
|
|
246
256
|
if (embeddings.isAvailable()) {
|
|
247
257
|
try { emb = await embeddings.embed(`${a.path} ${desc}`); } catch (e) { swallow("daemon:embedArtifact", e); }
|
|
248
258
|
}
|
|
249
|
-
await store.createArtifact(a.path, a.action ?? "modified", desc, emb);
|
|
259
|
+
const artId = await store.createArtifact(a.path, a.action ?? "modified", desc, emb);
|
|
260
|
+
if (artId) {
|
|
261
|
+
await upsertAndLinkConcepts(artId, "artifact_mentions", `${a.path} ${desc}`, store, embeddings, "daemon:artifact");
|
|
262
|
+
}
|
|
250
263
|
})());
|
|
251
264
|
}
|
|
252
265
|
}
|
|
@@ -262,7 +275,10 @@ export async function writeExtractionResults(
|
|
|
262
275
|
if (embeddings.isAvailable()) {
|
|
263
276
|
try { emb = await embeddings.embed(text); } catch (e) { swallow("daemon:embedDecision", e); }
|
|
264
277
|
}
|
|
265
|
-
await store.createMemory(text, emb, 7, "decision", sessionId);
|
|
278
|
+
const memId = await store.createMemory(text, emb, 7, "decision", sessionId);
|
|
279
|
+
if (memId) {
|
|
280
|
+
await upsertAndLinkConcepts(memId, "about_concept", text, store, embeddings, "daemon:decision");
|
|
281
|
+
}
|
|
266
282
|
})());
|
|
267
283
|
}
|
|
268
284
|
}
|