memory-mcp.test.mjs
155 lines 5.5 KB
Raw
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor ⚠ breaking 2 days ago
1 /**
2 * MCP memory tool and resource tests.
3 * Tests the registerMemoryTools registration and metadata resource builders.
4 */
5 import { describe, it, before, after, beforeEach } from 'node:test';
6 import assert from 'node:assert';
7 import fs from 'fs';
8 import path from 'path';
9 import os from 'os';
10
11 import {
12 buildMemoryResource,
13 buildMemorySummaryResource,
14 buildMemoryEventsResource,
15 buildMemoryTypeResource,
16 } from '../mcp/resources/metadata.mjs';
17 import { createMemoryManager, storeMemory } from '../lib/memory.mjs';
18
19 let tmpDir;
20
21 before(() => {
22 tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'knowtation-mcp-mem-'));
23 });
24
25 after(() => {
26 fs.rmSync(tmpDir, { recursive: true, force: true });
27 });
28
29 function makeConfig(extra = {}) {
30 const dataDir = path.join(tmpDir, 'data-' + Date.now() + '-' + Math.random().toString(36).slice(2, 6));
31 fs.mkdirSync(dataDir, { recursive: true });
32 return {
33 data_dir: dataDir,
34 memory: { enabled: true, provider: 'file', ...extra },
35 };
36 }
37
38 describe('MCP memory resources (metadata builders)', () => {
39 it('buildMemoryResource returns null when no events', () => {
40 const config = makeConfig();
41 const r = buildMemoryResource(config, 'search');
42 assert.strictEqual(r.value, null);
43 });
44
45 it('buildMemoryResource returns event data after store', () => {
46 const config = makeConfig();
47 const mm = createMemoryManager(config);
48 mm.store('search', { query: 'test', paths: ['a.md'], count: 1 });
49 const r = buildMemoryResource(config, 'search');
50 assert.strictEqual(r.value.query, 'test');
51 assert.strictEqual(typeof r.updated_at, 'string');
52 assert.match(r.id, /^mem_/);
53 });
54
55 it('buildMemoryResource falls back to legacy when memory disabled', () => {
56 const config = makeConfig();
57 config.memory.enabled = false;
58 const r = buildMemoryResource(config, 'search');
59 assert.strictEqual(r.value, null);
60 });
61
62 it('buildMemorySummaryResource returns summary', () => {
63 const config = makeConfig();
64 const mm = createMemoryManager(config);
65 mm.store('search', { query: 'a' });
66 mm.store('export', { format: 'md' });
67 const r = buildMemorySummaryResource(config);
68 assert.strictEqual(r.enabled, true);
69 assert.strictEqual(r.total_events, 2);
70 assert.strictEqual(r.counts_by_type.search, 1);
71 assert.strictEqual(r.counts_by_type.export, 1);
72 });
73
74 it('buildMemorySummaryResource when disabled', () => {
75 const config = makeConfig();
76 config.memory.enabled = false;
77 const r = buildMemorySummaryResource(config);
78 assert.strictEqual(r.enabled, false);
79 });
80
81 it('buildMemoryEventsResource returns events', () => {
82 const config = makeConfig();
83 const mm = createMemoryManager(config);
84 mm.store('search', { query: 'a' });
85 mm.store('search', { query: 'b' });
86 const r = buildMemoryEventsResource(config);
87 assert.strictEqual(r.enabled, true);
88 assert.strictEqual(r.count, 2);
89 assert(Array.isArray(r.events));
90 });
91
92 it('buildMemoryTypeResource returns latest + recent for type', () => {
93 const config = makeConfig();
94 const mm = createMemoryManager(config);
95 mm.store('search', { query: 'first' });
96 mm.store('search', { query: 'second' });
97 mm.store('export', { format: 'md' });
98 const r = buildMemoryTypeResource(config, 'search');
99 assert.strictEqual(r.enabled, true);
100 assert.strictEqual(r.type, 'search');
101 assert.strictEqual(r.latest.data.query, 'second');
102 assert.strictEqual(r.count, 2);
103 });
104
105 it('buildMemoryTypeResource for unknown type returns null latest', () => {
106 const config = makeConfig();
107 const r = buildMemoryTypeResource(config, 'agent_interaction');
108 assert.strictEqual(r.latest, null);
109 assert.strictEqual(r.count, 0);
110 });
111 });
112
113 describe('backward compat: buildMemoryResource with legacy storeMemory', () => {
114 it('legacy storeMemory data is readable via buildMemoryResource', () => {
115 const config = makeConfig();
116 storeMemory(config.data_dir, 'last_search', { query: 'legacy', paths: [], count: 0 });
117 const r = buildMemoryResource(config, 'search');
118 assert.strictEqual(r.value.query, 'legacy');
119 });
120 });
121
122 describe('formatMemoryEventsAsync helper', () => {
123 it('returns formatted memory events', async () => {
124 const { formatMemoryEventsAsync } = await import('../mcp/prompts/helpers.mjs');
125 const config = makeConfig();
126 const mm = createMemoryManager(config);
127 mm.store('search', { query: 'test-query' });
128 mm.store('export', { format: 'md' });
129 const { text, count } = await formatMemoryEventsAsync(config, { limit: 10 });
130 assert.strictEqual(count, 2);
131 assert.ok(text.includes('[search]'));
132 assert.ok(text.includes('[export]'));
133 assert.ok(text.includes('test-query'));
134 });
135
136 it('returns empty message when no events', async () => {
137 const { formatMemoryEventsAsync } = await import('../mcp/prompts/helpers.mjs');
138 const config = makeConfig();
139 const { text, count } = await formatMemoryEventsAsync(config, {});
140 assert.strictEqual(count, 0);
141 assert.ok(text.includes('No memory events'));
142 });
143
144 it('filters by type', async () => {
145 const { formatMemoryEventsAsync } = await import('../mcp/prompts/helpers.mjs');
146 const config = makeConfig();
147 const mm = createMemoryManager(config);
148 mm.store('search', { query: 'a' });
149 mm.store('export', { format: 'md' });
150 const { text, count } = await formatMemoryEventsAsync(config, { type: 'search' });
151 assert.strictEqual(count, 1);
152 assert.ok(text.includes('[search]'));
153 assert.ok(!text.includes('[export]'));
154 });
155 });
File History 2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor 2 days ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6 docs: accept Calendar Events v0 spec with Phase 0 security … Human 3 days ago