@j0hanz/memory-mcp 1.0.0 → 1.1.0

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 (131) hide show
  1. package/README.md +32 -25
  2. package/dist/completions/index.d.ts.map +1 -1
  3. package/dist/completions/index.js +11 -8
  4. package/dist/completions/index.js.map +1 -1
  5. package/dist/db/index.d.ts.map +1 -1
  6. package/dist/db/index.js +68 -8
  7. package/dist/db/index.js.map +1 -1
  8. package/dist/db/typed.d.ts +9 -3
  9. package/dist/db/typed.d.ts.map +1 -1
  10. package/dist/db/typed.js +33 -4
  11. package/dist/db/typed.js.map +1 -1
  12. package/dist/index.js +13 -8
  13. package/dist/index.js.map +1 -1
  14. package/dist/lib/errors.d.ts +4 -0
  15. package/dist/lib/errors.d.ts.map +1 -1
  16. package/dist/lib/errors.js +12 -4
  17. package/dist/lib/errors.js.map +1 -1
  18. package/dist/lib/hash.d.ts.map +1 -1
  19. package/dist/lib/hash.js +9 -2
  20. package/dist/lib/hash.js.map +1 -1
  21. package/dist/lib/instructions.d.ts +2 -0
  22. package/dist/lib/instructions.d.ts.map +1 -0
  23. package/dist/lib/instructions.js +96 -0
  24. package/dist/lib/instructions.js.map +1 -0
  25. package/dist/lib/mcp-utils.d.ts +6 -0
  26. package/dist/lib/mcp-utils.d.ts.map +1 -0
  27. package/dist/lib/mcp-utils.js +26 -0
  28. package/dist/lib/mcp-utils.js.map +1 -0
  29. package/dist/lib/pagination.d.ts.map +1 -1
  30. package/dist/lib/pagination.js +14 -7
  31. package/dist/lib/pagination.js.map +1 -1
  32. package/dist/lib/search-cursor.d.ts +13 -0
  33. package/dist/lib/search-cursor.d.ts.map +1 -0
  34. package/dist/lib/search-cursor.js +89 -0
  35. package/dist/lib/search-cursor.js.map +1 -0
  36. package/dist/lib/search.d.ts +16 -0
  37. package/dist/lib/search.d.ts.map +1 -1
  38. package/dist/lib/search.js +53 -12
  39. package/dist/lib/search.js.map +1 -1
  40. package/dist/lib/sql.d.ts +17 -0
  41. package/dist/lib/sql.d.ts.map +1 -0
  42. package/dist/lib/sql.js +18 -0
  43. package/dist/lib/sql.js.map +1 -0
  44. package/dist/lib/tool-contracts.d.ts +18 -0
  45. package/dist/lib/tool-contracts.d.ts.map +1 -0
  46. package/dist/lib/tool-contracts.js +120 -0
  47. package/dist/lib/tool-contracts.js.map +1 -0
  48. package/dist/lib/tool-response.d.ts +1 -5
  49. package/dist/lib/tool-response.d.ts.map +1 -1
  50. package/dist/lib/tool-response.js +9 -7
  51. package/dist/lib/tool-response.js.map +1 -1
  52. package/dist/lib/types.d.ts.map +1 -1
  53. package/dist/lib/types.js +10 -9
  54. package/dist/lib/types.js.map +1 -1
  55. package/dist/prompts/index.d.ts.map +1 -1
  56. package/dist/prompts/index.js +22 -36
  57. package/dist/prompts/index.js.map +1 -1
  58. package/dist/resources/index.d.ts.map +1 -1
  59. package/dist/resources/index.js +15 -36
  60. package/dist/resources/index.js.map +1 -1
  61. package/dist/schemas/index.d.ts.map +1 -1
  62. package/dist/schemas/index.js +1 -1
  63. package/dist/schemas/index.js.map +1 -1
  64. package/dist/schemas/inputs.d.ts +5 -5
  65. package/dist/schemas/inputs.d.ts.map +1 -1
  66. package/dist/schemas/inputs.js +21 -14
  67. package/dist/schemas/inputs.js.map +1 -1
  68. package/dist/schemas/outputs.d.ts +94 -148
  69. package/dist/schemas/outputs.d.ts.map +1 -1
  70. package/dist/schemas/outputs.js +59 -66
  71. package/dist/schemas/outputs.js.map +1 -1
  72. package/dist/server.d.ts.map +1 -1
  73. package/dist/server.js +20 -18
  74. package/dist/server.js.map +1 -1
  75. package/dist/tools/create-relationship.d.ts.map +1 -1
  76. package/dist/tools/create-relationship.js +38 -25
  77. package/dist/tools/create-relationship.js.map +1 -1
  78. package/dist/tools/delete-memories.d.ts.map +1 -1
  79. package/dist/tools/delete-memories.js +37 -30
  80. package/dist/tools/delete-memories.js.map +1 -1
  81. package/dist/tools/delete-memory.d.ts.map +1 -1
  82. package/dist/tools/delete-memory.js +24 -22
  83. package/dist/tools/delete-memory.js.map +1 -1
  84. package/dist/tools/delete-relationship.d.ts.map +1 -1
  85. package/dist/tools/delete-relationship.js +28 -20
  86. package/dist/tools/delete-relationship.js.map +1 -1
  87. package/dist/tools/get-memory.d.ts.map +1 -1
  88. package/dist/tools/get-memory.js +26 -16
  89. package/dist/tools/get-memory.js.map +1 -1
  90. package/dist/tools/get-relationships.d.ts.map +1 -1
  91. package/dist/tools/get-relationships.js +71 -40
  92. package/dist/tools/get-relationships.js.map +1 -1
  93. package/dist/tools/index.d.ts +6 -14
  94. package/dist/tools/index.d.ts.map +1 -1
  95. package/dist/tools/index.js +5 -0
  96. package/dist/tools/index.js.map +1 -1
  97. package/dist/tools/memory-stats.d.ts.map +1 -1
  98. package/dist/tools/memory-stats.js +29 -39
  99. package/dist/tools/memory-stats.js.map +1 -1
  100. package/dist/tools/progress.d.ts +34 -0
  101. package/dist/tools/progress.d.ts.map +1 -0
  102. package/dist/tools/progress.js +136 -0
  103. package/dist/tools/progress.js.map +1 -0
  104. package/dist/tools/recall.d.ts.map +1 -1
  105. package/dist/tools/recall.js +157 -105
  106. package/dist/tools/recall.js.map +1 -1
  107. package/dist/tools/result.d.ts +7 -0
  108. package/dist/tools/result.d.ts.map +1 -0
  109. package/dist/tools/result.js +19 -0
  110. package/dist/tools/result.js.map +1 -0
  111. package/dist/tools/retrieve-context.d.ts.map +1 -1
  112. package/dist/tools/retrieve-context.js +127 -40
  113. package/dist/tools/retrieve-context.js.map +1 -1
  114. package/dist/tools/search-memories.d.ts.map +1 -1
  115. package/dist/tools/search-memories.js +37 -47
  116. package/dist/tools/search-memories.js.map +1 -1
  117. package/dist/tools/store-memories.d.ts.map +1 -1
  118. package/dist/tools/store-memories.js +44 -28
  119. package/dist/tools/store-memories.js.map +1 -1
  120. package/dist/tools/store-memory.d.ts.map +1 -1
  121. package/dist/tools/store-memory.js +43 -23
  122. package/dist/tools/store-memory.js.map +1 -1
  123. package/dist/tools/update-memory.d.ts.map +1 -1
  124. package/dist/tools/update-memory.js +63 -29
  125. package/dist/tools/update-memory.js.map +1 -1
  126. package/package.json +1 -3
  127. package/dist/instructions.md +0 -123
  128. package/dist/tools/helpers.d.ts +0 -13
  129. package/dist/tools/helpers.d.ts.map +0 -1
  130. package/dist/tools/helpers.js +0 -49
  131. package/dist/tools/helpers.js.map +0 -1
