@pyxmate/memory 0.0.5-beta → 0.1.1-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.
@@ -0,0 +1,139 @@
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()`.
@@ -0,0 +1,82 @@
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 |
@@ -0,0 +1,63 @@
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` |
@@ -0,0 +1,203 @@
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) |