@jcyamacho/agent-memory 0.0.19 → 0.0.20
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 +4 -1
- package/dist/index.js +71 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,10 +6,11 @@ Persistent memory for MCP-powered coding agents.
|
|
|
6
6
|
by SQLite. It helps your agent remember preferences, project context, and prior
|
|
7
7
|
decisions across sessions.
|
|
8
8
|
|
|
9
|
-
It exposes
|
|
9
|
+
It exposes five tools:
|
|
10
10
|
|
|
11
11
|
- `remember` -> save facts, decisions, preferences, and project context
|
|
12
12
|
- `recall` -> retrieve the most relevant memories later
|
|
13
|
+
- `review` -> browse all memories for a workspace
|
|
13
14
|
- `revise` -> update an existing memory when it becomes outdated
|
|
14
15
|
- `forget` -> delete a memory that is no longer relevant
|
|
15
16
|
|
|
@@ -52,6 +53,8 @@ Optional LLM instructions to reinforce the MCP's built-in guidance:
|
|
|
52
53
|
conventions, edge cases, or saving memory.
|
|
53
54
|
- Query `memory_recall` with 2-5 short anchor-heavy terms or exact phrases,
|
|
54
55
|
not full questions or sentences.
|
|
56
|
+
- Use `memory_review` to browse all memories for a workspace before bulk review
|
|
57
|
+
or cleanup.
|
|
55
58
|
- Pass `workspace` for project-scoped memory. Omit it only for facts that
|
|
56
59
|
apply across projects.
|
|
57
60
|
- Use `memory_remember` to save one durable fact when the user states a stable
|
package/dist/index.js
CHANGED
|
@@ -12464,7 +12464,7 @@ class StdioServerTransport {
|
|
|
12464
12464
|
}
|
|
12465
12465
|
}
|
|
12466
12466
|
// package.json
|
|
12467
|
-
var version2 = "0.0.
|
|
12467
|
+
var version2 = "0.0.20";
|
|
12468
12468
|
|
|
12469
12469
|
// src/config.ts
|
|
12470
12470
|
import { homedir } from "node:os";
|
|
@@ -12533,14 +12533,20 @@ class PersistenceError extends MemoryError {
|
|
|
12533
12533
|
|
|
12534
12534
|
// src/embedding/service.ts
|
|
12535
12535
|
var DEFAULT_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2";
|
|
12536
|
+
function configureModelsCache(modelsCachePath) {
|
|
12537
|
+
mkdirSync(modelsCachePath, { recursive: true });
|
|
12538
|
+
transformersEnv.useFSCache = true;
|
|
12539
|
+
transformersEnv.cacheDir = modelsCachePath;
|
|
12540
|
+
}
|
|
12536
12541
|
|
|
12537
12542
|
class EmbeddingService {
|
|
12538
12543
|
options;
|
|
12539
12544
|
extractorPromise;
|
|
12540
|
-
modelsCachePath;
|
|
12541
12545
|
constructor(options = {}) {
|
|
12542
12546
|
this.options = options;
|
|
12543
|
-
|
|
12547
|
+
}
|
|
12548
|
+
async warmup() {
|
|
12549
|
+
await this.getExtractor();
|
|
12544
12550
|
}
|
|
12545
12551
|
async createVector(text) {
|
|
12546
12552
|
const normalizedText = text.trim();
|
|
@@ -12553,17 +12559,11 @@ class EmbeddingService {
|
|
|
12553
12559
|
}
|
|
12554
12560
|
getExtractor() {
|
|
12555
12561
|
if (!this.extractorPromise) {
|
|
12556
|
-
configureModelsCache(this.modelsCachePath);
|
|
12557
12562
|
this.extractorPromise = (this.options.createExtractor ?? createDefaultExtractor)();
|
|
12558
12563
|
}
|
|
12559
12564
|
return this.extractorPromise;
|
|
12560
12565
|
}
|
|
12561
12566
|
}
|
|
12562
|
-
function configureModelsCache(modelsCachePath) {
|
|
12563
|
-
mkdirSync(modelsCachePath, { recursive: true });
|
|
12564
|
-
transformersEnv.useFSCache = true;
|
|
12565
|
-
transformersEnv.cacheDir = modelsCachePath;
|
|
12566
|
-
}
|
|
12567
12567
|
async function createDefaultExtractor() {
|
|
12568
12568
|
const extractor = await pipeline("feature-extraction", DEFAULT_EMBEDDING_MODEL);
|
|
12569
12569
|
return (text) => extractor(text, {
|
|
@@ -20185,6 +20185,7 @@ class MemoryService {
|
|
|
20185
20185
|
return memory ? toPublicMemoryRecord(memory) : undefined;
|
|
20186
20186
|
}
|
|
20187
20187
|
async list(input) {
|
|
20188
|
+
const queryWorkspace = normalizeOptionalString(input.workspace);
|
|
20188
20189
|
const workspace = await this.workspaceResolver.resolve(input.workspace);
|
|
20189
20190
|
const page = await this.repository.list({
|
|
20190
20191
|
workspace,
|
|
@@ -20192,7 +20193,10 @@ class MemoryService {
|
|
|
20192
20193
|
offset: normalizeOffset(input.offset),
|
|
20193
20194
|
limit: normalizeListLimit(input.limit)
|
|
20194
20195
|
});
|
|
20195
|
-
return
|
|
20196
|
+
return {
|
|
20197
|
+
items: page.items.map((item) => toPublicMemoryRecord(remapWorkspace(item, workspace, queryWorkspace))),
|
|
20198
|
+
hasMore: page.hasMore
|
|
20199
|
+
};
|
|
20196
20200
|
}
|
|
20197
20201
|
async listWorkspaces() {
|
|
20198
20202
|
return this.repository.listWorkspaces();
|
|
@@ -20215,7 +20219,7 @@ class MemoryService {
|
|
|
20215
20219
|
this.repository.search(normalizedQuery),
|
|
20216
20220
|
this.embeddingService.createVector(terms.join(" "))
|
|
20217
20221
|
]);
|
|
20218
|
-
return rerankSearchResults(results, workspace, queryEmbedding).slice(0, requestedLimit).map((result) => toPublicSearchResult(
|
|
20222
|
+
return rerankSearchResults(results, workspace, queryEmbedding).slice(0, requestedLimit).map((result) => toPublicSearchResult(remapWorkspace(result, workspace, queryWorkspace)));
|
|
20219
20223
|
}
|
|
20220
20224
|
}
|
|
20221
20225
|
function toPublicMemoryRecord(memory) {
|
|
@@ -20237,12 +20241,6 @@ function toPublicSearchResult(result) {
|
|
|
20237
20241
|
updatedAt: result.updatedAt
|
|
20238
20242
|
};
|
|
20239
20243
|
}
|
|
20240
|
-
function toPublicMemoryPage(page) {
|
|
20241
|
-
return {
|
|
20242
|
-
items: page.items.map(toPublicMemoryRecord),
|
|
20243
|
-
hasMore: page.hasMore
|
|
20244
|
-
};
|
|
20245
|
-
}
|
|
20246
20244
|
function normalizeLimit(value) {
|
|
20247
20245
|
if (value === undefined) {
|
|
20248
20246
|
return DEFAULT_RECALL_LIMIT;
|
|
@@ -20269,14 +20267,11 @@ function normalizeOptionalString(value) {
|
|
|
20269
20267
|
const trimmed = value?.trim();
|
|
20270
20268
|
return trimmed ? trimmed : undefined;
|
|
20271
20269
|
}
|
|
20272
|
-
function
|
|
20273
|
-
if (
|
|
20274
|
-
return
|
|
20270
|
+
function remapWorkspace(record3, canonicalWorkspace, queryWorkspace) {
|
|
20271
|
+
if (record3.workspace !== canonicalWorkspace) {
|
|
20272
|
+
return record3;
|
|
20275
20273
|
}
|
|
20276
|
-
return {
|
|
20277
|
-
...result,
|
|
20278
|
-
workspace: queryWorkspace
|
|
20279
|
-
};
|
|
20274
|
+
return { ...record3, workspace: queryWorkspace };
|
|
20280
20275
|
}
|
|
20281
20276
|
|
|
20282
20277
|
// src/mcp/tools/recall.ts
|
|
@@ -20356,6 +20351,53 @@ function registerRememberTool(server, memory) {
|
|
|
20356
20351
|
});
|
|
20357
20352
|
}
|
|
20358
20353
|
|
|
20354
|
+
// src/mcp/tools/review.ts
|
|
20355
|
+
var REVIEW_PAGE_SIZE = 25;
|
|
20356
|
+
var reviewInputSchema = {
|
|
20357
|
+
workspace: string2().describe("Current working directory for project-scoped listing."),
|
|
20358
|
+
page: number2().int().min(0).optional().describe("Zero-based page number. Defaults to 0.")
|
|
20359
|
+
};
|
|
20360
|
+
function toMemoryXml2(record3) {
|
|
20361
|
+
const content = escapeXml(record3.content);
|
|
20362
|
+
return `<memory id="${record3.id}" updated_at="${record3.updatedAt.toISOString()}">
|
|
20363
|
+
${content}
|
|
20364
|
+
</memory>`;
|
|
20365
|
+
}
|
|
20366
|
+
function registerReviewTool(server, memory) {
|
|
20367
|
+
server.registerTool("review", {
|
|
20368
|
+
annotations: {
|
|
20369
|
+
title: "Review",
|
|
20370
|
+
readOnlyHint: true,
|
|
20371
|
+
openWorldHint: false
|
|
20372
|
+
},
|
|
20373
|
+
description: 'Browse all memories for a workspace in creation order. Use before bulk review, cleanup, or when you need to scan memories without specific search terms. For targeted retrieval by topic, use `recall` instead. Returns `<memories workspace="..." has_more="true|false">...</memories>` with pagination support.',
|
|
20374
|
+
inputSchema: reviewInputSchema
|
|
20375
|
+
}, async ({ workspace, page }) => {
|
|
20376
|
+
try {
|
|
20377
|
+
const pageIndex = page ?? 0;
|
|
20378
|
+
const result = await memory.list({
|
|
20379
|
+
workspace,
|
|
20380
|
+
offset: pageIndex * REVIEW_PAGE_SIZE,
|
|
20381
|
+
limit: REVIEW_PAGE_SIZE
|
|
20382
|
+
});
|
|
20383
|
+
if (result.items.length === 0) {
|
|
20384
|
+
return {
|
|
20385
|
+
content: [{ type: "text", text: "No memories found for this workspace." }]
|
|
20386
|
+
};
|
|
20387
|
+
}
|
|
20388
|
+
const text = `<memories workspace="${escapeXml(workspace)}" has_more="${result.hasMore}">
|
|
20389
|
+
${result.items.map(toMemoryXml2).join(`
|
|
20390
|
+
`)}
|
|
20391
|
+
</memories>`;
|
|
20392
|
+
return {
|
|
20393
|
+
content: [{ type: "text", text }]
|
|
20394
|
+
};
|
|
20395
|
+
} catch (error2) {
|
|
20396
|
+
throw toMcpError(error2);
|
|
20397
|
+
}
|
|
20398
|
+
});
|
|
20399
|
+
}
|
|
20400
|
+
|
|
20359
20401
|
// src/mcp/tools/revise.ts
|
|
20360
20402
|
var reviseInputSchema = {
|
|
20361
20403
|
id: string2().describe("Memory id to update. Use an id returned by `recall`."),
|
|
@@ -20392,6 +20434,7 @@ function registerReviseTool(server, memory) {
|
|
|
20392
20434
|
var SERVER_INSTRUCTIONS = [
|
|
20393
20435
|
"Use this server only for durable memory that should survive across turns: stable preferences, corrections, reusable decisions, and project context not obvious from code or git history.",
|
|
20394
20436
|
"Use `recall` at conversation start, before design choices, and before saving or revising memory.",
|
|
20437
|
+
"Use `review` to browse all memories for a workspace before bulk review or cleanup.",
|
|
20395
20438
|
"Use `remember` for one new durable fact. Use `revise` when the fact already exists but needs correction.",
|
|
20396
20439
|
"Use `forget` only when a memory is wrong or obsolete.",
|
|
20397
20440
|
"Pass workspace for project-scoped memory. Omit it only for facts that apply across projects.",
|
|
@@ -20408,6 +20451,7 @@ function createMcpServer(memory, version3) {
|
|
|
20408
20451
|
registerRecallTool(server, memory);
|
|
20409
20452
|
registerReviseTool(server, memory);
|
|
20410
20453
|
registerForgetTool(server, memory);
|
|
20454
|
+
registerReviewTool(server, memory);
|
|
20411
20455
|
return server;
|
|
20412
20456
|
}
|
|
20413
20457
|
|
|
@@ -24288,11 +24332,13 @@ function normalizeOptionalString2(value) {
|
|
|
24288
24332
|
|
|
24289
24333
|
// src/index.ts
|
|
24290
24334
|
var config2 = resolveConfig();
|
|
24291
|
-
|
|
24335
|
+
configureModelsCache(config2.modelsCachePath);
|
|
24336
|
+
var embeddingService = new EmbeddingService;
|
|
24292
24337
|
var workspaceResolver = createGitWorkspaceResolver();
|
|
24293
24338
|
var database = await openMemoryDatabase(config2.databasePath, { embeddingService, workspaceResolver });
|
|
24294
24339
|
var repository2 = new SqliteMemoryRepository(database);
|
|
24295
24340
|
var memoryService = new MemoryService(repository2, embeddingService, workspaceResolver);
|
|
24341
|
+
embeddingService.warmup();
|
|
24296
24342
|
if (config2.uiMode) {
|
|
24297
24343
|
let shutdown = function() {
|
|
24298
24344
|
server.close();
|