@pyxmate/memory 0.2.7-beta → 0.2.10-beta
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/package.json +2 -3
- package/skills/pyx-memory/SKILL.md +3 -0
- package/skills/pyx-memory/examples/minimal-embedded.ts +12 -0
- package/skills/pyx-memory/reference/http-api.md +41 -0
- package/skills/pyx-memory-integration/SKILL.md +0 -266
- package/skills/pyx-memory-integration/examples/disabled-memory.ts +0 -53
- package/skills/pyx-memory-integration/examples/minimal-embedded.ts +0 -25
- package/skills/pyx-memory-integration/examples/minimal-sidecar.ts +0 -14
- package/skills/pyx-memory-integration/patterns/consumer.md +0 -103
- package/skills/pyx-memory-integration/patterns/embedded.md +0 -223
- package/skills/pyx-memory-integration/reference/advanced.md +0 -139
- package/skills/pyx-memory-integration/reference/http-api.md +0 -82
- package/skills/pyx-memory-integration/reference/parity.md +0 -63
- package/skills/pyx-memory-integration/reference/types.md +0 -203
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyxmate/memory",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10-beta",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "SDK for pyx-memory — Memory as a Service for AI agents",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,8 +44,7 @@
|
|
|
44
44
|
"LICENSE"
|
|
45
45
|
],
|
|
46
46
|
"scripts": {
|
|
47
|
-
"
|
|
48
|
-
"build": "bun run copy-skills && tsup",
|
|
47
|
+
"build": "tsup",
|
|
49
48
|
"typecheck": "tsc --noEmit",
|
|
50
49
|
"clean": "rm -rf dist skills node_modules .turbo"
|
|
51
50
|
},
|
|
@@ -40,6 +40,8 @@ curl -s -X POST {{ENDPOINT}}/api/memory/ingest \
|
|
|
40
40
|
-d '{"content":"WHAT_HAPPENED","type":"long-term","metadata":{"source":"agent","topic":"TOPIC","project":"PROJECT_NAME"}}'
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
When the memory mentions specific people, tools, organizations, or other named subjects, also include `entities` and `relationships` to populate the knowledge graph. See [reference/http-api.md](reference/http-api.md) for entity types, relationship types, and examples.
|
|
44
|
+
|
|
43
45
|
## Search: before making assumptions
|
|
44
46
|
|
|
45
47
|
Search for relevant context in these situations:
|
|
@@ -60,6 +62,7 @@ curl -s "{{ENDPOINT}}/api/memory/search?q=QUERY&limit=5" \
|
|
|
60
62
|
- Keep content factual and concise — decisions, not deliberation
|
|
61
63
|
- Do NOT store ephemeral info (file contents, current state, in-progress work)
|
|
62
64
|
- One memory per concept — don't bundle unrelated things
|
|
65
|
+
- Extract entities when content mentions specific people, tools, technologies, organizations, locations, or events by name
|
|
63
66
|
|
|
64
67
|
---
|
|
65
68
|
|
|
@@ -10,6 +10,18 @@ await memory.store({
|
|
|
10
10
|
metadata: { source: 'settings' },
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
+
// Store with entities — populates the knowledge graph
|
|
14
|
+
await memory.store({
|
|
15
|
+
content: 'Alice switched the project to TypeScript for type safety',
|
|
16
|
+
type: 'long-term',
|
|
17
|
+
metadata: { source: 'decisions' },
|
|
18
|
+
entities: [
|
|
19
|
+
{ name: 'Alice', type: 'PERSON' },
|
|
20
|
+
{ name: 'TypeScript', type: 'TOOL' },
|
|
21
|
+
],
|
|
22
|
+
relationships: [{ source: 'Alice', target: 'TypeScript', type: 'USES' }],
|
|
23
|
+
});
|
|
24
|
+
|
|
13
25
|
// Store with explicit targets (e.g., sqlite only)
|
|
14
26
|
await memory.store({
|
|
15
27
|
content: 'Temporary working note',
|
|
@@ -54,6 +54,47 @@ const client = new MemoryClient('http://localhost:7822', process.env.MEMORY_API_
|
|
|
54
54
|
| GET | `/api/memory/query-as-of?asOf=...` | Bi-temporal point-in-time query (asOf, type, agentId, source, limit) |
|
|
55
55
|
| GET | `/api/memory/query-by-event-time?startTime=...&endTime=...` | Bi-temporal event time range query (startTime, endTime, type, agentId, source, limit) |
|
|
56
56
|
|
|
57
|
+
## Entity Extraction (Knowledge Graph)
|
|
58
|
+
|
|
59
|
+
When storing memories that mention named subjects, include `entities` and `relationships` in the ingest request to populate the knowledge graph. This enables graph-based RAG and dashboard visualization.
|
|
60
|
+
|
|
61
|
+
### Entity types
|
|
62
|
+
|
|
63
|
+
`PERSON`, `ORGANIZATION`, `CONCEPT`, `TOOL`, `LOCATION`, `EVENT`
|
|
64
|
+
|
|
65
|
+
### Relationship types
|
|
66
|
+
|
|
67
|
+
`USES`, `OWNS`, `DEPENDS_ON`, `RELATED_TO`, `CREATED_BY`, `PART_OF`, `IS_A`, `WORKS_AT`, `LOCATED_IN`
|
|
68
|
+
|
|
69
|
+
### Example: store with entities
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
curl -s -X POST {{ENDPOINT}}/api/memory/ingest \
|
|
73
|
+
-H "Authorization: Bearer {{API_KEY}}" \
|
|
74
|
+
-H "Content-Type: application/json" \
|
|
75
|
+
-d '{
|
|
76
|
+
"content":"Alice switched the frontend from JavaScript to TypeScript for type safety",
|
|
77
|
+
"type":"long-term",
|
|
78
|
+
"metadata":{"source":"agent","topic":"tech-stack","project":"my-project"},
|
|
79
|
+
"entities":[
|
|
80
|
+
{"name":"Alice","type":"PERSON"},
|
|
81
|
+
{"name":"TypeScript","type":"TOOL"},
|
|
82
|
+
{"name":"JavaScript","type":"TOOL"}
|
|
83
|
+
],
|
|
84
|
+
"relationships":[
|
|
85
|
+
{"from":"Alice","to":"TypeScript","type":"USES"},
|
|
86
|
+
{"from":"TypeScript","to":"JavaScript","type":"RELATED_TO"}
|
|
87
|
+
]
|
|
88
|
+
}'
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**When to extract**: Always extract when content mentions specific people, tools, technologies, organizations, locations, or events by name. Skip only for abstract observations with no named subjects (e.g., "prefer tabs over spaces").
|
|
92
|
+
|
|
93
|
+
**Entity fields**: `name` (required), `type` (required), `metadata` (optional properties object)
|
|
94
|
+
**Relationship fields**: `from` (source entity name), `to` (target entity name), `type` (required)
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
57
98
|
## Response Format
|
|
58
99
|
|
|
59
100
|
All responses follow: `{ success: boolean, data?: T, error?: string }`
|
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pyx-memory-integration
|
|
3
|
-
description: >
|
|
4
|
-
Integration guide for the pyx-memory universal memory system (TypeScript/Bun).
|
|
5
|
-
Use when integrating pyx-memory into a project, migrating to pyx-memory,
|
|
6
|
-
setting up embedded or sidecar memory, asking about pyx-memory API or types,
|
|
7
|
-
configuring RAG strategies, file ingestion, or lifecycle management.
|
|
8
|
-
Triggers on: 'integrate pyx-memory', 'add memory system', 'setup pyx-memory',
|
|
9
|
-
'memory store search', 'MemoryInterface', 'EmbeddingProvider', 'createMemory',
|
|
10
|
-
'pyx-memory configuration', 'memory consolidation', 'graph RAG'.
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# pyx-memory — AI Agent Integration Guide
|
|
14
|
-
|
|
15
|
-
Reference for AI agents integrating pyx-memory into TypeScript/Bun projects.
|
|
16
|
-
Runtime requirement: **Bun v1.2+** (not Node.js). Uses `bun:sqlite` natively.
|
|
17
|
-
|
|
18
|
-
> After integration work, run the diagnostic tool to verify correctness:
|
|
19
|
-
> ```bash
|
|
20
|
-
> bun .claude/skills/pyx-memory-integration/scripts/diagnose-integration.ts --json
|
|
21
|
-
> ```
|
|
22
|
-
> Parse the `verdict` field: `"healthy"` = done, otherwise fix each `criticalIssues` entry and re-run.
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## What are you trying to do?
|
|
27
|
-
|
|
28
|
-
**Integrate pyx-memory into a consumer project?**
|
|
29
|
-
→ See [patterns/consumer.md](patterns/consumer.md)
|
|
30
|
-
|
|
31
|
-
**Set up embedded memory with full features?**
|
|
32
|
-
→ See [patterns/embedded.md](patterns/embedded.md)
|
|
33
|
-
|
|
34
|
-
**Understand type signatures and interfaces?**
|
|
35
|
-
→ See [reference/types.md](reference/types.md)
|
|
36
|
-
|
|
37
|
-
**Check sidecar limitations before choosing a mode?**
|
|
38
|
-
→ See [reference/parity.md](reference/parity.md)
|
|
39
|
-
|
|
40
|
-
**Use the HTTP API directly?**
|
|
41
|
-
→ See [reference/http-api.md](reference/http-api.md)
|
|
42
|
-
|
|
43
|
-
**Configure RAG, bi-temporal queries, or consolidation?**
|
|
44
|
-
→ See [reference/advanced.md](reference/advanced.md)
|
|
45
|
-
|
|
46
|
-
**Validate your integration setup?**
|
|
47
|
-
→ Run: `bun .claude/skills/pyx-memory-integration/scripts/diagnose-integration.ts`
|
|
48
|
-
|
|
49
|
-
**Check server connectivity?**
|
|
50
|
-
→ Run: `bun .claude/skills/pyx-memory-integration/scripts/diagnose-integration.ts --phase=runtime`
|
|
51
|
-
|
|
52
|
-
**Get machine-readable diagnostic report?**
|
|
53
|
-
→ Run: `bun .claude/skills/pyx-memory-integration/scripts/diagnose-integration.ts --json`
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## Quick Decision Tree
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
Building pyx-memory itself or its server?
|
|
61
|
-
→ Embedded mode: import { Memory } from '@pyx-memory/core'
|
|
62
|
-
|
|
63
|
-
Consuming pyx-memory from another project (e.g., agent-forge)?
|
|
64
|
-
→ Sidecar mode: import { MemoryClient } from '@pyx-memory/client'
|
|
65
|
-
→ ONLY depend on @pyx-memory/client + @pyx-memory/shared
|
|
66
|
-
→ Do NOT import @pyx-memory/core — that's pyx-memory's internal implementation
|
|
67
|
-
→ See patterns/consumer.md
|
|
68
|
-
|
|
69
|
-
Need memory in your process (best perf, full feature set)?
|
|
70
|
-
→ Embedded mode: import { Memory } from '@pyx-memory/core'
|
|
71
|
-
|
|
72
|
-
Need memory as a separate service (HTTP)?
|
|
73
|
-
→ Sidecar mode: import { MemoryClient } from '@pyx-memory/client'
|
|
74
|
-
|
|
75
|
-
Need to switch modes via config?
|
|
76
|
-
→ Factory: import { createMemory } from '@pyx-memory/core'
|
|
77
|
-
- Returns MemoryInterface (base interface — no lifecycle methods)
|
|
78
|
-
- If you need consolidate/decay/summarize, use `new Memory()` directly
|
|
79
|
-
|
|
80
|
-
Need lifecycle methods (consolidate, decay, summarize)?
|
|
81
|
-
→ Use `new Memory(opts)` — returns ExtendedMemoryInterface
|
|
82
|
-
→ Or `new MemoryClient(url)` — also implements ExtendedMemoryInterface
|
|
83
|
-
→ NOT createMemory() — it returns MemoryInterface (missing lifecycle methods)
|
|
84
|
-
|
|
85
|
-
Need dashboard features (consolidation log, graph visualization)?
|
|
86
|
-
→ Use `DashboardClient` from '@pyx-memory/dashboard'
|
|
87
|
-
→ Extends MemoryClient with additional methods
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## Minimal Working Example (Embedded)
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
import { Memory } from '@pyx-memory/core';
|
|
96
|
-
|
|
97
|
-
// Embedding is internal — pyx-memory uses BGE-M3 (1024d) automatically
|
|
98
|
-
const memory = new Memory({ dataDir: './data' });
|
|
99
|
-
await memory.initialize(); // REQUIRED — throws if you skip this
|
|
100
|
-
|
|
101
|
-
// Store (default targets: sqlite + vector; or sqlite + vector + graph when graphStore configured)
|
|
102
|
-
// When graphStore is configured, graph is auto-included in defaults.
|
|
103
|
-
// If no entities provided, graph is silently skipped.
|
|
104
|
-
await memory.store({
|
|
105
|
-
content: 'User prefers dark mode',
|
|
106
|
-
type: 'long-term',
|
|
107
|
-
metadata: { source: 'settings' },
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
// Store with entities — graph is populated automatically when graphStore configured
|
|
111
|
-
await memory.store({
|
|
112
|
-
content: 'Alice works at Acme Corp',
|
|
113
|
-
type: 'long-term',
|
|
114
|
-
metadata: {},
|
|
115
|
-
entities: [
|
|
116
|
-
{ name: 'Alice', type: 'PERSON' },
|
|
117
|
-
{ name: 'Acme Corp', type: 'ORGANIZATION' },
|
|
118
|
-
],
|
|
119
|
-
relationships: [{ source: 'Alice', target: 'Acme Corp', type: 'WORKS_AT' }],
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// Search
|
|
123
|
-
const results = await memory.search({ query: 'user preferences', limit: 5 });
|
|
124
|
-
|
|
125
|
-
// Cleanup
|
|
126
|
-
await memory.shutdown(); // REQUIRED — releases SQLite + LanceDB resources
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
## Minimal Working Example (Sidecar / HTTP)
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
import { MemoryClient } from '@pyx-memory/client';
|
|
133
|
-
|
|
134
|
-
// Without auth (local dev)
|
|
135
|
-
const memory = new MemoryClient('http://localhost:7822');
|
|
136
|
-
|
|
137
|
-
// With auth (production — pass API key as second argument)
|
|
138
|
-
const authedMemory = new MemoryClient('http://localhost:7822', process.env.MEMORY_API_KEY);
|
|
139
|
-
|
|
140
|
-
await memory.initialize(); // verifies server connectivity via /health
|
|
141
|
-
|
|
142
|
-
await memory.store({ content: 'Important fact', type: 'long-term', metadata: {} });
|
|
143
|
-
const results = await memory.search({ query: 'fact', limit: 5 });
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
Start the server: `bun packages/server/src/index.ts`
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
|
-
## Package Map
|
|
151
|
-
|
|
152
|
-
```
|
|
153
|
-
@pyx-memory/shared → Types + constants only (zero runtime code)
|
|
154
|
-
↑ ↑
|
|
155
|
-
| |
|
|
156
|
-
@pyx-memory/client → MemoryInterface, ExtendedMemoryInterface, MemoryClient
|
|
157
|
-
↑
|
|
158
|
-
|
|
|
159
|
-
@pyx-memory/core → Memory class, embeddings, graph, RAG, ingestion, lifecycle
|
|
160
|
-
↑ (re-exports everything from client and shared)
|
|
161
|
-
|
|
|
162
|
-
@pyx-memory/server → HTTP sidecar server (23 endpoints)
|
|
163
|
-
|
|
164
|
-
@pyx-memory/dashboard → DashboardClient (extends MemoryClient), React hooks,
|
|
165
|
-
Poller, aggregations, graph transforms (D3/Graphology)
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
**Import rules:**
|
|
169
|
-
- **Embedded mode**: Import everything from `@pyx-memory/core` (it re-exports client + shared)
|
|
170
|
-
- **Sidecar mode (client only)**: Import from `@pyx-memory/client` (+ types from `@pyx-memory/shared`)
|
|
171
|
-
- **Dashboard features**: Import from `@pyx-memory/dashboard` (extends client with extra methods)
|
|
172
|
-
- **Types only**: Import from `@pyx-memory/shared`
|
|
173
|
-
- **Consumer projects**: ONLY use `@pyx-memory/client` + `@pyx-memory/shared` — never `@pyx-memory/core`
|
|
174
|
-
|
|
175
|
-
For full type definitions and interfaces, see [reference/types.md](reference/types.md).
|
|
176
|
-
|
|
177
|
-
For HTTP API endpoint reference, see [reference/http-api.md](reference/http-api.md).
|
|
178
|
-
|
|
179
|
-
For feature parity between embedded and sidecar modes, see [reference/parity.md](reference/parity.md).
|
|
180
|
-
|
|
181
|
-
For RAG strategies, bi-temporal model, consolidation, and community detection, see [reference/advanced.md](reference/advanced.md).
|
|
182
|
-
|
|
183
|
-
---
|
|
184
|
-
|
|
185
|
-
## DO / DON'T
|
|
186
|
-
|
|
187
|
-
### DO
|
|
188
|
-
|
|
189
|
-
- **DO** call `await memory.initialize()` before any operation
|
|
190
|
-
- **DO** call `await memory.shutdown()` when done (releases SQLite + LanceDB)
|
|
191
|
-
- **DO** provide `entities` to populate the graph — graph is auto-included in defaults when graphStore is configured, but silently skipped if no entities are provided
|
|
192
|
-
- **DO** initialize GraphStore BEFORE constructing Memory
|
|
193
|
-
- **DO** use `new Memory()` when you need lifecycle methods (ExtendedMemoryInterface)
|
|
194
|
-
- **DO** use `':memory:'` dataDir for tests
|
|
195
|
-
- **DO** handle `MemoryServerError` in sidecar mode (has `.status` and `.isNotFound`)
|
|
196
|
-
- **DO** use `MemoryClient` (not `MemoryInterface`) when you need graph or file ingestion — these are concrete methods
|
|
197
|
-
- **DO** use `DashboardClient` when you need consolidation logs, graph relationships, or enriched health data
|
|
198
|
-
- **DO** implement `DisabledMemory` (no-op) in consumer projects for graceful degradation when memory is unavailable
|
|
199
|
-
|
|
200
|
-
### DON'T
|
|
201
|
-
|
|
202
|
-
- **DON'T** assume `createMemory()` returns `ExtendedMemoryInterface` — it returns `MemoryInterface`
|
|
203
|
-
- **DON'T** use `targets: ['graph']` without a configured `graphStore` — throws MemoryError (but graph without entities is fine — silently skipped)
|
|
204
|
-
- **DON'T** use `strategy: 'graph'` without passing `graphStore` — throws "RAG strategy not registered"
|
|
205
|
-
- **DON'T** use `strategy: 'agentic'` without passing `reasoningProvider`
|
|
206
|
-
- **DON'T** construct multiple Memory instances with the same `dataDir` — LanceDB singleton causes conflicts
|
|
207
|
-
- **DON'T** use `':memory:'` in production — LanceDB still writes to `/tmp/autonomy-vectors`
|
|
208
|
-
- **DON'T** expose the server without configuring `API_KEY` for network deployments — use an API gateway for internet-facing deployments
|
|
209
|
-
- **DON'T** import `@pyx-memory/core` in consumer projects — use `@pyx-memory/client` for clean separation
|
|
210
|
-
- **DON'T** expect `filters`, `enableHyDE`, or `enableRerank` to work in sidecar mode — the HTTP API doesn't forward them
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
## AI Agent Post-Integration Checklist
|
|
215
|
-
|
|
216
|
-
After integrating pyx-memory, run the diagnostic tool to verify everything is wired correctly:
|
|
217
|
-
|
|
218
|
-
```bash
|
|
219
|
-
bun .claude/skills/pyx-memory-integration/scripts/diagnose-integration.ts --json
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
**Interpret the result:**
|
|
223
|
-
1. Parse the JSON `verdict` field:
|
|
224
|
-
- `"healthy"` → Integration is complete and working
|
|
225
|
-
- `"misconfigured"` → Environment or config issues — fix each item in `criticalIssues`
|
|
226
|
-
- `"broken"` → Server is down or unreachable — start the server first
|
|
227
|
-
- `"degraded"` → Working but with warnings (e.g., stub embeddings)
|
|
228
|
-
2. For each entry in `criticalIssues`, apply the `fix` instruction
|
|
229
|
-
3. Re-run until `verdict === "healthy"`
|
|
230
|
-
|
|
231
|
-
**Common failure: DisabledMemory (no-op)**
|
|
232
|
-
If `MEMORY_URL` is not set, the client will silently fall back to a DisabledMemory no-op implementation. Everything appears to work (store returns success, health reports "ok") but nothing is actually persisted. The diagnostic tool detects this via checks S5 (missing URL) and I1 (empty store ID).
|
|
233
|
-
|
|
234
|
-
---
|
|
235
|
-
|
|
236
|
-
## Error Types
|
|
237
|
-
|
|
238
|
-
```
|
|
239
|
-
MemoryError (base)
|
|
240
|
-
├── MemoryStoreError — SQLite store failures
|
|
241
|
-
├── MemoryNotFoundError — entry not found
|
|
242
|
-
├── MemorySearchError — search failures
|
|
243
|
-
├── VectorProviderError — LanceDB/vector issues
|
|
244
|
-
├── EmbeddingError — embedding generation failures
|
|
245
|
-
├── MigrationError — schema migration issues
|
|
246
|
-
├── IngestionError — file parsing / ingestion failures
|
|
247
|
-
├── LifecycleError — consolidation / decay failures
|
|
248
|
-
└── GraphError — graph store operations
|
|
249
|
-
|
|
250
|
-
MemoryServerError — HTTP client errors (has .status, .isNotFound)
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
All from `@pyx-memory/core` except `MemoryServerError` from `@pyx-memory/client`.
|
|
254
|
-
|
|
255
|
-
---
|
|
256
|
-
|
|
257
|
-
## Copy-Paste Examples
|
|
258
|
-
|
|
259
|
-
- [examples/minimal-embedded.ts](examples/minimal-embedded.ts) — Embedded setup with store/search/shutdown
|
|
260
|
-
- [examples/minimal-sidecar.ts](examples/minimal-sidecar.ts) — Sidecar HTTP client setup
|
|
261
|
-
- [examples/disabled-memory.ts](examples/disabled-memory.ts) — No-op DisabledMemory class for graceful degradation
|
|
262
|
-
|
|
263
|
-
## Further Reading
|
|
264
|
-
|
|
265
|
-
- `docs/ARCHITECTURE.md` — Deep architecture reference, research sources, cost analysis, competitive positioning
|
|
266
|
-
- `README.md` — Project overview, HTTP API examples, deployment guides, Docker setup
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import type { MemoryInterface, MemoryListResult } from '@pyx-memory/client';
|
|
2
|
-
import type { MemoryEntry, MemorySearchResult, MemoryStats } from '@pyx-memory/shared';
|
|
3
|
-
|
|
4
|
-
export class DisabledMemory implements MemoryInterface {
|
|
5
|
-
async initialize(): Promise<void> {
|
|
6
|
-
console.warn('Memory service not configured — running without memory');
|
|
7
|
-
}
|
|
8
|
-
async store(
|
|
9
|
-
entry: Omit<MemoryEntry, 'id' | 'createdAt'> & { id?: string; createdAt?: string },
|
|
10
|
-
): Promise<MemoryEntry> {
|
|
11
|
-
return {
|
|
12
|
-
id: '',
|
|
13
|
-
content: entry.content,
|
|
14
|
-
type: entry.type,
|
|
15
|
-
metadata: {},
|
|
16
|
-
createdAt: new Date().toISOString(),
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
async search(): Promise<MemorySearchResult> {
|
|
20
|
-
return { entries: [], totalCount: 0, strategy: 'naive' };
|
|
21
|
-
}
|
|
22
|
-
async list(): Promise<MemoryListResult> {
|
|
23
|
-
return { entries: [], totalCount: 0, page: 1, limit: 20 };
|
|
24
|
-
}
|
|
25
|
-
async get(): Promise<MemoryEntry | null> {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
async delete(): Promise<boolean> {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
async clearSession(): Promise<number> {
|
|
32
|
-
return 0;
|
|
33
|
-
}
|
|
34
|
-
async stats(): Promise<MemoryStats> {
|
|
35
|
-
return {
|
|
36
|
-
totalEntries: 0,
|
|
37
|
-
storageUsedBytes: 0,
|
|
38
|
-
vectorCount: 0,
|
|
39
|
-
recentAccessCount: 0,
|
|
40
|
-
connected: false,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
async shutdown(): Promise<void> {}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Usage: pick the right implementation based on config
|
|
47
|
-
import { MemoryClient } from '@pyx-memory/client';
|
|
48
|
-
|
|
49
|
-
const memory: MemoryInterface = process.env.MEMORY_URL
|
|
50
|
-
? new MemoryClient(process.env.MEMORY_URL, process.env.MEMORY_API_KEY)
|
|
51
|
-
: new DisabledMemory();
|
|
52
|
-
|
|
53
|
-
await memory.initialize();
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { Memory } from '@pyx-memory/core';
|
|
2
|
-
|
|
3
|
-
const memory = new Memory({ dataDir: './data' });
|
|
4
|
-
await memory.initialize(); // REQUIRED — throws if you skip this
|
|
5
|
-
|
|
6
|
-
// Store (default targets: sqlite + vector)
|
|
7
|
-
await memory.store({
|
|
8
|
-
content: 'User prefers dark mode',
|
|
9
|
-
type: 'long-term',
|
|
10
|
-
metadata: { source: 'settings' },
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
// Store with explicit targets (e.g., sqlite only)
|
|
14
|
-
await memory.store({
|
|
15
|
-
content: 'Temporary working note',
|
|
16
|
-
type: 'working',
|
|
17
|
-
metadata: {},
|
|
18
|
-
targets: ['sqlite'],
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
// Search
|
|
22
|
-
const _results = await memory.search({ query: 'user preferences', limit: 5 });
|
|
23
|
-
|
|
24
|
-
// Cleanup
|
|
25
|
-
await memory.shutdown(); // REQUIRED — releases SQLite + LanceDB resources
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { MemoryClient } from '@pyx-memory/client';
|
|
2
|
-
|
|
3
|
-
// Without auth (local dev)
|
|
4
|
-
const memory = new MemoryClient('http://localhost:7822');
|
|
5
|
-
|
|
6
|
-
// With auth (production — pass API key as second argument)
|
|
7
|
-
// const memory = new MemoryClient('http://localhost:7822', process.env.MEMORY_API_KEY);
|
|
8
|
-
|
|
9
|
-
await memory.initialize(); // verifies server connectivity via /health
|
|
10
|
-
|
|
11
|
-
await memory.store({ content: 'Important fact', type: 'long-term', metadata: {} });
|
|
12
|
-
const _results = await memory.search({ query: 'fact', limit: 5 });
|
|
13
|
-
|
|
14
|
-
// Start the server: bun packages/server/src/index.ts
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
# Consumer Integration Patterns
|
|
2
|
-
|
|
3
|
-
For downstream projects that **consume** pyx-memory (e.g., agent-forge, custom AI agents).
|
|
4
|
-
|
|
5
|
-
**Rule: Only depend on `@pyx-memory/client` + `@pyx-memory/shared`. Never import `@pyx-memory/core`.**
|
|
6
|
-
|
|
7
|
-
`@pyx-memory/core` is pyx-memory's internal implementation (SQLiteStore, LanceDB, embedding providers,
|
|
8
|
-
RAG engines, graph stores). Importing it creates tight coupling — any internal change can break your project.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Pattern 8: Consumer (Sidecar-Only)
|
|
13
|
-
|
|
14
|
-
```typescript
|
|
15
|
-
import { MemoryClient, MemoryServerError } from '@pyx-memory/client';
|
|
16
|
-
import type { MemoryInterface, ExtendedMemoryInterface } from '@pyx-memory/client';
|
|
17
|
-
import type { MemoryEntry, MemorySearchResult } from '@pyx-memory/shared';
|
|
18
|
-
|
|
19
|
-
const MEMORY_URL = process.env.MEMORY_URL; // e.g., 'http://localhost:7822'
|
|
20
|
-
|
|
21
|
-
let memory: MemoryClient | null = null;
|
|
22
|
-
|
|
23
|
-
if (MEMORY_URL) {
|
|
24
|
-
memory = new MemoryClient(MEMORY_URL, process.env.MEMORY_API_KEY);
|
|
25
|
-
await memory.initialize(); // verifies connectivity
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Use memory if available
|
|
29
|
-
if (memory) {
|
|
30
|
-
await memory.store({ content: 'fact', type: 'long-term', metadata: {} });
|
|
31
|
-
const results = await memory.search({ query: 'fact', limit: 5 });
|
|
32
|
-
|
|
33
|
-
// Graph queries — available on MemoryClient directly (no @pyx-memory/core needed)
|
|
34
|
-
const nodes = await memory.graphNodes();
|
|
35
|
-
const traversal = await memory.graphQuery({ nodeId: 'node-1', depth: 2 });
|
|
36
|
-
|
|
37
|
-
// File ingestion — also available on MemoryClient
|
|
38
|
-
const file = new File([buffer], 'report.pdf', { type: 'application/pdf' });
|
|
39
|
-
const result = await memory.ingestFile(file);
|
|
40
|
-
|
|
41
|
-
// Lifecycle
|
|
42
|
-
await memory.consolidate();
|
|
43
|
-
await memory.runDecay();
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
## Pattern 9: Graceful Degradation (DisabledMemory)
|
|
50
|
-
|
|
51
|
-
When your project should work with or without pyx-memory, implement a no-op wrapper.
|
|
52
|
-
See [examples/disabled-memory.ts](../examples/disabled-memory.ts) for a copy-paste ready implementation.
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
import { MemoryClient } from '@pyx-memory/client';
|
|
56
|
-
|
|
57
|
-
const memory: MemoryInterface = process.env.MEMORY_URL
|
|
58
|
-
? new MemoryClient(process.env.MEMORY_URL, process.env.MEMORY_API_KEY)
|
|
59
|
-
: new DisabledMemory();
|
|
60
|
-
|
|
61
|
-
await memory.initialize();
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
---
|
|
65
|
-
|
|
66
|
-
## Health Endpoint Pattern
|
|
67
|
-
|
|
68
|
-
Report memory status in your app's health check:
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
// In your health route
|
|
72
|
-
const memoryStatus = process.env.MEMORY_URL
|
|
73
|
-
? { status: 'connected', url: process.env.MEMORY_URL }
|
|
74
|
-
: { status: 'disabled' };
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
---
|
|
78
|
-
|
|
79
|
-
## Adding as Sidecar (Docker)
|
|
80
|
-
|
|
81
|
-
```yaml
|
|
82
|
-
# docker-compose.yaml
|
|
83
|
-
services:
|
|
84
|
-
memory:
|
|
85
|
-
build:
|
|
86
|
-
context: ./vendor/pyx-memory
|
|
87
|
-
dockerfile: docker/Dockerfile
|
|
88
|
-
ports:
|
|
89
|
-
- "7822:7822"
|
|
90
|
-
volumes:
|
|
91
|
-
- memory-data:/data
|
|
92
|
-
environment:
|
|
93
|
-
- DATA_DIR=/data
|
|
94
|
-
# Embedding is internal (BGE-M3, 1024d) — no API keys needed
|
|
95
|
-
# - EMBEDDING_DIMENSIONS=1024 # optional override
|
|
96
|
-
|
|
97
|
-
your-app:
|
|
98
|
-
environment:
|
|
99
|
-
- MEMORY_URL=http://memory:7822
|
|
100
|
-
|
|
101
|
-
volumes:
|
|
102
|
-
memory-data:
|
|
103
|
-
```
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
# Embedded Integration Patterns
|
|
2
|
-
|
|
3
|
-
For projects using pyx-memory directly in-process with full feature access.
|
|
4
|
-
|
|
5
|
-
## Contents
|
|
6
|
-
- [Pattern 1: Testing / Development](#pattern-1-testing--development)
|
|
7
|
-
- [Pattern 2: Production](#pattern-2-production)
|
|
8
|
-
- [Pattern 3: Production with Store Targets](#pattern-3-production-with-store-targets)
|
|
9
|
-
- [Pattern 4: With Knowledge Graph](#pattern-4-with-knowledge-graph)
|
|
10
|
-
- [Pattern 5: With LLM Lifecycle](#pattern-5-with-llm-lifecycle)
|
|
11
|
-
- [Pattern 6: File Ingestion](#pattern-6-file-ingestion)
|
|
12
|
-
- [Pattern 7: Factory with Auto-Mode Switching](#pattern-7-factory-with-auto-mode-switching)
|
|
13
|
-
- [Adding as Git Submodule](#adding-as-git-submodule-recommended-for-embedded-mode)
|
|
14
|
-
- [MemoryOptions Quick Reference](#memoryoptions-quick-reference)
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## Pattern 1: Testing / Development
|
|
19
|
-
|
|
20
|
-
```typescript
|
|
21
|
-
import { Memory } from '@pyx-memory/core';
|
|
22
|
-
|
|
23
|
-
const memory = new Memory({ dataDir: ':memory:' });
|
|
24
|
-
await memory.initialize();
|
|
25
|
-
// Memory internally creates a LocalEmbeddingProvider (BGE-M3, 1024d)
|
|
26
|
-
// No embedder needed — embedding is fully managed
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Pattern 2: Production
|
|
30
|
-
|
|
31
|
-
```typescript
|
|
32
|
-
import { Memory } from '@pyx-memory/core';
|
|
33
|
-
|
|
34
|
-
const memory = new Memory({ dataDir: './data' });
|
|
35
|
-
await memory.initialize();
|
|
36
|
-
// Embedding is handled internally by LocalEmbeddingProvider (BGE-M3 via @huggingface/transformers, 1024d)
|
|
37
|
-
// No external embedding provider needed
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Pattern 3: Production with Store Targets
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
import { Memory } from '@pyx-memory/core';
|
|
44
|
-
|
|
45
|
-
const memory = new Memory({ dataDir: './data' });
|
|
46
|
-
await memory.initialize();
|
|
47
|
-
|
|
48
|
-
// Default: stores to sqlite + vector
|
|
49
|
-
await memory.store({
|
|
50
|
-
content: 'User prefers dark mode',
|
|
51
|
-
type: 'long-term',
|
|
52
|
-
metadata: { source: 'settings' },
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// Explicit targets: sqlite only (skip vector indexing)
|
|
56
|
-
await memory.store({
|
|
57
|
-
content: 'Temporary note',
|
|
58
|
-
type: 'working',
|
|
59
|
-
metadata: {},
|
|
60
|
-
targets: ['sqlite'],
|
|
61
|
-
});
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Pattern 4: With Knowledge Graph
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
import { Memory, createGraphStore } from '@pyx-memory/core';
|
|
68
|
-
import type { StoreTarget, IngestEntity, IngestRelationship } from '@pyx-memory/shared';
|
|
69
|
-
|
|
70
|
-
// 1. Create and initialize graph store BEFORE Memory
|
|
71
|
-
const graphStore = createGraphStore({}); // returns SQLiteGraphStore (default)
|
|
72
|
-
await graphStore.initialize({}); // REQUIRED — Memory does NOT init this for you
|
|
73
|
-
|
|
74
|
-
// For Neo4j instead: createGraphStore({ neo4jUrl: 'bolt://localhost:7687' })
|
|
75
|
-
|
|
76
|
-
const memory = new Memory({
|
|
77
|
-
dataDir: './data',
|
|
78
|
-
graphStore, // enables graph RAG search
|
|
79
|
-
});
|
|
80
|
-
await memory.initialize();
|
|
81
|
-
|
|
82
|
-
// Graph storage is agent-driven — YOU provide entities and relationships explicitly
|
|
83
|
-
await memory.store({
|
|
84
|
-
content: 'Alice works at Acme Corp as a senior engineer',
|
|
85
|
-
type: 'long-term',
|
|
86
|
-
metadata: {},
|
|
87
|
-
targets: ['sqlite', 'vector', 'graph'],
|
|
88
|
-
entities: [
|
|
89
|
-
{ name: 'Alice', type: 'PERSON', properties: { role: 'senior engineer' } },
|
|
90
|
-
{ name: 'Acme Corp', type: 'ORGANIZATION' },
|
|
91
|
-
],
|
|
92
|
-
relationships: [
|
|
93
|
-
{ source: 'Alice', target: 'Acme Corp', type: 'WORKS_AT' },
|
|
94
|
-
],
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
// Graph-aware search
|
|
98
|
-
const results = await memory.search({ query: 'Alice employer', strategy: 'graph' });
|
|
99
|
-
|
|
100
|
-
// Cleanup both
|
|
101
|
-
await memory.shutdown();
|
|
102
|
-
await graphStore.shutdown();
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Pattern 5: With LLM Lifecycle
|
|
106
|
-
|
|
107
|
-
```typescript
|
|
108
|
-
import { Memory } from '@pyx-memory/core';
|
|
109
|
-
import type { LLMCallback } from '@pyx-memory/core';
|
|
110
|
-
|
|
111
|
-
// LLMCallback: any function that takes a prompt string and returns a completion string
|
|
112
|
-
const llm: LLMCallback = async (prompt) => {
|
|
113
|
-
const res = await fetch('https://api.anthropic.com/v1/messages', {
|
|
114
|
-
method: 'POST',
|
|
115
|
-
headers: {
|
|
116
|
-
'x-api-key': process.env.ANTHROPIC_API_KEY!,
|
|
117
|
-
'content-type': 'application/json',
|
|
118
|
-
'anthropic-version': '2023-06-01',
|
|
119
|
-
},
|
|
120
|
-
body: JSON.stringify({
|
|
121
|
-
model: 'claude-sonnet-4-20250514',
|
|
122
|
-
max_tokens: 1024,
|
|
123
|
-
messages: [{ role: 'user', content: prompt }],
|
|
124
|
-
}),
|
|
125
|
-
});
|
|
126
|
-
const data = await res.json() as any;
|
|
127
|
-
return data.content[0].text;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
const memory = new Memory({
|
|
131
|
-
dataDir: './data',
|
|
132
|
-
llm, // enables LLM-powered lifecycle
|
|
133
|
-
});
|
|
134
|
-
await memory.initialize();
|
|
135
|
-
|
|
136
|
-
// Now lifecycle methods use LLM intelligence
|
|
137
|
-
await memory.consolidate(); // LLM scoring + dedup + conflict resolution
|
|
138
|
-
await memory.summarizeSession('session-123'); // LLM summarization
|
|
139
|
-
await memory.runDecay(); // importance-based archival
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
**Without LLM**: Lifecycle still works using heuristic fallbacks (regex extraction, embedding-distance dedup, formula-based scoring). LLM makes it smarter, not mandatory.
|
|
143
|
-
|
|
144
|
-
## Pattern 6: File Ingestion
|
|
145
|
-
|
|
146
|
-
```typescript
|
|
147
|
-
import { IngestionAgent, Memory } from '@pyx-memory/core';
|
|
148
|
-
|
|
149
|
-
const memory = new Memory({ dataDir: './data' });
|
|
150
|
-
await memory.initialize();
|
|
151
|
-
|
|
152
|
-
const agent = new IngestionAgent({
|
|
153
|
-
llm: myLlmCallback, // optional: smart classification + enrichment
|
|
154
|
-
embedder: (texts) => myEmbedder.embed(texts), // optional: semantic chunking (separate from Memory's internal embedder)
|
|
155
|
-
useSemanticChunking: true,
|
|
156
|
-
useStructuralChunking: false,
|
|
157
|
-
enableEnrichment: true,
|
|
158
|
-
enableMetadata: true,
|
|
159
|
-
enableHierarchical: false, // requires LLM
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// Supported: .txt, .md, .csv, .pdf, .docx, .json, .html
|
|
163
|
-
const buffer = Buffer.from(await Bun.file('report.pdf').arrayBuffer());
|
|
164
|
-
const result = await agent.ingest(buffer, 'report.pdf', memory);
|
|
165
|
-
// result: { filename, fileType, chunks, entryIds, totalCharacters }
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
**Note**: `IngestionAgent` may accept its own `embedder` for semantic chunking. This is separate from Memory's internal embedding — Memory handles its own embedding automatically.
|
|
169
|
-
|
|
170
|
-
## Pattern 7: Factory with Auto-Mode Switching
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
import { createMemory } from '@pyx-memory/core';
|
|
174
|
-
|
|
175
|
-
// Embedded mode (default)
|
|
176
|
-
const memory = createMemory({
|
|
177
|
-
dataDir: './data',
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
// Sidecar mode (when MEMORY_URL is set)
|
|
181
|
-
const remote = createMemory({
|
|
182
|
-
memoryUrl: process.env.MEMORY_URL, // e.g., 'http://localhost:7822'
|
|
183
|
-
apiKey: process.env.MEMORY_API_KEY,
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
await memory.initialize();
|
|
187
|
-
|
|
188
|
-
// WARNING: createMemory() returns MemoryInterface, NOT ExtendedMemoryInterface.
|
|
189
|
-
// If you need lifecycle methods, cast:
|
|
190
|
-
// const extended = memory as ExtendedMemoryInterface;
|
|
191
|
-
// Or prefer `new Memory()` / `new MemoryClient()` directly.
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
## Adding as Git Submodule (Recommended for Embedded Mode)
|
|
197
|
-
|
|
198
|
-
```bash
|
|
199
|
-
git submodule add https://github.com/fysoul17/pyx-memory-v1.git vendor/pyx-memory
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
Add to your `package.json` workspaces:
|
|
203
|
-
|
|
204
|
-
```json
|
|
205
|
-
{
|
|
206
|
-
"workspaces": [
|
|
207
|
-
"packages/*",
|
|
208
|
-
"vendor/pyx-memory/packages/shared",
|
|
209
|
-
"vendor/pyx-memory/packages/client",
|
|
210
|
-
"vendor/pyx-memory/packages/core"
|
|
211
|
-
]
|
|
212
|
-
}
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
Then: `bun install`
|
|
216
|
-
|
|
217
|
-
---
|
|
218
|
-
|
|
219
|
-
## MemoryOptions Quick Reference
|
|
220
|
-
|
|
221
|
-
`embedder` has been removed from MemoryOptions. Memory internally creates a `LocalEmbeddingProvider` using BGE-M3 (1024 dimensions) via `@huggingface/transformers`. You never need to provide an embedding function.
|
|
222
|
-
|
|
223
|
-
See [reference/types.md](../reference/types.md#memoryoptions-reference) for the full MemoryOptions table.
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
# Advanced Features
|
|
2
|
-
|
|
3
|
-
## RAG Strategies
|
|
4
|
-
|
|
5
|
-
| Strategy | How It Works | Requirements |
|
|
6
|
-
|----------|-------------|--------------|
|
|
7
|
-
| `'naive'` | Embed query → vector similarity → top-K | (default, always available) |
|
|
8
|
-
| `'graph'` | Extract entities → graph traversal → context expansion | `graphStore` in MemoryOptions |
|
|
9
|
-
| `'hybrid'` | BM25 + vector + graph + community summaries → RRF fusion (k=60) → reranking | `graphStore` in MemoryOptions |
|
|
10
|
-
| `'agentic'` | LLM decides strategy → iterative refinement (3 rounds) | `reasoningProvider` in MemoryOptions |
|
|
11
|
-
|
|
12
|
-
```typescript
|
|
13
|
-
// Naive (default)
|
|
14
|
-
await memory.search({ query: 'user preferences', limit: 10 });
|
|
15
|
-
|
|
16
|
-
// Graph
|
|
17
|
-
await memory.search({ query: 'who works at Acme', strategy: 'graph', limit: 10 });
|
|
18
|
-
|
|
19
|
-
// Hybrid (recommended for best quality)
|
|
20
|
-
await memory.search({ query: 'deployment config', strategy: 'hybrid', limit: 10 });
|
|
21
|
-
|
|
22
|
-
// With query transformation (HyDE generates hypothetical answer, embeds that instead)
|
|
23
|
-
// EMBEDDED ONLY — enableHyDE not forwarded by HTTP API
|
|
24
|
-
await memory.search({ query: 'deployment config', strategy: 'hybrid', enableHyDE: true });
|
|
25
|
-
|
|
26
|
-
// With reranking (cross-encoder scores each result for precision)
|
|
27
|
-
// EMBEDDED ONLY — enableRerank not forwarded by HTTP API
|
|
28
|
-
await memory.search({ query: 'deployment config', strategy: 'hybrid', enableRerank: true });
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### Retrieval Pipeline (Hybrid Strategy)
|
|
32
|
-
|
|
33
|
-
```
|
|
34
|
-
Query → Stage 0: Transform (decompose, HyDE, multi-query)
|
|
35
|
-
→ Stage 1: Parallel retrieval (BM25/FTS5 + dense vector + graph traverse + community summaries)
|
|
36
|
-
→ Stage 2: RRF fusion (k=60) + dedup
|
|
37
|
-
→ Stage 3: Cross-encoder reranking → top-N
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## Bi-Temporal Model
|
|
43
|
-
|
|
44
|
-
Every entry tracks two timestamps for temporal reasoning:
|
|
45
|
-
|
|
46
|
-
- **`eventTime`**: When the fact/event actually occurred
|
|
47
|
-
- **`ingestTime`**: When it was stored in memory (auto-set)
|
|
48
|
-
|
|
49
|
-
**Sidecar note**: All `StoreInput` fields (including `eventTime`, `id`, `parentId`, `ingestTime`) are forwarded by `MemoryClient.store()`. Temporal search filters (`eventTimeRange`, `asOf`) are forwarded by `MemoryClient.search()`. However, `filters` (source, importanceMin, parentId, contentType), `enableHyDE`, and `enableRerank` are still not forwarded by the search endpoint.
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
// Store with explicit event time (works in both embedded and sidecar)
|
|
53
|
-
await memory.store({
|
|
54
|
-
content: 'User changed address to 123 Main St',
|
|
55
|
-
type: 'long-term',
|
|
56
|
-
metadata: {},
|
|
57
|
-
eventTime: '2026-01-15T00:00:00Z', // when it happened
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// Query as-of (available via MemoryClient.queryAsOf() or HTTP endpoint)
|
|
61
|
-
const snapshot = await memory.queryAsOf('2026-01-20T00:00:00Z', { type: 'long-term' });
|
|
62
|
-
|
|
63
|
-
// Query by event time range (available via MemoryClient.queryByEventTime() or HTTP endpoint)
|
|
64
|
-
const events = await memory.queryByEventTime('2026-01-01T00:00:00Z', '2026-02-01T00:00:00Z');
|
|
65
|
-
|
|
66
|
-
// Filter by event time range in search (EMBEDDED ONLY via filters param)
|
|
67
|
-
await memory.search({
|
|
68
|
-
query: 'address',
|
|
69
|
-
filters: { eventTimeRange: ['2026-01-01', '2026-02-01'] },
|
|
70
|
-
});
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
## Consolidation Pipeline
|
|
76
|
-
|
|
77
|
-
When `consolidate()` runs, it executes a 7-step pipeline:
|
|
78
|
-
|
|
79
|
-
1. **Extract facts** — LLM or regex extraction of factual statements
|
|
80
|
-
2. **Deduplicate** — Content hash + vector similarity (>0.90) → LLM classifies ADD/UPDATE/DELETE/NOOP
|
|
81
|
-
3. **Resolve conflicts** — Detect contradictions, resolve by recency and source trust
|
|
82
|
-
4. **Score importance** — LLM rates 1-10 (or heuristic: recency + access count + entity density)
|
|
83
|
-
5. **Enrich graph** — Extract entities and relationships, merge with existing graph
|
|
84
|
-
6. **Summarize** — Rolling session summaries, memory compaction
|
|
85
|
-
7. **Decay** — Archive entries below importance threshold: `importance * 0.995^hours * (1 + 0.02 * min(accessCount, 20)) * eventAgeFactor`
|
|
86
|
-
|
|
87
|
-
All steps have **non-LLM fallbacks** — consolidation works without an LLM, just less intelligently.
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## Community Detection
|
|
92
|
-
|
|
93
|
-
When a `graphStore` is configured, the system can detect communities of related entities using the Louvain algorithm:
|
|
94
|
-
|
|
95
|
-
```typescript
|
|
96
|
-
import { CommunityDetector } from '@pyx-memory/core';
|
|
97
|
-
|
|
98
|
-
const detector = new CommunityDetector(graphStore, llm);
|
|
99
|
-
const communities = await detector.detect();
|
|
100
|
-
// Each community: { id, nodeIds, summary? }
|
|
101
|
-
// Summaries are used by hybrid RAG for corpus-level queries
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
Communities are leveraged by the hybrid RAG strategy to answer broad "what are the themes" queries.
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
## Automatic Behaviors
|
|
109
|
-
|
|
110
|
-
These happen automatically — no configuration needed:
|
|
111
|
-
|
|
112
|
-
- **PII detection**: Every `store()` scans content and sets `metadata.piiDetected` + `metadata.piiTypes` if found
|
|
113
|
-
- **Content hashing**: Every `store()` computes SHA-256 `contentHash`
|
|
114
|
-
- **Access tracking**: Every `search()` increments `accessCount` and updates `lastAccessed` on returned entries
|
|
115
|
-
- **FTS5 sync**: SQLite triggers keep full-text search index in sync with memory_entries
|
|
116
|
-
- **Graph storage**: When `targets` includes `'graph'`, agent-provided `entities` are stored to the graph (best-effort — failures don't block store)
|
|
117
|
-
- **Auto-registration on import**: Importing `@pyx-memory/core` registers StubEmbeddingProvider, LanceDBProvider, and NaiveRAGEngine
|
|
118
|
-
- **Graph/Agentic RAG registration**: Memory constructor auto-registers GraphRAGEngine and AgenticRAGEngine when you pass `graphStore` or `reasoningProvider`
|
|
119
|
-
- **Agent scoping**: If `agentId` is set in MemoryOptions, all operations auto-filter by that agent
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## Initialization Sequence
|
|
124
|
-
|
|
125
|
-
```
|
|
126
|
-
1. (Optional) Create and await graphStore.initialize()
|
|
127
|
-
2. Construct: new Memory({ graphStore?, llm?, ... }) ← embedding is internal (BGE-M3)
|
|
128
|
-
3. Await: memory.initialize() ← creates SQLite DB + LanceDB vector store
|
|
129
|
-
4. Use: store(), search(), etc.
|
|
130
|
-
5. Cleanup: await memory.shutdown()
|
|
131
|
-
6. (Optional) await graphStore.shutdown()
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
**Memory.initialize()** creates:
|
|
135
|
-
- SQLite database at `{dataDir}/memory/memory.db` (with FTS5 + migrations)
|
|
136
|
-
- LanceDB vector store at `{dataDir}/vectors/`
|
|
137
|
-
- Both directories are created automatically (mkdirSync recursive)
|
|
138
|
-
|
|
139
|
-
**Memory does NOT** call `graphStore.initialize()` — you must do this yourself before or after constructing Memory, but before calling `memory.initialize()`.
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
# pyx-memory HTTP API Reference
|
|
2
|
-
|
|
3
|
-
## Authentication
|
|
4
|
-
|
|
5
|
-
When the server has `API_KEY` configured, all requests (except `/health`) require one of:
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
Authorization: Bearer <your-api-key>
|
|
9
|
-
X-API-Key: <your-api-key>
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
Destructive operations (DELETE, forget, decay, consolidate, reindex) require `ADMIN_API_KEY` when configured (falls back to `API_KEY`).
|
|
13
|
-
|
|
14
|
-
`MemoryClient` handles this automatically when `apiKey` is passed to the constructor:
|
|
15
|
-
```typescript
|
|
16
|
-
const client = new MemoryClient('http://localhost:7822', process.env.MEMORY_API_KEY);
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Core (10 endpoints)
|
|
20
|
-
|
|
21
|
-
| Method | Endpoint | Description |
|
|
22
|
-
|--------|----------|-------------|
|
|
23
|
-
| GET | `/health` | Public health check (status only — no internals exposed) |
|
|
24
|
-
| GET | `/admin/health` | Admin health check (version, uptime, embedding provider, memory stats) |
|
|
25
|
-
| POST | `/api/memory/ingest` | Store a memory (JSON: `{ content, type, metadata, agentId?, sessionId?, targets?, entities?, relationships?, importance?, source?, eventTime?, id?, parentId?, ingestTime? }`) |
|
|
26
|
-
| POST | `/api/memory/ingest/file` | Upload file (multipart, 50MB limit) |
|
|
27
|
-
| GET | `/api/memory/search?query=...&strategy=...&limit=...` | Search memories — **does NOT support** filters, enableHyDE, enableRerank |
|
|
28
|
-
| GET | `/api/memory/stats` | Memory statistics |
|
|
29
|
-
| GET | `/api/memory/entries?page=...&limit=...` | List entries (paginated) |
|
|
30
|
-
| GET | `/api/memory/entries/:id` | Get entry by ID |
|
|
31
|
-
| DELETE | `/api/memory/entries/:id` | Delete entry |
|
|
32
|
-
| DELETE | `/api/memory/sessions/:sessionId` | Clear session |
|
|
33
|
-
|
|
34
|
-
## Graph (4 endpoints)
|
|
35
|
-
|
|
36
|
-
| Method | Endpoint | Description |
|
|
37
|
-
|--------|----------|-------------|
|
|
38
|
-
| GET | `/api/memory/graph/nodes?name=...&type=...` | Find graph nodes |
|
|
39
|
-
| GET | `/api/memory/graph/edges` | Graph stats |
|
|
40
|
-
| GET | `/api/memory/graph/relationships` | List relationships |
|
|
41
|
-
| POST | `/api/memory/graph/query` | Traverse (JSON: `{ nodeId, depth? }`) |
|
|
42
|
-
|
|
43
|
-
## Lifecycle (9 endpoints)
|
|
44
|
-
|
|
45
|
-
| Method | Endpoint | Description |
|
|
46
|
-
|--------|----------|-------------|
|
|
47
|
-
| POST | `/api/memory/consolidate` | Run consolidation pipeline |
|
|
48
|
-
| POST | `/api/memory/forget/:id` | Soft-delete (JSON: `{ reason? }`) |
|
|
49
|
-
| POST | `/api/memory/sessions/:sid/summarize` | Summarize session |
|
|
50
|
-
| POST | `/api/memory/decay` | Run decay pass |
|
|
51
|
-
| POST | `/api/memory/reindex` | Rebuild FTS5 + vector indices |
|
|
52
|
-
| DELETE | `/api/memory/source/:source` | Delete by source |
|
|
53
|
-
| GET | `/api/memory/consolidation-log` | Audit trail |
|
|
54
|
-
| GET | `/api/memory/query-as-of?asOf=...` | Bi-temporal point-in-time query (asOf, type, agentId, source, limit) |
|
|
55
|
-
| GET | `/api/memory/query-by-event-time?startTime=...&endTime=...` | Bi-temporal event time range query (startTime, endTime, type, agentId, source, limit) |
|
|
56
|
-
|
|
57
|
-
## Response Format
|
|
58
|
-
|
|
59
|
-
All responses follow: `{ success: boolean, data?: T, error?: string }`
|
|
60
|
-
|
|
61
|
-
---
|
|
62
|
-
|
|
63
|
-
## Server Environment Variables
|
|
64
|
-
|
|
65
|
-
| Variable | Default | Description |
|
|
66
|
-
|----------|---------|-------------|
|
|
67
|
-
| `MEMORY_SERVER_PORT` | `7822` | HTTP server port |
|
|
68
|
-
| `DATA_DIR` | `./data` | Storage directory |
|
|
69
|
-
| ~~`EMBEDDING_PROVIDER`~~ | — | **Removed** — embedding is now internal (BGE-M3 via LocalEmbeddingProvider) |
|
|
70
|
-
| ~~`EMBEDDING_API_KEY`~~ | — | **Removed** — no external embedding provider needed |
|
|
71
|
-
| ~~`EMBEDDING_MODEL`~~ | — | **Removed** — model is always BGE-M3 (ONNX int8 quantized) |
|
|
72
|
-
| `EMBEDDING_DIMENSIONS` | `1024` | Dimension override for the internal LocalEmbeddingProvider (default: 1024) |
|
|
73
|
-
| `NEO4J_URL` | — | Neo4j bolt URL (enables Neo4j graph store) |
|
|
74
|
-
| `NEO4J_USERNAME` | `neo4j` | Neo4j username |
|
|
75
|
-
| `NEO4J_PASSWORD` | — | Neo4j password (never logged) |
|
|
76
|
-
| `API_KEY` | — | API key for authenticating requests. Unset = open access |
|
|
77
|
-
| `ADMIN_API_KEY` | — | Separate admin key for destructive ops (DELETE, forget, decay, consolidate, reindex). Falls back to `API_KEY` |
|
|
78
|
-
| `CORS_ORIGIN` | `*` | CORS allowed origin. Set to specific domain in production |
|
|
79
|
-
| `MAX_REQUEST_BODY_MB` | `10` | Maximum request body size in MB |
|
|
80
|
-
| `NODE_ENV` | `development` | Set to `production` to mask 5xx error details and enable HSTS |
|
|
81
|
-
| `PII_POLICY` | `flag` | PII handling: `flag` (detect + tag), `redact` (replace with [REDACTED]), `block` (reject 400) |
|
|
82
|
-
| `RATE_LIMIT_RPM` | `0` | Requests per minute per IP. 0 = disabled |
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
# Feature Parity: Embedded vs Sidecar
|
|
2
|
-
|
|
3
|
-
**Most features are available in both modes.** The HTTP API and MemoryClient forward all core `StoreInput` fields. A few advanced search parameters remain embedded-only.
|
|
4
|
-
|
|
5
|
-
## store() Field Parity
|
|
6
|
-
|
|
7
|
-
| Field | Embedded `Memory.store()` | Sidecar `MemoryClient.store()` |
|
|
8
|
-
|-------|--------------------------|-------------------------------|
|
|
9
|
-
| content | yes | yes |
|
|
10
|
-
| type | yes | yes |
|
|
11
|
-
| metadata | yes | yes |
|
|
12
|
-
| agentId | yes | yes |
|
|
13
|
-
| sessionId | yes | yes |
|
|
14
|
-
| targets | yes | yes |
|
|
15
|
-
| entities | yes | yes |
|
|
16
|
-
| relationships | yes | yes |
|
|
17
|
-
| importance | yes | yes |
|
|
18
|
-
| source | yes | yes |
|
|
19
|
-
| eventTime | yes | yes |
|
|
20
|
-
| id (custom) | yes | yes |
|
|
21
|
-
| parentId | yes | yes |
|
|
22
|
-
| ingestTime | yes | yes |
|
|
23
|
-
|
|
24
|
-
**All StoreInput fields are forwarded.** Full parity.
|
|
25
|
-
|
|
26
|
-
## search() Param Parity
|
|
27
|
-
|
|
28
|
-
| Param | Embedded `Memory.search()` | Sidecar `MemoryClient.search()` |
|
|
29
|
-
|-------|---------------------------|--------------------------------|
|
|
30
|
-
| query, limit, type, agentId, strategy | yes | yes |
|
|
31
|
-
| eventTimeRange (bi-temporal search) | yes | yes |
|
|
32
|
-
| asOf (point-in-time search) | yes | yes |
|
|
33
|
-
| **filters** (source, importanceMin, parentId, contentType) | yes | **NO** — not forwarded |
|
|
34
|
-
| **enableHyDE** | yes | **NO** — not forwarded |
|
|
35
|
-
| **enableRerank** | yes | **NO** — not forwarded |
|
|
36
|
-
|
|
37
|
-
**Impact**: Sidecar consumers cannot use advanced search filters, HyDE query expansion, or reranking. Temporal search filters (eventTimeRange, asOf) ARE supported.
|
|
38
|
-
|
|
39
|
-
## Endpoint Coverage by Client
|
|
40
|
-
|
|
41
|
-
| Server Endpoint | MemoryClient | DashboardClient |
|
|
42
|
-
|----------------|-------------|-----------------|
|
|
43
|
-
| All core (9) | yes | yes (inherited) |
|
|
44
|
-
| Graph nodes/edges/query (3) | yes (concrete methods) | yes (inherited) |
|
|
45
|
-
| **Graph relationships** | **NO** | yes (`graphRelationships()`) |
|
|
46
|
-
| All lifecycle (7) | yes | yes (inherited) |
|
|
47
|
-
| **Consolidation log** | **NO** | yes (`consolidationLog()`) |
|
|
48
|
-
| Query as-of (bi-temporal) | yes (`queryAsOf()`) | yes (inherited) |
|
|
49
|
-
| Query by event time | yes (`queryByEventTime()`) | yes (inherited) |
|
|
50
|
-
|
|
51
|
-
## Security Features (Server-side)
|
|
52
|
-
|
|
53
|
-
| Feature | Configuration |
|
|
54
|
-
|---------|--------------|
|
|
55
|
-
| API key auth | `API_KEY` env var (unset = open access) |
|
|
56
|
-
| Admin key for destructive ops | `ADMIN_API_KEY` env var |
|
|
57
|
-
| Rate limiting | `RATE_LIMIT_RPM` env var (0 = disabled) |
|
|
58
|
-
| CORS | `CORS_ORIGIN` env var (default: `*`) |
|
|
59
|
-
| Security headers | Always on (CSP, X-Frame-Options, nosniff) |
|
|
60
|
-
| HSTS | Auto-enabled when `NODE_ENV=production` |
|
|
61
|
-
| PII policy | `PII_POLICY` env var (`flag` / `redact` / `block`) |
|
|
62
|
-
| Body size limit | `MAX_REQUEST_BODY_MB` env var (default: 10) |
|
|
63
|
-
| Error masking | 5xx details hidden when `NODE_ENV=production` |
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
# pyx-memory Type Reference
|
|
2
|
-
|
|
3
|
-
## Contents
|
|
4
|
-
- Type Cheat Sheet
|
|
5
|
-
- MemoryInterface (9 methods)
|
|
6
|
-
- ExtendedMemoryInterface (6 lifecycle methods)
|
|
7
|
-
- MemoryClient Constructor and Concrete Methods
|
|
8
|
-
- DashboardClient
|
|
9
|
-
- MemorySearchResult, MemoryEntry, MemorySearchParams
|
|
10
|
-
- MemoryOptions Reference
|
|
11
|
-
- Embedding Dimension Defaults
|
|
12
|
-
|
|
13
|
-
## Type Cheat Sheet
|
|
14
|
-
|
|
15
|
-
| Type | Signature | Import From |
|
|
16
|
-
|------|-----------|-------------|
|
|
17
|
-
| `LLMCallback` | `(prompt: string) => Promise<string>` | `@pyx-memory/core` |
|
|
18
|
-
| `ReasoningProvider` | `(prompt: string) => Promise<string>` | `@pyx-memory/core` |
|
|
19
|
-
| `StoreInput` | `Omit<MemoryEntry, 'id' \| 'createdAt'> & { targets?, entities?, relationships? }` | `@pyx-memory/core` |
|
|
20
|
-
| `MemoryType` | `'short-term' \| 'long-term' \| 'working' \| 'episodic' \| 'summary'` | `@pyx-memory/shared` |
|
|
21
|
-
| `RAGStrategy` | `'naive' \| 'graph' \| 'agentic' \| 'hybrid'` | `@pyx-memory/shared` |
|
|
22
|
-
| `VectorProvider` | `'lancedb'` | `@pyx-memory/shared` |
|
|
23
|
-
| `StoreTarget` | `'sqlite' \| 'vector' \| 'graph'` | `@pyx-memory/shared` |
|
|
24
|
-
| `IngestEntity` | `{ name, type, properties? }` | `@pyx-memory/shared` |
|
|
25
|
-
| `IngestRelationship` | `{ source, target, type, properties? }` | `@pyx-memory/shared` |
|
|
26
|
-
| `EntityType` | `'PERSON' \| 'ORGANIZATION' \| 'CONCEPT' \| 'TOOL' \| 'LOCATION' \| 'EVENT'` | `@pyx-memory/core` |
|
|
27
|
-
| `RelationType` | `'USES' \| 'OWNS' \| 'DEPENDS_ON' \| 'RELATED_TO' \| 'CREATED_BY' \| 'PART_OF' \| 'IS_A' \| 'WORKS_AT' \| 'LOCATED_IN'` | `@pyx-memory/core` |
|
|
28
|
-
| `MemoryListParams` | `{ page?, limit?, type?, agentId? }` | `@pyx-memory/client` |
|
|
29
|
-
| `MemoryListResult` | `{ entries, totalCount, page, limit }` | `@pyx-memory/client` |
|
|
30
|
-
| `IngestionResult` | `{ filename, chunks, totalCharacters }` | `@pyx-memory/client` |
|
|
31
|
-
| `MemoryServerError` | `Error` with `.status` and `.isNotFound` | `@pyx-memory/client` |
|
|
32
|
-
| `GraphNode` | `{ id, name, type, properties, memoryEntryIds }` | `@pyx-memory/shared` |
|
|
33
|
-
| `GraphTraversalResult` | `{ nodes, relationships, paths }` | `@pyx-memory/shared` |
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## MemoryInterface (9 methods)
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
interface MemoryInterface {
|
|
41
|
-
initialize(): Promise<void>;
|
|
42
|
-
store(entry: Omit<MemoryEntry, 'id' | 'createdAt'> & { id?: string; createdAt?: string; targets?: StoreTarget[]; entities?: IngestEntity[]; relationships?: IngestRelationship[] }): Promise<MemoryEntry>;
|
|
43
|
-
search(params: MemorySearchParams): Promise<MemorySearchResult>;
|
|
44
|
-
list(params?: MemoryListParams): Promise<MemoryListResult>; // paginated entry listing
|
|
45
|
-
get(id: string): Promise<MemoryEntry | null>;
|
|
46
|
-
delete(id: string): Promise<boolean>;
|
|
47
|
-
clearSession(sessionId: string): Promise<number>;
|
|
48
|
-
stats(): Promise<MemoryStats>;
|
|
49
|
-
shutdown(): Promise<void>;
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## ExtendedMemoryInterface (adds 6 lifecycle methods)
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
interface ExtendedMemoryInterface extends MemoryInterface {
|
|
57
|
-
consolidate(): Promise<ConsolidationRunResult>;
|
|
58
|
-
forget(id: string, reason?: string): Promise<boolean>;
|
|
59
|
-
summarizeSession(sessionId: string): Promise<MemoryEntry | null>;
|
|
60
|
-
runDecay(): Promise<number>;
|
|
61
|
-
reindex(): Promise<void>;
|
|
62
|
-
deleteBySource(source: string): Promise<number>;
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## MemoryClient Constructor and Concrete Methods
|
|
67
|
-
|
|
68
|
-
```typescript
|
|
69
|
-
// Constructor: URL required, apiKey optional
|
|
70
|
-
const client = new MemoryClient('http://localhost:7822'); // no auth
|
|
71
|
-
const client = new MemoryClient('http://localhost:7822', 'my-api-key'); // with auth
|
|
72
|
-
const client = new MemoryClient('http://localhost:7822', process.env.MEMORY_API_KEY); // from env
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
When `apiKey` is provided, all requests include `Authorization: Bearer <key>`. Empty or whitespace-only keys are ignored.
|
|
76
|
-
|
|
77
|
-
`MemoryClient` implements `ExtendedMemoryInterface` AND has additional methods not on any interface.
|
|
78
|
-
Graph queries and file ingestion are available without `@pyx-memory/core`.
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
class MemoryClient implements ExtendedMemoryInterface {
|
|
82
|
-
// ... all 15 interface methods (9 base + 6 lifecycle) ...
|
|
83
|
-
|
|
84
|
-
// Graph operations (call pyx-memory server's graph endpoints)
|
|
85
|
-
graphNodes(): Promise<GraphNode[]>;
|
|
86
|
-
graphEdges(): Promise<{ stats: { nodeCount: number; edgeCount: number } }>;
|
|
87
|
-
graphQuery(query: { nodeId: string; depth?: number }): Promise<GraphTraversalResult>;
|
|
88
|
-
|
|
89
|
-
// File ingestion (multipart upload to server)
|
|
90
|
-
ingestFile(file: File): Promise<IngestionResult>;
|
|
91
|
-
|
|
92
|
-
// Bi-temporal queries
|
|
93
|
-
queryAsOf(asOf: string, filters?: TemporalQueryFilters): Promise<MemoryEntry[]>;
|
|
94
|
-
queryByEventTime(startTime: string, endTime: string, filters?: TemporalQueryFilters): Promise<MemoryEntry[]>;
|
|
95
|
-
}
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
**Key insight for consumers**: You do NOT need `@pyx-memory/core` for graph queries or file ingestion.
|
|
99
|
-
`MemoryClient` already proxies these through the HTTP API.
|
|
100
|
-
|
|
101
|
-
## DashboardClient (extends MemoryClient)
|
|
102
|
-
|
|
103
|
-
`DashboardClient` from `@pyx-memory/dashboard` adds dashboard-specific methods:
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
import { DashboardClient } from '@pyx-memory/dashboard';
|
|
107
|
-
|
|
108
|
-
class DashboardClient extends MemoryClient {
|
|
109
|
-
consolidationLog(limit?: number): Promise<ConsolidationLogEntry[]>;
|
|
110
|
-
graphRelationships(limit?: number): Promise<{ relationships: GraphRelationship[]; totalCount: number }>;
|
|
111
|
-
graphFull(limit?: number): Promise<{ nodes: GraphNode[]; relationships: GraphRelationship[] }>;
|
|
112
|
-
listEntriesPaginated(filters?: EntryFilters): Promise<PaginatedEntries>;
|
|
113
|
-
fetchHealthRaw(): Promise<RawHealthResponse>;
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
The dashboard package also provides: `Poller` (auto-polling), `computeMetrics()`, `computeTypeDistribution()`,
|
|
118
|
-
`enrichHealth()`, `transformGraphData()`, `toD3ForceFormat()`, `toGraphologyFormat()`, and React hooks
|
|
119
|
-
(`useMemoryStats`, `useMemoryEntries`, `useKnowledgeGraph`, `useConsolidationLog`, `useMemoryHealth`, `useTypeDistribution`).
|
|
120
|
-
|
|
121
|
-
## MemorySearchResult
|
|
122
|
-
|
|
123
|
-
```typescript
|
|
124
|
-
interface MemorySearchResult {
|
|
125
|
-
entries: MemoryEntry[];
|
|
126
|
-
totalCount: number;
|
|
127
|
-
strategy: RAGStrategy;
|
|
128
|
-
scoredEntries?: Array<{ entry: MemoryEntry; score: number }>; // ranked results with relevance scores
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
## MemoryEntry (full shape)
|
|
133
|
-
|
|
134
|
-
```typescript
|
|
135
|
-
interface MemoryEntry {
|
|
136
|
-
id: string;
|
|
137
|
-
content: string;
|
|
138
|
-
type: MemoryType;
|
|
139
|
-
agentId?: string;
|
|
140
|
-
sessionId?: string;
|
|
141
|
-
metadata: Record<string, unknown>;
|
|
142
|
-
embedding?: number[]; // @deprecated — managed internally by vector store
|
|
143
|
-
createdAt: string; // ISO 8601
|
|
144
|
-
contentHash?: string; // SHA-256
|
|
145
|
-
importance?: number; // 1-10
|
|
146
|
-
accessCount?: number;
|
|
147
|
-
lastAccessed?: string; // ISO 8601
|
|
148
|
-
parentId?: string; // hierarchical storage
|
|
149
|
-
source?: string; // filename, URL, session ID
|
|
150
|
-
eventTime?: string; // when event happened (bi-temporal)
|
|
151
|
-
ingestTime?: string; // when stored (bi-temporal)
|
|
152
|
-
}
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
## MemorySearchParams + SearchFilters
|
|
156
|
-
|
|
157
|
-
```typescript
|
|
158
|
-
interface MemorySearchParams {
|
|
159
|
-
query: string;
|
|
160
|
-
type?: MemoryType;
|
|
161
|
-
agentId?: string;
|
|
162
|
-
limit?: number; // default varies by engine
|
|
163
|
-
strategy?: RAGStrategy; // default: 'naive'
|
|
164
|
-
filters?: SearchFilters;
|
|
165
|
-
enableHyDE?: boolean; // Hypothetical Document Embedding for query expansion
|
|
166
|
-
enableRerank?: boolean; // Cross-encoder reranking of results
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
interface SearchFilters {
|
|
170
|
-
source?: string;
|
|
171
|
-
importanceMin?: number;
|
|
172
|
-
eventTimeRange?: [string, string]; // [start, end] ISO timestamps
|
|
173
|
-
parentId?: string;
|
|
174
|
-
contentType?: string;
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## MemoryOptions Reference
|
|
179
|
-
|
|
180
|
-
> **Embedding is internal** — pyx-memory uses `LocalEmbeddingProvider` with BGE-M3 (1024d) automatically. You do NOT pass an `embedder` option.
|
|
181
|
-
|
|
182
|
-
| Field | Type | Required | Default | Notes |
|
|
183
|
-
|-------|------|----------|---------|-------|
|
|
184
|
-
| `dataDir` | `string` | no | `'./data'` | Use `':memory:'` for tests (LanceDB still writes to `/tmp`) |
|
|
185
|
-
| `vectorProvider` | `VectorProvider` | no | `'lancedb'` | |
|
|
186
|
-
| `dimensions` | `number` | no | `1024` | Default: 1024 (matches internal BGE-M3 model) |
|
|
187
|
-
| `graphStore` | `GraphStore` | no | `undefined` | Enables graph target in store routing |
|
|
188
|
-
| `reasoningProvider` | `ReasoningProvider` | no | `undefined` | Enables agentic RAG |
|
|
189
|
-
| `llm` | `LLMCallback` | no | `undefined` | Enables LLM-powered lifecycle (consolidation, summarization, scoring) |
|
|
190
|
-
| `skipDuplicates` | `boolean` | no | `false` | Content-hash dedup on store |
|
|
191
|
-
| `agentId` | `string` | no | `undefined` | Auto-scopes ALL store/search/stats/decay operations to this agent |
|
|
192
|
-
| `qdrantUrl` | `string` | no | `undefined` | @deprecated — Qdrant support is vestigial |
|
|
193
|
-
|
|
194
|
-
## Embedding Dimension Defaults by Provider
|
|
195
|
-
|
|
196
|
-
> **Memory always uses `LocalEmbeddingProvider` internally.** The other providers are available for standalone use but are not used by the `Memory` class.
|
|
197
|
-
|
|
198
|
-
| Provider | Default Dimensions | Model |
|
|
199
|
-
|----------|-------------------|-------|
|
|
200
|
-
| `StubEmbeddingProvider` | 1024 | hash-based (testing only) |
|
|
201
|
-
| `OpenAIEmbeddingProvider` | 1536 | text-embedding-3-small |
|
|
202
|
-
| `AnthropicEmbeddingProvider` | 1024 | voyage-3 (Voyage AI) |
|
|
203
|
-
| `LocalEmbeddingProvider` | 1024 | BGE-M3 (ONNX int8 quantized) |
|