@memstack/core 0.4.0 → 0.6.4
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 +213 -49
- package/dist/index.cjs +268 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -1
- package/dist/index.d.ts +42 -1
- package/dist/index.js +268 -8
- package/dist/index.js.map +1 -1
- package/package.json +21 -18
package/README.md
CHANGED
|
@@ -82,15 +82,74 @@ Think of it as the open-source alternative to [Mem0](https://mem0.ai/) — plugg
|
|
|
82
82
|
|
|
83
83
|
## Quick Start
|
|
84
84
|
|
|
85
|
+
```bash
|
|
86
|
+
npm install @memstack/core
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### OpenAI
|
|
90
|
+
|
|
85
91
|
```typescript
|
|
86
92
|
import { MemStack, OpenAILLMAdapter, OpenAIEmbeddingAdapter, InMemoryStorageAdapter } from "@memstack/core";
|
|
87
93
|
|
|
94
|
+
const llm = new OpenAILLMAdapter({ apiKey: process.env.OPENAI_API_KEY! });
|
|
95
|
+
|
|
88
96
|
const memstack = new MemStack({
|
|
89
|
-
llm
|
|
97
|
+
llm,
|
|
90
98
|
embedding: new OpenAIEmbeddingAdapter({ apiKey: process.env.OPENAI_API_KEY! }),
|
|
91
99
|
storage: new InMemoryStorageAdapter(),
|
|
92
100
|
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### DeepSeek (no embeddings)
|
|
104
|
+
|
|
105
|
+
DeepSeek provides chat completions but has no embedding API. Use the OpenAI-compatible LLM adapter with `baseURL` and omit the embedding adapter — retrieval falls back to keyword + recency + importance ranking. You still get the full pipeline: store, summarize, prune, and compileContext.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { MemStack, OpenAILLMAdapter, InMemoryStorageAdapter } from "@memstack/core";
|
|
109
|
+
|
|
110
|
+
const llm = new OpenAILLMAdapter({
|
|
111
|
+
apiKey: process.env.DEEPSEEK_API_KEY!,
|
|
112
|
+
baseURL: "https://api.deepseek.com/v1",
|
|
113
|
+
defaultModel: "deepseek-chat",
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const memstack = new MemStack({
|
|
117
|
+
llm,
|
|
118
|
+
storage: new InMemoryStorageAdapter(),
|
|
119
|
+
// No embedding adapter — retrieval uses keyword matching
|
|
120
|
+
});
|
|
121
|
+
```
|
|
93
122
|
|
|
123
|
+
### OpenRouter / Together AI / any OpenAI-compatible API
|
|
124
|
+
|
|
125
|
+
Same pattern — change `baseURL` and `defaultModel`:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// OpenRouter
|
|
129
|
+
const llm = new OpenAILLMAdapter({
|
|
130
|
+
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
131
|
+
baseURL: "https://openrouter.ai/api/v1",
|
|
132
|
+
defaultModel: "openai/gpt-4o-mini",
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Together AI
|
|
136
|
+
const llm = new OpenAILLMAdapter({
|
|
137
|
+
apiKey: process.env.TOGETHER_API_KEY!,
|
|
138
|
+
baseURL: "https://api.together.xyz/v1",
|
|
139
|
+
defaultModel: "meta-llama/Llama-3.3-70B-Instruct-Turbo",
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Gemini (OpenAI-compatible endpoint)
|
|
143
|
+
const llm = new OpenAILLMAdapter({
|
|
144
|
+
apiKey: process.env.GEMINI_API_KEY!,
|
|
145
|
+
baseURL: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
146
|
+
defaultModel: "gemini-2.0-flash",
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Store and retrieve
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
94
153
|
// 1. Store what happened
|
|
95
154
|
await memstack.memory.store({
|
|
96
155
|
actorId: "support-bot-42",
|
|
@@ -106,18 +165,21 @@ const memories = await memstack.memory.retrieve({
|
|
|
106
165
|
strategy: "hybrid",
|
|
107
166
|
});
|
|
108
167
|
|
|
109
|
-
// 3.
|
|
168
|
+
// 3. Assemble an LLM-ready context
|
|
110
169
|
const ctx = await memstack.memory.compileContext({
|
|
111
170
|
actorId: "support-bot-42",
|
|
112
171
|
maxTokens: 2000,
|
|
113
172
|
});
|
|
114
173
|
|
|
115
|
-
const
|
|
174
|
+
const response = await llm.complete({
|
|
116
175
|
system: `You are a support bot. Here is what you remember:\n${ctx.systemPrompt}`,
|
|
117
176
|
user: "The user is back and still can't log in. What do you do?",
|
|
118
177
|
});
|
|
119
178
|
|
|
120
|
-
|
|
179
|
+
console.log(response.text);
|
|
180
|
+
// "Based on our history, the user has been experiencing 503 errors on Chrome 125..."
|
|
181
|
+
|
|
182
|
+
// 4. Every 100 interactions, summarization triggers automatically.
|
|
121
183
|
// Old interactions are compressed into a paragraph. Token costs stay flat.
|
|
122
184
|
```
|
|
123
185
|
|
|
@@ -192,7 +254,7 @@ No embedding adapter? `semantic` and `hybrid` fall back to keyword matching + im
|
|
|
192
254
|
|
|
193
255
|
### 3. Compile Context
|
|
194
256
|
|
|
195
|
-
|
|
257
|
+
`compileContext()` takes retrieval results and assembles an LLM-ready system prompt — deduplicated, sorted by recency and importance, with a token estimate so you know the cost before calling the LLM.
|
|
196
258
|
|
|
197
259
|
```typescript
|
|
198
260
|
const ctx = await ms.memory.compileContext({
|
|
@@ -213,13 +275,16 @@ const ctx = await ms.memory.compileContext({
|
|
|
213
275
|
console.log(ctx.tokenEstimate); // ~280
|
|
214
276
|
|
|
215
277
|
// Inject into your LLM call
|
|
278
|
+
const currentMessage = "The user is asking about their refund status.";
|
|
216
279
|
const response = await llm.complete({
|
|
217
280
|
system: ctx.systemPrompt,
|
|
218
|
-
user:
|
|
281
|
+
user: currentMessage,
|
|
219
282
|
});
|
|
283
|
+
|
|
284
|
+
console.log(response.text);
|
|
220
285
|
```
|
|
221
286
|
|
|
222
|
-
`compileContext()`
|
|
287
|
+
`compileContext()` handles deduplication, token budgeting, and splits context into important-vs-recent sections. Without it, you'd be concatenating raw retrieval results and risking context-window overflow.
|
|
223
288
|
|
|
224
289
|
### 4. Summarize
|
|
225
290
|
|
|
@@ -309,13 +374,29 @@ const ms = new MemStack({
|
|
|
309
374
|
### Support Agent
|
|
310
375
|
|
|
311
376
|
```typescript
|
|
377
|
+
// detectUrgency and classifyIntent are your own business logic.
|
|
378
|
+
// They could be simple keyword matchers, regex, or an LLM call.
|
|
379
|
+
function detectUrgency(msg: string): number {
|
|
380
|
+
if (msg.match(/urgent|asap|immediately/i)) return 0.9;
|
|
381
|
+
if (msg.match(/error|fail|broken/i)) return 0.7;
|
|
382
|
+
return 0.5;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function classifyIntent(msg: string): string[] {
|
|
386
|
+
const tags: string[] = [];
|
|
387
|
+
if (msg.match(/bill|refund|charge|payment/i)) tags.push("billing");
|
|
388
|
+
if (msg.match(/error|bug|fail|crash/i)) tags.push("bug");
|
|
389
|
+
if (msg.match(/login|password|account/i)) tags.push("account");
|
|
390
|
+
return tags;
|
|
391
|
+
}
|
|
392
|
+
|
|
312
393
|
// Every customer message becomes a memory
|
|
313
394
|
async function handleMessage(customerId: string, message: string) {
|
|
314
395
|
await ms.memory.store({
|
|
315
396
|
actorId: `customer:${customerId}`,
|
|
316
397
|
content: message,
|
|
317
|
-
importance: detectUrgency(message),
|
|
318
|
-
tags: classifyIntent(message),
|
|
398
|
+
importance: detectUrgency(message),
|
|
399
|
+
tags: classifyIntent(message),
|
|
319
400
|
});
|
|
320
401
|
|
|
321
402
|
// Retrieve everything relevant to this customer's history
|
|
@@ -339,6 +420,12 @@ async function handleMessage(customerId: string, message: string) {
|
|
|
339
420
|
### RAG Pipeline
|
|
340
421
|
|
|
341
422
|
```typescript
|
|
423
|
+
// Suppose you have documents from your knowledge base
|
|
424
|
+
const documents = [
|
|
425
|
+
{ text: "Authentication uses JWT tokens with 15-minute expiry.", url: "/docs/auth", section: "security" },
|
|
426
|
+
{ text: "Refunds are processed within 5-10 business days.", url: "/docs/billing", section: "billing" },
|
|
427
|
+
];
|
|
428
|
+
|
|
342
429
|
// Index documents as observation memories
|
|
343
430
|
for (const doc of documents) {
|
|
344
431
|
await ms.memory.store({
|
|
@@ -441,9 +528,61 @@ await ms.memory.retrieve({ actorId: "x", query: "login bug", strategy: "hybrid"
|
|
|
441
528
|
|
|
442
529
|
Embeddings power semantic search. They're optional — without them, retrieval uses keyword matching.
|
|
443
530
|
|
|
444
|
-
|
|
531
|
+
### With embeddings vs Without embeddings
|
|
445
532
|
|
|
446
|
-
**
|
|
533
|
+
**With embeddings** (`embedding` adapter configured):
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
import { MemStack, OpenAILLMAdapter, OpenAIEmbeddingAdapter, InMemoryStorageAdapter } from "@memstack/core";
|
|
537
|
+
|
|
538
|
+
const ms = new MemStack({
|
|
539
|
+
llm: new OpenAILLMAdapter({ apiKey: process.env.OPENAI_API_KEY! }),
|
|
540
|
+
embedding: new OpenAIEmbeddingAdapter({ apiKey: process.env.OPENAI_API_KEY! }),
|
|
541
|
+
storage: new InMemoryStorageAdapter(),
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
// store() computes a 1536-dim vector automatically
|
|
545
|
+
await ms.memory.store({
|
|
546
|
+
actorId: "agent-7",
|
|
547
|
+
content: "Customer asked about refund policy for Q2 purchases.",
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
// retrieve() with "semantic" or "hybrid" uses cosine similarity
|
|
551
|
+
// Query: "refund" finds the refund policy memory even though the word "refund"
|
|
552
|
+
// appears differently across stored memories.
|
|
553
|
+
const results = await ms.memory.retrieve({
|
|
554
|
+
actorId: "agent-7",
|
|
555
|
+
query: "how do I get my money back",
|
|
556
|
+
strategy: "semantic",
|
|
557
|
+
});
|
|
558
|
+
// Matches "Customer asked about refund policy" — semantic match, not keyword match.
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
**Without embeddings** (no `embedding` adapter):
|
|
562
|
+
|
|
563
|
+
```typescript
|
|
564
|
+
const ms = new MemStack({
|
|
565
|
+
llm: new OpenAILLMAdapter({ apiKey: process.env.OPENAI_API_KEY! }),
|
|
566
|
+
storage: new InMemoryStorageAdapter(),
|
|
567
|
+
// no embedding adapter
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
// store() works identically, just no vector computed
|
|
571
|
+
await ms.memory.store({
|
|
572
|
+
actorId: "agent-7",
|
|
573
|
+
content: "Customer asked about refund policy for Q2 purchases.",
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
// retrieve() with "semantic" or "hybrid" falls back to keyword matching
|
|
577
|
+
// plus importance/recency sorting. No API costs, no setup required.
|
|
578
|
+
const results = await ms.memory.retrieve({
|
|
579
|
+
actorId: "agent-7",
|
|
580
|
+
query: "refund",
|
|
581
|
+
strategy: "hybrid", // falls back to keyword + importance
|
|
582
|
+
});
|
|
583
|
+
// Still works — finds "refund" via substring match. Less precise for
|
|
584
|
+
// paraphrased queries ("money back" won't match "refund").
|
|
585
|
+
```
|
|
447
586
|
|
|
448
587
|
**Batch embedding:** `storeBatch()` sends all texts in one embedding API call, reducing cost and latency.
|
|
449
588
|
|
|
@@ -456,6 +595,28 @@ const ms = new MemStack({
|
|
|
456
595
|
});
|
|
457
596
|
```
|
|
458
597
|
|
|
598
|
+
### Vector dimensions and model compatibility
|
|
599
|
+
|
|
600
|
+
Different embedding models produce vectors of different lengths. Cosine similarity only works between vectors of the same dimension. If you change embedding models, existing vectors become incompatible — they can't be compared to new ones.
|
|
601
|
+
|
|
602
|
+
| Adapter | Default model | Dimensions |
|
|
603
|
+
|---------|--------------|------------|
|
|
604
|
+
| `OpenAIEmbeddingAdapter` | `text-embedding-3-small` | 1536 |
|
|
605
|
+
| `OpenAIEmbeddingAdapter` | `text-embedding-3-large` | 3072 |
|
|
606
|
+
| `CohereEmbeddingAdapter` | `embed-english-v3.0` | 1024 |
|
|
607
|
+
| `CohereEmbeddingAdapter` | `embed-english-light-v3.0` | 384 |
|
|
608
|
+
| `CohereEmbeddingAdapter` | `embed-english-v2.0` | 4096 |
|
|
609
|
+
| `CohereEmbeddingAdapter` | `embed-multilingual-v3.0` | 1024 |
|
|
610
|
+
|
|
611
|
+
**What happens if dimensions don't match:** If you store memories with one model (e.g., 1536 dims) then switch to another model (e.g., 1024 dims), the storage adapter receives query vectors and stored vectors of different lengths. Cosine similarity between vectors of different dimensions is undefined — results depend on the storage backend's behavior. Most will either error, return empty results, or produce meaningless scores.
|
|
612
|
+
|
|
613
|
+
**Recommendation:** Pick one embedding model per storage instance and stick with it. If you need to switch models, create a new storage instance and re-embed from scratch.
|
|
614
|
+
|
|
615
|
+
**DeepSeek users:** DeepSeek has no embeddings API. If you use DeepSeek as your LLM, you must either:
|
|
616
|
+
1. Omit the embedding adapter and use `"recent"` or `"important"` retrieval strategies (no API costs, less precise)
|
|
617
|
+
2. Pair DeepSeek with a separate embedding provider (e.g., OpenAI for embeddings, DeepSeek for chat)
|
|
618
|
+
|
|
619
|
+
|
|
459
620
|
---
|
|
460
621
|
|
|
461
622
|
## Adapters
|
|
@@ -512,6 +673,8 @@ new OpenAIEmbeddingAdapter({ apiKey: "...", baseURL: "https://api.voyageai.com/v
|
|
|
512
673
|
|
|
513
674
|
MemStack ships with **11 production-ready storage adapters (7 experimental)** — every major backend, zero peer dependencies, all client-injected.
|
|
514
675
|
|
|
676
|
+
### Production (e2e verified against real instances)
|
|
677
|
+
|
|
515
678
|
**Built-in (zero external deps):**
|
|
516
679
|
| Adapter | Backend | Use case |
|
|
517
680
|
|---|---|---|
|
|
@@ -524,21 +687,11 @@ MemStack ships with **11 production-ready storage adapters (7 experimental)**
|
|
|
524
687
|
| Adapter | Backend | Vector search |
|
|
525
688
|
|---|---|---|
|
|
526
689
|
| `PostgresStorageAdapter` | PostgreSQL + pgvector | HNSW native |
|
|
527
|
-
| `SQLiteStorageAdapter` | SQLite (better-sqlite3) | In-memory cosine |
|
|
528
|
-
| `TursoStorageAdapter` | Turso (libsql) | DiskANN native |
|
|
529
|
-
|
|
530
|
-
**Aggregators:**
|
|
531
|
-
| Adapter | Delegates to |
|
|
532
|
-
|---|---|
|
|
533
|
-
| `Mem0StorageAdapter` | Mem0 OSS or Cloud |
|
|
534
|
-
| `ZepStorageAdapter` | Zep Cloud or Community Edition |
|
|
535
690
|
|
|
536
691
|
**Vector databases:**
|
|
537
692
|
| Adapter | Backend |
|
|
538
693
|
|---|---|
|
|
539
694
|
| `QdrantStorageAdapter` | Qdrant |
|
|
540
|
-
| `PineconeStorageAdapter` | Pinecone |
|
|
541
|
-
| `ChromaStorageAdapter` | ChromaDB |
|
|
542
695
|
| `WeaviateStorageAdapter` | Weaviate |
|
|
543
696
|
| `LanceDBStorageAdapter` | LanceDB |
|
|
544
697
|
| `MongoDBStorageAdapter` | MongoDB Atlas Vector Search |
|
|
@@ -547,13 +700,28 @@ MemStack ships with **11 production-ready storage adapters (7 experimental)**
|
|
|
547
700
|
| Adapter | Backend |
|
|
548
701
|
|---|---|
|
|
549
702
|
| `RedisStorageAdapter` | Redis (ioredis) |
|
|
550
|
-
| `UpstashStorageAdapter` | Upstash Redis + Vector |
|
|
551
703
|
|
|
552
704
|
**Graph:**
|
|
553
705
|
| Adapter | Backend |
|
|
554
706
|
|---|---|
|
|
555
707
|
| `Neo4jStorageAdapter` | Neo4j |
|
|
556
708
|
|
|
709
|
+
### Experimental (mock-tested, blocked by cloud deps or platform constraints)
|
|
710
|
+
|
|
711
|
+
Available via direct source import. Not yet in the barrel export — uncomment in `src/index.ts` when e2e verified.
|
|
712
|
+
|
|
713
|
+
| Adapter | Backend | Blocker |
|
|
714
|
+
|---|---|---|
|
|
715
|
+
| `SQLiteStorageAdapter` | SQLite (better-sqlite3) | Native binary for Node 24 |
|
|
716
|
+
| `TursoStorageAdapter` | Turso (libsql) | Cloud-only (needs Turso account) |
|
|
717
|
+
| `ChromaStorageAdapter` | ChromaDB | Embedding function dependency |
|
|
718
|
+
| `PineconeStorageAdapter` | Pinecone | Cloud-only (needs API key) |
|
|
719
|
+
| `UpstashStorageAdapter` | Upstash Redis + Vector | Cloud-only (needs API key) |
|
|
720
|
+
| `Mem0StorageAdapter` | Mem0 OSS or Cloud | Cloud-only (needs API key) |
|
|
721
|
+
| `ZepStorageAdapter` | Zep Cloud or CE | Cloud-only (needs API key) |
|
|
722
|
+
|
|
723
|
+
> **Direct import:** `import { ChromaStorageAdapter } from "@memstack/core/src/adapters/storage/chroma.js"`
|
|
724
|
+
|
|
557
725
|
**Quick-start per backend:**
|
|
558
726
|
|
|
559
727
|
```ts
|
|
@@ -561,11 +729,6 @@ MemStack ships with **11 production-ready storage adapters (7 experimental)**
|
|
|
561
729
|
import { PostgresStorageAdapter } from "@memstack/core";
|
|
562
730
|
const storage = new PostgresStorageAdapter({ connectionString: "postgres://..." });
|
|
563
731
|
|
|
564
|
-
// SQLite
|
|
565
|
-
import Database from "better-sqlite3";
|
|
566
|
-
import { SQLiteStorageAdapter } from "@memstack/core";
|
|
567
|
-
const storage = new SQLiteStorageAdapter({ db: new Database("memory.db") });
|
|
568
|
-
|
|
569
732
|
// Redis
|
|
570
733
|
import Redis from "ioredis";
|
|
571
734
|
import { RedisStorageAdapter } from "@memstack/core";
|
|
@@ -604,26 +767,21 @@ class MyStorage implements StorageProvider {
|
|
|
604
767
|
|
|
605
768
|
## Backend Comparison
|
|
606
769
|
|
|
607
|
-
| Backend | Vector search | Touch |
|
|
770
|
+
| Backend | Vector search | Touch | Status |
|
|
608
771
|
|---|---|---|---|
|
|
609
|
-
| InMemory | Cosine in-memory | Yes |
|
|
610
|
-
| Disk (JSON) | Keyword + importance | Yes |
|
|
611
|
-
| Markdown | Keyword + importance | No |
|
|
612
|
-
| Postgres | pgvector HNSW | Yes | Production
|
|
613
|
-
|
|
|
614
|
-
|
|
|
615
|
-
|
|
|
616
|
-
|
|
|
617
|
-
|
|
|
618
|
-
|
|
|
619
|
-
|
|
|
620
|
-
|
|
|
621
|
-
|
|
|
622
|
-
| MongoDB | Atlas Vector Search | No | Existing MongoDB deployments |
|
|
623
|
-
| Neo4j | Neo4j vector index | No | Relationship-aware agents |
|
|
624
|
-
| Hybrid | Delegates to cache/durable | If durable supports | Read-through cache pattern |
|
|
625
|
-
| Mem0 | Delegates to Mem0 | No | Multi-backend via Mem0 |
|
|
626
|
-
| Zep | Graphiti temporal graph | No | Temporal graph memory |
|
|
772
|
+
| InMemory | Cosine in-memory | Yes | ✅ Production |
|
|
773
|
+
| Disk (JSON) | Keyword + importance | Yes | ✅ Production |
|
|
774
|
+
| Markdown | Keyword + importance | No | ✅ Production |
|
|
775
|
+
| Postgres | pgvector HNSW | Yes | ✅ Production |
|
|
776
|
+
| Redis | RediSearch KNN (auto-detect) | Yes | ✅ Production |
|
|
777
|
+
| Qdrant | ANN native | No | ✅ Production |
|
|
778
|
+
| Weaviate | BM25 + vector hybrid | No | ✅ Production |
|
|
779
|
+
| LanceDB | DiskANN native | No | ✅ Production |
|
|
780
|
+
| MongoDB | Atlas Vector Search | No | ✅ Production |
|
|
781
|
+
| Neo4j | Neo4j vector index | No | ✅ Production |
|
|
782
|
+
| Hybrid | Delegates to cache/durable | If durable supports | ✅ Production |
|
|
783
|
+
| SQLite | Cosine in-memory | Yes | ✅ Production |
|
|
784
|
+
| Hybrid | Delegates to cache/durable | If durable supports | ✅ Production |
|
|
627
785
|
|
|
628
786
|
---
|
|
629
787
|
|
|
@@ -676,7 +834,11 @@ ms.memory.dryRunPrune(strategy: PruneStrategy): Promise<{ wouldPrune: string[];
|
|
|
676
834
|
ms.memory.count(filter?: MemoryCountFilter): Promise<number>
|
|
677
835
|
ms.memory.delete(id: string): Promise<void>
|
|
678
836
|
ms.memory.deleteMany(ids: string[]): Promise<number>
|
|
679
|
-
ms.memory.touch(id: string): Promise<void>
|
|
837
|
+
ms.memory.touch(id: string): Promise<void>
|
|
838
|
+
ms.memory.purgeActor(actorId: string): Promise<number>
|
|
839
|
+
ms.memory.merge(ids: string[]): Promise<Memory>
|
|
840
|
+
ms.memory.stats(actorId?: string): Promise<MemoryStats>
|
|
841
|
+
ms.memory.summarizeStream(options: SummarizeOptions): AsyncIterable<{ chunk: string; text: string }>
|
|
680
842
|
```
|
|
681
843
|
|
|
682
844
|
### Export / Import
|
|
@@ -684,6 +846,8 @@ ms.memory.touch(id: string): Promise<void> // bump recency without changing con
|
|
|
684
846
|
Snapshot and restore full state for persistence, backups, or migration:
|
|
685
847
|
|
|
686
848
|
```typescript
|
|
849
|
+
import * as fs from "node:fs";
|
|
850
|
+
|
|
687
851
|
// Save
|
|
688
852
|
const snapshot = await ms.export();
|
|
689
853
|
fs.writeFileSync("state.json", JSON.stringify(snapshot, null, 2));
|
|
@@ -785,6 +949,7 @@ cd memstack
|
|
|
785
949
|
pnpm install
|
|
786
950
|
|
|
787
951
|
pnpm test # 393 tests, no external services needed
|
|
952
|
+
pnpm test:e2e # 82 E2E tests (requires Docker)
|
|
788
953
|
pnpm test:watch # Watch mode
|
|
789
954
|
pnpm build # CJS + ESM + type declarations
|
|
790
955
|
pnpm check # TypeScript type-check only
|
|
@@ -839,7 +1004,7 @@ npm login
|
|
|
839
1004
|
npm publish --access public
|
|
840
1005
|
```
|
|
841
1006
|
|
|
842
|
-
The `@memstack` scope requires `--access public
|
|
1007
|
+
The `@memstack` scope requires `--access public`.
|
|
843
1008
|
|
|
844
1009
|
---
|
|
845
1010
|
|
|
@@ -847,7 +1012,6 @@ The `@memstack` scope requires `--access public` on first publish.
|
|
|
847
1012
|
|
|
848
1013
|
Most needed contributions:
|
|
849
1014
|
|
|
850
|
-
- **Docker Compose** for integration testing
|
|
851
1015
|
- **LLM adapters**: Google Gemini (native), Amazon Bedrock, Vertex AI
|
|
852
1016
|
- **Embedding adapters**: local inference (transformers.js, ONNX)
|
|
853
1017
|
- **Benchmarks**: retrieval quality, latency, cost comparisons
|