@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.
Files changed (3) hide show
  1. package/README.md +4 -1
  2. package/dist/index.js +71 -25
  3. 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 four tools:
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.19";
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
- this.modelsCachePath = options.modelsCachePath ?? resolveModelsCachePath();
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 toPublicMemoryPage(page);
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(remapSearchResultWorkspace(result, workspace, queryWorkspace)));
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 remapSearchResultWorkspace(result, canonicalWorkspace, queryWorkspace) {
20273
- if (!queryWorkspace || !canonicalWorkspace || result.workspace !== canonicalWorkspace) {
20274
- return result;
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
- var embeddingService = new EmbeddingService({ modelsCachePath: config2.modelsCachePath });
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();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jcyamacho/agent-memory",
3
3
  "main": "dist/index.js",
4
- "version": "0.0.19",
4
+ "version": "0.0.20",
5
5
  "bin": {
6
6
  "agent-memory": "dist/index.js"
7
7
  },