@amaster.ai/pi-memory-mem0 0.1.2-beta.54 → 0.1.2-beta.56
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 +50 -31
- package/dist/dedup.d.ts +1 -1
- package/dist/dedup.js +3 -3
- package/dist/dedup.js.map +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +109 -22
- package/dist/index.js.map +1 -1
- package/dist/prefetch.d.ts +19 -0
- package/dist/prefetch.d.ts.map +1 -0
- package/dist/prefetch.js +58 -0
- package/dist/prefetch.js.map +1 -0
- package/dist/privacy.d.ts +2 -1
- package/dist/privacy.d.ts.map +1 -1
- package/dist/privacy.js +3 -1
- package/dist/privacy.js.map +1 -1
- package/dist/provider.d.ts +12 -5
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +171 -42
- package/dist/provider.js.map +1 -1
- package/dist/types.d.ts +10 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/tools.d.ts +0 -15
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js +0 -108
- package/dist/tools.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,22 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Passive semantic memory extension powered by [Mem0](https://mem0.ai), with Platform, embedded, and self-hosted modes.
|
|
6
6
|
|
|
7
7
|
## How It Works
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
After each conversation turn, the user + assistant messages are automatically sent to Mem0 for fact extraction and storage. When you send a prompt, a semantic search is prefetched in the background and relevant memories are recalled before the agent starts — **zero effort required**.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Safety boundaries:
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
- **Recall channel**: recalled memories are injected as a custom message delivered on the user channel — never into the system prompt. Each entry is wrapped as `[UNTRUSTED MEMORY DATA]` (JSON-quoted), and entries matching prompt-injection patterns are replaced with `[BLOCKED UNTRUSTED MEMORY: ...]`.
|
|
14
|
+
- **Project namespacing**: memories are scoped to `userId:project:<cwd-hash>` by default, so one project's memories are not visible in another. Set `userIdScope: "exact"` when one identity must be shared across projects.
|
|
15
|
+
- **Credential redaction**: private keys, bearer tokens, and `api_key=…`-style values are redacted before anything is stored.
|
|
16
|
+
- **Platform mode disclosure**: in `platform` mode the captured turns leave your machine and are processed by Mem0 Cloud. Use `embedded` or `self-hosted` mode to keep memory traffic off third-party infrastructure.
|
|
17
|
+
|
|
18
|
+
## Modes
|
|
14
19
|
|
|
15
20
|
| Mode | Vector Store | Persistence | Dependencies | Use Case |
|
|
16
21
|
|------|-------------|-------------|--------------|----------|
|
|
17
22
|
| `platform` | Mem0 Cloud | Cloud-managed | `MEM0_API_KEY` | Quick start, multi-device sync |
|
|
18
|
-
| `
|
|
23
|
+
| `embedded` | Mem0 OSS vector store | Vector-store managed | LLM + Embedding API | Data privacy, no Mem0 Cloud |
|
|
24
|
+
| `self-hosted` | Mem0 OSS REST server | Server-managed | Server URL, optional API key | Shared infrastructure |
|
|
19
25
|
|
|
20
|
-
## Architecture (
|
|
26
|
+
## Architecture (Embedded Mode)
|
|
21
27
|
|
|
22
28
|
```
|
|
23
29
|
User ←→ Agent ←→ Mem0 OSS Memory
|
|
@@ -50,14 +56,14 @@ in user or agent settings.
|
|
|
50
56
|
}
|
|
51
57
|
```
|
|
52
58
|
|
|
53
|
-
###
|
|
59
|
+
### Embedded Mode (Recommended)
|
|
54
60
|
|
|
55
61
|
Reuses API keys and base URLs from pi's configured model providers — **no extra environment variables needed**.
|
|
56
62
|
|
|
57
63
|
```json
|
|
58
64
|
{
|
|
59
65
|
"pi-memory-mem0": {
|
|
60
|
-
"mode": "
|
|
66
|
+
"mode": "embedded",
|
|
61
67
|
"userId": "${USER}"
|
|
62
68
|
}
|
|
63
69
|
}
|
|
@@ -65,6 +71,24 @@ Reuses API keys and base URLs from pi's configured model providers — **no extr
|
|
|
65
71
|
|
|
66
72
|
Defaults to OpenAI `text-embedding-3-small` (embedding) + `gpt-4.1-nano` (extraction). API keys and base URLs are automatically resolved from pi's model registry.
|
|
67
73
|
|
|
74
|
+
Existing settings with `mode: "open-source"` continue to load as `embedded`, but `open-source` is not part of the supported configuration interface. New settings should use `embedded`.
|
|
75
|
+
|
|
76
|
+
### Self-Hosted Mode
|
|
77
|
+
|
|
78
|
+
Calls the OSS REST server directly. The server uses `/memories` and `/search`, not the Mem0 Platform `/v1` paths.
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"pi-memory-mem0": {
|
|
83
|
+
"mode": "self-hosted",
|
|
84
|
+
"baseUrl": "${MEM0_BASE_URL}",
|
|
85
|
+
"apiKey": "${MEM0_API_KEY}",
|
|
86
|
+
"userId": "${PAPERCLIP_COMPANY_ID}",
|
|
87
|
+
"userIdScope": "exact"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
68
92
|
### Custom Provider
|
|
69
93
|
|
|
70
94
|
When your model registry defines a custom provider with `api: "openai-completions"`, you can use it directly:
|
|
@@ -72,7 +96,7 @@ When your model registry defines a custom provider with `api: "openai-completion
|
|
|
72
96
|
```json
|
|
73
97
|
{
|
|
74
98
|
"pi-memory-mem0": {
|
|
75
|
-
"mode": "
|
|
99
|
+
"mode": "embedded",
|
|
76
100
|
"oss": {
|
|
77
101
|
"llm": {
|
|
78
102
|
"provider": "my-provider",
|
|
@@ -97,7 +121,7 @@ The extension automatically:
|
|
|
97
121
|
```json
|
|
98
122
|
{
|
|
99
123
|
"pi-memory-mem0": {
|
|
100
|
-
"mode": "
|
|
124
|
+
"mode": "embedded",
|
|
101
125
|
"userId": "${USER}",
|
|
102
126
|
"oss": {
|
|
103
127
|
"llm": {
|
|
@@ -121,7 +145,7 @@ For production workloads that need a dedicated vector database:
|
|
|
121
145
|
```json
|
|
122
146
|
{
|
|
123
147
|
"pi-memory-mem0": {
|
|
124
|
-
"mode": "
|
|
148
|
+
"mode": "embedded",
|
|
125
149
|
"oss": {
|
|
126
150
|
"vectorStore": {
|
|
127
151
|
"provider": "qdrant",
|
|
@@ -140,10 +164,12 @@ The configured vector store always owns persistence. To request an intentionally
|
|
|
140
164
|
|
|
141
165
|
| Field | Type | Default | Description |
|
|
142
166
|
|-------|------|---------|-------------|
|
|
143
|
-
| `mode` | `"platform"` \| `"
|
|
144
|
-
| `apiKey` | string | — |
|
|
145
|
-
| `baseUrl` | string | `https://api.mem0.ai` |
|
|
167
|
+
| `mode` | `"platform"` \| `"embedded"` \| `"self-hosted"` | `"platform"` | Operating mode |
|
|
168
|
+
| `apiKey` | string | — | Platform or self-hosted API key. Supports `${MEM0_API_KEY}` |
|
|
169
|
+
| `baseUrl` | string | `https://api.mem0.ai` | Platform override; required for self-hosted mode |
|
|
170
|
+
| `requestTimeoutMs` | number | `30000` | Self-hosted request timeout |
|
|
146
171
|
| `userId` | string | `$USER` or `"default-user"` | Memory scoping identifier |
|
|
172
|
+
| `userIdScope` | `"project"` \| `"exact"` | `"project"` | Append the cwd hash or use `userId` verbatim |
|
|
147
173
|
| `topK` | number | `5` | Max recalled memories per turn |
|
|
148
174
|
| `useRegistryKeys` | boolean | `true` | Whether OSS mode resolves keys from pi registry |
|
|
149
175
|
| `oss.llm` | object | OpenAI gpt-4.1-nano | OSS extraction model |
|
|
@@ -158,9 +184,10 @@ The configured vector store always owns persistence. To request an intentionally
|
|
|
158
184
|
| Mode | Vector Data | History |
|
|
159
185
|
|------|-------------|---------|
|
|
160
186
|
| Platform | Mem0 Cloud | Cloud-managed |
|
|
161
|
-
|
|
|
162
|
-
|
|
|
163
|
-
|
|
|
187
|
+
| Embedded (default paths) | `<home>/memories/mem0-vectors.db` | `<home>/memories/mem0-history.db` |
|
|
188
|
+
| Embedded (`memory`, `dbPath: ":memory:"`) | Process-local SQLite; lost on restart | `<home>/memories/mem0-history.db` |
|
|
189
|
+
| Embedded (Qdrant) | Qdrant server | `<home>/memories/mem0-history.db` |
|
|
190
|
+
| Self-hosted | Remote server | Remote server |
|
|
164
191
|
|
|
165
192
|
The `home` directory is resolved via `resolveHome()` from `@amaster.ai/pi-shared/settings` (defaults to `~/.pi/agent`).
|
|
166
193
|
|
|
@@ -179,7 +206,7 @@ This happens transparently — just configure the provider name as it appears in
|
|
|
179
206
|
|
|
180
207
|
## Installation Notes
|
|
181
208
|
|
|
182
|
-
The default
|
|
209
|
+
The default Embedded configuration depends on `better-sqlite3` (native addon, transitive dependency of `mem0ai`) for both the vector store and history. This remains true for `dbPath: ":memory:"`: it changes where SQLite stores pages, not which vector-store implementation is used.
|
|
183
210
|
|
|
184
211
|
**For pi-agent users**: pi-agent's `package.json` includes `better-sqlite3` in `pnpm.onlyBuiltDependencies` — it compiles automatically during `pnpm install`. No extra steps needed.
|
|
185
212
|
|
|
@@ -195,14 +222,6 @@ The default Open-Source mode depends on `better-sqlite3` (native addon, transiti
|
|
|
195
222
|
|
|
196
223
|
If `better-sqlite3` fails to load (for example, because of a Node ABI mismatch), the default `memory` vector store cannot start. An external vector store can still be used with history disabled or configured to a working provider.
|
|
197
224
|
|
|
198
|
-
## Tools
|
|
199
|
-
|
|
200
|
-
| Tool | Description |
|
|
201
|
-
|------|-------------|
|
|
202
|
-
| `mem0_search` | Semantic search over long-term memories |
|
|
203
|
-
| `mem0_profile` | List all stored memories |
|
|
204
|
-
| `mem0_save` | Store a fact verbatim (bypasses LLM extraction) |
|
|
205
|
-
|
|
206
225
|
## Commands
|
|
207
226
|
|
|
208
227
|
```
|
|
@@ -215,12 +234,12 @@ If `better-sqlite3` fails to load (for example, because of a Node ABI mismatch),
|
|
|
215
234
|
|
|
216
235
|
`pi-memory-mem0` and `pi-memory` run **independently in parallel** as separate extensions:
|
|
217
236
|
|
|
218
|
-
- `pi-memory`: Active memory — agent explicitly manages via tools, local `.md` files, hard char limits
|
|
219
|
-
- `pi-memory-mem0`:
|
|
237
|
+
- `pi-memory`: Active memory — the agent explicitly manages memories via tools, local `.md` files, hard char limits
|
|
238
|
+
- `pi-memory-mem0`: Passive memory — automatic extraction/storage and semantic recall, no capacity limits
|
|
220
239
|
|
|
221
|
-
They do not interfere with each other. `pi-memory-mem0`
|
|
222
|
-
|
|
223
|
-
|
|
240
|
+
They do not interfere with each other. `pi-memory-mem0` injects recalled text as a
|
|
241
|
+
custom user-channel message (never the system prompt); `pi-memory` injects its own
|
|
242
|
+
context separately.
|
|
224
243
|
|
|
225
244
|
## Dedup API
|
|
226
245
|
|
package/dist/dedup.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Normalizes content, identifies exact duplicates (case-insensitive, whitespace-collapsed),
|
|
5
5
|
* deletes the older entries, and keeps only the most recently updated.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* All modes use the provider interface. In embedded mode the configured
|
|
8
8
|
* vector store is the source of truth and its IDs remain stable across restarts.
|
|
9
9
|
*/
|
|
10
10
|
import { type ProviderResolver } from './provider.js';
|
package/dist/dedup.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Normalizes content, identifies exact duplicates (case-insensitive, whitespace-collapsed),
|
|
5
5
|
* deletes the older entries, and keeps only the most recently updated.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* All modes use the provider interface. In embedded mode the configured
|
|
8
8
|
* vector store is the source of truth and its IDs remain stable across restarts.
|
|
9
9
|
*/
|
|
10
10
|
import { createMem0Provider } from './provider.js';
|
|
@@ -14,7 +14,7 @@ export async function dedupMemories(opts) {
|
|
|
14
14
|
config,
|
|
15
15
|
...(resolveProvider ? { resolveProvider } : {}),
|
|
16
16
|
});
|
|
17
|
-
const allMemories = await provider.getAll({ userId });
|
|
17
|
+
const allMemories = await provider.getAll({ userId, ...(signal ? { signal } : {}) });
|
|
18
18
|
if (allMemories.length === 0) {
|
|
19
19
|
return { total: 0, duplicatesRemoved: 0 };
|
|
20
20
|
}
|
|
@@ -24,7 +24,7 @@ export async function dedupMemories(opts) {
|
|
|
24
24
|
if (signal?.aborted)
|
|
25
25
|
break;
|
|
26
26
|
try {
|
|
27
|
-
await provider.delete(id);
|
|
27
|
+
await (signal ? provider.delete(id, { signal }) : provider.delete(id));
|
|
28
28
|
removed++;
|
|
29
29
|
}
|
|
30
30
|
catch {
|
package/dist/dedup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dedup.js","sourceRoot":"","sources":["../src/dedup.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,kBAAkB,EAAyB,MAAM,eAAe,CAAC;AAe1E,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAkB;IACpD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAEzD,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC;QACxC,MAAM;QACN,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChD,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"dedup.js","sourceRoot":"","sources":["../src/dedup.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* pi-memory-mem0 —
|
|
2
|
+
* pi-memory-mem0 — Passive semantic memory extension powered by Mem0.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Modes:
|
|
5
5
|
* - **platform**: Uses Mem0 Cloud API (needs MEM0_API_KEY)
|
|
6
|
-
* - **
|
|
6
|
+
* - **embedded**: Runs Mem0 OSS in-process
|
|
7
|
+
* - **self-hosted**: Calls a remote Mem0 OSS REST server
|
|
8
|
+
*
|
|
9
|
+
* After each conversation turn, user + assistant messages are sent to Mem0
|
|
10
|
+
* for fact extraction and storage (credentials are redacted first). Recalled
|
|
11
|
+
* memories are injected as a custom message (delivered to the model on the
|
|
12
|
+
* user channel, never the system prompt) and wrapped as untrusted data.
|
|
7
13
|
*
|
|
8
14
|
* Configuration via settings.json key "pi-memory-mem0".
|
|
9
15
|
* Supports ${ENV_VAR:-fallback} in user and agent settings.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AA4BpE,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAqL5D"}
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* pi-memory-mem0 —
|
|
2
|
+
* pi-memory-mem0 — Passive semantic memory extension powered by Mem0.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Modes:
|
|
5
5
|
* - **platform**: Uses Mem0 Cloud API (needs MEM0_API_KEY)
|
|
6
|
-
* - **
|
|
6
|
+
* - **embedded**: Runs Mem0 OSS in-process
|
|
7
|
+
* - **self-hosted**: Calls a remote Mem0 OSS REST server
|
|
8
|
+
*
|
|
9
|
+
* After each conversation turn, user + assistant messages are sent to Mem0
|
|
10
|
+
* for fact extraction and storage (credentials are redacted first). Recalled
|
|
11
|
+
* memories are injected as a custom message (delivered to the model on the
|
|
12
|
+
* user channel, never the system prompt) and wrapped as untrusted data.
|
|
7
13
|
*
|
|
8
14
|
* Configuration via settings.json key "pi-memory-mem0".
|
|
9
15
|
* Supports ${ENV_VAR:-fallback} in user and agent settings.
|
|
10
16
|
* Trusted project settings are loaded without environment interpolation.
|
|
11
17
|
*/
|
|
12
18
|
import { isProjectTrusted, loadPiSettings } from '@amaster.ai/pi-shared/settings';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
19
|
+
import { Prefetch } from './prefetch.js';
|
|
20
|
+
import { formatRecalledMemory, redactMemoryText, scopeMemoryUserId } from './privacy.js';
|
|
21
|
+
import { createMem0Provider, normalizeMem0Mode } from './provider.js';
|
|
16
22
|
const SETTINGS_KEY = 'pi-memory-mem0';
|
|
17
23
|
const STATUS_KEY = 'mem0';
|
|
18
24
|
function loadConfig(cwd, projectTrusted = false) {
|
|
@@ -26,9 +32,11 @@ function loadConfig(cwd, projectTrusted = false) {
|
|
|
26
32
|
return {};
|
|
27
33
|
}
|
|
28
34
|
}
|
|
29
|
-
function resolveUserId(configUserId) {
|
|
35
|
+
function resolveUserId(configUserId, scope = 'project') {
|
|
30
36
|
if (configUserId?.trim())
|
|
31
37
|
return configUserId.trim();
|
|
38
|
+
if (scope === 'exact')
|
|
39
|
+
throw new Error('Mem0 exact userId resolved to an empty value.');
|
|
32
40
|
if (process.env.USER)
|
|
33
41
|
return process.env.USER;
|
|
34
42
|
if (process.env.USERNAME)
|
|
@@ -37,17 +45,22 @@ function resolveUserId(configUserId) {
|
|
|
37
45
|
}
|
|
38
46
|
export default function mem0Extension(pi) {
|
|
39
47
|
let provider;
|
|
48
|
+
let prefetch;
|
|
40
49
|
let userId = '';
|
|
50
|
+
let activeMode = '';
|
|
51
|
+
let lastUserText = '';
|
|
52
|
+
let pendingWrite = Promise.resolve();
|
|
41
53
|
pi.on('session_start', async (_event, ctx) => {
|
|
42
54
|
provider = undefined;
|
|
55
|
+
prefetch = undefined;
|
|
43
56
|
const config = loadConfig(ctx.cwd, isProjectTrusted(ctx));
|
|
44
|
-
const mode = config.mode ?? 'platform';
|
|
45
|
-
// Platform mode requires apiKey; OSS mode requires an LLM provider (env key)
|
|
46
|
-
if (mode === 'platform' && !config.apiKey?.trim()) {
|
|
47
|
-
ctx.ui.setStatus(STATUS_KEY, 'mem0: disabled (no API key)');
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
57
|
try {
|
|
58
|
+
const mode = normalizeMem0Mode(config.mode);
|
|
59
|
+
if (mode === 'platform' && !config.apiKey?.trim()) {
|
|
60
|
+
ctx.ui.setStatus(STATUS_KEY, 'mem0: disabled (no API key)');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const resolvedUserId = resolveUserId(config.userId, config.userIdScope);
|
|
51
64
|
provider = await createMem0Provider({
|
|
52
65
|
config,
|
|
53
66
|
resolveProvider: async (providerName) => {
|
|
@@ -71,18 +84,76 @@ export default function mem0Extension(pi) {
|
|
|
71
84
|
return result;
|
|
72
85
|
},
|
|
73
86
|
});
|
|
87
|
+
userId = scopeMemoryUserId(resolvedUserId, ctx.cwd, config.userIdScope);
|
|
88
|
+
activeMode = mode;
|
|
89
|
+
prefetch = new Prefetch(provider, userId, { topK: config.topK ?? 5 });
|
|
74
90
|
}
|
|
75
91
|
catch (err) {
|
|
76
92
|
ctx.ui.setStatus(STATUS_KEY, 'mem0: init failed');
|
|
77
93
|
ctx.ui.notify(`Mem0 init failed: ${err instanceof Error ? err.message : String(err)}`, 'error');
|
|
78
94
|
return;
|
|
79
95
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
96
|
+
ctx.ui.setStatus(STATUS_KEY, `mem0: ${activeMode}`);
|
|
97
|
+
});
|
|
98
|
+
pi.on('input', async (event) => {
|
|
99
|
+
if (!prefetch)
|
|
100
|
+
return;
|
|
101
|
+
const text = event.text ?? '';
|
|
102
|
+
if (text) {
|
|
103
|
+
prefetch.queue(redactMemoryText(text));
|
|
104
|
+
lastUserText = text;
|
|
84
105
|
}
|
|
85
106
|
});
|
|
107
|
+
pi.on('turn_end', async (event) => {
|
|
108
|
+
if (!provider || !lastUserText)
|
|
109
|
+
return;
|
|
110
|
+
const msg = event.message;
|
|
111
|
+
const text = extractText(msg);
|
|
112
|
+
if (!text || msg.role !== 'assistant')
|
|
113
|
+
return;
|
|
114
|
+
const userText = lastUserText;
|
|
115
|
+
lastUserText = '';
|
|
116
|
+
const activeProvider = provider;
|
|
117
|
+
const activeUserId = userId;
|
|
118
|
+
pendingWrite = pendingWrite
|
|
119
|
+
.catch(() => { })
|
|
120
|
+
.then(async () => {
|
|
121
|
+
const result = await activeProvider.add([
|
|
122
|
+
{ role: 'user', content: redactMemoryText(userText) },
|
|
123
|
+
{ role: 'assistant', content: redactMemoryText(text) },
|
|
124
|
+
], { userId: activeUserId });
|
|
125
|
+
// Extraction legitimately finds nothing in many turns, but a totally
|
|
126
|
+
// silent no-op makes a broken pipeline indistinguishable from a quiet
|
|
127
|
+
// one — gate a diagnostic behind DEBUG.
|
|
128
|
+
if (process.env.DEBUG?.includes('pi-memory-mem0') && !result?.results?.length) {
|
|
129
|
+
console.error('[pi-memory-mem0] turn capture stored no memories (extraction empty?)');
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
.catch((err) => {
|
|
133
|
+
console.error(`[pi-memory-mem0] failed to store turn: ${err instanceof Error ? err.message : String(err)}`);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
pi.on('before_agent_start', async () => {
|
|
137
|
+
if (!prefetch)
|
|
138
|
+
return;
|
|
139
|
+
const recalled = await prefetch.consume();
|
|
140
|
+
if (!recalled)
|
|
141
|
+
return;
|
|
142
|
+
return {
|
|
143
|
+
message: {
|
|
144
|
+
customType: 'mem0-recall',
|
|
145
|
+
content: recalled,
|
|
146
|
+
display: true,
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
pi.on('session_shutdown', async () => {
|
|
151
|
+
await pendingWrite;
|
|
152
|
+
provider = undefined;
|
|
153
|
+
prefetch = undefined;
|
|
154
|
+
lastUserText = '';
|
|
155
|
+
pendingWrite = Promise.resolve();
|
|
156
|
+
});
|
|
86
157
|
pi.registerCommand('mem0', {
|
|
87
158
|
description: 'Mem0 memory commands. Subcommands: status, search <query>, profile.',
|
|
88
159
|
handler: async (args, ctx) => {
|
|
@@ -90,14 +161,12 @@ export default function mem0Extension(pi) {
|
|
|
90
161
|
ctx.ui.notify('Mem0 is not active.', 'warning');
|
|
91
162
|
return;
|
|
92
163
|
}
|
|
93
|
-
const config = loadConfig(ctx.cwd, isProjectTrusted(ctx));
|
|
94
|
-
const userId = scopeMemoryUserId(resolveUserId(config.userId), ctx.cwd);
|
|
95
164
|
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
96
165
|
const subcommand = parts[0]?.toLowerCase() ?? 'status';
|
|
97
166
|
const rest = parts.slice(1).join(' ').trim();
|
|
98
167
|
switch (subcommand) {
|
|
99
168
|
case 'status': {
|
|
100
|
-
ctx.ui.notify(`Mem0: active (mode: ${
|
|
169
|
+
ctx.ui.notify(`Mem0: active (mode: ${activeMode})`, 'info');
|
|
101
170
|
break;
|
|
102
171
|
}
|
|
103
172
|
case 'search': {
|
|
@@ -105,7 +174,11 @@ export default function mem0Extension(pi) {
|
|
|
105
174
|
ctx.ui.notify('Usage: /mem0 search <query>', 'warning');
|
|
106
175
|
break;
|
|
107
176
|
}
|
|
108
|
-
const results = await provider.search(rest, {
|
|
177
|
+
const results = await provider.search(rest, {
|
|
178
|
+
userId,
|
|
179
|
+
topK: 10,
|
|
180
|
+
...(ctx.signal ? { signal: ctx.signal } : {}),
|
|
181
|
+
});
|
|
109
182
|
if (results.length === 0) {
|
|
110
183
|
ctx.ui.notify('No relevant memories found.', 'info');
|
|
111
184
|
}
|
|
@@ -116,7 +189,10 @@ export default function mem0Extension(pi) {
|
|
|
116
189
|
break;
|
|
117
190
|
}
|
|
118
191
|
case 'profile': {
|
|
119
|
-
const all = await provider.getAll({
|
|
192
|
+
const all = await provider.getAll({
|
|
193
|
+
userId,
|
|
194
|
+
...(ctx.signal ? { signal: ctx.signal } : {}),
|
|
195
|
+
});
|
|
120
196
|
if (all.length === 0) {
|
|
121
197
|
ctx.ui.notify('No memories stored yet.', 'info');
|
|
122
198
|
}
|
|
@@ -132,4 +208,15 @@ export default function mem0Extension(pi) {
|
|
|
132
208
|
},
|
|
133
209
|
});
|
|
134
210
|
}
|
|
211
|
+
function extractText(msg) {
|
|
212
|
+
if (typeof msg.content === 'string')
|
|
213
|
+
return msg.content;
|
|
214
|
+
if (Array.isArray(msg.content)) {
|
|
215
|
+
return msg.content
|
|
216
|
+
.filter((c) => c.type === 'text' && c.text)
|
|
217
|
+
.map((c) => c.text)
|
|
218
|
+
.join('\n');
|
|
219
|
+
}
|
|
220
|
+
return '';
|
|
221
|
+
}
|
|
135
222
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Two-phase semantic prefetch — kicks off a background search on input,
|
|
3
|
+
* consumes the result on before_agent_start with a timeout.
|
|
4
|
+
*/
|
|
5
|
+
import type { Mem0Provider } from './provider.js';
|
|
6
|
+
export declare class Prefetch {
|
|
7
|
+
private readonly provider;
|
|
8
|
+
private readonly userId;
|
|
9
|
+
private readonly topK;
|
|
10
|
+
private pending;
|
|
11
|
+
constructor(provider: Mem0Provider, userId: string, opts: {
|
|
12
|
+
topK: number;
|
|
13
|
+
});
|
|
14
|
+
/** Phase 1: kick off a background search (called on input with user text). */
|
|
15
|
+
queue(query: string): void;
|
|
16
|
+
/** Phase 2: consume the result with a timeout (called on before_agent_start). */
|
|
17
|
+
consume(timeoutMs?: number): Promise<string>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=prefetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefetch.d.ts","sourceRoot":"","sources":["../src/prefetch.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAQlD,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,OAAO,CAAsC;gBAEzC,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;IAM1E,8EAA8E;IAC9E,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQ1B,iFAAiF;IAC3E,OAAO,CAAC,SAAS,SAAO,GAAG,OAAO,CAAC,MAAM,CAAC;CA6BjD"}
|
package/dist/prefetch.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Two-phase semantic prefetch — kicks off a background search on input,
|
|
3
|
+
* consumes the result on before_agent_start with a timeout.
|
|
4
|
+
*/
|
|
5
|
+
import { truncateHead, truncateLine } from '@earendil-works/pi-coding-agent';
|
|
6
|
+
import { formatRecalledMemory } from './privacy.js';
|
|
7
|
+
/** Recalled entries land in per-turn model context — keep the block small. */
|
|
8
|
+
const MAX_ENTRY_CHARS = 1_000;
|
|
9
|
+
const MAX_BLOCK_BYTES = 8 * 1024;
|
|
10
|
+
const MAX_BLOCK_LINES = 50;
|
|
11
|
+
export class Prefetch {
|
|
12
|
+
provider;
|
|
13
|
+
userId;
|
|
14
|
+
topK;
|
|
15
|
+
pending = null;
|
|
16
|
+
constructor(provider, userId, opts) {
|
|
17
|
+
this.provider = provider;
|
|
18
|
+
this.userId = userId;
|
|
19
|
+
this.topK = opts.topK;
|
|
20
|
+
}
|
|
21
|
+
/** Phase 1: kick off a background search (called on input with user text). */
|
|
22
|
+
queue(query) {
|
|
23
|
+
if (!query.trim())
|
|
24
|
+
return;
|
|
25
|
+
const search = this.provider.search(query, { userId: this.userId, topK: this.topK });
|
|
26
|
+
// A replaced or never-consumed search must not surface as an unhandled rejection.
|
|
27
|
+
search.catch(() => { });
|
|
28
|
+
this.pending = search;
|
|
29
|
+
}
|
|
30
|
+
/** Phase 2: consume the result with a timeout (called on before_agent_start). */
|
|
31
|
+
async consume(timeoutMs = 3000) {
|
|
32
|
+
if (!this.pending)
|
|
33
|
+
return '';
|
|
34
|
+
const promise = this.pending;
|
|
35
|
+
this.pending = null;
|
|
36
|
+
try {
|
|
37
|
+
const memories = await Promise.race([
|
|
38
|
+
promise,
|
|
39
|
+
new Promise((resolve) => setTimeout(() => resolve([]), timeoutMs)),
|
|
40
|
+
]);
|
|
41
|
+
if (memories.length === 0)
|
|
42
|
+
return '';
|
|
43
|
+
const lines = memories
|
|
44
|
+
.filter((m) => m.memory?.trim())
|
|
45
|
+
.map((m) => `- ${formatRecalledMemory(truncateLine(m.memory.trim(), MAX_ENTRY_CHARS).text)}`);
|
|
46
|
+
if (lines.length === 0)
|
|
47
|
+
return '';
|
|
48
|
+
return truncateHead(`## Recalled Memories (Mem0)\n${lines.join('\n')}`, {
|
|
49
|
+
maxBytes: MAX_BLOCK_BYTES,
|
|
50
|
+
maxLines: MAX_BLOCK_LINES,
|
|
51
|
+
}).content;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return '';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=prefetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefetch.js","sourceRoot":"","sources":["../src/prefetch.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAIpD,8EAA8E;AAC9E,MAAM,eAAe,GAAG,KAAK,CAAC;AAC9B,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,CAAC;AACjC,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B,MAAM,OAAO,QAAQ;IACF,QAAQ,CAAe;IACvB,MAAM,CAAS;IACf,IAAI,CAAS;IACtB,OAAO,GAAiC,IAAI,CAAC;IAErD,YAAY,QAAsB,EAAE,MAAc,EAAE,IAAsB;QACxE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,KAAa;QACjB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YAAE,OAAO;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACrF,kFAAkF;QAClF,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,iFAAiF;IACjF,KAAK,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI;QAC5B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QAE7B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;gBAClC,OAAO;gBACP,IAAI,OAAO,CAAe,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;aACjF,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YAErC,MAAM,KAAK,GAAG,QAAQ;iBACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;iBAC/B,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,oBAAoB,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE,CACxF,CAAC;YAEJ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YAClC,OAAO,YAAY,CAAC,gCAAgC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;gBACtE,QAAQ,EAAE,eAAe;gBACzB,QAAQ,EAAE,eAAe;aAC1B,CAAC,CAAC,OAAO,CAAC;QACb,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;CACF"}
|
package/dist/privacy.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import type { MemoryUserIdScope } from './types.js';
|
|
2
|
+
export declare function scopeMemoryUserId(baseUserId: string, cwd: string, scope?: MemoryUserIdScope): string;
|
|
2
3
|
export declare function redactMemoryText(text: string): string;
|
|
3
4
|
export declare function formatRecalledMemory(text: string): string;
|
|
4
5
|
//# sourceMappingURL=privacy.d.ts.map
|
package/dist/privacy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"privacy.d.ts","sourceRoot":"","sources":["../src/privacy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"privacy.d.ts","sourceRoot":"","sources":["../src/privacy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,iBAA6B,GACnC,MAAM,CAIR;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWrD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMzD"}
|
package/dist/privacy.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { scanForThreats } from '@amaster.ai/pi-shared/threat-patterns';
|
|
4
|
-
export function scopeMemoryUserId(baseUserId, cwd) {
|
|
4
|
+
export function scopeMemoryUserId(baseUserId, cwd, scope = 'project') {
|
|
5
|
+
if (scope === 'exact')
|
|
6
|
+
return baseUserId;
|
|
5
7
|
const project = createHash('sha256').update(path.resolve(cwd)).digest('hex').slice(0, 12);
|
|
6
8
|
return `${baseUserId}:project:${project}`;
|
|
7
9
|
}
|
package/dist/privacy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"privacy.js","sourceRoot":"","sources":["../src/privacy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"privacy.js","sourceRoot":"","sources":["../src/privacy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAGvE,MAAM,UAAU,iBAAiB,CAC/B,UAAkB,EAClB,GAAW,EACX,QAA2B,SAAS;IAEpC,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,UAAU,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1F,OAAO,GAAG,UAAU,YAAY,OAAO,EAAE,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI;SACR,OAAO,CACN,4EAA4E,EAC5E,YAAY,CACb;SACA,OAAO,CAAC,wCAAwC,EAAE,eAAe,CAAC;SAClE,OAAO,CACN,qEAAqE,EACrE,eAAe,CAChB,CAAC;AACN,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAChD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,8BAA8B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IAC9D,CAAC;IACD,OAAO,2BAA2B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;AAC3D,CAAC"}
|