@pyxmate/memory 0.20.5 → 0.21.2
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/LICENSE +1 -1
- package/README.md +63 -34
- package/dist/chunk-7P6ASYW6.mjs +9 -0
- package/dist/cli/pyx-mem.mjs +15744 -0
- package/dist/dashboard.mjs +1 -0
- package/dist/index.mjs +1 -0
- package/dist/react.mjs +1 -0
- package/package.json +7 -4
- package/bin/init.mjs +0 -672
- package/skills/pyx-memory/SKILL.md +0 -128
- package/skills/pyx-memory/examples/disabled-memory.ts +0 -53
- package/skills/pyx-memory/examples/minimal-embedded.ts +0 -37
- package/skills/pyx-memory/examples/minimal-sidecar.ts +0 -14
- package/skills/pyx-memory/patterns/access-control.md +0 -586
- package/skills/pyx-memory/patterns/consumer.md +0 -129
- package/skills/pyx-memory/patterns/embedded.md +0 -249
- package/skills/pyx-memory/patterns/file-uploads.md +0 -78
- package/skills/pyx-memory/reference/advanced.md +0 -274
- package/skills/pyx-memory/reference/http-api.md +0 -526
- package/skills/pyx-memory/reference/parity.md +0 -74
- package/skills/pyx-memory/reference/sdk-guide.md +0 -233
- package/skills/pyx-memory/reference/types.md +0 -344
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
# pyx-memory SDK Integration Guide
|
|
2
|
-
|
|
3
|
-
Reference for integrating pyx-memory into TypeScript/Bun projects.
|
|
4
|
-
Runtime requirement: **Bun v1.2+** (not Node.js). Uses `bun:sqlite` natively.
|
|
5
|
-
|
|
6
|
-
## Quick Decision Tree
|
|
7
|
-
|
|
8
|
-
```
|
|
9
|
-
Building pyx-memory itself or its server?
|
|
10
|
-
→ Embedded mode: import { Memory } from '@pyx-memory/core'
|
|
11
|
-
|
|
12
|
-
Consuming pyx-memory from another project?
|
|
13
|
-
→ Sidecar mode: import { MemoryClient } from '@pyx-memory/client'
|
|
14
|
-
→ ONLY depend on @pyx-memory/client + @pyx-memory/shared
|
|
15
|
-
→ Do NOT import @pyx-memory/core — that's pyx-memory's internal implementation
|
|
16
|
-
→ See patterns/consumer.md
|
|
17
|
-
|
|
18
|
-
Need memory in your process (best perf, full feature set)?
|
|
19
|
-
→ Embedded mode: import { Memory } from '@pyx-memory/core'
|
|
20
|
-
|
|
21
|
-
Need memory as a separate service (HTTP)?
|
|
22
|
-
→ Sidecar mode: import { MemoryClient } from '@pyx-memory/client'
|
|
23
|
-
|
|
24
|
-
Need to switch modes via config?
|
|
25
|
-
→ Factory: import { createMemory } from '@pyx-memory/core'
|
|
26
|
-
- Returns MemoryInterface (base interface — no lifecycle methods)
|
|
27
|
-
- If you need consolidate/decay/summarize, use `new Memory()` directly
|
|
28
|
-
|
|
29
|
-
Need lifecycle methods (consolidate, decay, summarize)?
|
|
30
|
-
→ Use `new Memory(opts)` — returns ExtendedMemoryInterface
|
|
31
|
-
→ Or `new MemoryClient(url)` — also implements ExtendedMemoryInterface
|
|
32
|
-
→ NOT createMemory() — it returns MemoryInterface (missing lifecycle methods)
|
|
33
|
-
|
|
34
|
-
Need dashboard features (consolidation log, graph visualization)?
|
|
35
|
-
→ Use `DashboardClient` from '@pyx-memory/dashboard'
|
|
36
|
-
→ Extends MemoryClient with additional methods
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Minimal Working Example (Embedded)
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
import { Memory } from '@pyx-memory/core';
|
|
43
|
-
|
|
44
|
-
const memory = new Memory({ dataDir: './data' });
|
|
45
|
-
await memory.initialize(); // REQUIRED — throws if you skip this
|
|
46
|
-
|
|
47
|
-
await memory.store({
|
|
48
|
-
content: 'User prefers dark mode',
|
|
49
|
-
type: 'long-term',
|
|
50
|
-
metadata: { source: 'settings' },
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
// Store with entities — graph is populated automatically when graphStore configured
|
|
54
|
-
await memory.store({
|
|
55
|
-
content: 'Alice works at Acme Corp',
|
|
56
|
-
type: 'long-term',
|
|
57
|
-
metadata: {},
|
|
58
|
-
entities: [
|
|
59
|
-
{ name: 'Alice', type: 'PERSON' },
|
|
60
|
-
{ name: 'Acme Corp', type: 'ORGANIZATION' },
|
|
61
|
-
],
|
|
62
|
-
relationships: [{ source: 'Alice', target: 'Acme Corp', type: 'WORKS_AT' }],
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const results = await memory.search({ query: 'user preferences', limit: 5 });
|
|
66
|
-
|
|
67
|
-
await memory.shutdown(); // REQUIRED — releases SQLite + LanceDB resources
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Minimal Working Example (Sidecar / HTTP)
|
|
71
|
-
|
|
72
|
-
```typescript
|
|
73
|
-
import { MemoryClient } from '@pyx-memory/client';
|
|
74
|
-
|
|
75
|
-
const memory = new MemoryClient('http://localhost:7822');
|
|
76
|
-
|
|
77
|
-
// With auth (production)
|
|
78
|
-
const authedMemory = new MemoryClient('http://localhost:7822', process.env.MEMORY_API_KEY);
|
|
79
|
-
|
|
80
|
-
// With auth + multi-tenant headers (production, multi-tenant mode)
|
|
81
|
-
const tenantMemory = new MemoryClient('http://localhost:7822', {
|
|
82
|
-
apiKey: process.env.MEMORY_API_KEY,
|
|
83
|
-
defaultHeaders: {
|
|
84
|
-
'X-Tenant-Id': 'tenant-abc',
|
|
85
|
-
'X-User-Id': 'user-123',
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
await memory.initialize(); // verifies server connectivity via /health
|
|
90
|
-
|
|
91
|
-
await memory.store({ content: 'Important fact', type: 'long-term', metadata: {} });
|
|
92
|
-
const results = await memory.search({ query: 'fact', limit: 5 });
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Start the server: `bun packages/server/src/index.ts`
|
|
96
|
-
|
|
97
|
-
## Package Map
|
|
98
|
-
|
|
99
|
-
```
|
|
100
|
-
@pyx-memory/shared → Types + constants only (zero runtime code)
|
|
101
|
-
↑ ↑
|
|
102
|
-
| |
|
|
103
|
-
@pyx-memory/client → MemoryInterface, ExtendedMemoryInterface, MemoryClient
|
|
104
|
-
↑
|
|
105
|
-
|
|
|
106
|
-
@pyx-memory/core → Memory class, embeddings, graph, RAG, ingestion, lifecycle
|
|
107
|
-
↑ (re-exports everything from client and shared)
|
|
108
|
-
|
|
|
109
|
-
@pyx-memory/server → HTTP sidecar server (25 endpoints)
|
|
110
|
-
|
|
111
|
-
@pyx-memory/dashboard → DashboardClient (extends MemoryClient), React hooks,
|
|
112
|
-
Poller, aggregations, graph transforms (D3/Graphology)
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
**Import rules:**
|
|
116
|
-
- **Embedded mode**: Import everything from `@pyx-memory/core` (it re-exports client + shared)
|
|
117
|
-
- **Sidecar mode (client only)**: Import from `@pyx-memory/client` (+ types from `@pyx-memory/shared`)
|
|
118
|
-
- **Dashboard features**: Import from `@pyx-memory/dashboard` (extends client with extra methods)
|
|
119
|
-
- **Types only**: Import from `@pyx-memory/shared`
|
|
120
|
-
- **Consumer projects**: ONLY use `@pyx-memory/client` + `@pyx-memory/shared` — never `@pyx-memory/core`
|
|
121
|
-
|
|
122
|
-
## DO / DON'T
|
|
123
|
-
|
|
124
|
-
### DO
|
|
125
|
-
|
|
126
|
-
- **DO** call `await memory.initialize()` before any operation
|
|
127
|
-
- **DO** call `await memory.shutdown()` when done (releases SQLite + LanceDB)
|
|
128
|
-
- **DO** provide `entities` to populate the graph
|
|
129
|
-
- **DO** initialize GraphStore BEFORE constructing Memory
|
|
130
|
-
- **DO** use `new Memory()` when you need lifecycle methods (ExtendedMemoryInterface)
|
|
131
|
-
- **DO** use `':memory:'` dataDir for tests
|
|
132
|
-
- **DO** handle `MemoryServerError` in sidecar mode (has `.status` and `.isNotFound`)
|
|
133
|
-
- **DO** implement `DisabledMemory` (no-op) for graceful degradation when memory is unavailable
|
|
134
|
-
- **DO** set `tenantId` on `MemoryOptions` or pass `X-Tenant-Id` header for multi-tenant deployments
|
|
135
|
-
- **DO** use `MemoryClientOptions` with `defaultHeaders` for tenant/access-level headers in sidecar mode
|
|
136
|
-
|
|
137
|
-
### DON'T
|
|
138
|
-
|
|
139
|
-
- **DON'T** assume `createMemory()` returns `ExtendedMemoryInterface` — it returns `MemoryInterface`
|
|
140
|
-
- **DON'T** use `targets: ['graph']` without a configured `graphStore` — throws MemoryError
|
|
141
|
-
- **DON'T** use `strategy: 'graph'` without passing `graphStore`
|
|
142
|
-
- **DON'T** use `strategy: 'agentic'` without passing `reasoningProvider`
|
|
143
|
-
- **DON'T** construct multiple Memory instances with the same `dataDir` — LanceDB singleton causes conflicts
|
|
144
|
-
- **DON'T** use `':memory:'` in production — LanceDB still writes to `/tmp/autonomy-vectors`
|
|
145
|
-
- **DON'T** expose the server without configuring `API_KEY` for network deployments
|
|
146
|
-
- **DON'T** run `TENANT_MODE=multi` without `API_KEY` — multi-tenant without auth is dangerous
|
|
147
|
-
- **DON'T** import `@pyx-memory/core` in consumer projects — use `@pyx-memory/client`
|
|
148
|
-
- **DON'T** expect `filters`, `enableHyDE`, or `enableRerank` to work in sidecar mode
|
|
149
|
-
|
|
150
|
-
## Post-Integration Checklist
|
|
151
|
-
|
|
152
|
-
```bash
|
|
153
|
-
bun .claude/skills/pyx-memory/scripts/diagnose-integration.ts --json
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
Interpret `verdict`: `"healthy"` = done, otherwise fix each `criticalIssues` entry and re-run.
|
|
157
|
-
|
|
158
|
-
**Common failure: DisabledMemory (no-op)**
|
|
159
|
-
If `MEMORY_URL` is not set, the client silently falls back to a no-op implementation. The diagnostic tool detects this via checks S5 and I1.
|
|
160
|
-
|
|
161
|
-
## Error Types
|
|
162
|
-
|
|
163
|
-
```
|
|
164
|
-
MemoryError (base)
|
|
165
|
-
├── MemoryStoreError — SQLite store failures
|
|
166
|
-
├── MemoryNotFoundError — entry not found
|
|
167
|
-
├── MemorySearchError — search failures
|
|
168
|
-
├── VectorProviderError — LanceDB/vector issues
|
|
169
|
-
├── EmbeddingError — embedding generation failures
|
|
170
|
-
├── MigrationError — schema migration issues
|
|
171
|
-
├── IngestionError — file parsing / ingestion failures
|
|
172
|
-
├── LifecycleError — consolidation / decay failures
|
|
173
|
-
└── GraphError — graph store operations
|
|
174
|
-
|
|
175
|
-
MemoryServerError — HTTP client errors (has .status, .isNotFound)
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
All from `@pyx-memory/core` except `MemoryServerError` from `@pyx-memory/client`.
|
|
179
|
-
|
|
180
|
-
## Two-Phase PDF Enrichment
|
|
181
|
-
|
|
182
|
-
When ingesting PDFs that contain images, `ingestFileEvents()` runs a three-phase enrichment flow via `EnrichmentCallbacks`. The SDK handles all phases automatically and emits typed `IngestEvent`s as it goes:
|
|
183
|
-
|
|
184
|
-
1. **Server upload** — text extracted and stored immediately; server emits `progress` events with stage `parsing` then `storing`
|
|
185
|
-
2. **Image description** — each extracted image is fetched and described via your LLM vision callback (batched, 5 concurrent); SDK emits `progress`/`heartbeat` events with stage `enrichment`
|
|
186
|
-
3. **Enrichment write** — descriptions + entities POSTed back to the server's `/enrich` endpoint; SDK emits the terminal `result` event
|
|
187
|
-
|
|
188
|
-
```typescript
|
|
189
|
-
import { MemoryClient, type EnrichmentCallbacks, type FileIngestResult } from '@pyxmate/memory';
|
|
190
|
-
|
|
191
|
-
const memory = new MemoryClient('http://localhost:7822', apiKey);
|
|
192
|
-
|
|
193
|
-
const enrichment: EnrichmentCallbacks = {
|
|
194
|
-
// Optional: describe each image using LLM vision
|
|
195
|
-
describeImage: async (imageBuffer, meta) => {
|
|
196
|
-
// imageBuffer is ArrayBuffer of the extracted PNG/JPEG
|
|
197
|
-
// meta has: imageId, pageNumber, width, height, mimeType
|
|
198
|
-
return await myVisionModel.describe(imageBuffer);
|
|
199
|
-
},
|
|
200
|
-
// Optional: extract entities from text windows + image descriptions
|
|
201
|
-
extractEntitiesV2: async ({ textWindows, imageDescriptions, filename, mimeType }) => ({
|
|
202
|
-
entities: [{ name: 'Revenue', type: 'METRIC' }],
|
|
203
|
-
relationships: [{ source: 'Revenue', target: 'Q4', type: 'RELATED_TO' }],
|
|
204
|
-
}),
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
let result: FileIngestResult | null = null;
|
|
208
|
-
for await (const event of memory.ingestFileEvents(pdfFile, { enrichment })) {
|
|
209
|
-
if (event.type === 'progress') {
|
|
210
|
-
console.log(`[${event.stage}] ${event.message ?? ''}`);
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
if (event.type === 'error') {
|
|
214
|
-
// Enrichment-stage errors (e.g. extractEntitiesV2 throws on a 401 storm)
|
|
215
|
-
// carry the server's pre-enrichment FileIngestResult under
|
|
216
|
-
// `partialResult` — the chunks/entryIds/catalog are durably stored.
|
|
217
|
-
// Persist them BEFORE surfacing the error so vector retrieval keeps
|
|
218
|
-
// working on the file. Parsing/storing/transport errors do not set it.
|
|
219
|
-
if (event.partialResult) {
|
|
220
|
-
result = event.partialResult;
|
|
221
|
-
// surface a "partial" status to the user, then throw to mark failure
|
|
222
|
-
}
|
|
223
|
-
throw new Error(event.message ?? event.error);
|
|
224
|
-
}
|
|
225
|
-
if (event.type === 'result') {
|
|
226
|
-
const { schemaVersion: _v, type: _t, stage: _s, message: _m, ...payload } = event;
|
|
227
|
-
result = payload;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
if (!result) throw new Error('memory ingest stream ended without a result');
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
Without `enrichment` callbacks, the stream still emits `parsing` → `storing` progress events and a terminal `result` — the SDK just skips Phase 2/3.
|
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
# pyx-memory Type Reference
|
|
2
|
-
|
|
3
|
-
## Contents
|
|
4
|
-
- Type Cheat Sheet
|
|
5
|
-
- MemoryInterface (9 methods)
|
|
6
|
-
- ExtendedMemoryInterface (10 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
|
-
| `TenantScopeOptions` | `{ tenantId? }` | `@pyx-memory/client` |
|
|
29
|
-
| `SensitivityLevel` | `'public' \| 'internal' \| 'secret'` | `@pyx-memory/shared` |
|
|
30
|
-
| `MemoryClientOptions` | `{ apiKey?, defaultHeaders? }` | `@pyx-memory/client` |
|
|
31
|
-
| `MemoryListParams` | `{ page?, limit?, type?, agentId?, tenantId? }` | `@pyx-memory/client` |
|
|
32
|
-
| `MemoryListResult` | `{ entries, totalCount, page, limit }` | `@pyx-memory/client` |
|
|
33
|
-
| `IngestionResult` | `{ filename, chunks, totalCharacters }` | `@pyx-memory/client` |
|
|
34
|
-
| `FileIngestResult` | `IngestionResult & { enrichment?: EnrichmentPending }` | `@pyx-memory/shared` |
|
|
35
|
-
| `EnrichmentPending` | `{ fileId, token, expiresAt, images: ExtractedImageMeta[] }` | `@pyx-memory/shared` |
|
|
36
|
-
| `ExtractedImageMeta` | `{ imageId, pageNumber, width, height, mimeType }` | `@pyx-memory/shared` |
|
|
37
|
-
| `EnrichmentCallbacks` | `{ describeImage, extractEntities? }` | `@pyx-memory/client` |
|
|
38
|
-
| `EnrichRequest` | `{ imageDescriptions, entities?, relationships? }` | `@pyx-memory/shared` |
|
|
39
|
-
| `EnrichResult` | `{ entryIds, entitiesStored, relationshipsStored }` | `@pyx-memory/shared` |
|
|
40
|
-
| `ImageDescription` | `{ imageId, description }` | `@pyx-memory/shared` |
|
|
41
|
-
| `MemoryServerError` | `Error` with `.status` and `.isNotFound` | `@pyx-memory/client` |
|
|
42
|
-
| `GraphNode` | `{ id, name, type, properties, memoryEntryIds }` | `@pyx-memory/shared` |
|
|
43
|
-
| `GraphTraversalResult` | `{ nodes, relationships, paths }` | `@pyx-memory/shared` |
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## MemoryInterface (9 methods)
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
interface MemoryInterface {
|
|
51
|
-
initialize(): Promise<void>;
|
|
52
|
-
store(entry: Omit<MemoryEntry, 'id' | 'createdAt'> & { id?: string; createdAt?: string; targets?: StoreTarget[]; entities?: IngestEntity[]; relationships?: IngestRelationship[] }): Promise<MemoryEntry>;
|
|
53
|
-
search(params: MemorySearchParams): Promise<MemorySearchResult>;
|
|
54
|
-
list(params?: MemoryListParams): Promise<MemoryListResult>; // paginated entry listing
|
|
55
|
-
get(id: string, options?: TenantScopeOptions): Promise<MemoryEntry | null>;
|
|
56
|
-
delete(id: string, options?: TenantScopeOptions): Promise<boolean>;
|
|
57
|
-
clearSession(sessionId: string, options?: TenantScopeOptions): Promise<number>;
|
|
58
|
-
stats(options?: TenantScopeOptions): Promise<MemoryStats>;
|
|
59
|
-
queryAsOf(asOfDate: string, filters?: TemporalQueryFilters): Promise<MemoryEntry[]>;
|
|
60
|
-
queryByEventTime(startTime: string, endTime: string, filters?: TemporalQueryFilters): Promise<MemoryEntry[]>;
|
|
61
|
-
shutdown(): Promise<void>;
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## ExtendedMemoryInterface (adds 10 lifecycle methods)
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
interface ExtendedMemoryInterface extends MemoryInterface {
|
|
69
|
-
consolidate(): Promise<ConsolidationRunResult>;
|
|
70
|
-
forget(id: string, reason?: string): Promise<boolean>;
|
|
71
|
-
summarizeSession(sessionId: string): Promise<MemoryEntry | null>;
|
|
72
|
-
runDecay(): Promise<number>;
|
|
73
|
-
reindex(): Promise<void>;
|
|
74
|
-
deleteBySource(source: string): Promise<number>;
|
|
75
|
-
// v0.18.0 — read-only memory-wide lint report (graph orphans, decay
|
|
76
|
-
// candidates, stale syntheses, content-hash dedup candidates).
|
|
77
|
-
lint(options?: { limit?: number }): Promise<WikiLintReport>;
|
|
78
|
-
// v0.18.1 — chronological feed (Karpathy log.md primitive). Cursor-style
|
|
79
|
-
// via `since` (created_at lower bound). No totalCount.
|
|
80
|
-
log(filters?: MemoryLogFilters): Promise<MemoryEntry[]>;
|
|
81
|
-
// v0.19.0 — entity synthesis (Karpathy "wiki page" primitive).
|
|
82
|
-
// summarizeEntity is LLM-driven and caller-triggered; it stores a pinned
|
|
83
|
-
// `_kind:'entity-summary'` entry with `_search_visibility:'on-demand'`
|
|
84
|
-
// (excluded from search). getEntitySynthesis is the O(1) read path.
|
|
85
|
-
summarizeEntity(name: string): Promise<MemoryEntry>;
|
|
86
|
-
getEntitySynthesis(name: string): Promise<MemoryEntry | null>;
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
`MemoryLogFilters` = `{ since?: string; limit?: number; type?: MemoryType; agentId?: string; source?: string }`.
|
|
91
|
-
|
|
92
|
-
### Reserved metadata conventions
|
|
93
|
-
|
|
94
|
-
Some `metadata` keys carry behavior, not just data:
|
|
95
|
-
|
|
96
|
-
| Key | Value | Effect |
|
|
97
|
-
|-----|-------|--------|
|
|
98
|
-
| `_search_visibility` | `'on-demand'` | Entry is excluded from every RAG engine's retrieval pool (v0.18.2 hook). Still reachable via `get` / `list` / `log` and deterministic-id fetch. Field absent ⇒ visible. |
|
|
99
|
-
| `_kind` | `'entity-summary'` | Marks an entity synthesis. `Memory.lint` flags stale ones; the `synthesis:` id prefix is reserved for entries carrying this. |
|
|
100
|
-
| `_sourceEntryIds` | `string[]` | Provenance — the entries a synthesis was built from. |
|
|
101
|
-
| `_maxEventTime` | ISO string \| null | Staleness contract — `lint` flags the synthesis when a source's eventTime later exceeds this. |
|
|
102
|
-
|
|
103
|
-
## MemoryClient Constructor and Concrete Methods
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
// Constructor: URL required, second param is string (apiKey) or MemoryClientOptions
|
|
107
|
-
const client = new MemoryClient('http://localhost:7822'); // no auth
|
|
108
|
-
const client = new MemoryClient('http://localhost:7822', 'my-api-key'); // with auth (string shorthand)
|
|
109
|
-
const client = new MemoryClient('http://localhost:7822', process.env.MEMORY_API_KEY); // from env
|
|
110
|
-
|
|
111
|
-
// Advanced: options object with default headers (e.g., multi-tenant access control)
|
|
112
|
-
const client = new MemoryClient('http://localhost:7822', {
|
|
113
|
-
apiKey: 'my-api-key',
|
|
114
|
-
defaultHeaders: {
|
|
115
|
-
'X-Tenant-Id': 'tenant-abc',
|
|
116
|
-
'X-Caller-Access-Level': 'internal',
|
|
117
|
-
},
|
|
118
|
-
});
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
When `apiKey` is provided, all requests include `Authorization: Bearer <key>`. Empty or whitespace-only keys are ignored. Default headers are merged into every request.
|
|
122
|
-
|
|
123
|
-
`MemoryClient` implements `ExtendedMemoryInterface` AND has additional methods not on any interface.
|
|
124
|
-
Graph queries and file ingestion are available without `@pyx-memory/core`.
|
|
125
|
-
|
|
126
|
-
```typescript
|
|
127
|
-
class MemoryClient implements ExtendedMemoryInterface {
|
|
128
|
-
// ... all 19 interface methods (9 base + 10 lifecycle) ...
|
|
129
|
-
|
|
130
|
-
// Graph operations (call pyx-memory server's graph endpoints)
|
|
131
|
-
graphNodes(): Promise<GraphNode[]>;
|
|
132
|
-
graphEdges(): Promise<{ stats: { nodeCount: number; edgeCount: number } }>;
|
|
133
|
-
graphQuery(query: { nodeId: string; depth?: number }): Promise<GraphTraversalResult>;
|
|
134
|
-
|
|
135
|
-
// File ingestion — native NDJSON streaming (v0.15.0+)
|
|
136
|
-
// Yields typed IngestEvents (progress / heartbeat / result / error).
|
|
137
|
-
// With enrichment callbacks: fetches extracted images, calls describeImage,
|
|
138
|
-
// calls extractEntitiesV2, posts /enrich, then yields the terminal `result`.
|
|
139
|
-
ingestFileEvents(file: File, options?: IngestFileOptions): AsyncIterable<IngestEvent>;
|
|
140
|
-
|
|
141
|
-
// Bi-temporal queries
|
|
142
|
-
queryAsOf(asOf: string, filters?: TemporalQueryFilters): Promise<MemoryEntry[]>;
|
|
143
|
-
queryByEventTime(startTime: string, endTime: string, filters?: TemporalQueryFilters): Promise<MemoryEntry[]>;
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
**Key insight for consumers**: You do NOT need `@pyx-memory/core` for graph queries or file ingestion.
|
|
148
|
-
`MemoryClient` already proxies these through the HTTP API.
|
|
149
|
-
|
|
150
|
-
## DashboardClient (extends MemoryClient)
|
|
151
|
-
|
|
152
|
-
`DashboardClient` from `@pyx-memory/dashboard` adds dashboard-specific methods:
|
|
153
|
-
|
|
154
|
-
```typescript
|
|
155
|
-
import { DashboardClient } from '@pyx-memory/dashboard';
|
|
156
|
-
|
|
157
|
-
class DashboardClient extends MemoryClient {
|
|
158
|
-
consolidationLog(limit?: number): Promise<ConsolidationLogEntry[]>;
|
|
159
|
-
graphRelationships(limit?: number): Promise<{ relationships: GraphRelationship[]; totalCount: number }>;
|
|
160
|
-
graphFull(limit?: number): Promise<{ nodes: GraphNode[]; relationships: GraphRelationship[] }>;
|
|
161
|
-
listEntriesPaginated(filters?: EntryFilters): Promise<PaginatedEntries>;
|
|
162
|
-
fetchHealthRaw(): Promise<RawHealthResponse>;
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
The dashboard package also provides: `Poller` (auto-polling), `computeMetrics()`, `computeTypeDistribution()`,
|
|
167
|
-
`enrichHealth()`, `transformGraphData()`, `toD3ForceFormat()`, `toGraphologyFormat()`, and React hooks
|
|
168
|
-
(`useMemoryStats`, `useMemoryEntries`, `useKnowledgeGraph`, `useConsolidationLog`, `useMemoryHealth`, `useTypeDistribution`).
|
|
169
|
-
|
|
170
|
-
## MemorySearchResult
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
interface MemorySearchResult {
|
|
174
|
-
entries: MemoryEntry[];
|
|
175
|
-
totalCount: number;
|
|
176
|
-
strategy: RAGStrategy;
|
|
177
|
-
scoredEntries?: Array<{ entry: MemoryEntry; score: number }>; // ranked results with relevance scores
|
|
178
|
-
confidence?: { // present when abstentionThreshold is set or strategy uses scoring
|
|
179
|
-
confidence: number; // 0-1 confidence score
|
|
180
|
-
shouldAbstain: boolean; // true when confidence < abstentionThreshold
|
|
181
|
-
signals: {
|
|
182
|
-
topScore: number; // magnitude of the highest-scoring result
|
|
183
|
-
scoreGap: number; // difference between #1 and #2 results
|
|
184
|
-
scoreStdDev: number; // spread of scores (high = clear winner)
|
|
185
|
-
resultCount: number; // how many results were returned
|
|
186
|
-
aboveThresholdRatio: number; // fraction of results above threshold
|
|
187
|
-
scoreSeparation: number; // how much top-1 stands out from the pack
|
|
188
|
-
};
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## MemoryEntry (full shape)
|
|
194
|
-
|
|
195
|
-
```typescript
|
|
196
|
-
interface MemoryEntry {
|
|
197
|
-
id: string;
|
|
198
|
-
content: string;
|
|
199
|
-
type: MemoryType;
|
|
200
|
-
agentId?: string;
|
|
201
|
-
sessionId?: string;
|
|
202
|
-
metadata: Record<string, unknown>;
|
|
203
|
-
embedding?: number[]; // @deprecated — managed internally by vector store
|
|
204
|
-
createdAt: string; // ISO 8601
|
|
205
|
-
contentHash?: string; // SHA-256
|
|
206
|
-
importance?: number; // 1-10
|
|
207
|
-
accessCount?: number;
|
|
208
|
-
lastAccessed?: string; // ISO 8601
|
|
209
|
-
parentId?: string; // hierarchical storage
|
|
210
|
-
source?: string; // filename, URL, session ID
|
|
211
|
-
eventTime?: string; // when event happened (bi-temporal)
|
|
212
|
-
ingestTime?: string; // when stored (bi-temporal)
|
|
213
|
-
tenantId?: string; // multi-tenant isolation (hard boundary)
|
|
214
|
-
userId?: string; // user within tenant (legacy soft-scope)
|
|
215
|
-
teamId?: string; // team/group within tenant (legacy soft-scope)
|
|
216
|
-
namespaceId?: string; // ReBAC resource coordinate; NULL = legacy tenant-root bucket
|
|
217
|
-
sensitivity?: SensitivityLevel; // auto-classified: 'public' | 'internal' | 'secret'
|
|
218
|
-
encrypted?: boolean; // true when content is encrypted at rest
|
|
219
|
-
pinned?: boolean; // exempt from consolidation (decay-archive + dedup-merge); use for stable anchors referenced by external systems
|
|
220
|
-
}
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
## MemorySearchParams + SearchFilters
|
|
224
|
-
|
|
225
|
-
```typescript
|
|
226
|
-
interface MemorySearchParams {
|
|
227
|
-
query: string;
|
|
228
|
-
type?: MemoryType;
|
|
229
|
-
agentId?: string;
|
|
230
|
-
limit?: number; // default varies by engine
|
|
231
|
-
strategy?: RAGStrategy; // default: 'naive'
|
|
232
|
-
filters?: SearchFilters;
|
|
233
|
-
enableHyDE?: boolean; // Hypothetical Document Embedding for query expansion
|
|
234
|
-
enableRerank?: boolean; // Cross-encoder reranking of results
|
|
235
|
-
tenantId?: string; // multi-tenant scoping
|
|
236
|
-
userId?: string; // user-level scoping
|
|
237
|
-
teamId?: string; // team-level scoping
|
|
238
|
-
/** Calling principal — drives ReBAC AuthzPlan. Search applies it as a
|
|
239
|
-
* native pre-filter on SQLite/FTS, vector, and graph layers; forbidden
|
|
240
|
-
* entries never enter RRF / reranker / abstention. Optional. */
|
|
241
|
-
principal?: PrincipalContext;
|
|
242
|
-
namespaceIds?: string[]; // populated internally from AuthzPlan — do not set directly
|
|
243
|
-
maxSensitivity?: SensitivityLevel; // filter by max sensitivity level
|
|
244
|
-
abstentionThreshold?: number; // 0-1, below this confidence → shouldAbstain=true (default: 0.3)
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
interface SearchFilters {
|
|
248
|
-
source?: string;
|
|
249
|
-
importanceMin?: number;
|
|
250
|
-
eventTimeRange?: [string, string]; // [start, end] ISO timestamps
|
|
251
|
-
parentId?: string;
|
|
252
|
-
contentType?: string;
|
|
253
|
-
excludePinned?: boolean; // SQL-side `pinned = 0` filter (used internally by consolidation/decay; available to callers too)
|
|
254
|
-
}
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
## PrincipalContext + ReBAC Types (v0.16.0+)
|
|
258
|
-
|
|
259
|
-
The calling identity used to compute search-time AuthzPlan. Comes from
|
|
260
|
-
authenticated request context (`X-Tenant-Id` + `X-User-Id` / `X-Agent-Id`),
|
|
261
|
-
NEVER from request bodies.
|
|
262
|
-
|
|
263
|
-
```typescript
|
|
264
|
-
interface PrincipalContext {
|
|
265
|
-
tenantId: string; // hard boundary; SINGLE_TENANT_ID sentinel in single mode
|
|
266
|
-
principalId: string; // userId | agentId | service identifier
|
|
267
|
-
kind: 'user' | 'agent' | 'service';
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
interface Namespace {
|
|
271
|
-
id: string;
|
|
272
|
-
tenantId: string;
|
|
273
|
-
name: string;
|
|
274
|
-
parentId?: string; // adjacency tree, max-depth 8
|
|
275
|
-
createdAt: string;
|
|
276
|
-
createdBy?: string;
|
|
277
|
-
metadata: Record<string, unknown>;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
interface Principal {
|
|
281
|
-
id: string;
|
|
282
|
-
tenantId: string;
|
|
283
|
-
kind: 'user' | 'team' | 'group' | 'agent' | 'service' | 'everyone';
|
|
284
|
-
externalId?: string; // maps to userId / agentId / teamId on entries
|
|
285
|
-
displayName?: string;
|
|
286
|
-
createdAt: string;
|
|
287
|
-
metadata: Record<string, unknown>;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
interface AuthzTuple {
|
|
291
|
-
tenantId: string;
|
|
292
|
-
subjectKind: PrincipalKind;
|
|
293
|
-
subjectId: string;
|
|
294
|
-
subjectRelation?: string; // for usersets like "members of team-eng"
|
|
295
|
-
relation: 'viewer' | 'editor' | 'owner' | string;
|
|
296
|
-
objectKind: 'namespace'; // v1 only supports namespace-level grants
|
|
297
|
-
objectId: string;
|
|
298
|
-
createdAt: string;
|
|
299
|
-
createdBy?: string;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
interface AuthzPlan {
|
|
303
|
-
tenantId: string;
|
|
304
|
-
visibleNamespaceIds: string[]; // resolved + transitively expanded
|
|
305
|
-
visibleEntryOverrides: string[]; // reserved for v1.1
|
|
306
|
-
revision: string; // bumps on every tuple/principal/membership mutation
|
|
307
|
-
}
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
Built-in relation rewrite: `owner ⊇ editor ⊇ viewer`. Adding new relations
|
|
311
|
-
is a code change, not a schema migration.
|
|
312
|
-
|
|
313
|
-
In-process API: `Memory.authz` exposes `AuthzStore` with `createNamespace`,
|
|
314
|
-
`upsertPrincipal`, `addMember`, `writeTuple`, `deleteTuple`, `buildAuthzPlan`
|
|
315
|
-
etc. Sidecar / HTTP API: see [`http-api.md`](./http-api.md) §ReBAC Admin.
|
|
316
|
-
|
|
317
|
-
## MemoryOptions Reference
|
|
318
|
-
|
|
319
|
-
> **Embedding is internal** — pyx-memory uses `LocalEmbeddingProvider` with BGE-M3 (1024d) automatically. You do NOT pass an `embedder` option.
|
|
320
|
-
|
|
321
|
-
| Field | Type | Required | Default | Notes |
|
|
322
|
-
|-------|------|----------|---------|-------|
|
|
323
|
-
| `dataDir` | `string` | no | `'./data'` | Use `':memory:'` for tests (LanceDB still writes to `/tmp`) |
|
|
324
|
-
| `vectorProvider` | `VectorProvider` | no | `'lancedb'` | |
|
|
325
|
-
| `dimensions` | `number` | no | `1024` | Default: 1024 (matches internal BGE-M3 model) |
|
|
326
|
-
| `graphStore` | `GraphStore` | no | `undefined` | Enables graph target in store routing |
|
|
327
|
-
| `reasoningProvider` | `ReasoningProvider` | no | `undefined` | Enables agentic RAG |
|
|
328
|
-
| `llm` | `LLMCallback` | no | `undefined` | Enables LLM-powered lifecycle (consolidation, summarization, scoring) |
|
|
329
|
-
| `skipDuplicates` | `boolean` | no | `false` | Content-hash dedup on store |
|
|
330
|
-
| `agentId` | `string` | no | `undefined` | Auto-scopes ALL store/search/stats/decay operations to this agent |
|
|
331
|
-
| `tenantId` | `string` | no | `undefined` | Auto-scopes ALL operations to this tenant (multi-tenant isolation) |
|
|
332
|
-
| `encryptionKey` | `Buffer` | no | `undefined` | 32-byte AES-256-GCM key for encrypting `secret` entries at rest |
|
|
333
|
-
| `qdrantUrl` | `string` | no | `undefined` | @deprecated — Qdrant support is vestigial |
|
|
334
|
-
|
|
335
|
-
## Embedding Dimension Defaults by Provider
|
|
336
|
-
|
|
337
|
-
> **Memory always uses `LocalEmbeddingProvider` internally.** The other providers are available for standalone use but are not used by the `Memory` class.
|
|
338
|
-
|
|
339
|
-
| Provider | Default Dimensions | Model |
|
|
340
|
-
|----------|-------------------|-------|
|
|
341
|
-
| `StubEmbeddingProvider` | 1024 | hash-based (testing only) |
|
|
342
|
-
| `OpenAIEmbeddingProvider` | 1536 | text-embedding-3-small |
|
|
343
|
-
| `AnthropicEmbeddingProvider` | 1024 | voyage-3 (Voyage AI) |
|
|
344
|
-
| `LocalEmbeddingProvider` | 1024 | BGE-M3 (ONNX int8 quantized) |
|