@synapcores/openclaw-memory 0.3.0 → 0.5.0
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 +41 -22
- package/dist/config.d.ts +0 -17
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -40
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +54 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +703 -283
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +1 -26
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
# @synapcores/openclaw-memory
|
|
2
2
|
|
|
3
|
-
A long-term memory plugin for [OpenClaw](https://github.com/openclaw/openclaw) that uses **SynapCores AIDB** as the storage backend. Drop-in alternative to `@openclaw/memory-lancedb` with the same auto-recall / auto-capture lifecycle, plus
|
|
3
|
+
A long-term memory plugin for [OpenClaw](https://github.com/openclaw/openclaw) that uses **SynapCores AIDB** as the storage backend. Drop-in alternative to `@openclaw/memory-lancedb` with the same auto-recall / auto-capture lifecycle, plus four SynapCores-only extensions: SQL-filtered semantic recall, graph-relation walks, AutoML relevance scoring, and a model-training helper.
|
|
4
4
|
|
|
5
|
-
> **0.
|
|
5
|
+
> **0.5.0 shipping note:** the core memory ops (`memory_store` / `memory_recall` / `memory_forget`) ride the engine-side `MEMORY_STORE` / `MEMORY_RECALL` / `MEMORY_FORGET` primitives via `@synapcores/sdk@^0.6.0`'s `client.memory` surface. The plugin's public API (tools, CLI, extensions, types) is unchanged.
|
|
6
6
|
>
|
|
7
|
-
> -
|
|
8
|
-
> -
|
|
9
|
-
> -
|
|
7
|
+
> - **Requires SynapCores gateway `v1.8.5-ce` or newer** (the version that ships the `MEMORY_*` SQL functions).
|
|
8
|
+
> - **Fully engine-native embeddings — zero external-LLM dependency.** The `memory_store` / `memory_recall` hot path embeds server-side inside the engine's `MEMORY_STORE` / `MEMORY_RECALL` primitives; the relevance extensions (`predictRelevance` / `trainRelevanceModel`) and the `autoLinkSimilar` graph-node embedding call the gateway's native `client.embed()`. All embeddings come from the SynapCores gateway (embedding dimension is the gateway model's, e.g. 384 for `all-minilm`). OpenAI has been removed entirely — no OpenAI key, no `openai` dependency.
|
|
9
|
+
> - **Migration from 0.3.x: the engine-managed table is `_memory_<namespace>`, a different storage backend from the v0.3.x vector collection. Existing v0.3.x memories WILL NOT appear after upgrade — re-capture them.** See "Upgrading from 0.3.x" below.
|
|
10
|
+
> - **`collection` config field becomes the engine `namespace`.** It must now match `^[A-Za-z_][A-Za-z0-9_]*$`. The default `openclaw_memories` continues to work; other custom values with hyphens or other non-identifier characters need updating.
|
|
11
|
+
> - **`recallFiltered` WHERE clauses are applied client-side.** The engine cannot apply a `WHERE` to the table-valued `MEMORY_RECALL(?, ?, ?)` result-set (it drops every row), so the plugin fetches an oversampled, unfiltered recall and evaluates the predicate in JS. Legacy column shorthands (`category`, `importance`, `createdAt`, `text`) and the JSON-extract form (`metadata->>'…'`) are both understood directly — no rewriting required.
|
|
12
|
+
|
|
13
|
+
## Upgrading from 0.3.x
|
|
14
|
+
|
|
15
|
+
`@synapcores/openclaw-memory@0.5.0` is a **hard cut** from 0.3.x: the storage backend changed (at 0.4.0), so old memories will not migrate automatically. Steps:
|
|
16
|
+
|
|
17
|
+
1. Upgrade the SynapCores gateway to `v1.8.5-ce` or newer.
|
|
18
|
+
2. `npm install @synapcores/openclaw-memory@0.5.0`.
|
|
19
|
+
3. If your `collection` config value contains hyphens or other non-identifier characters, rename it to match `^[A-Za-z_][A-Za-z0-9_]*$` before restarting.
|
|
20
|
+
4. (Optional) export any high-value memories from the v0.3.x vector collection (the legacy `openclaw_memories` collection in your gateway) and re-store them via `memory_store` so they land in the new `_memory_<namespace>` table.
|
|
21
|
+
5. (Optional) drop the old vector collection from the gateway once you're sure the export is done.
|
|
22
|
+
|
|
23
|
+
If your `recallFiltered` callers use plain column names (`category`, `importance`, `createdAt`, `text`), they continue to work — the client-side filter understands those column names directly. Callers filtering on arbitrary metadata keys use the JSON-extract form (`metadata->>'…'`).
|
|
10
24
|
|
|
11
25
|
## Why use this over `@openclaw/memory-lancedb`?
|
|
12
26
|
|
|
@@ -68,10 +82,6 @@ typically `~/.openclaw/openclaw.json`). Three things matter: the
|
|
|
68
82
|
"memory-synapcores": {
|
|
69
83
|
"enabled": true,
|
|
70
84
|
"config": {
|
|
71
|
-
"embedding": {
|
|
72
|
-
"apiKey": "${OPENAI_API_KEY}",
|
|
73
|
-
"model": "text-embedding-3-small"
|
|
74
|
-
},
|
|
75
85
|
"synapcores": {
|
|
76
86
|
"host": "localhost",
|
|
77
87
|
"port": 8080,
|
|
@@ -96,7 +106,7 @@ typically `~/.openclaw/openclaw.json`). Three things matter: the
|
|
|
96
106
|
> **disabled**.
|
|
97
107
|
|
|
98
108
|
Then `openclaw config validate`. Environment-variable interpolation
|
|
99
|
-
(`${
|
|
109
|
+
(`${SYNAPCORES_API_KEY}`) is supported in any string field
|
|
100
110
|
so you don't have to commit secrets. (Store keys **clean** — a trailing newline
|
|
101
111
|
in `apiKey` will break auth.)
|
|
102
112
|
|
|
@@ -104,8 +114,6 @@ in `apiKey` will break auth.)
|
|
|
104
114
|
|
|
105
115
|
| Field | Required | Default | Notes |
|
|
106
116
|
| --- | --- | --- | --- |
|
|
107
|
-
| `embedding.apiKey` | yes | — | OpenAI API key for the embedding model. |
|
|
108
|
-
| `embedding.model` | no | `text-embedding-3-small` | Either `text-embedding-3-small` (1536 dims) or `text-embedding-3-large` (3072 dims). |
|
|
109
117
|
| `synapcores.apiKey` | yes | — | SynapCores API key (`ak_prod_…` or `aidb_…`). |
|
|
110
118
|
| `synapcores.host` | no | `localhost` | SynapCores gateway hostname. |
|
|
111
119
|
| `synapcores.port` | no | `8080` | SynapCores gateway port. |
|
|
@@ -114,7 +122,7 @@ in `apiKey` will break auth.)
|
|
|
114
122
|
| `graph` | no | `openclaw_memory_graph` | SynapCores graph name (used for `SIMILAR_TO` edges and `recallRelated` walks). |
|
|
115
123
|
| `autoCapture` | no | `true` | Auto-store memorable utterances after each agent turn. |
|
|
116
124
|
| `autoRecall` | no | `true` | Auto-inject relevant memories before each agent turn. |
|
|
117
|
-
| `autoLinkSimilar` | no | `true` | On capture, insert each Memory as a graph node carrying the embedding so `recallRelated` returns useful neighborhoods out of the box. Adds ~30-
|
|
125
|
+
| `autoLinkSimilar` | no | `true` | On capture, insert each Memory as a graph node carrying the embedding so `recallRelated` returns useful neighborhoods out of the box. Adds ~30-50ms per capture; disable if you never call `recallRelated`. |
|
|
118
126
|
| `workspace` | no | — | Optional workspace suffix on the AutoML relevance model name so multiple installations sharing one gateway can train independent models. |
|
|
119
127
|
|
|
120
128
|
## What you get
|
|
@@ -135,7 +143,7 @@ Once registered, the plugin:
|
|
|
135
143
|
| --- | --- |
|
|
136
144
|
| `memory_recall` | Vector-search the memory store. Params: `{ query: string, limit?: number }` (default 5). |
|
|
137
145
|
| `memory_store` | Persist a new memory. Params: `{ text, importance?, category? }`. De-dupes against >0.95 cosine similarity. |
|
|
138
|
-
| `memory_forget` | Delete a memory by `memoryId` (
|
|
146
|
+
| `memory_forget` | Delete a memory by `memoryId` (engine-assigned id, e.g. `mem_…`) or by `query` (auto-deletes if exactly one candidate at >0.9 similarity, otherwise returns candidates). |
|
|
139
147
|
|
|
140
148
|
### Extensions (programmatic, SynapCores-only)
|
|
141
149
|
|
|
@@ -152,8 +160,10 @@ interface MemorySynapCoresExtensions {
|
|
|
152
160
|
|
|
153
161
|
/** Walk SIMILAR_TO / MENTIONS / RELATES_TO edges from a memory. */
|
|
154
162
|
recallRelated(memoryId: string, opts?: {
|
|
155
|
-
hops?: number;
|
|
156
|
-
edgeKinds?: string[];
|
|
163
|
+
hops?: number; // default 1 (capped at 4)
|
|
164
|
+
edgeKinds?: string[]; // default: ["SIMILAR_TO"]
|
|
165
|
+
similarityThreshold?: number; // default 0.5 (synthetic SIMILAR_TO edges only)
|
|
166
|
+
limit?: number; // default 20
|
|
157
167
|
}): Promise<RelatedMemoryResult[]>;
|
|
158
168
|
|
|
159
169
|
/** Score candidates with an AutoML model (with heuristic fallback). */
|
|
@@ -178,7 +188,16 @@ const results = await plugin.extensions.recallFiltered({
|
|
|
178
188
|
});
|
|
179
189
|
```
|
|
180
190
|
|
|
181
|
-
|
|
191
|
+
Because the engine cannot apply a `WHERE` to the table-valued `MEMORY_RECALL(?, ?, ?)` result-set, the plugin runs an oversampled unfiltered recall and evaluates the `where` predicate **client-side in JS**. A malformed clause surfaces as a descriptive `recallFiltered: …` error thrown by the plugin (not an engine error).
|
|
192
|
+
|
|
193
|
+
Supported `where` surface (parsed by the plugin's predicate compiler):
|
|
194
|
+
|
|
195
|
+
- **Fields:** `category`, `importance`, `createdAt`, `text` / `content`, `id`, `similarity` / `score`, and JSON-extract `metadata->>'key'` for any other metadata field.
|
|
196
|
+
- **Comparison operators:** `=` / `==`, `!=` / `<>`, `>`, `>=`, `<`, `<=`, `LIKE` (SQL `%` / `_` wildcards), and `IN (…)`.
|
|
197
|
+
- **Boolean combinators:** `AND`, `OR`, `NOT`, and parentheses.
|
|
198
|
+
- **Literals:** single-quoted strings, numbers, `TRUE` / `FALSE` / `NULL`.
|
|
199
|
+
|
|
200
|
+
An empty clause or `1=1` passes all rows. Anything outside this surface (subqueries, functions, joins) throws rather than silently returning wrong rows.
|
|
182
201
|
|
|
183
202
|
#### `recallRelated` — graph neighborhood walk
|
|
184
203
|
|
|
@@ -206,8 +225,8 @@ ranked.sort((a, b) => b.relevance - a.relevance);
|
|
|
206
225
|
When a model named `openclaw_memory_relevance[_<workspace>]` exists, candidates are scored by it. Otherwise the plugin falls back to:
|
|
207
226
|
|
|
208
227
|
```
|
|
209
|
-
relevance = 0.6 * cosine_similarity(query, memory)
|
|
210
|
-
+ 0.25 * exp(-age_days / 14)
|
|
228
|
+
relevance = 0.6 * (cosine_similarity(query, memory) + 1) / 2 # cosine mapped [-1,1] -> [0,1]
|
|
229
|
+
+ 0.25 * exp(-age_days / 14) # ~14-day recency decay
|
|
211
230
|
+ 0.15 * memory.importance
|
|
212
231
|
```
|
|
213
232
|
|
|
@@ -225,14 +244,14 @@ await plugin.extensions.trainRelevanceModel(feedback);
|
|
|
225
244
|
|
|
226
245
|
Requires at least 10 samples; throws otherwise. Train periodically (cron / on-demand) — the next `predictRelevance` call will detect the model and switch out of heuristic mode.
|
|
227
246
|
|
|
228
|
-
Under the hood,
|
|
247
|
+
Under the hood, the plugin stages feedback rows in a SQL table (`openclaw_memory_relevance_training[_<workspace>]`) on the gateway, then calls `/v1/automl/train` with `target: 'score'` and `task: 'regression'`. The table is preserved across calls so feedback accumulates between sessions; clear it manually with `DROP TABLE` (via `client.executeQuery`) if you want a clean restart. Memory hydration is via `MEMORY_RECALL(?, ?, ?) WHERE id = ?` against the engine's namespace; rows whose memories have been deleted are skipped.
|
|
229
248
|
|
|
230
|
-
## Roadmap
|
|
249
|
+
## Roadmap
|
|
231
250
|
|
|
232
251
|
- **Entity extraction on capture** — parse `@mention` tokens and known-contact names out of incoming text and create `Person` / `Project` graph nodes with `MENTIONS` edges back to the memory.
|
|
233
252
|
- **Tag inference** — auto-classify memories into a configurable tag vocabulary on capture (small classifier or LLM call) so `recallFiltered` queries can use tags out of the box.
|
|
234
253
|
- **`synapcores-import-lancedb` migration script** — read an existing `~/.openclaw/memory/lancedb` store, re-embed if needed, and bulk-load into a SynapCores collection. Ships as a `bin` entry on the package.
|
|
235
|
-
- **Drop the `_getHttpClient` graph-node
|
|
254
|
+
- **Drop the `_getHttpClient` graph-node / graph-match workarounds** once the SDK restores a native graph API: `client.graph.nodes.create` needs to post `{labels: [label]}` (not `{label}`) to match the gateway's `/v1/graph/nodes` handler, and `recallRelated` currently posts Cypher to `/v1/graph/match` directly because `@synapcores/sdk@^0.6.0` no longer exposes `client.graph.cypher`.
|
|
236
255
|
|
|
237
256
|
## Upstream
|
|
238
257
|
|
package/dist/config.d.ts
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
export type MemoryConfig = {
|
|
2
|
-
embedding: {
|
|
3
|
-
provider: "openai";
|
|
4
|
-
model?: string;
|
|
5
|
-
apiKey: string;
|
|
6
|
-
};
|
|
7
2
|
synapcores: {
|
|
8
3
|
host: string;
|
|
9
4
|
port: number;
|
|
@@ -33,21 +28,9 @@ export type MemoryConfig = {
|
|
|
33
28
|
};
|
|
34
29
|
export declare const MEMORY_CATEGORIES: readonly ["preference", "fact", "decision", "entity", "other"];
|
|
35
30
|
export type MemoryCategory = (typeof MEMORY_CATEGORIES)[number];
|
|
36
|
-
export declare function vectorDimsForModel(model: string): number;
|
|
37
31
|
export declare const memoryConfigSchema: {
|
|
38
32
|
parse(value: unknown): MemoryConfig;
|
|
39
33
|
uiHints: {
|
|
40
|
-
"embedding.apiKey": {
|
|
41
|
-
label: string;
|
|
42
|
-
sensitive: boolean;
|
|
43
|
-
placeholder: string;
|
|
44
|
-
help: string;
|
|
45
|
-
};
|
|
46
|
-
"embedding.model": {
|
|
47
|
-
label: string;
|
|
48
|
-
placeholder: string;
|
|
49
|
-
help: string;
|
|
50
|
-
};
|
|
51
34
|
"synapcores.host": {
|
|
52
35
|
label: string;
|
|
53
36
|
placeholder: string;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../config.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../config.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,iBAAiB,gEAAiE,CAAC;AAChG,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAmChE,eAAO,MAAM,kBAAkB;iBAChB,OAAO,GAAG,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwGpC,CAAC"}
|
package/dist/config.js
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
export const MEMORY_CATEGORIES = ["preference", "fact", "decision", "entity", "other"];
|
|
2
|
-
const DEFAULT_MODEL = "text-embedding-3-small";
|
|
3
2
|
const DEFAULT_HOST = "localhost";
|
|
4
3
|
const DEFAULT_PORT = 8080;
|
|
5
4
|
const DEFAULT_COLLECTION = "openclaw_memories";
|
|
6
5
|
const DEFAULT_GRAPH = "openclaw_memory_graph";
|
|
7
|
-
const EMBEDDING_DIMENSIONS = {
|
|
8
|
-
"text-embedding-3-small": 1536,
|
|
9
|
-
"text-embedding-3-large": 3072,
|
|
10
|
-
};
|
|
11
6
|
function assertAllowedKeys(value, allowed, label) {
|
|
12
7
|
const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
|
|
13
8
|
if (unknown.length === 0) {
|
|
@@ -15,13 +10,6 @@ function assertAllowedKeys(value, allowed, label) {
|
|
|
15
10
|
}
|
|
16
11
|
throw new Error(`${label} has unknown keys: ${unknown.join(", ")}`);
|
|
17
12
|
}
|
|
18
|
-
export function vectorDimsForModel(model) {
|
|
19
|
-
const dims = EMBEDDING_DIMENSIONS[model];
|
|
20
|
-
if (!dims) {
|
|
21
|
-
throw new Error(`Unsupported embedding model: ${model}`);
|
|
22
|
-
}
|
|
23
|
-
return dims;
|
|
24
|
-
}
|
|
25
13
|
function resolveEnvVars(value) {
|
|
26
14
|
return value.replace(/\$\{([^}]+)\}/g, (_, envVar) => {
|
|
27
15
|
const envValue = process.env[envVar];
|
|
@@ -31,11 +19,6 @@ function resolveEnvVars(value) {
|
|
|
31
19
|
return envValue;
|
|
32
20
|
});
|
|
33
21
|
}
|
|
34
|
-
function resolveEmbeddingModel(embedding) {
|
|
35
|
-
const model = typeof embedding.model === "string" ? embedding.model : DEFAULT_MODEL;
|
|
36
|
-
vectorDimsForModel(model);
|
|
37
|
-
return model;
|
|
38
|
-
}
|
|
39
22
|
function parsePort(value) {
|
|
40
23
|
if (value === undefined) {
|
|
41
24
|
return DEFAULT_PORT;
|
|
@@ -52,7 +35,6 @@ export const memoryConfigSchema = {
|
|
|
52
35
|
}
|
|
53
36
|
const cfg = value;
|
|
54
37
|
assertAllowedKeys(cfg, [
|
|
55
|
-
"embedding",
|
|
56
38
|
"synapcores",
|
|
57
39
|
"collection",
|
|
58
40
|
"graph",
|
|
@@ -61,12 +43,6 @@ export const memoryConfigSchema = {
|
|
|
61
43
|
"autoLinkSimilar",
|
|
62
44
|
"workspace",
|
|
63
45
|
], "memory config");
|
|
64
|
-
const embedding = cfg.embedding;
|
|
65
|
-
if (!embedding || typeof embedding.apiKey !== "string") {
|
|
66
|
-
throw new Error("embedding.apiKey is required");
|
|
67
|
-
}
|
|
68
|
-
assertAllowedKeys(embedding, ["apiKey", "model"], "embedding config");
|
|
69
|
-
const model = resolveEmbeddingModel(embedding);
|
|
70
46
|
const synapcores = cfg.synapcores;
|
|
71
47
|
if (!synapcores || typeof synapcores.apiKey !== "string") {
|
|
72
48
|
throw new Error("synapcores.apiKey is required");
|
|
@@ -78,11 +54,6 @@ export const memoryConfigSchema = {
|
|
|
78
54
|
const port = parsePort(synapcores.port);
|
|
79
55
|
const useHttps = synapcores.useHttps === true;
|
|
80
56
|
return {
|
|
81
|
-
embedding: {
|
|
82
|
-
provider: "openai",
|
|
83
|
-
model,
|
|
84
|
-
apiKey: resolveEnvVars(embedding.apiKey),
|
|
85
|
-
},
|
|
86
57
|
synapcores: {
|
|
87
58
|
host,
|
|
88
59
|
port,
|
|
@@ -98,17 +69,6 @@ export const memoryConfigSchema = {
|
|
|
98
69
|
};
|
|
99
70
|
},
|
|
100
71
|
uiHints: {
|
|
101
|
-
"embedding.apiKey": {
|
|
102
|
-
label: "OpenAI API Key",
|
|
103
|
-
sensitive: true,
|
|
104
|
-
placeholder: "sk-proj-...",
|
|
105
|
-
help: "API key for OpenAI embeddings (or use ${OPENAI_API_KEY})",
|
|
106
|
-
},
|
|
107
|
-
"embedding.model": {
|
|
108
|
-
label: "Embedding Model",
|
|
109
|
-
placeholder: DEFAULT_MODEL,
|
|
110
|
-
help: "OpenAI embedding model to use",
|
|
111
|
-
},
|
|
112
72
|
"synapcores.host": {
|
|
113
73
|
label: "SynapCores Host",
|
|
114
74
|
placeholder: DEFAULT_HOST,
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,19 +2,30 @@
|
|
|
2
2
|
* OpenClaw Memory (SynapCores) Plugin
|
|
3
3
|
*
|
|
4
4
|
* Long-term memory with vector search for AI conversations.
|
|
5
|
-
* Uses SynapCores AIDB for storage
|
|
5
|
+
* Uses SynapCores AIDB for storage via the engine-side
|
|
6
|
+
* `MEMORY_STORE` / `MEMORY_RECALL` / `MEMORY_FORGET` primitives, and the
|
|
7
|
+
* engine-native `client.embed()` for the relevance-extension features that
|
|
8
|
+
* need a client-side embedding (cosine feature in `predictRelevance`,
|
|
9
|
+
* graph-node embedding when `autoLinkSimilar` is on). No external
|
|
10
|
+
* embedding provider is required.
|
|
11
|
+
*
|
|
6
12
|
* Provides seamless auto-recall and auto-capture via lifecycle hooks,
|
|
7
|
-
* plus
|
|
8
|
-
* walks,
|
|
9
|
-
* `recallRelated`,
|
|
13
|
+
* plus four SynapCores-only extensions (SQL-filtered recall, graph-relation
|
|
14
|
+
* walks, AutoML relevance scoring, and a model-training helper) — see
|
|
15
|
+
* `recallFiltered`, `recallRelated`, `predictRelevance`, and
|
|
16
|
+
* `trainRelevanceModel`.
|
|
10
17
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* gateway v1.6.5.2-ce. Requires @synapcores/sdk@^0.4.0 — which added
|
|
14
|
-
* `client.vectorCollection(name)` + `client.createVectorCollection(...)`
|
|
15
|
-
* and switched API-key auth to `Authorization: Bearer`.
|
|
18
|
+
* v0.4.0 migrates the core memory ops to `@synapcores/sdk@^0.5.0`'s
|
|
19
|
+
* `client.memory` surface. Requires SynapCores gateway v1.8.5-ce+.
|
|
16
20
|
*/
|
|
17
21
|
import { type MemoryCategory } from "./config.js";
|
|
22
|
+
/**
|
|
23
|
+
* Internal memory record shape used throughout the plugin. The legacy v0.3.x
|
|
24
|
+
* surface guaranteed `vector: number[]` on every entry because storage went
|
|
25
|
+
* through `client.vectorCollection(...)`. v0.4.0's `client.memory.recall`
|
|
26
|
+
* does not return embeddings — `vector` is filled lazily by callers that
|
|
27
|
+
* need it (currently only `predictRelevance` / `trainRelevanceModel`).
|
|
28
|
+
*/
|
|
18
29
|
export type MemoryEntry = {
|
|
19
30
|
id: string;
|
|
20
31
|
text: string;
|
|
@@ -33,9 +44,21 @@ export type MemorySearchResult = {
|
|
|
33
44
|
* importance thresholds, category equality, etc.).
|
|
34
45
|
*/
|
|
35
46
|
export type RecallFilteredOptions = {
|
|
36
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* SQL fragment applied as the search filter.
|
|
49
|
+
*
|
|
50
|
+
* v0.4.0 note: the WHERE clause is now evaluated against the columns
|
|
51
|
+
* returned by `MEMORY_RECALL(?, ?, ?)` — `id`, `content`, `similarity`,
|
|
52
|
+
* `metadata`, `created_at`. The legacy v0.3.x `category = 'preference'`
|
|
53
|
+
* shorthand still works for callers that wrote category/importance into
|
|
54
|
+
* the metadata blob (the plugin always does so) BUT the path is now
|
|
55
|
+
* engine-side JSON access: `metadata->>'category' = 'preference'` is the
|
|
56
|
+
* portable form. The plugin auto-rewrites a handful of the legacy
|
|
57
|
+
* shorthands (`category`, `importance`, `createdAt`, `text`) into the
|
|
58
|
+
* JSON-extract form so most existing callers keep working unchanged.
|
|
59
|
+
*/
|
|
37
60
|
where: string;
|
|
38
|
-
/** Natural-language query that gets embedded and used as the search vector. */
|
|
61
|
+
/** Natural-language query that gets embedded engine-side and used as the search vector. */
|
|
39
62
|
semantic: string;
|
|
40
63
|
/** Maximum results to return (default: 5). */
|
|
41
64
|
limit?: number;
|
|
@@ -96,11 +119,12 @@ export type RelevanceFeedback = {
|
|
|
96
119
|
/**
|
|
97
120
|
* Escape a string literal for safe inlining into a Cypher query.
|
|
98
121
|
*
|
|
99
|
-
* Gateway v1.6.5.2
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
* safe, BUT we never trust
|
|
103
|
-
* inside `'...'` in a Cypher
|
|
122
|
+
* Gateway v1.6.5.2+ rejects named-parameter bindings (`$param`) with HTTP
|
|
123
|
+
* 400; the supported path is to inline literal values into the query
|
|
124
|
+
* string. Memory IDs flow in from `MEMORY_STORE` (engine-generated, e.g.
|
|
125
|
+
* `mem_1kv69sxfn_5ofzwK`) so they are normally safe, BUT we never trust
|
|
126
|
+
* upstream input — every string that ends up inside `'...'` in a Cypher
|
|
127
|
+
* fragment must go through this helper.
|
|
104
128
|
*
|
|
105
129
|
* Escapes single quotes (`'` -> `\'`) and backslashes (`\` -> `\\`).
|
|
106
130
|
* Returns the inner content only; callers are responsible for the
|
|
@@ -113,9 +137,8 @@ export declare function escapeCypherString(value: string): string;
|
|
|
113
137
|
* them through the OpenClaw plugin registry.
|
|
114
138
|
*
|
|
115
139
|
* The four SynapCores-only methods use:
|
|
116
|
-
* - `
|
|
117
|
-
*
|
|
118
|
-
* `filter: { sql: where }`.
|
|
140
|
+
* - `client.executeQuery(...)` against MEMORY_RECALL for `recallFiltered`,
|
|
141
|
+
* wrapping the user's WHERE clause around the engine's recall result-set.
|
|
119
142
|
* - `client.graph.cypher(...)` for `recallRelated`, walking the synthetic
|
|
120
143
|
* `SIMILAR_TO` edges that resolve against `Memory.embedding`.
|
|
121
144
|
* - `client.automl.getModel(...).predict(...)` for `predictRelevance`, with
|
|
@@ -130,7 +153,7 @@ export interface MemorySynapCoresExtensions {
|
|
|
130
153
|
*
|
|
131
154
|
* @example
|
|
132
155
|
* await ext.recallFiltered({
|
|
133
|
-
* where: "category = 'preference' AND importance >= 0.7
|
|
156
|
+
* where: "category = 'preference' AND importance >= 0.7",
|
|
134
157
|
* semantic: "what kind of UI does the user prefer?",
|
|
135
158
|
* limit: 5,
|
|
136
159
|
* });
|
|
@@ -140,13 +163,13 @@ export interface MemorySynapCoresExtensions {
|
|
|
140
163
|
* Graph walk from a memory through `SIMILAR_TO` / `MENTIONS` / `RELATES_TO`
|
|
141
164
|
* edges, returning the neighborhood.
|
|
142
165
|
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
166
|
+
* Wires against the gateway's synthetic-SIMILAR_TO Cypher syntax
|
|
167
|
+
* (`[:SIMILAR_TO > T]`) which resolves against the `embedding` property
|
|
168
|
+
* the plugin writes onto every captured Memory node. If a source memory
|
|
169
|
+
* has not been promoted to a graph node yet (e.g. `autoLinkSimilar:
|
|
170
|
+
* false`), this returns an empty array.
|
|
148
171
|
*
|
|
149
|
-
* @param memoryId -
|
|
172
|
+
* @param memoryId - id of the source memory (engine-assigned, e.g. `mem_...`).
|
|
150
173
|
* @param options - Hops, edge-kind filter, similarity threshold, limit.
|
|
151
174
|
*/
|
|
152
175
|
recallRelated(memoryId: string, options?: RecallRelatedOptions): Promise<RelatedMemoryResult[]>;
|
|
@@ -171,12 +194,12 @@ export interface MemorySynapCoresExtensions {
|
|
|
171
194
|
/**
|
|
172
195
|
* Train (or retrain) the AutoML model used by `predictRelevance`.
|
|
173
196
|
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
197
|
+
* Wires against the staged-collection workflow: feedback rows are
|
|
198
|
+
* inserted into a SQL table the gateway's AutoML can read via
|
|
199
|
+
* `SELECT * FROM {table}`, then `/v1/automl/train` is invoked with
|
|
177
200
|
* `target: 'score'` to fit a regression model. Existing training data
|
|
178
|
-
* in the staging table is preserved across calls so feedback
|
|
179
|
-
*
|
|
201
|
+
* in the staging table is preserved across calls so feedback accumulates
|
|
202
|
+
* across sessions.
|
|
180
203
|
*
|
|
181
204
|
* @param feedback - Array of `{ memoryId, queryText, score }` samples.
|
|
182
205
|
* Requires at least {@link MIN_TRAINING_SAMPLES} samples;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAQH,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,aAAa,CAAC;AAMrB;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;;;;;;;;;OAYG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,2FAA2F;IAC3F,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,uFAAuF;IACvF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,EAAE,CAAC;CACf,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,WAAW,CAAC;IACnB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAg4BF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAuGD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;;;;;;OASG;IACH,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAE9E;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAEhG;;;;;;;;;;;;;;;;OAgBG;IACH,gBAAgB,CACd,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,WAAW,EAAE,GACxB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAEpC;;;;;;;;;;;;;;OAcG;IACH,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrG;AAyzBD,QAAA,MAAM,WAAW;;;;;;yIAAkC,CAAC;AAEpD,eAAe,WAAW,CAAC"}
|