kongbrain 0.4.4 → 0.5.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.
@@ -0,0 +1,8 @@
1
+ {
2
+ "sessionId": "7a2dcd89-1468-49c3-a1be-24dac5a05662",
3
+ "timestamp": "2026-05-02T21:39:49.691Z",
4
+ "userTurnCount": 1,
5
+ "lastUserText": "Drain the KongCode pending_work queue. Loop: call mcp__plugin_kongcode_kongcode__fetch_pending_work to claim the next item, analyze the data per the work-type instructions, then call mcp__plugin_kongcode_kongcode__commit_work_results with your output. Repeat until fetch_pending_work returns empty. Be efficient: minimize per-item analysis. This is auto-drain, not user-facing — produce no narration, just process items.",
6
+ "lastAssistantText": "",
7
+ "unextractedTokens": 0
8
+ }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,53 @@
2
2
 
3
3
  All notable changes to KongBrain are documented here.
4
4
 
5
+ ## [0.5.0] - 2026-04-25
6
+
7
+ Configurable embedding providers. Closes #1.
8
+
9
+ ### Features
10
+ - **Configurable embedding provider**: New `embedding.provider` config field. Options: `local` (BGE-M3 via node-llama-cpp, default and unchanged) or `openai-compat` (any OpenAI-compatible `/v1/embeddings` endpoint — OpenAI, Azure OpenAI, Together, Anyscale, vLLM, LM Studio, Ollama, DeepInfra, Fireworks).
11
+ - **OpenAI-compatible provider**: `fetch`-based, no SDK dependency. Batches inputs at 96/request, retries 429 + 5xx with exponential backoff and `Retry-After` honoring, hard-fails on 401/403/404 and `insufficient_quota` with clear error messages, verifies returned dimensionality matches config.
12
+ - **Per-row provider tagging**: Every vector-bearing table (`turn`, `concept`, `memory`, `artifact`, `identity_chunk`, `skill`, `reflection`, `monologue`) gets an `embedding_provider` column. Searches filter by the active provider so vectors from different models (different vector spaces) never mix in HNSW results.
13
+ - **Re-embed migration tool**: `npx kongbrain-reembed --from <provider-id> [--dry-run] [--tables …] [--batch …]`. Resumable on interruption (the WHERE filter naturally excludes processed rows). Reports per-table progress and estimated cost.
14
+ - **Startup mismatch warning**: Logs a clear notice (with row counts and migration command) when the configured provider does not match what is in the database.
15
+ - **Provider env overrides**: `KONGBRAIN_EMBED_PROVIDER` flips provider without editing config; `OPENAI_BASE_URL` overrides endpoint (matches the official OpenAI SDK convention); `embedding.openaiCompat.apiKeyEnv` names the env var holding the secret so keys never appear in config files.
16
+ - **Plugin manifest**: `openclaw.plugin.json` extended with `provider` / `dimensions` / `openaiCompat` schema and uiHints with inline help text.
17
+
18
+ ### Infrastructure
19
+ - **Idempotent schema migration + backfill**: All schema additions use `IF NOT EXISTS`. On first startup with this version, existing rows are tagged with `local-bge-m3`. Runs cleanly on every subsequent startup as a no-op.
20
+
21
+ ### Tests
22
+ - 439 → 469 tests. New: 17 OpenAI provider unit tests (success, batching, dim mismatch, retry, hard-fail), 4 config tests (provider, env overrides, fallback), 8 migration tests (full migrate, table filter, dry-run, blank-text, multi-batch, refusal, no-op, format), 4 backfill upgrade-path integration tests, plus 6 gated live tests (real OpenAI / real DB / real reembed) that skip in CI.
23
+
24
+ ### Documentation
25
+ - README and README.npm updated with embedding-provider comparison table, switching instructions for OpenAI / Ollama / vLLM, and migration command.
26
+
27
+ ### Upgrade notes
28
+ - **No action required for existing local BGE-M3 deployments.** The schema migration adds the new column and tags all existing rows as `local-bge-m3`. Search continues to work identically.
29
+ - **To switch providers**: set `embedding.provider: "openai-compat"` and `OPENAI_API_KEY`. On restart you will see a warning about rows in the old vector space. Run `npx kongbrain-reembed --from local-bge-m3 --dry-run` to estimate cost (~$0.04 per ~3,400 turns on text-embedding-3-small), then drop `--dry-run` to migrate. Resumable if interrupted.
30
+
31
+ ## [0.4.4] - 2026-04-04
32
+
33
+ ### Performance
34
+ - **WMR rebalance**: Cosine-dominant scoring weights, dampen access count feedback loop that was reinforcing already-popular memories.
35
+ - **Tag-boosted concept retrieval**: Surface topically relevant concepts even when embedding similarity alone misses them.
36
+
37
+ ### Bug Fixes
38
+ - **Empty LLM extraction responses**: `outputFormat` injected via pi-ai's `onPayload` hook caused Anthropic API to return 0 content blocks. Removed structured output from pi-ai code path; daemon's JSON parsing cascade handles free-text reliably.
39
+ - **`SELECT WHERE id IN $ids` binding**: Same silent no-op as `bumpAccessCounts` — SurrealDB string arrays don't resolve to record references. Fixed in `getSessionRetrievedMemories` and ACAN `fetchTrainingData`.
40
+ - **ACAN NaN/Infinity validation**: `loadWeights` now rejects corrupted weights (null, NaN, Infinity in bias, W_final, or spot-checked W_q/W_k rows).
41
+ - **Lazy daemon start**: If gateway restarts mid-session, `afterTurn` now starts the daemon on demand instead of silently skipping extraction.
42
+ - **`getOrCreateSession` in afterTurn**: Resumed sessions after gateway restart no longer return null.
43
+ - **Model object unwrapping**: `defaults.model` can be `{primary: "provider/model"}` — unwrap and split provider/model format.
44
+
45
+ ### Infrastructure
46
+ - **CI pipeline**: GitHub Actions with SurrealDB service container, Node 22, 439 tests (unit + integration).
47
+ - **PR checks**: Type checking + unit tests on all pull requests.
48
+
49
+ ### Tests
50
+ - 415 → 439 tests. New: ACAN NaN/Infinity validation (7), score stability/performance (3), `SELECT IN` integration test, additional integration coverage.
51
+
5
52
  ## [0.4.2] - 2026-04-03
