@pyxmate/memory 0.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Pyxmate
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # @pyxmate/memory
2
+
3
+ SDK for **pyx-memory** — Memory as a Service for AI agents.
4
+
5
+ Provides an HTTP client, shared types, and optional dashboard + React hooks for interacting with a pyx-memory server.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @pyxmate/memory
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```ts
16
+ import { MemoryClient } from '@pyxmate/memory';
17
+ import type { MemoryEntry } from '@pyxmate/memory';
18
+
19
+ const client = new MemoryClient('http://localhost:7822');
20
+ await client.initialize();
21
+
22
+ // Store a memory
23
+ await client.store({
24
+ content: 'The project deadline is March 15th',
25
+ agentId: 'my-agent',
26
+ });
27
+
28
+ // Search memories
29
+ const results = await client.search({ query: 'deadline', limit: 5 });
30
+ ```
31
+
32
+ ## Entry Points
33
+
34
+ | Import | Description |
35
+ |--------|-------------|
36
+ | `@pyxmate/memory` | Core SDK — `MemoryClient`, shared types, constants |
37
+ | `@pyxmate/memory/dashboard` | Headless dashboard utilities — `DashboardClient`, aggregations, graph transforms (no React) |
38
+ | `@pyxmate/memory/react` | React hooks — `useMemoryStats`, `useMemoryHealth`, `useKnowledgeGraph`, etc. (requires React >= 18) |
39
+
40
+ ## Running the Server
41
+
42
+ ```bash
43
+ docker pull ghcr.io/fysoul17/pyx-memory:latest
44
+ docker run -p 7822:7822 ghcr.io/fysoul17/pyx-memory:latest
45
+ ```
46
+
47
+ ## Requirements
48
+
49
+ - ESM only (`"type": "module"`)
50
+ - React >= 18 (optional, only for `@pyxmate/memory/react`)
51
+
52
+ ## License
53
+
54
+ MIT
@@ -0,0 +1,385 @@
1
+ import {
2
+ MemoryClient
3
+ } from "./chunk-Q4QIILKH.mjs";
4
+
5
+ // ../dashboard/src/aggregations/consolidation-analytics.ts
6
+ function analyzeConsolidationLog(entries) {
7
+ const totalRuns = entries.length;
8
+ if (totalRuns === 0) {
9
+ return {
10
+ entries,
11
+ totalRuns: 0,
12
+ avgDurationMs: 0,
13
+ avgEntriesProcessed: 0,
14
+ avgEntriesMerged: 0,
15
+ avgEntriesArchived: 0,
16
+ lastRunAt: null,
17
+ consolidationTrend: "insufficient_data"
18
+ };
19
+ }
20
+ const avgDurationMs = Math.round(entries.reduce((sum, e) => sum + e.durationMs, 0) / totalRuns);
21
+ const avgEntriesProcessed = Math.round(entries.reduce((sum, e) => sum + e.entriesProcessed, 0) / totalRuns * 100) / 100;
22
+ const avgEntriesMerged = Math.round(entries.reduce((sum, e) => sum + e.entriesMerged, 0) / totalRuns * 100) / 100;
23
+ const avgEntriesArchived = Math.round(entries.reduce((sum, e) => sum + e.entriesArchived, 0) / totalRuns * 100) / 100;
24
+ const lastRunAt = entries[0]?.runAt ?? null;
25
+ const consolidationTrend = computeTrend(entries);
26
+ return {
27
+ entries,
28
+ totalRuns,
29
+ avgDurationMs,
30
+ avgEntriesProcessed,
31
+ avgEntriesMerged,
32
+ avgEntriesArchived,
33
+ lastRunAt,
34
+ consolidationTrend
35
+ };
36
+ }
37
+ function computeTrend(entries) {
38
+ if (entries.length < 3) return "insufficient_data";
39
+ const mid = Math.floor(entries.length / 2);
40
+ const recentHalf = entries.slice(0, mid);
41
+ const olderHalf = entries.slice(mid);
42
+ const recentAvg = recentHalf.reduce((sum, e) => sum + e.entriesMerged, 0) / recentHalf.length;
43
+ const olderAvg = olderHalf.reduce((sum, e) => sum + e.entriesMerged, 0) / olderHalf.length;
44
+ const diff = recentAvg - olderAvg;
45
+ const threshold = Math.max(olderAvg * 0.2, 1);
46
+ if (diff > threshold) return "increasing";
47
+ if (diff < -threshold) return "decreasing";
48
+ return "stable";
49
+ }
50
+
51
+ // ../dashboard/src/aggregations/health-enrichment.ts
52
+ function formatUptime(seconds) {
53
+ const days = Math.floor(seconds / 86400);
54
+ const hours = Math.floor(seconds % 86400 / 3600);
55
+ const minutes = Math.floor(seconds % 3600 / 60);
56
+ const parts = [];
57
+ if (days > 0) parts.push(`${days}d`);
58
+ if (hours > 0) parts.push(`${hours}h`);
59
+ if (minutes > 0 || parts.length === 0) parts.push(`${minutes}m`);
60
+ return parts.join(" ");
61
+ }
62
+ function formatBytes(bytes) {
63
+ if (bytes === 0) return "0 B";
64
+ const units = ["B", "KB", "MB", "GB", "TB"];
65
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
66
+ const value = bytes / 1024 ** i;
67
+ return `${Math.round(value * 100) / 100} ${units[i]}`;
68
+ }
69
+ function enrichHealth(raw) {
70
+ const storageMB = raw.stats ? Math.round(raw.stats.storageUsedBytes / (1024 * 1024) * 100) / 100 : 0;
71
+ return {
72
+ status: raw.status === "ok" ? "ok" : "degraded",
73
+ uptime: raw.uptime,
74
+ uptimeFormatted: formatUptime(raw.uptime),
75
+ storageMB,
76
+ isHealthy: raw.status === "ok",
77
+ embeddingProvider: raw.embeddingProvider,
78
+ stats: raw.stats
79
+ };
80
+ }
81
+ function unreachableHealth(_error) {
82
+ return {
83
+ status: "unreachable",
84
+ uptime: 0,
85
+ uptimeFormatted: "0m",
86
+ storageMB: 0,
87
+ isHealthy: false,
88
+ embeddingProvider: "unknown",
89
+ stats: void 0
90
+ };
91
+ }
92
+
93
+ // ../dashboard/src/aggregations/metrics.ts
94
+ var STALE_DAYS = 30;
95
+ function computeMetrics(stats, entries) {
96
+ const storageMB = Math.round(stats.storageUsedBytes / (1024 * 1024) * 100) / 100;
97
+ let importanceSum = 0;
98
+ let importanceCount = 0;
99
+ let staleCandidates = 0;
100
+ const staleThreshold = /* @__PURE__ */ new Date();
101
+ staleThreshold.setDate(staleThreshold.getDate() - STALE_DAYS);
102
+ const staleThresholdStr = staleThreshold.toISOString();
103
+ for (const entry of entries) {
104
+ if (entry.importance != null) {
105
+ importanceSum += entry.importance;
106
+ importanceCount++;
107
+ }
108
+ const lastAccess = entry.lastAccessed ?? entry.createdAt;
109
+ if (lastAccess < staleThresholdStr && (entry.importance ?? 0.5) < 0.3) {
110
+ staleCandidates++;
111
+ }
112
+ }
113
+ const avgImportance = importanceCount > 0 ? Math.round(importanceSum / importanceCount * 1e3) / 1e3 : 0;
114
+ return {
115
+ totalEntries: stats.totalEntries,
116
+ vectorCount: stats.vectorCount,
117
+ storageUsedBytes: stats.storageUsedBytes,
118
+ storageMB,
119
+ avgImportance,
120
+ staleCandidates,
121
+ graphNodeCount: stats.graphNodeCount ?? 0,
122
+ graphEdgeCount: stats.graphEdgeCount ?? 0
123
+ };
124
+ }
125
+
126
+ // ../dashboard/src/aggregations/type-distribution.ts
127
+ function computeTypeDistribution(entries) {
128
+ const counts = {};
129
+ for (const entry of entries) {
130
+ counts[entry.type] = (counts[entry.type] ?? 0) + 1;
131
+ }
132
+ const total = entries.length;
133
+ const percentages = {};
134
+ for (const [type, count] of Object.entries(counts)) {
135
+ percentages[type] = total > 0 ? Math.round(count / total * 1e4) / 100 : 0;
136
+ }
137
+ let dominant = "";
138
+ let maxCount = 0;
139
+ for (const [type, count] of Object.entries(counts)) {
140
+ if (count > maxCount) {
141
+ maxCount = count;
142
+ dominant = type;
143
+ }
144
+ }
145
+ return { counts, percentages, total, dominant };
146
+ }
147
+
148
+ // ../dashboard/src/client/dashboard-client.ts
149
+ var DashboardClient = class extends MemoryClient {
150
+ async consolidationLog(limit = 10) {
151
+ return this.fetchApi(`/api/memory/consolidation-log?limit=${limit}`);
152
+ }
153
+ async listEntriesPaginated(filters = {}) {
154
+ const params = new URLSearchParams();
155
+ if (filters.page) params.set("page", String(filters.page));
156
+ if (filters.limit) params.set("limit", String(filters.limit));
157
+ if (filters.type) params.set("type", filters.type);
158
+ if (filters.agentId) params.set("agentId", filters.agentId);
159
+ if (filters.query) params.set("query", filters.query);
160
+ const qs = params.toString();
161
+ const raw = await this.fetchApi(`/api/memory/entries${qs ? `?${qs}` : ""}`);
162
+ return {
163
+ ...raw,
164
+ totalPages: Math.ceil(raw.totalCount / raw.limit),
165
+ hasNextPage: raw.page * raw.limit < raw.totalCount,
166
+ hasPreviousPage: raw.page > 1
167
+ };
168
+ }
169
+ async graphRelationships(limit = 200) {
170
+ return this.fetchApi(
171
+ `/api/memory/graph/relationships?limit=${limit}`
172
+ );
173
+ }
174
+ async graphFull(limit = 50) {
175
+ const [nodesResponse, relsResponse] = await Promise.all([
176
+ this.fetchApi(
177
+ `/api/memory/graph/nodes?limit=${limit}`
178
+ ),
179
+ this.graphRelationships(limit * 4).catch(() => ({
180
+ relationships: [],
181
+ totalCount: 0
182
+ }))
183
+ ]);
184
+ return {
185
+ nodes: nodesResponse.nodes,
186
+ relationships: relsResponse.relationships
187
+ };
188
+ }
189
+ async fetchHealthRaw() {
190
+ return this.fetchApi("/health");
191
+ }
192
+ };
193
+
194
+ // ../dashboard/src/graph/transform.ts
195
+ function transformGraphData(nodes, relationships, opts = {}) {
196
+ const { minWeight = 0, maxNodes } = opts;
197
+ const degreeMap = /* @__PURE__ */ new Map();
198
+ for (const rel of relationships) {
199
+ degreeMap.set(rel.sourceId, (degreeMap.get(rel.sourceId) ?? 0) + 1);
200
+ degreeMap.set(rel.targetId, (degreeMap.get(rel.targetId) ?? 0) + 1);
201
+ }
202
+ let vizNodes = nodes.map((node) => ({
203
+ id: node.id,
204
+ label: node.name,
205
+ type: node.type,
206
+ memoryCount: node.memoryEntryIds.length,
207
+ degree: degreeMap.get(node.id) ?? 0,
208
+ properties: node.properties
209
+ }));
210
+ if (maxNodes && vizNodes.length > maxNodes) {
211
+ vizNodes.sort((a, b) => b.degree - a.degree);
212
+ vizNodes = vizNodes.slice(0, maxNodes);
213
+ }
214
+ const nodeIdSet = new Set(vizNodes.map((n) => n.id));
215
+ const filteredRels = relationships.filter(
216
+ (rel) => nodeIdSet.has(rel.sourceId) && nodeIdSet.has(rel.targetId) && (rel.properties?.weight ?? 1) >= minWeight
217
+ );
218
+ const vizEdges = filteredRels.map((rel) => ({
219
+ id: rel.id,
220
+ source: rel.sourceId,
221
+ target: rel.targetId,
222
+ label: rel.type,
223
+ weight: rel.properties?.weight ?? 1
224
+ }));
225
+ const nodeTypes = {};
226
+ for (const node of vizNodes) {
227
+ nodeTypes[node.type] = (nodeTypes[node.type] ?? 0) + 1;
228
+ }
229
+ const edgeTypes = {};
230
+ for (const edge of vizEdges) {
231
+ edgeTypes[edge.label] = (edgeTypes[edge.label] ?? 0) + 1;
232
+ }
233
+ return {
234
+ nodes: vizNodes,
235
+ edges: vizEdges,
236
+ nodeCount: vizNodes.length,
237
+ edgeCount: vizEdges.length,
238
+ nodeTypes,
239
+ edgeTypes
240
+ };
241
+ }
242
+
243
+ // ../dashboard/src/graph/types.ts
244
+ function toGraphologyFormat(data) {
245
+ const nodes = data.nodes.map((node) => ({
246
+ key: node.id,
247
+ attributes: {
248
+ label: node.label,
249
+ type: node.type,
250
+ memoryCount: node.memoryCount,
251
+ degree: node.degree,
252
+ ...node.properties
253
+ }
254
+ }));
255
+ const edges = data.edges.map((edge) => ({
256
+ key: edge.id,
257
+ source: edge.source,
258
+ target: edge.target,
259
+ attributes: {
260
+ label: edge.label,
261
+ weight: edge.weight
262
+ }
263
+ }));
264
+ return { nodes, edges };
265
+ }
266
+ function toD3ForceFormat(data) {
267
+ const nodes = data.nodes.map((node) => ({
268
+ id: node.id,
269
+ label: node.label,
270
+ type: node.type,
271
+ memoryCount: node.memoryCount,
272
+ degree: node.degree
273
+ }));
274
+ const links = data.edges.map((edge) => ({
275
+ source: edge.source,
276
+ target: edge.target,
277
+ label: edge.label,
278
+ weight: edge.weight
279
+ }));
280
+ return { nodes, links };
281
+ }
282
+
283
+ // ../dashboard/src/polling/poller.ts
284
+ var Poller = class {
285
+ fetcher;
286
+ options;
287
+ timer = null;
288
+ state = {
289
+ data: null,
290
+ error: null,
291
+ isLoading: false,
292
+ lastUpdated: null
293
+ };
294
+ updateListeners = [];
295
+ errorListeners = [];
296
+ constructor(fetcher, options) {
297
+ this.fetcher = fetcher;
298
+ this.options = {
299
+ intervalMs: options.intervalMs,
300
+ immediate: options.immediate ?? true
301
+ };
302
+ }
303
+ on(event, listener) {
304
+ if (event === "update") {
305
+ this.updateListeners.push(listener);
306
+ } else if (event === "error") {
307
+ this.errorListeners.push(listener);
308
+ }
309
+ return this;
310
+ }
311
+ off(event, listener) {
312
+ if (event === "update") {
313
+ this.updateListeners = this.updateListeners.filter((l) => l !== listener);
314
+ } else if (event === "error") {
315
+ this.errorListeners = this.errorListeners.filter((l) => l !== listener);
316
+ }
317
+ return this;
318
+ }
319
+ async start() {
320
+ if (this.timer) return;
321
+ if (this.options.immediate) {
322
+ await this.poll();
323
+ }
324
+ this.timer = setInterval(() => {
325
+ void this.poll();
326
+ }, this.options.intervalMs);
327
+ }
328
+ stop() {
329
+ if (this.timer) {
330
+ clearInterval(this.timer);
331
+ this.timer = null;
332
+ }
333
+ }
334
+ getState() {
335
+ return { ...this.state };
336
+ }
337
+ isRunning() {
338
+ return this.timer !== null;
339
+ }
340
+ async poll() {
341
+ this.state = { ...this.state, isLoading: true };
342
+ this.emit("update", this.state);
343
+ try {
344
+ const data = await this.fetcher();
345
+ this.state = {
346
+ data,
347
+ error: null,
348
+ isLoading: false,
349
+ lastUpdated: /* @__PURE__ */ new Date()
350
+ };
351
+ this.emit("update", this.state);
352
+ } catch (err) {
353
+ const error = err instanceof Error ? err : new Error(String(err));
354
+ this.state = { ...this.state, error, isLoading: false };
355
+ this.emit("update", this.state);
356
+ this.emit("error", error);
357
+ }
358
+ }
359
+ emit(event, payload) {
360
+ if (event === "update") {
361
+ for (const listener of this.updateListeners) {
362
+ listener(payload);
363
+ }
364
+ } else if (event === "error") {
365
+ for (const listener of this.errorListeners) {
366
+ listener(payload);
367
+ }
368
+ }
369
+ }
370
+ };
371
+
372
+ export {
373
+ analyzeConsolidationLog,
374
+ formatUptime,
375
+ formatBytes,
376
+ enrichHealth,
377
+ unreachableHealth,
378
+ computeMetrics,
379
+ computeTypeDistribution,
380
+ DashboardClient,
381
+ transformGraphData,
382
+ toGraphologyFormat,
383
+ toD3ForceFormat,
384
+ Poller
385
+ };
@@ -0,0 +1,190 @@
1
+ // ../client/src/memory-client.ts
2
+ var MemoryServerError = class extends Error {
3
+ status;
4
+ constructor(message, status) {
5
+ super(message);
6
+ this.name = "MemoryServerError";
7
+ this.status = status;
8
+ }
9
+ /** True when the server returned HTTP 404 (not found). */
10
+ get isNotFound() {
11
+ return this.status === 404;
12
+ }
13
+ };
14
+ var MemoryClient = class {
15
+ baseUrl;
16
+ constructor(memoryUrl) {
17
+ this.baseUrl = memoryUrl.replace(/\/$/, "");
18
+ }
19
+ /** Encode a path segment to prevent URL injection */
20
+ encodePathSegment(segment) {
21
+ return encodeURIComponent(segment);
22
+ }
23
+ async initialize() {
24
+ const response = await fetch(`${this.baseUrl}/health`);
25
+ if (!response.ok) {
26
+ throw new Error(`Memory server not reachable at ${this.baseUrl}: ${response.status}`);
27
+ }
28
+ }
29
+ async store(entry) {
30
+ return this.fetchApi("/api/memory/ingest", {
31
+ method: "POST",
32
+ body: JSON.stringify({
33
+ content: entry.content,
34
+ type: entry.type,
35
+ metadata: entry.metadata,
36
+ agentId: entry.agentId,
37
+ sessionId: entry.sessionId
38
+ })
39
+ });
40
+ }
41
+ async search(params) {
42
+ const searchParams = new URLSearchParams({ query: params.query });
43
+ if (params.limit) searchParams.set("limit", String(params.limit));
44
+ if (params.type) searchParams.set("type", params.type);
45
+ if (params.agentId) searchParams.set("agentId", params.agentId);
46
+ if (params.strategy) searchParams.set("strategy", params.strategy);
47
+ return this.fetchApi(`/api/memory/search?${searchParams}`);
48
+ }
49
+ async get(id) {
50
+ try {
51
+ return await this.fetchApi(`/api/memory/entries/${this.encodePathSegment(id)}`);
52
+ } catch (error) {
53
+ if (error instanceof MemoryServerError && error.isNotFound) return null;
54
+ throw error;
55
+ }
56
+ }
57
+ async delete(id) {
58
+ try {
59
+ await this.fetchApi(`/api/memory/entries/${this.encodePathSegment(id)}`, {
60
+ method: "DELETE"
61
+ });
62
+ return true;
63
+ } catch (error) {
64
+ if (error instanceof MemoryServerError && error.isNotFound) return false;
65
+ throw error;
66
+ }
67
+ }
68
+ async clearSession(sessionId) {
69
+ const result = await this.fetchApi(
70
+ `/api/memory/sessions/${this.encodePathSegment(sessionId)}`,
71
+ { method: "DELETE" }
72
+ );
73
+ return result.cleared;
74
+ }
75
+ async stats() {
76
+ const stats = await this.fetchApi("/api/memory/stats");
77
+ return { ...stats, connected: true };
78
+ }
79
+ async shutdown() {
80
+ }
81
+ async list(params = {}) {
82
+ const searchParams = new URLSearchParams();
83
+ if (params.page != null) searchParams.set("page", String(params.page));
84
+ if (params.limit != null) searchParams.set("limit", String(params.limit));
85
+ if (params.type) searchParams.set("type", params.type);
86
+ if (params.agentId) searchParams.set("agentId", params.agentId);
87
+ const qs = searchParams.toString();
88
+ return this.fetchApi(`/api/memory/entries${qs ? `?${qs}` : ""}`);
89
+ }
90
+ // --- Additional endpoints ---
91
+ async ingestFile(file) {
92
+ const formData = new FormData();
93
+ formData.append("file", file);
94
+ const res = await fetch(`${this.baseUrl}/api/memory/ingest/file`, {
95
+ method: "POST",
96
+ body: formData
97
+ });
98
+ const body = await res.json();
99
+ if (!body.success || body.data === void 0) {
100
+ throw new Error(body.error ?? `Memory server error: ${res.status}`);
101
+ }
102
+ return body.data;
103
+ }
104
+ /** @deprecated Use {@link list} instead. Kept for backwards compatibility. */
105
+ async listEntries(params) {
106
+ const result = await this.list(params);
107
+ return result.entries;
108
+ }
109
+ async graphNodes() {
110
+ const result = await this.fetchApi(
111
+ "/api/memory/graph/nodes"
112
+ );
113
+ return result.nodes;
114
+ }
115
+ async graphEdges() {
116
+ return this.fetchApi(
117
+ "/api/memory/graph/edges"
118
+ );
119
+ }
120
+ async graphQuery(query) {
121
+ return this.fetchApi("/api/memory/graph/query", {
122
+ method: "POST",
123
+ body: JSON.stringify(query)
124
+ });
125
+ }
126
+ // --- ExtendedMemoryInterface methods ---
127
+ async consolidate() {
128
+ return this.fetchApi("/api/memory/consolidate", {
129
+ method: "POST"
130
+ });
131
+ }
132
+ async forget(id, reason) {
133
+ try {
134
+ await this.fetchApi(`/api/memory/forget/${this.encodePathSegment(id)}`, {
135
+ method: "POST",
136
+ body: JSON.stringify({ reason })
137
+ });
138
+ return true;
139
+ } catch (error) {
140
+ if (error instanceof MemoryServerError && error.isNotFound) return false;
141
+ throw error;
142
+ }
143
+ }
144
+ async summarizeSession(sessionId) {
145
+ try {
146
+ return await this.fetchApi(
147
+ `/api/memory/sessions/${this.encodePathSegment(sessionId)}/summarize`,
148
+ { method: "POST" }
149
+ );
150
+ } catch (error) {
151
+ if (error instanceof MemoryServerError && error.isNotFound) return null;
152
+ throw error;
153
+ }
154
+ }
155
+ async runDecay() {
156
+ const result = await this.fetchApi("/api/memory/decay", {
157
+ method: "POST"
158
+ });
159
+ return result.archived;
160
+ }
161
+ async reindex() {
162
+ await this.fetchApi("/api/memory/reindex", { method: "POST" });
163
+ }
164
+ async deleteBySource(source) {
165
+ const result = await this.fetchApi(
166
+ `/api/memory/source/${this.encodePathSegment(source)}`,
167
+ { method: "DELETE" }
168
+ );
169
+ return result.deleted;
170
+ }
171
+ async fetchApi(path, options) {
172
+ const res = await fetch(`${this.baseUrl}${path}`, {
173
+ ...options,
174
+ headers: {
175
+ "Content-Type": "application/json",
176
+ ...options?.headers
177
+ }
178
+ });
179
+ const body = await res.json();
180
+ if (!body.success || body.data === void 0) {
181
+ throw new MemoryServerError(body.error ?? `Memory server error: ${res.status}`, res.status);
182
+ }
183
+ return body.data;
184
+ }
185
+ };
186
+
187
+ export {
188
+ MemoryServerError,
189
+ MemoryClient
190
+ };