@pyxmate/memory 0.3.1-beta → 0.4.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/dist/{chunk-L62JXWDM.mjs → chunk-AXTWVLDO.mjs} +1 -1
- package/dist/{chunk-FEOGTCSW.mjs → chunk-YL5QMN6G.mjs} +65 -1
- package/dist/dashboard.mjs +2 -2
- package/dist/index.d.ts +28 -10
- package/dist/index.mjs +1 -1
- package/dist/react.mjs +2 -2
- package/package.json +1 -1
- package/skills/pyx-memory/reference/http-api.md +80 -4
- package/skills/pyx-memory/reference/sdk-guide.md +37 -1
- package/skills/pyx-memory/reference/types.md +14 -3
|
@@ -94,6 +94,13 @@ var MemoryClient = class {
|
|
|
94
94
|
return this.fetchApi(`/api/memory/entries${qs ? `?${qs}` : ""}`);
|
|
95
95
|
}
|
|
96
96
|
// --- Additional endpoints ---
|
|
97
|
+
/**
|
|
98
|
+
* Ingest a file with optional two-phase enrichment.
|
|
99
|
+
*
|
|
100
|
+
* Without enrichment callbacks: standard single-phase ingest (backwards compatible).
|
|
101
|
+
* With enrichment callbacks: fetches extracted images, calls describeImage for each,
|
|
102
|
+
* optionally extracts entities, then submits enrichment data back to the server.
|
|
103
|
+
*/
|
|
97
104
|
async ingestFile(file, options) {
|
|
98
105
|
const formData = new FormData();
|
|
99
106
|
formData.append("file", file);
|
|
@@ -105,7 +112,64 @@ var MemoryClient = class {
|
|
|
105
112
|
body: formData,
|
|
106
113
|
headers: this._authHeaders
|
|
107
114
|
});
|
|
108
|
-
|
|
115
|
+
const result = await this.parseApiResponse(res);
|
|
116
|
+
if (result.enrichment && options?.enrichment?.describeImage) {
|
|
117
|
+
const { fileId, token, expiresAt, images } = result.enrichment;
|
|
118
|
+
const descriptions = [];
|
|
119
|
+
const CONCURRENCY = 5;
|
|
120
|
+
for (let i = 0; i < images.length; i += CONCURRENCY) {
|
|
121
|
+
const batch = images.slice(i, i + CONCURRENCY);
|
|
122
|
+
const batchResults = await Promise.all(
|
|
123
|
+
batch.map(async (imageMeta) => {
|
|
124
|
+
const imageRes = await fetch(
|
|
125
|
+
`${this.baseUrl}/api/memory/files/${fileId}/images/${imageMeta.imageId}?token=${encodeURIComponent(token)}`,
|
|
126
|
+
{ headers: this._authHeaders }
|
|
127
|
+
);
|
|
128
|
+
if (!imageRes.ok) {
|
|
129
|
+
throw new MemoryServerError(
|
|
130
|
+
`Failed to fetch image ${imageMeta.imageId}: ${imageRes.status}`,
|
|
131
|
+
imageRes.status
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
const imageBuffer = await imageRes.arrayBuffer();
|
|
135
|
+
const description = await options.enrichment.describeImage(imageBuffer, imageMeta);
|
|
136
|
+
return { imageId: imageMeta.imageId, description };
|
|
137
|
+
})
|
|
138
|
+
);
|
|
139
|
+
descriptions.push(...batchResults);
|
|
140
|
+
}
|
|
141
|
+
let entities;
|
|
142
|
+
let relationships;
|
|
143
|
+
if (options.enrichment.extractEntities && descriptions.length > 0) {
|
|
144
|
+
const extracted = await options.enrichment.extractEntities(
|
|
145
|
+
descriptions.map((d) => d.description)
|
|
146
|
+
);
|
|
147
|
+
entities = extracted.entities;
|
|
148
|
+
relationships = extracted.relationships;
|
|
149
|
+
}
|
|
150
|
+
const enrichTokenHeader = `${token}:${expiresAt}`;
|
|
151
|
+
const enrichRes = await fetch(`${this.baseUrl}/api/memory/files/${fileId}/enrich`, {
|
|
152
|
+
method: "POST",
|
|
153
|
+
headers: {
|
|
154
|
+
"Content-Type": "application/json",
|
|
155
|
+
"X-Enrichment-Token": enrichTokenHeader,
|
|
156
|
+
...this._authHeaders
|
|
157
|
+
},
|
|
158
|
+
body: JSON.stringify({
|
|
159
|
+
imageDescriptions: descriptions,
|
|
160
|
+
entities,
|
|
161
|
+
relationships
|
|
162
|
+
})
|
|
163
|
+
});
|
|
164
|
+
if (!enrichRes.ok) {
|
|
165
|
+
const body = await enrichRes.json().catch(() => ({}));
|
|
166
|
+
throw new MemoryServerError(
|
|
167
|
+
body.error ?? `Enrichment failed: ${enrichRes.status}`,
|
|
168
|
+
enrichRes.status
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return result;
|
|
109
173
|
}
|
|
110
174
|
/** @deprecated Use {@link list} instead. Kept for backwards compatibility. */
|
|
111
175
|
async listEntries(params) {
|
package/dist/dashboard.mjs
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StoreInput as StoreInput$1, MemoryEntry as MemoryEntry$1, MemorySearchParams as MemorySearchParams$1, MemorySearchResult as MemorySearchResult$1, MemoryType as MemoryType$1, MemoryStats as MemoryStats$1, GraphNode as GraphNode$1, GraphTraversalResult as GraphTraversalResult$1 } from '@pyx-memory/shared';
|
|
1
|
+
import { StoreInput as StoreInput$1, MemoryEntry as MemoryEntry$1, MemorySearchParams as MemorySearchParams$1, MemorySearchResult as MemorySearchResult$1, MemoryType as MemoryType$1, MemoryStats as MemoryStats$1, ExtractedImageMeta, IngestEntity as IngestEntity$1, IngestRelationship as IngestRelationship$1, FileIngestResult, GraphNode as GraphNode$1, GraphTraversalResult as GraphTraversalResult$1 } from '@pyx-memory/shared';
|
|
2
2
|
|
|
3
3
|
/** Parameters for paginated entry listing. */
|
|
4
4
|
interface MemoryListParams {
|
|
@@ -65,14 +65,16 @@ interface ExtendedMemoryInterface extends MemoryInterface {
|
|
|
65
65
|
deleteBySource(source: string): Promise<number>;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
/** Callbacks for two-phase file enrichment. */
|
|
69
|
+
interface EnrichmentCallbacks {
|
|
70
|
+
/** Describe an image using LLM vision. Receives the raw image buffer and metadata. */
|
|
71
|
+
describeImage: (imageBuffer: ArrayBuffer, meta: ExtractedImageMeta) => Promise<string>;
|
|
72
|
+
/** Optionally extract entities/relationships from all image descriptions. */
|
|
73
|
+
extractEntities?: (descriptions: string[]) => Promise<{
|
|
74
|
+
entities: IngestEntity$1[];
|
|
75
|
+
relationships: IngestRelationship$1[];
|
|
76
|
+
}>;
|
|
74
77
|
}
|
|
75
|
-
|
|
76
78
|
/** Error thrown by MemoryClient when the server returns a non-success response. */
|
|
77
79
|
declare class MemoryServerError extends Error {
|
|
78
80
|
readonly status: number;
|
|
@@ -95,9 +97,17 @@ declare class MemoryClient implements ExtendedMemoryInterface {
|
|
|
95
97
|
stats(): Promise<MemoryStats$1>;
|
|
96
98
|
shutdown(): Promise<void>;
|
|
97
99
|
list(params?: MemoryListParams): Promise<MemoryListResult>;
|
|
100
|
+
/**
|
|
101
|
+
* Ingest a file with optional two-phase enrichment.
|
|
102
|
+
*
|
|
103
|
+
* Without enrichment callbacks: standard single-phase ingest (backwards compatible).
|
|
104
|
+
* With enrichment callbacks: fetches extracted images, calls describeImage for each,
|
|
105
|
+
* optionally extracts entities, then submits enrichment data back to the server.
|
|
106
|
+
*/
|
|
98
107
|
ingestFile(file: File, options?: {
|
|
99
108
|
description?: string;
|
|
100
|
-
|
|
109
|
+
enrichment?: EnrichmentCallbacks;
|
|
110
|
+
}): Promise<FileIngestResult>;
|
|
101
111
|
/** @deprecated Use {@link list} instead. Kept for backwards compatibility. */
|
|
102
112
|
listEntries(params?: {
|
|
103
113
|
page?: number;
|
|
@@ -127,6 +137,14 @@ declare class MemoryClient implements ExtendedMemoryInterface {
|
|
|
127
137
|
private parseApiResponse;
|
|
128
138
|
}
|
|
129
139
|
|
|
140
|
+
interface IngestionResult {
|
|
141
|
+
filename: string;
|
|
142
|
+
fileType: string;
|
|
143
|
+
chunks: number;
|
|
144
|
+
entryIds: string[];
|
|
145
|
+
totalCharacters: number;
|
|
146
|
+
}
|
|
147
|
+
|
|
130
148
|
declare const DEFAULTS: {
|
|
131
149
|
readonly DATA_DIR: "./data";
|
|
132
150
|
readonly VECTOR_PROVIDER: "lancedb";
|
|
@@ -336,4 +354,4 @@ interface GraphTraversalResult {
|
|
|
336
354
|
}>;
|
|
337
355
|
}
|
|
338
356
|
|
|
339
|
-
export { type AgentId, type ApiResponse, type ConsolidationRunResult, DEFAULTS, EmbeddingProviderName, type ExtendedMemoryInterface, type GraphNode, type GraphRelationship, type GraphTraversalResult, type IngestEntity, type IngestRelationship, type IngestionResult, MemoryClient, type MemoryEntry, type MemoryIngestRequest, type MemoryInterface, type MemoryListParams, type MemoryListResult, type MemorySearchParams, type MemorySearchResult, MemoryServerError, type MemoryStats, MemoryType, RAGStrategy, type StoreInput, StoreTarget, type TemporalQueryFilters, type Timestamp, VectorProvider };
|
|
357
|
+
export { type AgentId, type ApiResponse, type ConsolidationRunResult, DEFAULTS, EmbeddingProviderName, type EnrichmentCallbacks, type ExtendedMemoryInterface, type GraphNode, type GraphRelationship, type GraphTraversalResult, type IngestEntity, type IngestRelationship, type IngestionResult, MemoryClient, type MemoryEntry, type MemoryIngestRequest, type MemoryInterface, type MemoryListParams, type MemoryListResult, type MemorySearchParams, type MemorySearchResult, MemoryServerError, type MemoryStats, MemoryType, RAGStrategy, type StoreInput, StoreTarget, type TemporalQueryFilters, type Timestamp, VectorProvider };
|
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-AXTWVLDO.mjs";
|
|
15
|
+
import "./chunk-YL5QMN6G.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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Authentication
|
|
4
4
|
|
|
5
|
-
When the server has `API_KEY` configured, all requests (except `/health`) require one of:
|
|
5
|
+
When the server has `API_KEY` configured, all requests (except `/health` and enrichment routes) require one of:
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
Authorization: Bearer <your-api-key>
|
|
@@ -11,19 +11,23 @@ X-API-Key: <your-api-key>
|
|
|
11
11
|
|
|
12
12
|
Destructive operations (DELETE, forget, decay, consolidate, reindex) require `ADMIN_API_KEY` when configured (falls back to `API_KEY`).
|
|
13
13
|
|
|
14
|
+
**Enrichment routes** (`/api/memory/files/*`) use HMAC token auth instead of API keys. Tokens are issued by the server during file ingestion and are short-lived (30 minutes).
|
|
15
|
+
|
|
14
16
|
`MemoryClient` handles this automatically when `apiKey` is passed to the constructor:
|
|
15
17
|
```typescript
|
|
16
18
|
const client = new MemoryClient('http://localhost:7822', process.env.MEMORY_API_KEY);
|
|
17
19
|
```
|
|
18
20
|
|
|
19
|
-
## Core (
|
|
21
|
+
## Core (12 endpoints)
|
|
20
22
|
|
|
21
23
|
| Method | Endpoint | Description |
|
|
22
24
|
|--------|----------|-------------|
|
|
23
25
|
| GET | `/health` | Public health check (status only — no internals exposed) |
|
|
24
26
|
| GET | `/admin/health` | Admin health check (version, uptime, embedding provider, memory stats) |
|
|
25
27
|
| 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).
|
|
28
|
+
| POST | `/api/memory/ingest/file` | Upload file (multipart, 50MB limit). For PDFs with images, returns an `enrichment` block with HMAC token and image metadata for two-phase enrichment. |
|
|
29
|
+
| GET | `/api/memory/files/:fileId/images/:imageId?token=...` | Fetch an extracted PDF image (binary). Requires HMAC token from ingest response. |
|
|
30
|
+
| POST | `/api/memory/files/:fileId/enrich` | Submit image descriptions + entities after LLM vision processing. Requires `X-Enrichment-Token` header. |
|
|
27
31
|
| GET | `/api/memory/search?query=...&strategy=...&limit=...` | Search memories — **does NOT support** filters, enableHyDE, enableRerank |
|
|
28
32
|
| GET | `/api/memory/stats` | Memory statistics |
|
|
29
33
|
| GET | `/api/memory/entries?page=...&limit=...` | List entries (paginated) |
|
|
@@ -70,9 +74,12 @@ const client = new MemoryClient('http://localhost:7822', process.env.MEMORY_API_
|
|
|
70
74
|
2. Text is extracted (documents) or description is used (images)
|
|
71
75
|
3. Content is chunked and stored in SQLite + vector for semantic search
|
|
72
76
|
4. Source-aware dedup: re-uploading the same filename replaces the previous version
|
|
77
|
+
5. **PDFs with images**: Images are extracted via pdfjs-dist, saved to a temp directory, and an `enrichment` block is returned with HMAC-signed tokens for two-phase enrichment
|
|
73
78
|
|
|
74
79
|
**Image ingestion**: Images cannot have text extracted. Pass a `description` field with a natural-language description (e.g., from an LLM with vision). Without a description, images get a minimal placeholder (`[Image] filename (size KB)`).
|
|
75
80
|
|
|
81
|
+
**PDF enrichment**: When a PDF contains images (≥50x50px), the response includes an `enrichment` block. The SDK's `ingestFile()` with `EnrichmentCallbacks` handles the full flow automatically — see [sdk-guide.md](sdk-guide.md#two-phase-pdf-enrichment).
|
|
82
|
+
|
|
76
83
|
### Example: ingest a document
|
|
77
84
|
|
|
78
85
|
```bash
|
|
@@ -93,7 +100,7 @@ curl -X POST {{ENDPOINT}}/api/memory/ingest/file \
|
|
|
93
100
|
### SDK usage
|
|
94
101
|
|
|
95
102
|
```typescript
|
|
96
|
-
// Document
|
|
103
|
+
// Document (text-only)
|
|
97
104
|
const doc = new File([buffer], 'report.pdf', { type: 'application/pdf' });
|
|
98
105
|
await memory.ingestFile(doc);
|
|
99
106
|
|
|
@@ -102,8 +109,76 @@ const img = new File([imgBuffer], 'photo.png', { type: 'image/png' });
|
|
|
102
109
|
await memory.ingestFile(img, {
|
|
103
110
|
description: 'A photo of the whiteboard from the architecture meeting',
|
|
104
111
|
});
|
|
112
|
+
|
|
113
|
+
// PDF with two-phase enrichment (images described via LLM vision)
|
|
114
|
+
await memory.ingestFile(pdfFile, {
|
|
115
|
+
enrichment: {
|
|
116
|
+
describeImage: async (buffer, meta) => {
|
|
117
|
+
// Call your LLM vision model to describe the image
|
|
118
|
+
return 'A bar chart showing Q4 revenue growth of 23%';
|
|
119
|
+
},
|
|
120
|
+
extractEntities: async (descriptions) => ({
|
|
121
|
+
entities: [{ name: 'Q4 Revenue', type: 'METRIC' }],
|
|
122
|
+
relationships: [],
|
|
123
|
+
}),
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Two-Phase PDF Enrichment
|
|
129
|
+
|
|
130
|
+
When a PDF contains extractable images, the server returns an `enrichment` block from `POST /api/memory/ingest/file`. The SDK wraps the full three-phase flow into a single `ingestFile()` call with `EnrichmentCallbacks`.
|
|
131
|
+
|
|
132
|
+
### Flow
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
Phase 1: POST /api/memory/ingest/file → text stored immediately
|
|
136
|
+
Response: { ...result, enrichment: { fileId, token, expiresAt, images: [...] } }
|
|
137
|
+
|
|
138
|
+
Phase 2: GET /api/memory/files/{fileId}/images/{imageId}?token=... → binary image
|
|
139
|
+
(SDK fetches each image, calls describeImage callback)
|
|
140
|
+
|
|
141
|
+
Phase 3: POST /api/memory/files/{fileId}/enrich
|
|
142
|
+
Header: X-Enrichment-Token: {token}:{expiresAt}
|
|
143
|
+
Body: { imageDescriptions: [...], entities?: [...], relationships?: [...] }
|
|
144
|
+
→ descriptions stored as memory entries, temp images cleaned up
|
|
105
145
|
```
|
|
106
146
|
|
|
147
|
+
### Image fetch endpoint
|
|
148
|
+
|
|
149
|
+
`GET /api/memory/files/:fileId/images/:imageId?token=<hmac>`
|
|
150
|
+
|
|
151
|
+
Returns the binary image with `Content-Type: image/png` or `image/jpeg`. The HMAC token is issued by the server during Phase 1 and expires after 30 minutes.
|
|
152
|
+
|
|
153
|
+
### Enrich endpoint
|
|
154
|
+
|
|
155
|
+
`POST /api/memory/files/:fileId/enrich`
|
|
156
|
+
|
|
157
|
+
| Header | Required | Description |
|
|
158
|
+
|--------|----------|-------------|
|
|
159
|
+
| `X-Enrichment-Token` | Yes | Format: `{hmac_token}:{expiresAt_iso}` |
|
|
160
|
+
|
|
161
|
+
Body:
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"imageDescriptions": [
|
|
165
|
+
{ "imageId": "uuid-img-0", "description": "A chart showing..." }
|
|
166
|
+
],
|
|
167
|
+
"entities": [{ "name": "Revenue", "type": "METRIC" }],
|
|
168
|
+
"relationships": []
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Input limits: descriptions max 10,000 chars each, entities max 200, relationships max 500.
|
|
173
|
+
|
|
174
|
+
### Security
|
|
175
|
+
|
|
176
|
+
- Tokens are HMAC-SHA256 signed (server secret + fileId + expiresAt)
|
|
177
|
+
- `fileId` must be a valid UUIDv4
|
|
178
|
+
- `imageId` must match `^[a-zA-Z0-9_-]+$`
|
|
179
|
+
- Image paths are sandboxed via `resolve()` + `startsWith()` to prevent path traversal
|
|
180
|
+
- Enrichment routes bypass API key auth — they use their own HMAC verification
|
|
181
|
+
|
|
107
182
|
---
|
|
108
183
|
|
|
109
184
|
## Entity Extraction (Knowledge Graph)
|
|
@@ -173,3 +248,4 @@ All responses follow: `{ success: boolean, data?: T, error?: string }`
|
|
|
173
248
|
| `NODE_ENV` | `development` | Set to `production` to mask 5xx error details and enable HSTS |
|
|
174
249
|
| `PII_POLICY` | `flag` | PII handling: `flag` (detect + tag), `redact` (replace with [REDACTED]), `block` (reject 400) |
|
|
175
250
|
| `RATE_LIMIT_RPM` | `0` | Requests per minute per IP. 0 = disabled |
|
|
251
|
+
| `ENRICHMENT_SECRET` | (auto-generated) | HMAC secret for enrichment token signing. Auto-generated if unset (tokens won't survive restarts). Min 32 bytes for production. |
|
|
@@ -97,7 +97,7 @@ Start the server: `bun packages/server/src/index.ts`
|
|
|
97
97
|
@pyx-memory/core → Memory class, embeddings, graph, RAG, ingestion, lifecycle
|
|
98
98
|
↑ (re-exports everything from client and shared)
|
|
99
99
|
|
|
|
100
|
-
@pyx-memory/server → HTTP sidecar server (
|
|
100
|
+
@pyx-memory/server → HTTP sidecar server (25 endpoints)
|
|
101
101
|
|
|
102
102
|
@pyx-memory/dashboard → DashboardClient (extends MemoryClient), React hooks,
|
|
103
103
|
Poller, aggregations, graph transforms (D3/Graphology)
|
|
@@ -164,3 +164,39 @@ MemoryServerError — HTTP client errors (has .status, .isNotFound)
|
|
|
164
164
|
```
|
|
165
165
|
|
|
166
166
|
All from `@pyx-memory/core` except `MemoryServerError` from `@pyx-memory/client`.
|
|
167
|
+
|
|
168
|
+
## Two-Phase PDF Enrichment
|
|
169
|
+
|
|
170
|
+
When ingesting PDFs that contain images, `ingestFile()` supports a two-phase enrichment flow via `EnrichmentCallbacks`. The SDK handles all three phases automatically:
|
|
171
|
+
|
|
172
|
+
1. **Upload** — text extracted and stored immediately
|
|
173
|
+
2. **Image description** — each extracted image is fetched and described via your LLM vision callback (batched, 5 concurrent)
|
|
174
|
+
3. **Enrichment** — descriptions + entities submitted back to the server
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { MemoryClient, type EnrichmentCallbacks } from '@pyx-memory/client';
|
|
178
|
+
|
|
179
|
+
const memory = new MemoryClient('http://localhost:7822', apiKey);
|
|
180
|
+
|
|
181
|
+
const enrichment: EnrichmentCallbacks = {
|
|
182
|
+
// Required: describe each image using LLM vision
|
|
183
|
+
describeImage: async (imageBuffer, meta) => {
|
|
184
|
+
// imageBuffer is ArrayBuffer of the extracted PNG/JPEG
|
|
185
|
+
// meta has: imageId, pageNumber, width, height, mimeType
|
|
186
|
+
const description = await myVisionModel.describe(imageBuffer);
|
|
187
|
+
return description;
|
|
188
|
+
},
|
|
189
|
+
// Optional: extract entities from all descriptions at once
|
|
190
|
+
extractEntities: async (descriptions) => ({
|
|
191
|
+
entities: [{ name: 'Revenue', type: 'METRIC' }],
|
|
192
|
+
relationships: [{ source: 'Revenue', target: 'Q4', type: 'RELATED_TO' }],
|
|
193
|
+
}),
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const result = await memory.ingestFile(pdfFile, { enrichment });
|
|
197
|
+
// result.enrichment is defined when PDF had images
|
|
198
|
+
// Text chunks are already stored from Phase 1
|
|
199
|
+
// Image descriptions are stored from Phase 3
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Without `enrichment` callbacks, `ingestFile()` behaves identically to before — fully backwards compatible.
|
|
@@ -28,6 +28,13 @@
|
|
|
28
28
|
| `MemoryListParams` | `{ page?, limit?, type?, agentId? }` | `@pyx-memory/client` |
|
|
29
29
|
| `MemoryListResult` | `{ entries, totalCount, page, limit }` | `@pyx-memory/client` |
|
|
30
30
|
| `IngestionResult` | `{ filename, chunks, totalCharacters }` | `@pyx-memory/client` |
|
|
31
|
+
| `FileIngestResult` | `IngestionResult & { enrichment?: EnrichmentPending }` | `@pyx-memory/shared` |
|
|
32
|
+
| `EnrichmentPending` | `{ fileId, token, expiresAt, images: ExtractedImageMeta[] }` | `@pyx-memory/shared` |
|
|
33
|
+
| `ExtractedImageMeta` | `{ imageId, pageNumber, width, height, mimeType }` | `@pyx-memory/shared` |
|
|
34
|
+
| `EnrichmentCallbacks` | `{ describeImage, extractEntities? }` | `@pyx-memory/client` |
|
|
35
|
+
| `EnrichRequest` | `{ imageDescriptions, entities?, relationships? }` | `@pyx-memory/shared` |
|
|
36
|
+
| `EnrichResult` | `{ entryIds, entitiesStored, relationshipsStored }` | `@pyx-memory/shared` |
|
|
37
|
+
| `ImageDescription` | `{ imageId, description }` | `@pyx-memory/shared` |
|
|
31
38
|
| `MemoryServerError` | `Error` with `.status` and `.isNotFound` | `@pyx-memory/client` |
|
|
32
39
|
| `GraphNode` | `{ id, name, type, properties, memoryEntryIds }` | `@pyx-memory/shared` |
|
|
33
40
|
| `GraphTraversalResult` | `{ nodes, relationships, paths }` | `@pyx-memory/shared` |
|
|
@@ -86,9 +93,13 @@ class MemoryClient implements ExtendedMemoryInterface {
|
|
|
86
93
|
graphEdges(): Promise<{ stats: { nodeCount: number; edgeCount: number } }>;
|
|
87
94
|
graphQuery(query: { nodeId: string; depth?: number }): Promise<GraphTraversalResult>;
|
|
88
95
|
|
|
89
|
-
// File ingestion
|
|
90
|
-
//
|
|
91
|
-
|
|
96
|
+
// File ingestion with optional two-phase enrichment
|
|
97
|
+
// Without callbacks: standard single-phase ingest (backwards compatible)
|
|
98
|
+
// With callbacks: fetches extracted images, calls describeImage, submits enrichment
|
|
99
|
+
ingestFile(file: File, options?: {
|
|
100
|
+
description?: string;
|
|
101
|
+
enrichment?: EnrichmentCallbacks;
|
|
102
|
+
}): Promise<FileIngestResult>;
|
|
92
103
|
|
|
93
104
|
// Bi-temporal queries
|
|
94
105
|
queryAsOf(asOf: string, filters?: TemporalQueryFilters): Promise<MemoryEntry[]>;
|