6
53
 
7
54
  ### Performance
package/README.github.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  ![KongBrain](KongClaw.png)
6
6
 
7
+ [![VoidOrigin](https://img.shields.io/badge/VOIDORIGIN-voidorigin.com-0a0a0a?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSI+PGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iMTAiIHN0cm9rZT0iI2ZmNmIzNSIgc3Ryb2tlLXdpZHRoPSIyIi8+PGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iNCIgZmlsbD0iI2ZmNmIzNSIvPjwvc3ZnPg==&logoColor=ff6b35&labelColor=0a0a0a)](https://voidorigin.com)
8
+
7
9
  [![npm](https://img.shields.io/npm/v/kongbrain?style=for-the-badge&logo=npm&color=cb3837)](https://www.npmjs.com/package/kongbrain)
8
10
  [![ClawHub](https://img.shields.io/badge/ClawHub-kongbrain-ff6b35?style=for-the-badge)](https://clawhub.ai/packages/kongbrain)
9
11
  [![GitHub Stars](https://img.shields.io/github/stars/42U/kongbrain?style=for-the-badge&logo=github&color=gold)](https://github.com/42U/kongbrain)
@@ -11,7 +13,7 @@
11
13
  [![Node.js](https://img.shields.io/badge/Node.js-20+-339933?style=for-the-badge&logo=node.js&logoColor=white)](https://nodejs.org)
12
14
  [![SurrealDB](https://img.shields.io/badge/SurrealDB-3.0-ff00a0?style=for-the-badge&logo=surrealdb&logoColor=white)](https://surrealdb.com)
13
15
  [![OpenClaw](https://img.shields.io/badge/OpenClaw-Plugin-ff6b35?style=for-the-badge)](https://github.com/openclaw/openclaw)
14
- [![Tests](https://img.shields.io/badge/Tests-415_passing-brightgreen?style=for-the-badge&logo=vitest&logoColor=white)](https://vitest.dev)
16
+ [![Tests](https://img.shields.io/badge/Tests-469_passing-brightgreen?style=for-the-badge&logo=vitest&logoColor=white)](https://vitest.dev)
15
17
 
16
18
  **A graph-backed cognitive engine for [OpenClaw](https://github.com/openclaw/openclaw).**
17
19
 
@@ -121,7 +123,9 @@ openclaw tui
121
123
 
122
124
  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
125
 
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.
126
+ By default KongBrain runs the BGE-M3 embedding model locally via `node-llama-cpp` — the GGUF (~420MB) auto-downloads from [Hugging Face](https://huggingface.co/BAAI/bge-m3) on first startup. For high-traffic deployments the local model can become a bottleneck on serial embedding calls; in that case switch to any OpenAI-compatible API (real OpenAI, Azure OpenAI, Together, vLLM, LM Studio, Ollama) by changing one config field. See [Embedding Providers](#embedding-providers) below.
127
+
128
+ All database tables and indexes are created automatically on first run. No manual setup required.
125
129
 
126
130
  <details>
127
131
  <summary><strong>Configuration Options</strong></summary>
@@ -135,8 +139,12 @@ All options have sensible defaults. Override via plugin config or environment va
135
139
  | `surreal.pass` | `SURREAL_PASS` | (required) |
136
140
  | `surreal.ns` | `SURREAL_NS` | `kong` |
137
141
  | `surreal.db` | `SURREAL_DB` | `memory` |
138
- | `embedding.modelPath` | `KONGBRAIN_EMBEDDING_MODEL` | Auto-downloaded BGE-M3 Q4_K_M |
142
+ | `embedding.provider` | `KONGBRAIN_EMBED_PROVIDER` | `local` (or `openai-compat`) |
139
143
  | `embedding.dimensions` | - | `1024` |
144
+ | `embedding.modelPath` | `EMBED_MODEL_PATH` | Auto-downloaded BGE-M3 Q4_K_M |
145
+ | `embedding.openaiCompat.model` | - | `text-embedding-3-small` |
146
+ | `embedding.openaiCompat.baseURL` | `OPENAI_BASE_URL` | `https://api.openai.com/v1` |
147
+ | `embedding.openaiCompat.apiKeyEnv` | - | `OPENAI_API_KEY` |
140
148
 
141
149
  Full config example:
142
150
 
@@ -166,6 +174,50 @@ Full config example:
166
174
 
167
175
  </details>
168
176
 
177
+ ### Embedding Providers
178
+
179
+ | | `local` (default) | `openai-compat` |
180
+ |---|---|---|
181
+ | **Inference** | BGE-M3 GGUF via node-llama-cpp, in-process | HTTP POST to `/v1/embeddings` |
182
+ | **Cost** | Zero (~420MB model on disk, CPU inference) | Per-token API charges |
183
+ | **Throughput** | Serial; bottlenecks under high turn volume | High parallelism, batched at 96 inputs/request |
184
+ | **Network** | None required | Required |
185
+ | **Compatible servers** | n/a | OpenAI, Azure OpenAI, Together, Anyscale, vLLM, LM Studio, Ollama, DeepInfra, Fireworks |
186
+
187
+ Switching providers is safe by design. Every embedding written to the database is tagged with the provider that produced it (`embedding_provider` column). At search time, KongBrain only compares vectors that were produced by the active provider — vectors from a different provider live in a different vector space and would corrupt similarity scores if mixed.
188
+
189
+ When you switch from `local` to `openai-compat`, pre-existing rows stay in the database but become invisible to recall until re-embedded. Run the included migration tool to bring them into the new vector space:
190
+
191
+ ```bash
192
+ # Estimate cost first (no writes)
193
+ npx kongbrain-reembed --from local-bge-m3 --dry-run
194
+
195
+ # Then run for real (resumable on interruption)
196
+ npx kongbrain-reembed --from local-bge-m3
197
+ ```
198
+
199
+ Cost is small: text-embedding-3-small is $0.02 per 1M tokens; a typical 3,400-turn database costs ~$0.04 to re-embed.
200
+
201
+ #### Switching to OpenAI
202
+
203
+ ```bash
204
+ export KONGBRAIN_EMBED_PROVIDER=openai-compat
205
+ export OPENAI_API_KEY=sk-...
206
+ # Restart the plugin. Migration tool handles existing data.
207
+ ```
208
+
209
+ #### Switching to a local OpenAI-compatible server (Ollama, vLLM, LM Studio)
210
+
211
+ ```bash
212
+ # Ollama example — runs entirely locally, no API key needed
213
+ ollama pull nomic-embed-text
214
+ export OPENAI_BASE_URL=http://localhost:11434/v1
215
+ export OPENAI_API_KEY=ollama # any non-empty string; Ollama doesn't validate
216
+ export KONGBRAIN_EMBED_PROVIDER=openai-compat
217
+ ```
218
+
219
+ Set `embedding.dimensions` to match the server's native output dim. KongBrain verifies the returned vector size on every response and fails loudly if the server ignores the `dimensions` parameter — preventing silently corrupted indexes.
220
+
169
221
  ---
170
222
 
171
223
  ## Architecture
@@ -448,6 +500,6 @@ The lobster doesn't accept contributions. The ape does.
448
500
 
449
501
  <div align="center">
450
502
 
451
- MIT License | Built by [42U](https://github.com/42U)
503
+ MIT License | Built by [42U](https://github.com/42U) | [VoidOrigin](https://voidorigin.com)
452
504
 
453
505
  </div>
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![Node.js](https://img.shields.io/badge/Node.js-20+-339933?style=for-the-badge&logo=node.js&logoColor=white)](https://nodejs.org)
8
8
  [![SurrealDB](https://img.shields.io/badge/SurrealDB-3.0-ff00a0?style=for-the-badge&logo=surrealdb&logoColor=white)](https://surrealdb.com)
9
9
  [![OpenClaw](https://img.shields.io/badge/OpenClaw-Plugin-ff6b35?style=for-the-badge)](https://github.com/openclaw/openclaw)
10
- [![Tests](https://img.shields.io/badge/Tests-88_passing-brightgreen?style=for-the-badge&logo=vitest&logoColor=white)](https://vitest.dev)
10
+ [![Tests](https://img.shields.io/badge/Tests-469_passing-brightgreen?style=for-the-badge&logo=vitest&logoColor=white)](https://vitest.dev)
11
11
 
12
12
  **A graph-backed cognitive engine for [OpenClaw](https://github.com/openclaw/openclaw).**
13
13
 
@@ -111,7 +111,9 @@ openclaw tui
111
111
 
112
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
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.
114
+ By default KongBrain runs the BGE-M3 embedding model locally via `node-llama-cpp` — the GGUF (~420MB) auto-downloads from [Hugging Face](https://huggingface.co/BAAI/bge-m3) on first startup. For high-traffic deployments the local model can become a bottleneck on serial embedding calls; in that case switch to any OpenAI-compatible API (real OpenAI, Azure OpenAI, Together, vLLM, LM Studio, Ollama) by changing one config field.
115
+
116
+ All database tables and indexes are created automatically on first run. No manual setup required.
115
117
 
116
118
  <details>
117
119
  <summary><strong>Configuration Options</strong></summary>
@@ -125,8 +127,12 @@ All options have sensible defaults. Override via plugin config or environment va
125
127
  | `surreal.pass` | `SURREAL_PASS` | (required) |
126
128
  | `surreal.ns` | `SURREAL_NS` | `kong` |
127
129
  | `surreal.db` | `SURREAL_DB` | `memory` |
128
- | `embedding.modelPath` | `KONGBRAIN_EMBEDDING_MODEL` | Auto-downloaded BGE-M3 Q4_K_M |
130
+ | `embedding.provider` | `KONGBRAIN_EMBED_PROVIDER` | `local` (or `openai-compat`) |
129
131
  | `embedding.dimensions` | - | `1024` |
132
+ | `embedding.modelPath` | `EMBED_MODEL_PATH` | Auto-downloaded BGE-M3 Q4_K_M |
133
+ | `embedding.openaiCompat.model` | - | `text-embedding-3-small` |
134
+ | `embedding.openaiCompat.baseURL` | `OPENAI_BASE_URL` | `https://api.openai.com/v1` |
135
+ | `embedding.openaiCompat.apiKeyEnv` | - | `OPENAI_API_KEY` |
130
136
 
131
137
  Full config example:
132
138
 
@@ -156,6 +162,26 @@ Full config example:
156
162
 
157
163
  </details>
158
164
 
165
+ ### Embedding Providers
166
+
167
+ | | `local` (default) | `openai-compat` |
168
+ |---|---|---|
169
+ | **Inference** | BGE-M3 GGUF via node-llama-cpp, in-process | HTTP POST to `/v1/embeddings` |
170
+ | **Cost** | Zero | Per-token API charges |
171
+ | **Throughput** | Serial; bottlenecks under high turn volume | High parallelism, batched at 96 inputs/request |
172
+ | **Compatible servers** | n/a | OpenAI, Azure OpenAI, Together, Anyscale, vLLM, LM Studio, Ollama, DeepInfra, Fireworks |
173
+
174
+ Every embedding is tagged with the provider that produced it. At search time, KongBrain only compares vectors from the active provider — vectors from a different provider live in a different vector space.
175
+
176
+ When you switch providers, run the included migration tool to re-embed pre-existing rows:
177
+
178
+ ```bash
179
+ npx kongbrain-reembed --from local-bge-m3 --dry-run # estimate cost
180
+ npx kongbrain-reembed --from local-bge-m3 # run for real (resumable)
181
+ ```
182
+
183
+ text-embedding-3-small costs ~$0.04 to re-embed a typical 3,400-turn database.
184
+
159
185
  ---
160
186
 
161
187
  ## Architecture
package/README.npm.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![Node.js](https://img.shields.io/badge/Node.js-20+-339933?style=for-the-badge&logo=node.js&logoColor=white)](https://nodejs.org)
8
8
  [![SurrealDB](https://img.shields.io/badge/SurrealDB-3.0-ff00a0?style=for-the-badge&logo=surrealdb&logoColor=white)](https://surrealdb.com)
9
9
  [![OpenClaw](https://img.shields.io/badge/OpenClaw-Plugin-ff6b35?style=for-the-badge)](https://github.com/openclaw/openclaw)
10
- [![Tests](https://img.shields.io/badge/Tests-88_passing-brightgreen?style=for-the-badge&logo=vitest&logoColor=white)](https://vitest.dev)
10
+ [![Tests](https://img.shields.io/badge/Tests-469_passing-brightgreen?style=for-the-badge&logo=vitest&logoColor=white)](https://vitest.dev)
11
11
 
12
12
  **A graph-backed cognitive engine for [OpenClaw](https://github.com/openclaw/openclaw).**
13
13
 
@@ -111,7 +111,9 @@ openclaw tui
111
111
 
112
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
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.
114
+ By default KongBrain runs the BGE-M3 embedding model locally via `node-llama-cpp` — the GGUF (~420MB) auto-downloads from [Hugging Face](https://huggingface.co/BAAI/bge-m3) on first startup. For high-traffic deployments the local model can become a bottleneck on serial embedding calls; in that case switch to any OpenAI-compatible API (real OpenAI, Azure OpenAI, Together, vLLM, LM Studio, Ollama) by changing one config field.
115
+
116
+ All database tables and indexes are created automatically on first run. No manual setup required.
115
117
 
116
118
  <details>
117
119
  <summary><strong>Configuration Options</strong></summary>
@@ -125,8 +127,12 @@ All options have sensible defaults. Override via plugin config or environment va
125
127
  | `surreal.pass` | `SURREAL_PASS` | (required) |
126
128
  | `surreal.ns` | `SURREAL_NS` | `kong` |
127
129
  | `surreal.db` | `SURREAL_DB` | `memory` |
128
- | `embedding.modelPath` | `KONGBRAIN_EMBEDDING_MODEL` | Auto-downloaded BGE-M3 Q4_K_M |
130
+ | `embedding.provider` | `KONGBRAIN_EMBED_PROVIDER` | `local` (or `openai-compat`) |
129
131
  | `embedding.dimensions` | - | `1024` |
132
+ | `embedding.modelPath` | `EMBED_MODEL_PATH` | Auto-downloaded BGE-M3 Q4_K_M |
133
+ | `embedding.openaiCompat.model` | - | `text-embedding-3-small` |
134
+ | `embedding.openaiCompat.baseURL` | `OPENAI_BASE_URL` | `https://api.openai.com/v1` |
135
+ | `embedding.openaiCompat.apiKeyEnv` | - | `OPENAI_API_KEY` |
130
136
 
131
137
  Full config example:
132
138
 
@@ -156,6 +162,26 @@ Full config example:
156
162
 
157
163
  </details>
158
164
 
165
+ ### Embedding Providers
166
+
167
+ | | `local` (default) | `openai-compat` |
168
+ |---|---|---|
169
+ | **Inference** | BGE-M3 GGUF via node-llama-cpp, in-process | HTTP POST to `/v1/embeddings` |
170
+ | **Cost** | Zero | Per-token API charges |
171
+ | **Throughput** | Serial; bottlenecks under high turn volume | High parallelism, batched at 96 inputs/request |
172
+ | **Compatible servers** | n/a | OpenAI, Azure OpenAI, Together, Anyscale, vLLM, LM Studio, Ollama, DeepInfra, Fireworks |
173
+
174
+ Every embedding is tagged with the provider that produced it. At search time, KongBrain only compares vectors from the active provider — vectors from a different provider live in a different vector space.
175
+
176
+ When you switch providers, run the included migration tool to re-embed pre-existing rows:
177
+
178
+ ```bash
179
+ npx kongbrain-reembed --from local-bge-m3 --dry-run # estimate cost
180
+ npx kongbrain-reembed --from local-bge-m3 # run for real (resumable)
181
+ ```
182
+
183
+ text-embedding-3-small costs ~$0.04 to re-embed a typical 3,400-turn database.
184
+
159
185
  ---
160
186
 
161
187
  ## Architecture
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.4.4
4
+ version: 0.5.1
5
5
  homepage: https://github.com/42U/kongbrain
6
6
  metadata:
7
7
  openclaw:
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * kongbrain-reembed — re-embed migration CLI.
4
+ *
5
+ * Reads connection settings from the same env vars the plugin uses, plus
6
+ * KONGBRAIN_EMBED_PROVIDER / OPENAI_BASE_URL / etc. for the target
7
+ * provider. Migrates rows tagged with --from to the active provider's
8
+ * vector space.
9
+ *
10
+ * Usage:
11
+ * kongbrain-reembed --from local-bge-m3 [--dry-run] [--tables turn,memory] [--batch 256]
12
+ *
13
+ * Resumable: each batch flips embedding_provider so processed rows leave
14
+ * the FROM filter. Restarting after a crash continues from where it
15
+ * stopped.
16
+ */
17
+
18
+ import { parsePluginConfig } from "../src/config.js";
19
+ import { createEmbeddingService } from "../src/embeddings.js";
20
+ import { SurrealStore } from "../src/surreal.js";
21
+ import {
22
+ formatResult,
23
+ reembedAll,
24
+ VECTOR_TABLES,
25
+ type VectorTable,
26
+ } from "../src/migrate-reembed.js";
27
+
28
+ interface CliFlags {
29
+ from: string | null;
30
+ dryRun: boolean;
31
+ tables: VectorTable[] | null;
32
+ batch: number;
33
+ help: boolean;
34
+ }
35
+
36
+ function parseArgs(argv: string[]): CliFlags {
37
+ const flags: CliFlags = {
38
+ from: null,
39
+ dryRun: false,
40
+ tables: null,
41
+ batch: 256,
42
+ help: false,
43
+ };
44
+ for (let i = 0; i < argv.length; i++) {
45
+ const a = argv[i];
46
+ if (a === "--help" || a === "-h") flags.help = true;
47
+ else if (a === "--dry-run") flags.dryRun = true;
48
+ else if (a === "--from") flags.from = argv[++i] ?? null;
49
+ else if (a === "--batch") flags.batch = Number(argv[++i] ?? "256");
50
+ else if (a === "--tables") {
51
+ const list = (argv[++i] ?? "").split(",").map(s => s.trim()).filter(Boolean);
52
+ const valid: VectorTable[] = [];
53
+ for (const t of list) {
54
+ if ((VECTOR_TABLES as readonly string[]).includes(t)) valid.push(t as VectorTable);
55
+ else throw new Error(`Unknown table: ${t}. Valid: ${VECTOR_TABLES.join(", ")}`);
56
+ }
57
+ flags.tables = valid;
58
+ }
59
+ }
60
+ return flags;
61
+ }
62
+
63
+ const HELP = `kongbrain-reembed — migrate embeddings between providers
64
+
65
+ Required:
66
+ --from <provider-id> Provider tag to migrate FROM (e.g. local-bge-m3)
67
+
68
+ Optional:
69
+ --dry-run Count rows + estimate cost without writing
70
+ --tables turn,memory Only migrate these tables (default: all 8)
71
+ --batch <n> Rows per batch (default: 256)
72
+ --help Show this message
73
+
74
+ The TARGET provider is whatever the active EmbeddingService produces, set
75
+ via plugin config + env vars (KONGBRAIN_EMBED_PROVIDER, OPENAI_BASE_URL,
76
+ the API key env var named in embedding.openaiCompat.apiKeyEnv).
77
+
78
+ Resumability: each batch flips the embedding_provider tag, so re-running
79
+ after an interruption picks up from where the last successful batch left
80
+ off — no checkpoint file needed.
81
+
82
+ Example: migrate from local BGE-M3 to OpenAI text-embedding-3-small at 1024d:
83
+ export KONGBRAIN_EMBED_PROVIDER=openai-compat
84
+ export OPENAI_API_KEY=sk-...
85
+ npx kongbrain-reembed --from local-bge-m3 --dry-run # check the size
86
+ npx kongbrain-reembed --from local-bge-m3 # run for real
87
+ `;
88
+
89
+ async function main(): Promise<number> {
90
+ const flags = parseArgs(process.argv.slice(2));
91
+ if (flags.help) {
92
+ console.log(HELP);
93
+ return 0;
94
+ }
95
+ if (!flags.from) {
96
+ console.error("Missing required --from <provider-id>. See --help.");
97
+ return 2;
98
+ }
99
+
100
+ const config = parsePluginConfig();
101
+ const store = new SurrealStore(config.surreal);
102
+ const embeddings = createEmbeddingService(config.embedding);
103
+
104
+ console.log(`Source provider: ${flags.from}`);
105
+ console.log(`Target provider: ${embeddings.providerId}`);
106
+ console.log(`SurrealDB: ${config.surreal.url}`);
107
+ console.log(`Mode: ${flags.dryRun ? "DRY RUN" : "WRITE"}`);
108
+ console.log("");
109
+
110
+ await store.initialize();
111
+ store.setActiveProvider(embeddings.providerId);
112
+ if (!flags.dryRun) {
113
+ await embeddings.initialize();
114
+ }
115
+
116
+ try {
117
+ const result = await reembedAll(store, embeddings, {
118
+ fromProvider: flags.from,
119
+ tables: flags.tables ?? undefined,
120
+ batchSize: flags.batch,
121
+ dryRun: flags.dryRun,
122
+ onProgress: ev => {
123
+ process.stdout.write(
124
+ `[${ev.table}] ${ev.tableProcessed}/${ev.tableTotal}\r`,
125
+ );
126
+ },
127
+ });
128
+ process.stdout.write("\n");
129
+ console.log(formatResult(result, embeddings.providerId));
130
+ return 0;
131
+ } finally {
132
+ await embeddings.dispose().catch(() => {});
133
+ await store.close().catch(() => {});
134
+ }
135
+ }
136
+
137
+ main().then(
138
+ code => process.exit(code),
139
+ err => {
140
+ console.error("kongbrain-reembed failed:", err?.message ?? err);
141
+ process.exit(1);
142
+ },
143
+ );
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "kongbrain",
3
3
  "name": "KongBrain",
4
- "description": "Graph-backed cognitive context engine with SurrealDB + BGE-M3",
4
+ "description": "Graph-backed cognitive context engine with SurrealDB + pluggable embeddings (local BGE-M3 or OpenAI-compatible)",
5
5
  "kind": "context-engine",
6
6
  "requires": {
7
7
  "bins": ["surreal"],
@@ -30,16 +30,36 @@
30
30
  "label": "SurrealDB Database",
31
31
  "placeholder": "memory"
32
32
  },
33
- "embedding.modelPath": {
34
- "label": "Embedding Model Path",
35
- "placeholder": "~/.node-llama-cpp/models/bge-m3-q4_k_m.gguf",
36
- "help": "Path to BGE-M3 GGUF model file (~420MB, auto-downloaded if missing)",
37
- "advanced": true
33
+ "embedding.provider": {
34
+ "label": "Embedding Provider",
35
+ "placeholder": "local",
36
+ "help": "Either 'local' (BGE-M3 via node-llama-cpp) or 'openai-compat' (any OpenAI-compatible /v1/embeddings endpoint: OpenAI, Azure, Together, vLLM, Ollama, etc.)"
38
37
  },
39
38
  "embedding.dimensions": {
40
39
  "label": "Embedding Dimensions",
41
40
  "placeholder": "1024",
41
+ "help": "Output vector dimensionality. Must match across providers if you intend to swap them. text-embedding-3-* honors arbitrary values; non-OpenAI compat servers may return their native dim regardless."
42
+ },
43
+ "embedding.modelPath": {
44
+ "label": "Local Model Path",
45
+ "placeholder": "~/.node-llama-cpp/models/bge-m3-q4_k_m.gguf",
46
+ "help": "Path to BGE-M3 GGUF file. Only used when provider is 'local'.",
42
47
  "advanced": true
48
+ },
49
+ "embedding.openaiCompat.model": {
50
+ "label": "OpenAI-compat Model",
51
+ "placeholder": "text-embedding-3-small",
52
+ "help": "Model name passed in the embeddings request body. Only used when provider is 'openai-compat'."
53
+ },
54
+ "embedding.openaiCompat.baseURL": {
55
+ "label": "OpenAI-compat Base URL",
56
+ "placeholder": "https://api.openai.com/v1",
57
+ "help": "Endpoint base. The OPENAI_BASE_URL env var overrides this if set. Only used when provider is 'openai-compat'."
58
+ },
59
+ "embedding.openaiCompat.apiKeyEnv": {
60
+ "label": "API Key Env Var",
61
+ "placeholder": "OPENAI_API_KEY",
62
+ "help": "Name of the env var holding the API key (the secret stays out of config files). Only used when provider is 'openai-compat'."
43
63
  }
44
64
  },
45
65
  "configSchema": {
@@ -61,8 +81,18 @@
61
81
  "type": "object",
62
82
  "additionalProperties": false,
63
83
  "properties": {
84
+ "provider": { "type": "string", "enum": ["local", "openai-compat"] },
85
+ "dimensions": { "type": "number" },
64
86
  "modelPath": { "type": "string" },
65
- "dimensions": { "type": "number" }
87
+ "openaiCompat": {
88
+ "type": "object",
89
+ "additionalProperties": false,
90
+ "properties": {
91
+ "model": { "type": "string" },
92
+ "baseURL": { "type": "string" },
93
+ "apiKeyEnv": { "type": "string" }
94
+ }
95
+ }
66
96
  }
67
97
  }
68
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kongbrain",
3
- "version": "0.4.4",
3
+ "version": "0.5.1",
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",
@@ -24,6 +24,9 @@
24
24
  "knowledge-graph",
25
25
  "llm"
26
26
  ],
27
+ "bin": {
28
+ "kongbrain-reembed": "./bin/kongbrain-reembed.ts"
29
+ },
27
30
  "openclaw": {
28
31
  "extensions": [
29
32
  "./src/index.ts"
package/src/causal.ts CHANGED
@@ -127,9 +127,12 @@ export async function queryCausalContext(
127
127
  const seen = new Set<string>(validIds);
128
128
  let frontier = validIds;
129
129
  const results: VectorSearchResult[] = [];
130
- const bindings = { vec: queryVec };
130
+ // Score only against rows in the active provider's vector space; rows from
131
+ // other providers still appear via graph traversal but score 0.
132
+ const bindings = { vec: queryVec, provider: store.getActiveProvider() };
131
133
 
132
134
  const scoreExpr = `, IF embedding != NONE AND array::len(embedding) > 0
135
+ AND embedding_provider = $provider
133
136
  THEN vector::similarity::cosine(embedding, $vec)
134
137
  ELSE 0 END AS score`;
135
138
 
@@ -146,6 +146,7 @@ export async function seedCognitiveBootstrap(
146
146
  chunk_index: i,
147
147
  text: chunk.text,
148
148
  embedding: vec,
149
+ embedding_provider: embeddings.providerId,
149
150
  importance: chunk.importance,
150
151
  },
151
152
  });
@@ -108,9 +108,10 @@ export async function linkToRelevantConcepts(
108
108
  `SELECT id, vector::similarity::cosine(embedding, $vec) AS score
109
109
  FROM concept
110
110
  WHERE embedding != NONE AND array::len(embedding) > 0
111
+ AND embedding_provider = $provider
111
112
  ORDER BY score DESC
112
113
  LIMIT $lim`,
113
- { vec, lim: limit },
114
+ { vec, lim: limit, provider: embeddings.providerId },
114
115
  );
115
116
  for (const m of matches) {
116
117
  if (m.score < threshold) break;
@@ -175,9 +176,10 @@ export async function linkConceptHierarchy(
175
176
  FROM concept
176
177
  WHERE id != $cid
177
178
  AND embedding != NONE AND array::len(embedding) > 0
179
+ AND embedding_provider = $provider
178
180
  ORDER BY score DESC
179
181
  LIMIT 3`,
180
- { vec: conceptEmb, cid: conceptId },
182
+ { vec: conceptEmb, cid: conceptId, provider: embeddings.providerId },
181
183
  );
182
184
  for (const s of similar) {
183
185
  if (s.score < 0.75) break;