@@ -1,11 +1,17 @@
1
+ import { McpError, } from '@modelcontextprotocol/sdk/types.js';
1
2
  import process from 'node:process';
2
- import { E_UNKNOWN, getErrorMessage } from '../lib/errors.js';
3
- import { decodeCursor, encodeCursor, splitPage } from '../lib/pagination.js';
4
- import { buildAndWhereClause, buildFilterClauses, sanitizeFtsQuery, } from '../lib/search.js';
3
+ import { E_UNKNOWN, getErrorMessage, rethrowMcpError } from '../lib/errors.js';
4
+ import { logToolEvent } from '../lib/mcp-utils.js';
5
+ import { splitPage } from '../lib/pagination.js';
6
+ import { buildSearchCursorScope, decodeSearchCursor, encodeSearchCursor, } from '../lib/search-cursor.js';
7
+ import { loadRankedSearchRows, toMemoryFilters } from '../lib/search.js';
8
+ import { getToolContract } from '../lib/tool-contracts.js';
5
9
  import { createErrorResponse, createToolResponse, } from '../lib/tool-response.js';
6
10
  import { parseMemoryRow } from '../lib/types.js';
7
- import { RecallInputSchema } from '../schemas/inputs.js';
8
- import { RecallResultSchema } from '../schemas/outputs.js';
11
+ import {} from '../schemas/inputs.js';
12
+ import {} from '../schemas/outputs.js';
13
+ import { createProgressReporter, notifyProgress, progressWithMessage, } from './progress.js';
14
+ import { countPayloadArrayItems, getToolResultPayload, isOkStructuredToolResult, } from './result.js';
9
15
  function parseEnvInt(name, fallback, min, max) {
10
16
  const raw = process.env[name];
11
17
  if (raw == null)
@@ -18,42 +24,25 @@ function parseEnvInt(name, fallback, min, max) {
18
24
  const MAX_FRONTIER_SIZE = parseEnvInt('RECALL_MAX_FRONTIER_SIZE', 1000, 100, 50000);
19
25
  const MAX_EDGE_ROWS = parseEnvInt('RECALL_MAX_EDGE_ROWS', 5000, 100, 50000);
20
26
  const MAX_VISITED_NODES = parseEnvInt('RECALL_MAX_VISITED_NODES', 5000, 100, 50000);
21
- function toMemoryFilters(params) {
22
- const filters = {};
23
- if (params.min_importance != null) {
24
- filters.min_importance = params.min_importance;
27
+ const EDGE_QUERY_SQL = `SELECT from_hash, to_hash, relation_type FROM relationships
28
+ WHERE from_hash IN (SELECT value FROM json_each(?))
29
+ OR to_hash IN (SELECT value FROM json_each(?))
30
+ LIMIT ?`;
31
+ const MEMORIES_BY_HASH_SQL = 'SELECT * FROM memories WHERE hash IN (SELECT value FROM json_each(?))';
32
+ async function traverseGraph(db, seeds, depth, signal, onHop) {
33
+ const visited = new Set();
34
+ const frontier = [];
35
+ for (const seed of seeds) {
36
+ visited.add(seed.hash);
37
+ frontier.push(seed.hash);
25
38
  }
26
- if (params.max_importance != null) {
27
- filters.max_importance = params.max_importance;
28
- }
29
- if (params.memory_type != null) {
30
- filters.memory_type = params.memory_type;
31
- }
32
- return filters;
33
- }
34
- function createPlaceholders(count) {
35
- return new Array(count).fill('?').join(',');
36
- }
37
- function loadSeedRows(db, query, limit, offset, filters) {
38
- const ftsQuery = sanitizeFtsQuery(query);
39
- const filter = buildFilterClauses(filters);
40
- const whereExtra = buildAndWhereClause(filter.clauses);
41
- return db
42
- .prepare(`SELECT m.*, memories_fts.rank AS rank FROM memories m
43
- JOIN memories_fts ON memories_fts.rowid = m.rowid
44
- WHERE memories_fts MATCH ?${whereExtra}
45
- ORDER BY memories_fts.rank
46
- LIMIT ? OFFSET ?`)
47
- .all(ftsQuery, ...filter.params, limit + 1, offset);
48
- }
49
- function traverseGraph(db, seeds, depth, signal, onHop) {
50
- const visited = new Set(seeds.map((r) => r.hash));
51
39
  const edges = [];
52
40
  const seenEdges = new Set();
53
- let frontier = seeds.map((r) => r.hash);
54
41
  let depthReached = 0;
55
42
  let aborted = false;
56
- for (let hop = 0; hop < depth && frontier.length > 0; hop++) {
43
+ for (let hop = 0; hop < depth && frontier.length > 0; hop += 1) {
44
+ // Yield to event loop to allow progress notifications and cancellation
45
+ await new Promise((resolve) => setImmediate(resolve));
57
46
  if (signal?.aborted) {
58
47
  aborted = true;
59
48
  break;
@@ -61,7 +50,7 @@ function traverseGraph(db, seeds, depth, signal, onHop) {
61
50
  depthReached = hop + 1;
62
51
  onHop?.(hop, depth);
63
52
  if (frontier.length > MAX_FRONTIER_SIZE) {
64
- frontier = frontier.slice(0, MAX_FRONTIER_SIZE);
53
+ frontier.length = MAX_FRONTIER_SIZE;
65
54
  aborted = true;
66
55
  }
67
56
  const remainingEdgeBudget = MAX_EDGE_ROWS - edges.length;
@@ -70,20 +59,22 @@ function traverseGraph(db, seeds, depth, signal, onHop) {
70
59
  aborted = true;
71
60
  break;
72
61
  }
73
- const placeholders = createPlaceholders(frontier.length);
62
+ const frontierJson = JSON.stringify(frontier);
74
63
  const edgeRows = db
75
- .prepare(`SELECT from_hash, to_hash, relation_type FROM relationships
76
- WHERE from_hash IN (${placeholders}) OR to_hash IN (${placeholders})
77
- LIMIT ?`)
78
- .all(...frontier, ...frontier, remainingEdgeBudget + 1);
79
- const rows = edgeRows.length > remainingEdgeBudget
80
- ? edgeRows.slice(0, remainingEdgeBudget)
81
- : edgeRows;
64
+ .prepareOnce(EDGE_QUERY_SQL)
65
+ .all(frontierJson, frontierJson, remainingEdgeBudget + 1);
66
+ const rowsToProcess = edgeRows.length > remainingEdgeBudget
67
+ ? remainingEdgeBudget
68
+ : edgeRows.length;
82
69
  if (edgeRows.length > remainingEdgeBudget) {
83
70
  aborted = true;
84
71
  }
85
72
  const nextHashes = [];
86
- for (const edge of rows) {
73
+ for (let i = 0; i < rowsToProcess; i += 1) {
74
+ const edge = edgeRows[i];
75
+ if (edge === undefined) {
76
+ break;
77
+ }
87
78
  const edgeKey = `${edge.from_hash}|${edge.to_hash}|${edge.relation_type}`;
88
79
  if (!seenEdges.has(edgeKey)) {
89
80
  seenEdges.add(edgeKey);
@@ -93,19 +84,30 @@ function traverseGraph(db, seeds, depth, signal, onHop) {
93
84
  relation_type: edge.relation_type,
94
85
  });
95
86
  }
96
- for (const h of [edge.from_hash, edge.to_hash]) {
97
- if (!visited.has(h)) {
98
- if (visited.size >= MAX_VISITED_NODES) {
99
- aborted = true;
100
- break;
101
- }
102
- visited.add(h);
103
- if (nextHashes.length < MAX_FRONTIER_SIZE) {
104
- nextHashes.push(h);
105
- }
106
- else {
107
- aborted = true;
108
- }
87
+ if (!visited.has(edge.from_hash)) {
88
+ if (visited.size >= MAX_VISITED_NODES) {
89
+ aborted = true;
90
+ break;
91
+ }
92
+ visited.add(edge.from_hash);
93
+ if (nextHashes.length < MAX_FRONTIER_SIZE) {
94
+ nextHashes.push(edge.from_hash);
95
+ }
96
+ else {
97
+ aborted = true;
98
+ }
99
+ }
100
+ if (!visited.has(edge.to_hash)) {
101
+ if (visited.size >= MAX_VISITED_NODES) {
102
+ aborted = true;
103
+ break;
104
+ }
105
+ visited.add(edge.to_hash);
106
+ if (nextHashes.length < MAX_FRONTIER_SIZE) {
107
+ nextHashes.push(edge.to_hash);
108
+ }
109
+ else {
110
+ aborted = true;
109
111
  }
110
112
  }
111
113
  if (aborted &&
@@ -113,7 +115,8 @@ function traverseGraph(db, seeds, depth, signal, onHop) {
113
115
  break;
114
116
  }
115
117
  }
116
- frontier = nextHashes;
118
+ frontier.length = 0;
119
+ frontier.push(...nextHashes);
117
120
  }
118
121
  return { edges, visited, depthReached, aborted };
119
122
  }
@@ -121,46 +124,61 @@ function loadMemoriesByHashes(db, hashes) {
121
124
  if (hashes.length === 0) {
122
125
  return [];
123
126
  }
124
- const placeholders = createPlaceholders(hashes.length);
125
- const memRows = db
126
- .prepare(`SELECT * FROM memories WHERE hash IN (${placeholders})`)
127
- .all(...hashes);
128
- return memRows.map(parseMemoryRow);
127
+ return db
128
+ .prepareOnce(MEMORIES_BY_HASH_SQL)
129
+ .all(JSON.stringify(hashes));
129
130
  }
130
- function createHopNotifier(progressToken, sendNotification) {
131
- if (progressToken == null) {
132
- return undefined;
131
+ function formatRecallCompletionMessage(query, result) {
132
+ const failedMessage = `⊙ recall: ${query} • failed`;
133
+ if (result.isError) {
134
+ return failedMessage;
133
135
  }
134
- return (hop, total) => {
135
- void sendNotification({
136
- method: 'notifications/progress',
137
- params: { progressToken, progress: hop + 1, total },
138
- }).catch(() => { });
139
- };
140
- }
141
- function toProgressToken(value) {
142
- if (typeof value === 'string' || typeof value === 'number') {
143
- return value;
136
+ if (!isOkStructuredToolResult(result)) {
137
+ return failedMessage;
138
+ }
139
+ const payload = getToolResultPayload(result);
140
+ if (!payload) {
141
+ return `⊙ recall: ${query} • completed`;
144
142
  }
145
- return undefined;
143
+ const memoriesCount = countPayloadArrayItems(payload, 'memories');
144
+ const edgesCount = countPayloadArrayItems(payload, 'graph');
145
+ const aborted = 'aborted' in payload && payload.aborted === true;
146
+ return `⊙ recall: ${query} • ${memoriesCount} memories, ${edgesCount} edges${aborted ? ' [aborted]' : ''}`;
146
147
  }
147
148
  export function registerRecall(server, db) {
148
- server.registerTool('recall', {
149
- title: 'Recall (BFS Graph Traversal)',
150
- description: 'Search memories by full-text query, then traverse the relationship graph up to `depth` hops via BFS. Returns all discovered memories and the edges connecting them.',
151
- inputSchema: RecallInputSchema,
152
- outputSchema: RecallResultSchema,
153
- annotations: { readOnlyHint: true, openWorldHint: false },
154
- }, (params, { signal, _meta, sendNotification }) => {
149
+ const contract = getToolContract('recall');
150
+ server.registerTool(contract.name, {
151
+ title: contract.title,
152
+ description: contract.description,
153
+ inputSchema: contract.inputSchema,
154
+ outputSchema: contract.outputSchema,
155
+ annotations: contract.annotations,
156
+ }, async (params, extra) => {
157
+ const { depth, limit, cursor } = params;
158
+ const filters = toMemoryFilters(params);
159
+ const scope = buildSearchCursorScope(params.query, filters);
160
+ const contextLabel = `⊙ recall: ${params.query} [depth ${depth}]`;
161
+ const completionCurrent = depth + 1;
162
+ await notifyProgress(extra, {
163
+ current: 0,
164
+ total: completionCurrent,
165
+ message: contextLabel,
166
+ });
167
+ const hopReporter = progressWithMessage(createProgressReporter(extra), ({ current, total }) => `⊙ recall: ${params.query} [hop ${current}/${Math.max((total ?? current) - 1, current)}]`);
168
+ const onHop = (hop) => {
169
+ hopReporter({ current: hop + 1, total: completionCurrent });
170
+ };
171
+ let result;
172
+ let thrownError;
155
173
  try {
156
- const { depth, limit, cursor } = params;
157
- const offset = cursor ? decodeCursor(cursor) : 0;
158
- const onHop = createHopNotifier(toProgressToken(_meta?.progressToken), sendNotification);
174
+ const decodedCursor = cursor
175
+ ? decodeSearchCursor(cursor, scope)
176
+ : undefined;
159
177
  // Step 1: FTS seed search
160
- const seedRows = loadSeedRows(db, params.query, limit, offset, toMemoryFilters(params));
178
+ const seedRows = loadRankedSearchRows(db, params.query, limit, decodedCursor, filters);
161
179
  const { page: pageSeeds, hasMore } = splitPage(seedRows, limit);
162
180
  // Step 2: BFS traversal up to `depth` hops
163
- const traversal = traverseGraph(db, pageSeeds, depth, signal, onHop);
181
+ const traversal = await traverseGraph(db, pageSeeds, depth, extra.signal, onHop);
164
182
  // Step 3: Load all discovered memory rows
165
183
  const allHashes = Array.from(traversal.visited);
166
184
  const seedRelevance = new Map();
@@ -168,25 +186,59 @@ export function registerRecall(server, db) {
168
186
  if (seed.rank != null)
169
187
  seedRelevance.set(seed.hash, -seed.rank);
170
188
  }
171
- const memories = loadMemoriesByHashes(db, allHashes).map((m) => {
172
- const rel = seedRelevance.get(m.hash);
173
- return rel != null ? { ...m, relevance: rel } : m;
189
+ const memoryRows = loadMemoriesByHashes(db, allHashes);
190
+ const memories = memoryRows.map((row) => {
191
+ const memory = parseMemoryRow(row);
192
+ const rel = seedRelevance.get(memory.hash);
193
+ if (rel != null) {
194
+ memory.relevance = rel;
195
+ }
196
+ return memory;
197
+ });
198
+ let nextCursor;
199
+ if (hasMore && pageSeeds.length > 0) {
200
+ const lastSeed = pageSeeds[pageSeeds.length - 1];
201
+ if (lastSeed !== undefined) {
202
+ const rank = lastSeed.rank ?? 0;
203
+ nextCursor = encodeSearchCursor(scope, rank, lastSeed.hash);
204
+ }
205
+ }
206
+ await logToolEvent(server, 'recall', {
207
+ depth,
208
+ depth_reached: traversal.depthReached,
209
+ seed_count: pageSeeds.length,
210
+ visited_nodes: traversal.visited.size,
211
+ edge_count: traversal.edges.length,
212
+ aborted: traversal.aborted,
174
213
  });
175
- const nextCursor = hasMore ? encodeCursor(offset + limit) : undefined;
176
- return createToolResponse({
177
- ok: true,
178
- result: {
179
- memories,
180
- graph: traversal.edges,
181
- depth_reached: traversal.depthReached,
182
- ...(traversal.aborted ? { aborted: true } : {}),
183
- ...(nextCursor ? { nextCursor } : {}),
184
- },
214
+ result = createToolResponse({
215
+ memories,
216
+ graph: traversal.edges,
217
+ depth_reached: traversal.depthReached,
218
+ ...(traversal.aborted ? { aborted: true } : {}),
219
+ ...(nextCursor ? { nextCursor } : {}),
185
220
  });
186
221
  }
187
222
  catch (err) {
188
- return createErrorResponse(E_UNKNOWN, getErrorMessage(err));
223
+ if (err instanceof McpError) {
224
+ thrownError = err;
225
+ }
226
+ else {
227
+ rethrowMcpError(err);
228
+ result = createErrorResponse(E_UNKNOWN, getErrorMessage(err));
229
+ }
230
+ }
231
+ await hopReporter.flush();
232
+ const completionResult = result ?? createErrorResponse(E_UNKNOWN, getErrorMessage(thrownError));
233
+ await notifyProgress(extra, {
234
+ current: completionCurrent,
235
+ total: completionCurrent,
236
+ message: formatRecallCompletionMessage(params.query, completionResult),
237
+ });
238
+ if (thrownError) {
239
+ throw thrownError;
189
240
  }
241
+ return completionResult;
190
242
  });
191
243
  }
192
244
  //# sourceMappingURL=recall.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"recall.js","sourceRoot":"","sources":["../../src/tools/recall.ts"],"names":[],"mappings":"AAEA,OAAO,OAAO,MAAM,cAAc,CAAC;AAKnC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAOjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAS3D,SAAS,WAAW,CAClB,IAAY,EACZ,QAAgB,EAChB,GAAW,EACX,GAAW;IAEX,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,QAAQ,CAAC;IACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACjC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,iBAAiB,GAAG,WAAW,CACnC,0BAA0B,EAC1B,IAAI,EACJ,GAAG,EACH,KAAK,CACN,CAAC;AACF,MAAM,aAAa,GAAG,WAAW,CAAC,sBAAsB,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAC5E,MAAM,iBAAiB,GAAG,WAAW,CACnC,0BAA0B,EAC1B,IAAI,EACJ,GAAG,EACH,KAAK,CACN,CAAC;AAEF,SAAS,eAAe,CAAC,MAAmB;IAC1C,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,IAAI,MAAM,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;QAClC,OAAO,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;IACjD,CAAC;IACD,IAAI,MAAM,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;QAClC,OAAO,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;IACjD,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,IAAI,IAAI,EAAE,CAAC;QAC/B,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;IAC3C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACvC,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,YAAY,CACnB,EAAW,EACX,KAAa,EACb,KAAa,EACb,MAAc,EACd,OAAsB;IAEtB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACvD,OAAO,EAAE;SACN,OAAO,CACN;;mCAE6B,UAAU;;wBAErB,CACnB;SACA,GAAG,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,aAAa,CACpB,EAAW,EACX,KAAkB,EAClB,KAAa,EACb,MAAoB,EACpB,KAAwB;IAOxB,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAuB,EAAE,CAAC;IACrC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,IAAI,QAAQ,GAAa,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAClD,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,KAAK,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;QAC5D,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,MAAM;QACR,CAAC;QACD,YAAY,GAAG,GAAG,GAAG,CAAC,CAAC;QACvB,KAAK,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpB,IAAI,QAAQ,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;YACxC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;YAChD,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QACD,MAAM,mBAAmB,GAAG,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC;QACzD,MAAM,mBAAmB,GAAG,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;QAC7D,IAAI,mBAAmB,IAAI,CAAC,IAAI,mBAAmB,IAAI,CAAC,EAAE,CAAC;YACzD,OAAO,GAAG,IAAI,CAAC;YACf,MAAM;QACR,CAAC;QAED,MAAM,YAAY,GAAG,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,EAAE;aAChB,OAAO,CACN;+BACuB,YAAY,oBAAoB,YAAY;iBAC1D,CACV;aACA,GAAG,CAAC,GAAG,QAAQ,EAAE,GAAG,QAAQ,EAAE,mBAAmB,GAAG,CAAC,CAAC,CAAC;QAE1D,MAAM,IAAI,GACR,QAAQ,CAAC,MAAM,GAAG,mBAAmB;YACnC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,CAAC;YACxC,CAAC,CAAC,QAAQ,CAAC;QACf,IAAI,QAAQ,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;YAC1C,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QAED,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAC1E,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACvB,KAAK,CAAC,IAAI,CAAC;oBACT,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,aAAa,EAAE,IAAI,CAAC,aAAa;iBAClC,CAAC,CAAC;YACL,CAAC;YAED,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;oBACpB,IAAI,OAAO,CAAC,IAAI,IAAI,iBAAiB,EAAE,CAAC;wBACtC,OAAO,GAAG,IAAI,CAAC;wBACf,MAAM;oBACR,CAAC;oBACD,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBACf,IAAI,UAAU,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;wBAC1C,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBACrB,CAAC;yBAAM,CAAC;wBACN,OAAO,GAAG,IAAI,CAAC;oBACjB,CAAC;gBACH,CAAC;YACH,CAAC;YACD,IACE,OAAO;gBACP,CAAC,KAAK,CAAC,MAAM,IAAI,aAAa,IAAI,OAAO,CAAC,IAAI,IAAI,iBAAiB,CAAC,EACpE,CAAC;gBACD,MAAM;YACR,CAAC;QACH,CAAC;QACD,QAAQ,GAAG,UAAU,CAAC;IACxB,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;AACnD,CAAC;AAED,SAAS,oBAAoB,CAAC,EAAW,EAAE,MAAgB;IACzD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,YAAY,GAAG,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,EAAE;SACf,OAAO,CACN,yCAAyC,YAAY,GAAG,CACzD;SACA,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAClB,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,iBAAiB,CACxB,aAAwC,EACxC,gBAGmB;IAEnB,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,CAAC,GAAW,EAAE,KAAa,EAAE,EAAE;QACpC,KAAK,gBAAgB,CAAC;YACpB,MAAM,EAAE,wBAAwB;YAChC,MAAM,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;SACpD,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrB,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC3D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAiB,EAAE,EAAW;IAC3D,MAAM,CAAC,YAAY,CACjB,QAAQ,EACR;QACE,KAAK,EAAE,8BAA8B;QACrC,WAAW,EACT,qKAAqK;QACvK,WAAW,EAAE,iBAAiB;QAC9B,YAAY,EAAE,kBAAkB;QAChC,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KAC1D,EACD,CAAC,MAAmB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE;QAC3D,IAAI,CAAC;YACH,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;YACxC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAEjD,MAAM,KAAK,GAAG,iBAAiB,CAC7B,eAAe,CAAC,KAAK,EAAE,aAAa,CAAC,EACrC,gBAAgB,CACjB,CAAC;YAEF,0BAA0B;YAC1B,MAAM,QAAQ,GAAG,YAAY,CAC3B,EAAE,EACF,MAAM,CAAC,KAAK,EACZ,KAAK,EACL,MAAM,EACN,eAAe,CAAC,MAAM,CAAC,CACxB,CAAC;YACF,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAEhE,2CAA2C;YAC3C,MAAM,SAAS,GAAG,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAErE,0CAA0C;YAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAChD,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;YAChD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI;oBAAE,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClE,CAAC;YACD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC7D,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBACtC,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACpD,CAAC,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAEtE,OAAO,kBAAkB,CAAC;gBACxB,EAAE,EAAE,IAAI;gBACR,MAAM,EAAE;oBACN,QAAQ;oBACR,KAAK,EAAE,SAAS,CAAC,KAAK;oBACtB,aAAa,EAAE,SAAS,CAAC,YAAY;oBACrC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC/C,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACtC;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,mBAAmB,CAAC,SAAS,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"recall.js","sourceRoot":"","sources":["../../src/tools/recall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ export type ToolResultPayload = Record<string, unknown>;
3
+ export declare function isOkStructuredToolResult(result: CallToolResult): boolean;
4
+ export declare function getToolResultPayload(result: CallToolResult): ToolResultPayload | undefined;
5
+ /** Count items in a named array field of a tool result payload. */
6
+ export declare function countPayloadArrayItems(payload: Record<string, unknown>, key: string): number;
7
+ //# sourceMappingURL=result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/tools/result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAMxD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAExE;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,cAAc,GACrB,iBAAiB,GAAG,SAAS,CAO/B;AAED,mEAAmE;AACnE,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,GAAG,EAAE,MAAM,GACV,MAAM,CAGR"}
@@ -0,0 +1,19 @@
1
+ function isRecord(value) {
2
+ return typeof value === 'object' && value !== null;
3
+ }
4
+ export function isOkStructuredToolResult(result) {
5
+ return result.isError !== true && isRecord(result.structuredContent);
6
+ }
7
+ export function getToolResultPayload(result) {
8
+ const { structuredContent } = result;
9
+ if (result.isError === true || !isRecord(structuredContent)) {
10
+ return undefined;
11
+ }
12
+ return structuredContent;
13
+ }
14
+ /** Count items in a named array field of a tool result payload. */
15
+ export function countPayloadArrayItems(payload, key) {
16
+ const value = payload[key];
17
+ return Array.isArray(value) ? value.length : 0;
18
+ }
19
+ //# sourceMappingURL=result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/tools/result.ts"],"names":[],"mappings":"AAIA,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAAsB;IAC7D,OAAO,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,QAAQ,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,MAAsB;IAEtB,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAAC;IACrC,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC5D,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,sBAAsB,CACpC,OAAgC,EAChC,GAAW;IAEX,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"retrieve-context.d.ts","sourceRoot":"","sources":["../../src/tools/retrieve-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAiD9C,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,GAAG,IAAI,CAkD5E"}
1
+ {"version":3,"file":"retrieve-context.d.ts","sourceRoot":"","sources":["../../src/tools/retrieve-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAoI9C,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,GAAG,IAAI,CA+G5E"}
@@ -1,56 +1,125 @@
1
- import { E_UNKNOWN, getErrorMessage } from '../lib/errors.js';
1
+ import { McpError } from '@modelcontextprotocol/sdk/types.js';
2
+ import { E_CANCELLED, E_UNKNOWN, getErrorMessage, rethrowMcpError, } from '../lib/errors.js';
2
3
  import { sanitizeFtsQuery } from '../lib/search.js';
4
+ import { getToolContract } from '../lib/tool-contracts.js';
3
5
  import { createErrorResponse, createToolResponse, } from '../lib/tool-response.js';
4
6
  import { parseMemoryRow } from '../lib/types.js';
5
- import { RetrieveContextInputSchema } from '../schemas/inputs.js';
6
- import { RetrieveContextResultSchema } from '../schemas/outputs.js';
7
- const RETRIEVE_CONTEXT_LIMIT = 200;
7
+ import {} from '../schemas/inputs.js';
8
+ import {} from '../schemas/outputs.js';
9
+ import { createProgressReporter, notifyProgress, progressWithMessage, } from './progress.js';
10
+ import { countPayloadArrayItems, getToolResultPayload, isOkStructuredToolResult, } from './result.js';
11
+ const MIN_CANDIDATE_ROWS = 200;
12
+ const MAX_CANDIDATE_ROWS = 2000;
8
13
  const ESTIMATED_CHARS_PER_TOKEN = 4;
9
- function getOrderBy(strategy) {
10
- if (strategy === 'importance') {
11
- return 'm.importance DESC, memories_fts.rank';
12
- }
13
- if (strategy === 'recency') {
14
- return 'm.created_at DESC, memories_fts.rank';
15
- }
16
- return 'memories_fts.rank';
14
+ // Assume average memory is ~20 tokens to set a reasonable upper bound for candidates
15
+ const ESTIMATED_TOKENS_PER_MEMORY = 20;
16
+ const RETRIEVE_CONTEXT_PROGRESS_MILESTONE = 25;
17
+ const ORDER_BY_MAP = {
18
+ importance: 'm.importance DESC, memories_fts.rank',
19
+ recency: 'm.created_at DESC, memories_fts.rank',
20
+ relevance: 'memories_fts.rank',
21
+ };
22
+ function countPayloadMemories(payload) {
23
+ return countPayloadArrayItems(payload, 'memories');
17
24
  }
18
25
  function estimateTokens(content) {
19
26
  return Math.ceil(content.length / ESTIMATED_CHARS_PER_TOKEN);
20
27
  }
21
- function loadContextRows(db, query, orderBy) {
28
+ function loadContextRows(db, query, orderBy, limit) {
22
29
  const ftsQuery = sanitizeFtsQuery(query);
23
30
  return db
24
- .prepare(`SELECT m.*, memories_fts.rank AS rank FROM memories m
31
+ .prepareOnce(`SELECT m.*, memories_fts.rank AS rank FROM memories m
25
32
  JOIN memories_fts ON memories_fts.rowid = m.rowid
26
33
  WHERE memories_fts MATCH ?
27
34
  ORDER BY ${orderBy}
28
- LIMIT ${RETRIEVE_CONTEXT_LIMIT + 1}`)
29
- .all(ftsQuery);
35
+ LIMIT ?`)
36
+ .all(ftsQuery, limit + 1);
37
+ }
38
+ function reportSelectionProgress(onProgress, current, total, force = false) {
39
+ if (!onProgress || current === 0) {
40
+ return;
41
+ }
42
+ if (!force && current % RETRIEVE_CONTEXT_PROGRESS_MILESTONE !== 0) {
43
+ return;
44
+ }
45
+ onProgress({ current, total });
46
+ }
47
+ function formatCompletionMessage(query, result) {
48
+ if (result.structuredContent?.error) {
49
+ const error = result.structuredContent.error;
50
+ if (error.code === E_CANCELLED) {
51
+ return `⊙ retrieve_context: ${query} • cancelled`;
52
+ }
53
+ }
54
+ const failedMessage = `⊙ retrieve_context: ${query} • failed`;
55
+ if (result.isError) {
56
+ return failedMessage;
57
+ }
58
+ if (!isOkStructuredToolResult(result)) {
59
+ return failedMessage;
60
+ }
61
+ const payload = getToolResultPayload(result);
62
+ if (!payload) {
63
+ return `⊙ retrieve_context: ${query} • completed`;
64
+ }
65
+ const memoriesCount = countPayloadMemories(payload);
66
+ const estimatedTokens = 'estimated_tokens' in payload &&
67
+ typeof payload.estimated_tokens === 'number'
68
+ ? payload.estimated_tokens
69
+ : 0;
70
+ const truncated = 'truncated' in payload && payload.truncated === true ? ' [truncated]' : '';
71
+ return `⊙ retrieve_context: ${query} • ${memoriesCount} memories, ${estimatedTokens} tokens${truncated}`;
72
+ }
73
+ function throwIfAborted(signal) {
74
+ if (!signal?.aborted) {
75
+ return;
76
+ }
77
+ throw new Error(E_CANCELLED);
30
78
  }
31
79
  export function registerRetrieveContext(server, db) {
32
- server.registerTool('retrieve_context', {
33
- title: 'Retrieve Context',
34
- description: 'Search memories and return relevance-ranked results that fit within a caller-specified token budget. Eliminates manual pagination and token counting for context window management.',
35
- inputSchema: RetrieveContextInputSchema,
36
- outputSchema: RetrieveContextResultSchema,
37
- annotations: { readOnlyHint: true, openWorldHint: false },
38
- }, (params) => {
80
+ const contract = getToolContract('retrieve_context');
81
+ server.registerTool(contract.name, {
82
+ title: contract.title,
83
+ description: contract.description,
84
+ inputSchema: contract.inputSchema,
85
+ outputSchema: contract.outputSchema,
86
+ annotations: contract.annotations,
87
+ }, async (params, extra) => {
88
+ const { query, strategy } = params;
89
+ const tokenBudget = params.token_budget;
90
+ const contextLabel = `⊙ retrieve_context: ${query} [${strategy}]`;
91
+ let completionCurrent = 1;
92
+ // Heuristic: Load enough candidates to likely fill the budget, but cap to avoid massive queries
93
+ const estimatedCandidates = Math.ceil(tokenBudget / ESTIMATED_TOKENS_PER_MEMORY);
94
+ const limit = Math.min(Math.max(MIN_CANDIDATE_ROWS, estimatedCandidates), MAX_CANDIDATE_ROWS);
95
+ await notifyProgress(extra, {
96
+ current: 0,
97
+ message: `${contextLabel} [budget ${tokenBudget}]`,
98
+ });
99
+ const loopProgress = progressWithMessage(createProgressReporter(extra), ({ current, total }) => `${contextLabel} [scan ${current}/${Math.max((total ?? current) - 1, current)}]`);
100
+ let result;
101
+ let thrownError;
39
102
  try {
40
- const { query, strategy } = params;
41
- const tokenBudget = params.token_budget;
42
- const orderBy = getOrderBy(strategy);
43
- const rows = loadContextRows(db, query, orderBy);
44
- const rowCapExceeded = rows.length > RETRIEVE_CONTEXT_LIMIT;
45
- const candidateRows = rowCapExceeded
46
- ? rows.slice(0, RETRIEVE_CONTEXT_LIMIT)
47
- : rows;
103
+ throwIfAborted(extra.signal);
104
+ const orderBy = ORDER_BY_MAP[strategy];
105
+ const rows = loadContextRows(db, query, orderBy, limit);
106
+ const rowCapExceeded = rows.length > limit;
107
+ const candidateCount = rowCapExceeded ? limit : rows.length;
108
+ completionCurrent = candidateCount + 1;
48
109
  let estimatedTokens = 0;
49
110
  let truncated = rowCapExceeded;
50
111
  const selected = [];
51
- for (const row of candidateRows) {
112
+ let scanned = 0;
113
+ for (let i = 0; i < candidateCount; i += 1) {
114
+ throwIfAborted(extra.signal);
115
+ const row = rows[i];
116
+ if (row === undefined) {
117
+ break;
118
+ }
52
119
  const mem = parseMemoryRow(row);
53
120
  const tokens = estimateTokens(mem.content);
121
+ scanned += 1;
122
+ reportSelectionProgress(loopProgress, scanned, completionCurrent, false);
54
123
  if (estimatedTokens + tokens > tokenBudget) {
55
124
  truncated = true;
56
125
  break;
@@ -58,18 +127,36 @@ export function registerRetrieveContext(server, db) {
58
127
  estimatedTokens += tokens;
59
128
  selected.push(mem);
60
129
  }
61
- return createToolResponse({
62
- ok: true,
63
- result: {
64
- memories: selected,
65
- estimated_tokens: estimatedTokens,
66
- truncated,
67
- },
130
+ reportSelectionProgress(loopProgress, scanned, completionCurrent, true);
131
+ result = createToolResponse({
132
+ memories: selected,
133
+ estimated_tokens: estimatedTokens,
134
+ truncated,
68
135
  });
69
136
  }
70
137
  catch (err) {
71
- return createErrorResponse(E_UNKNOWN, getErrorMessage(err));
138
+ if (err instanceof Error && err.message === E_CANCELLED) {
139
+ result = createErrorResponse(E_CANCELLED, 'Request cancelled');
140
+ }
141
+ else if (err instanceof McpError) {
142
+ thrownError = err;
143
+ }
144
+ else {
145
+ rethrowMcpError(err);
146
+ result = createErrorResponse(E_UNKNOWN, getErrorMessage(err));
147
+ }
148
+ }
149
+ await loopProgress.flush();
150
+ const completionResult = result ?? createErrorResponse(E_UNKNOWN, getErrorMessage(thrownError));
151
+ await notifyProgress(extra, {
152
+ current: completionCurrent,
153
+ total: completionCurrent,
154
+ message: formatCompletionMessage(query, completionResult),
155
+ });
156
+ if (thrownError) {
157
+ throw thrownError;
72
158
  }
159
+ return completionResult;
73
160
  });
74
161
  }
75
162
  //# sourceMappingURL=retrieve-context.js.map