@pyxmate/memory 0.1.0-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.
- package/README.md +10 -0
- package/bin/init.mjs +63 -0
- package/dist/{chunk-VJGRAIVX.mjs → chunk-JMXAZPDT.mjs} +11 -4
- package/dist/{chunk-ACMIMR43.mjs → chunk-XNKO7F3P.mjs} +1 -1
- package/dist/dashboard.mjs +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +1 -1
- package/dist/react.mjs +2 -2
- package/package.json +9 -3
- package/skills/pyx-memory-integration/SKILL.md +266 -0
- package/skills/pyx-memory-integration/examples/disabled-memory.ts +53 -0
- package/skills/pyx-memory-integration/examples/minimal-embedded.ts +25 -0
- package/skills/pyx-memory-integration/examples/minimal-sidecar.ts +14 -0
- package/skills/pyx-memory-integration/patterns/consumer.md +103 -0
- package/skills/pyx-memory-integration/patterns/embedded.md +223 -0
- package/skills/pyx-memory-integration/reference/advanced.md +139 -0
- package/skills/pyx-memory-integration/reference/http-api.md +82 -0
- package/skills/pyx-memory-integration/reference/parity.md +63 -0
- package/skills/pyx-memory-integration/reference/types.md +203 -0
package/README.md
CHANGED
|
@@ -10,6 +10,16 @@ Provides an HTTP client, shared types, and optional dashboard + React hooks for
|
|
|
10
10
|
npm install @pyxmate/memory
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
## Setup Claude Code Skills
|
|
14
|
+
|
|
15
|
+
If you use [Claude Code](https://docs.anthropic.com/en/docs/claude-code), run this command to install pyx-memory integration skills:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx @pyxmate/memory init
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This copies skill files into `.claude/skills/pyx-memory-integration/` so Claude Code auto-discovers pyx-memory patterns, types, and API reference when working in your project.
|
|
22
|
+
|
|
13
23
|
## Usage
|
|
14
24
|
|
|
15
25
|
```ts
|
package/bin/init.mjs
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { cpSync, existsSync, mkdirSync, readdirSync } from 'node:fs';
|
|
4
|
+
import { dirname, join, resolve } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
|
|
9
|
+
const command = process.argv[2];
|
|
10
|
+
|
|
11
|
+
if (command !== 'init') {
|
|
12
|
+
console.log(`Usage: pyxmate-memory init
|
|
13
|
+
|
|
14
|
+
Commands:
|
|
15
|
+
init Copy pyx-memory skill files into .claude/skills/ for Claude Code auto-discovery`);
|
|
16
|
+
process.exit(command ? 1 : 0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const source = resolve(__dirname, '..', 'skills', 'pyx-memory-integration');
|
|
20
|
+
const target = resolve(process.cwd(), '.claude', 'skills', 'pyx-memory-integration');
|
|
21
|
+
|
|
22
|
+
if (!existsSync(source)) {
|
|
23
|
+
console.error('Error: Skills directory not found in package. Please reinstall @pyxmate/memory.');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Ensure target parent exists
|
|
28
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
29
|
+
|
|
30
|
+
// Copy skills (overwrites existing files for idempotency)
|
|
31
|
+
cpSync(source, target, { recursive: true });
|
|
32
|
+
|
|
33
|
+
// Count copied files
|
|
34
|
+
function countFiles(dir) {
|
|
35
|
+
let count = 0;
|
|
36
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
37
|
+
if (entry.isDirectory()) {
|
|
38
|
+
count += countFiles(join(dir, entry.name));
|
|
39
|
+
} else {
|
|
40
|
+
count++;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return count;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function listFiles(dir, prefix = '') {
|
|
47
|
+
const lines = [];
|
|
48
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
49
|
+
if (entry.isDirectory()) {
|
|
50
|
+
lines.push(...listFiles(join(dir, entry.name), `${prefix}${entry.name}/`));
|
|
51
|
+
} else {
|
|
52
|
+
lines.push(` ${prefix}${entry.name}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return lines;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const fileCount = countFiles(target);
|
|
59
|
+
const fileList = listFiles(target);
|
|
60
|
+
|
|
61
|
+
console.log(`Copied ${fileCount} skill files to .claude/skills/pyx-memory-integration/\n`);
|
|
62
|
+
console.log(fileList.join('\n'));
|
|
63
|
+
console.log('\nClaude Code will now auto-discover pyx-memory integration patterns.');
|
|
@@ -13,15 +13,20 @@ var MemoryServerError = class extends Error {
|
|
|
13
13
|
};
|
|
14
14
|
var MemoryClient = class {
|
|
15
15
|
baseUrl;
|
|
16
|
-
|
|
16
|
+
_authHeaders;
|
|
17
|
+
constructor(memoryUrl, apiKey) {
|
|
17
18
|
this.baseUrl = memoryUrl.replace(/\/$/, "");
|
|
19
|
+
const trimmed = apiKey?.trim();
|
|
20
|
+
this._authHeaders = trimmed ? { Authorization: `Bearer ${trimmed}` } : {};
|
|
18
21
|
}
|
|
19
22
|
/** Encode a path segment to prevent URL injection */
|
|
20
23
|
encodePathSegment(segment) {
|
|
21
24
|
return encodeURIComponent(segment);
|
|
22
25
|
}
|
|
23
26
|
async initialize() {
|
|
24
|
-
const response = await fetch(`${this.baseUrl}/health
|
|
27
|
+
const response = await fetch(`${this.baseUrl}/health`, {
|
|
28
|
+
headers: this._authHeaders
|
|
29
|
+
});
|
|
25
30
|
if (!response.ok) {
|
|
26
31
|
throw new Error(`Memory server not reachable at ${this.baseUrl}: ${response.status}`);
|
|
27
32
|
}
|
|
@@ -92,7 +97,8 @@ var MemoryClient = class {
|
|
|
92
97
|
formData.append("file", file);
|
|
93
98
|
const res = await fetch(`${this.baseUrl}/api/memory/ingest/file`, {
|
|
94
99
|
method: "POST",
|
|
95
|
-
body: formData
|
|
100
|
+
body: formData,
|
|
101
|
+
headers: this._authHeaders
|
|
96
102
|
});
|
|
97
103
|
const body = await res.json();
|
|
98
104
|
if (!body.success || body.data === void 0) {
|
|
@@ -194,7 +200,8 @@ var MemoryClient = class {
|
|
|
194
200
|
...options,
|
|
195
201
|
headers: {
|
|
196
202
|
"Content-Type": "application/json",
|
|
197
|
-
...options?.headers
|
|
203
|
+
...options?.headers,
|
|
204
|
+
...this._authHeaders
|
|
198
205
|
}
|
|
199
206
|
});
|
|
200
207
|
const body = await res.json();
|
package/dist/dashboard.mjs
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -82,7 +82,8 @@ declare class MemoryServerError extends Error {
|
|
|
82
82
|
}
|
|
83
83
|
declare class MemoryClient implements ExtendedMemoryInterface {
|
|
84
84
|
protected baseUrl: string;
|
|
85
|
-
|
|
85
|
+
private readonly _authHeaders;
|
|
86
|
+
constructor(memoryUrl: string, apiKey?: string);
|
|
86
87
|
/** Encode a path segment to prevent URL injection */
|
|
87
88
|
private encodePathSegment;
|
|
88
89
|
initialize(): Promise<void>;
|
package/dist/index.mjs
CHANGED
package/dist/react.mjs
CHANGED
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
toGraphologyFormat,
|
|
12
12
|
transformGraphData,
|
|
13
13
|
unreachableHealth
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-XNKO7F3P.mjs";
|
|
15
|
+
import "./chunk-JMXAZPDT.mjs";
|
|
16
16
|
|
|
17
17
|
// ../dashboard/src/hooks/use-consolidation-log.ts
|
|
18
18
|
import { useCallback as useCallback2, useMemo } from "react";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyxmate/memory",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1-beta",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "SDK for pyx-memory — Memory as a Service for AI agents",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,15 +33,21 @@
|
|
|
33
33
|
"types": "./dist/react.d.ts"
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
|
+
"bin": {
|
|
37
|
+
"pyxmate-memory": "./bin/init.mjs"
|
|
38
|
+
},
|
|
36
39
|
"files": [
|
|
37
40
|
"dist",
|
|
41
|
+
"bin",
|
|
42
|
+
"skills",
|
|
38
43
|
"README.md",
|
|
39
44
|
"LICENSE"
|
|
40
45
|
],
|
|
41
46
|
"scripts": {
|
|
42
|
-
"
|
|
47
|
+
"copy-skills": "rm -rf skills/pyx-memory-integration && mkdir -p skills && cp -r ../../.claude/skills/pyx-memory-integration skills/pyx-memory-integration && rm -rf skills/pyx-memory-integration/scripts",
|
|
48
|
+
"build": "bun run copy-skills && tsup",
|
|
43
49
|
"typecheck": "tsc --noEmit",
|
|
44
|
-
"clean": "rm -rf dist node_modules .turbo"
|
|
50
|
+
"clean": "rm -rf dist skills node_modules .turbo"
|
|
45
51
|
},
|
|
46
52
|
"peerDependencies": {
|
|
47
53
|
"react": ">=18.0.0"
|
|
@@ -0,0 +1,266 @@
|
|
|
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)
|
|
102
|
+
await memory.store({
|
|
103
|
+
content: 'User prefers dark mode',
|
|
104
|
+
type: 'long-term',
|
|
105
|
+
metadata: { source: 'settings' },
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Store with graph routing (agent provides entities)
|
|
109
|
+
await memory.store({
|
|
110
|
+
content: 'Alice works at Acme Corp',
|
|
111
|
+
type: 'long-term',
|
|
112
|
+
metadata: {},
|
|
113
|
+
targets: ['sqlite', 'vector', 'graph'],
|
|
114
|
+
entities: [
|
|
115
|
+
{ name: 'Alice', type: 'PERSON' },
|
|
116
|
+
{ name: 'Acme Corp', type: 'ORGANIZATION' },
|
|
117
|
+
],
|
|
118
|
+
relationships: [{ source: 'Alice', target: 'Acme Corp', type: 'WORKS_AT' }],
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Search
|
|
122
|
+
const results = await memory.search({ query: 'user preferences', limit: 5 });
|
|
123
|
+
|
|
124
|
+
// Cleanup
|
|
125
|
+
await memory.shutdown(); // REQUIRED — releases SQLite + LanceDB resources
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Minimal Working Example (Sidecar / HTTP)
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { MemoryClient } from '@pyx-memory/client';
|
|
132
|
+
|
|
133
|
+
// Without auth (local dev)
|
|
134
|
+
const memory = new MemoryClient('http://localhost:7822');
|
|
135
|
+
|
|
136
|
+
// With auth (production — pass API key as second argument)
|
|
137
|
+
const authedMemory = new MemoryClient('http://localhost:7822', process.env.MEMORY_API_KEY);
|
|
138
|
+
|
|
139
|
+
await memory.initialize(); // verifies server connectivity via /health
|
|
140
|
+
|
|
141
|
+
await memory.store({ content: 'Important fact', type: 'long-term', metadata: {} });
|
|
142
|
+
const results = await memory.search({ query: 'fact', limit: 5 });
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Start the server: `bun packages/server/src/index.ts`
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Package Map
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
@pyx-memory/shared → Types + constants only (zero runtime code)
|
|
153
|
+
↑ ↑
|
|
154
|
+
| |
|
|
155
|
+
@pyx-memory/client → MemoryInterface, ExtendedMemoryInterface, MemoryClient
|
|
156
|
+
↑
|
|
157
|
+
|
|
|
158
|
+
@pyx-memory/core → Memory class, embeddings, graph, RAG, ingestion, lifecycle
|
|
159
|
+
↑ (re-exports everything from client and shared)
|
|
160
|
+
|
|
|
161
|
+
@pyx-memory/server → HTTP sidecar server (23 endpoints)
|
|
162
|
+
|
|
163
|
+
@pyx-memory/dashboard → DashboardClient (extends MemoryClient), React hooks,
|
|
164
|
+
Poller, aggregations, graph transforms (D3/Graphology)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Import rules:**
|
|
168
|
+
- **Embedded mode**: Import everything from `@pyx-memory/core` (it re-exports client + shared)
|
|
169
|
+
- **Sidecar mode (client only)**: Import from `@pyx-memory/client` (+ types from `@pyx-memory/shared`)
|
|
170
|
+
- **Dashboard features**: Import from `@pyx-memory/dashboard` (extends client with extra methods)
|
|
171
|
+
- **Types only**: Import from `@pyx-memory/shared`
|
|
172
|
+
- **Consumer projects**: ONLY use `@pyx-memory/client` + `@pyx-memory/shared` — never `@pyx-memory/core`
|
|
173
|
+
|
|
174
|
+
For full type definitions and interfaces, see [reference/types.md](reference/types.md).
|
|
175
|
+
|
|
176
|
+
For HTTP API endpoint reference, see [reference/http-api.md](reference/http-api.md).
|
|
177
|
+
|
|
178
|
+
For feature parity between embedded and sidecar modes, see [reference/parity.md](reference/parity.md).
|
|
179
|
+
|
|
180
|
+
For RAG strategies, bi-temporal model, consolidation, and community detection, see [reference/advanced.md](reference/advanced.md).
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## DO / DON'T
|
|
185
|
+
|
|
186
|
+
### DO
|
|
187
|
+
|
|
188
|
+
- **DO** call `await memory.initialize()` before any operation
|
|
189
|
+
- **DO** call `await memory.shutdown()` when done (releases SQLite + LanceDB)
|
|
190
|
+
- **DO** provide `entities` when using `targets: ['graph']` — graph storage requires agent-provided entities
|
|
191
|
+
- **DO** initialize GraphStore BEFORE constructing Memory
|
|
192
|
+
- **DO** use `new Memory()` when you need lifecycle methods (ExtendedMemoryInterface)
|
|
193
|
+
- **DO** use `':memory:'` dataDir for tests
|
|
194
|
+
- **DO** handle `MemoryServerError` in sidecar mode (has `.status` and `.isNotFound`)
|
|
195
|
+
- **DO** use `MemoryClient` (not `MemoryInterface`) when you need graph or file ingestion — these are concrete methods
|
|
196
|
+
- **DO** use `DashboardClient` when you need consolidation logs, graph relationships, or enriched health data
|
|
197
|
+
- **DO** implement `DisabledMemory` (no-op) in consumer projects for graceful degradation when memory is unavailable
|
|
198
|
+
|
|
199
|
+
### DON'T
|
|
200
|
+
|
|
201
|
+
- **DON'T** assume `createMemory()` returns `ExtendedMemoryInterface` — it returns `MemoryInterface`
|
|
202
|
+
- **DON'T** use `targets: ['graph']` without entities — throws MemoryError
|
|
203
|
+
- **DON'T** use `targets: ['graph']` without a configured `graphStore` — throws MemoryError
|
|
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
|
|
@@ -0,0 +1,53 @@
|
|
|
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();
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
|
@@ -0,0 +1,103 @@
|
|
|
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
|
+
```
|