@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.
- package/README.md +32 -25
- package/dist/completions/index.d.ts.map +1 -1
- package/dist/completions/index.js +11 -8
- package/dist/completions/index.js.map +1 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +68 -8
- package/dist/db/index.js.map +1 -1
- package/dist/db/typed.d.ts +9 -3
- package/dist/db/typed.d.ts.map +1 -1
- package/dist/db/typed.js +33 -4
- package/dist/db/typed.js.map +1 -1
- package/dist/index.js +13 -8
- package/dist/index.js.map +1 -1
- package/dist/lib/errors.d.ts +4 -0
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +12 -4
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/hash.d.ts.map +1 -1
- package/dist/lib/hash.js +9 -2
- package/dist/lib/hash.js.map +1 -1
- package/dist/lib/instructions.d.ts +2 -0
- package/dist/lib/instructions.d.ts.map +1 -0
- package/dist/lib/instructions.js +96 -0
- package/dist/lib/instructions.js.map +1 -0
- package/dist/lib/mcp-utils.d.ts +6 -0
- package/dist/lib/mcp-utils.d.ts.map +1 -0
- package/dist/lib/mcp-utils.js +26 -0
- package/dist/lib/mcp-utils.js.map +1 -0
- package/dist/lib/pagination.d.ts.map +1 -1
- package/dist/lib/pagination.js +14 -7
- package/dist/lib/pagination.js.map +1 -1
- package/dist/lib/search-cursor.d.ts +13 -0
- package/dist/lib/search-cursor.d.ts.map +1 -0
- package/dist/lib/search-cursor.js +89 -0
- package/dist/lib/search-cursor.js.map +1 -0
- package/dist/lib/search.d.ts +16 -0
- package/dist/lib/search.d.ts.map +1 -1
- package/dist/lib/search.js +53 -12
- package/dist/lib/search.js.map +1 -1
- package/dist/lib/sql.d.ts +17 -0
- package/dist/lib/sql.d.ts.map +1 -0
- package/dist/lib/sql.js +18 -0
- package/dist/lib/sql.js.map +1 -0
- package/dist/lib/tool-contracts.d.ts +18 -0
- package/dist/lib/tool-contracts.d.ts.map +1 -0
- package/dist/lib/tool-contracts.js +120 -0
- package/dist/lib/tool-contracts.js.map +1 -0
- package/dist/lib/tool-response.d.ts +1 -5
- package/dist/lib/tool-response.d.ts.map +1 -1
- package/dist/lib/tool-response.js +9 -7
- package/dist/lib/tool-response.js.map +1 -1
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js +10 -9
- package/dist/lib/types.js.map +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +22 -36
- package/dist/prompts/index.js.map +1 -1
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +15 -36
- package/dist/resources/index.js.map +1 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +1 -1
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/inputs.d.ts +5 -5
- package/dist/schemas/inputs.d.ts.map +1 -1
- package/dist/schemas/inputs.js +21 -14
- package/dist/schemas/inputs.js.map +1 -1
- package/dist/schemas/outputs.d.ts +94 -148
- package/dist/schemas/outputs.d.ts.map +1 -1
- package/dist/schemas/outputs.js +59 -66
- package/dist/schemas/outputs.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +20 -18
- package/dist/server.js.map +1 -1
- package/dist/tools/create-relationship.d.ts.map +1 -1
- package/dist/tools/create-relationship.js +38 -25
- package/dist/tools/create-relationship.js.map +1 -1
- package/dist/tools/delete-memories.d.ts.map +1 -1
- package/dist/tools/delete-memories.js +37 -30
- package/dist/tools/delete-memories.js.map +1 -1
- package/dist/tools/delete-memory.d.ts.map +1 -1
- package/dist/tools/delete-memory.js +24 -22
- package/dist/tools/delete-memory.js.map +1 -1
- package/dist/tools/delete-relationship.d.ts.map +1 -1
- package/dist/tools/delete-relationship.js +28 -20
- package/dist/tools/delete-relationship.js.map +1 -1
- package/dist/tools/get-memory.d.ts.map +1 -1
- package/dist/tools/get-memory.js +26 -16
- package/dist/tools/get-memory.js.map +1 -1
- package/dist/tools/get-relationships.d.ts.map +1 -1
- package/dist/tools/get-relationships.js +71 -40
- package/dist/tools/get-relationships.js.map +1 -1
- package/dist/tools/index.d.ts +6 -14
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +5 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/memory-stats.d.ts.map +1 -1
- package/dist/tools/memory-stats.js +29 -39
- package/dist/tools/memory-stats.js.map +1 -1
- package/dist/tools/progress.d.ts +34 -0
- package/dist/tools/progress.d.ts.map +1 -0
- package/dist/tools/progress.js +136 -0
- package/dist/tools/progress.js.map +1 -0
- package/dist/tools/recall.d.ts.map +1 -1
- package/dist/tools/recall.js +157 -105
- package/dist/tools/recall.js.map +1 -1
- package/dist/tools/result.d.ts +7 -0
- package/dist/tools/result.d.ts.map +1 -0
- package/dist/tools/result.js +19 -0
- package/dist/tools/result.js.map +1 -0
- package/dist/tools/retrieve-context.d.ts.map +1 -1
- package/dist/tools/retrieve-context.js +127 -40
- package/dist/tools/retrieve-context.js.map +1 -1
- package/dist/tools/search-memories.d.ts.map +1 -1
- package/dist/tools/search-memories.js +37 -47
- package/dist/tools/search-memories.js.map +1 -1
- package/dist/tools/store-memories.d.ts.map +1 -1
- package/dist/tools/store-memories.js +44 -28
- package/dist/tools/store-memories.js.map +1 -1
- package/dist/tools/store-memory.d.ts.map +1 -1
- package/dist/tools/store-memory.js +43 -23
- package/dist/tools/store-memory.js.map +1 -1
- package/dist/tools/update-memory.d.ts.map +1 -1
- package/dist/tools/update-memory.js +63 -29
- package/dist/tools/update-memory.js.map +1 -1
- package/package.json +1 -3
- package/dist/instructions.md +0 -123
- package/dist/tools/helpers.d.ts +0 -13
- package/dist/tools/helpers.d.ts.map +0 -1
- package/dist/tools/helpers.js +0 -49
- package/dist/tools/helpers.js.map +0 -1
package/dist/tools/recall.js
CHANGED
|
@@ -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 {
|
|
4
|
-
import {
|
|
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 {
|
|
8
|
-
import {
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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 =
|
|
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
|
|
62
|
+
const frontierJson = JSON.stringify(frontier);
|
|
74
63
|
const edgeRows = db
|
|
75
|
-
.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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 (
|
|
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
|
-
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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 =
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
.
|
|
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
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
function formatRecallCompletionMessage(query, result) {
|
|
132
|
+
const failedMessage = `⊙ recall: ${query} • failed`;
|
|
133
|
+
if (result.isError) {
|
|
134
|
+
return failedMessage;
|
|
133
135
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
|
157
|
-
|
|
158
|
-
|
|
174
|
+
const decodedCursor = cursor
|
|
175
|
+
? decodeSearchCursor(cursor, scope)
|
|
176
|
+
: undefined;
|
|
159
177
|
// Step 1: FTS seed search
|
|
160
|
-
const seedRows =
|
|
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
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
-
|
|
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
|
package/dist/tools/recall.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recall.js","sourceRoot":"","sources":["../../src/tools/recall.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"recall.js","sourceRoot":"","sources":["../../src/tools/recall.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,QAAQ,GACT,MAAM,oCAAoC,CAAC;AAE5C,OAAO,OAAO,MAAM,cAAc,CAAC;AAKnC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EACL,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAOjD,OAAO,EAA0B,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAA2B,MAAM,uBAAuB,CAAC;AAChE,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,aAAa,CAAC;AAKrB,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,MAAM,cAAc,GAAG;;;iBAGN,CAAC;AAElB,MAAM,oBAAoB,GACxB,uEAAuE,CAAC;AAE1E,KAAK,UAAU,aAAa,CAC1B,EAAW,EACX,KAAkB,EAClB,KAAa,EACb,MAAoB,EACpB,KAAwB;IAOxB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,KAAK,GAAuB,EAAE,CAAC;IACrC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,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,IAAI,CAAC,EAAE,CAAC;QAC/D,uEAAuE;QACvE,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;QAEtD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,MAAM;QACR,CAAC;QAED,YAAY,GAAG,GAAG,GAAG,CAAC,CAAC;QACvB,KAAK,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAEpB,IAAI,QAAQ,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;YACxC,QAAQ,CAAC,MAAM,GAAG,iBAAiB,CAAC;YACpC,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QAED,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,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,EAAE;aAChB,WAAW,CAAU,cAAc,CAAC;aACpC,GAAG,CAAC,YAAY,EAAE,YAAY,EAAE,mBAAmB,GAAG,CAAC,CAAC,CAAC;QAC5D,MAAM,aAAa,GACjB,QAAQ,CAAC,MAAM,GAAG,mBAAmB;YACnC,CAAC,CAAC,mBAAmB;YACrB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QACtB,IAAI,QAAQ,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;YAC1C,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QAED,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,MAAM;YACR,CAAC;YACD,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,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBACjC,IAAI,OAAO,CAAC,IAAI,IAAI,iBAAiB,EAAE,CAAC;oBACtC,OAAO,GAAG,IAAI,CAAC;oBACf,MAAM;gBACR,CAAC;gBAED,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC5B,IAAI,UAAU,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;oBAC1C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAClC,CAAC;qBAAM,CAAC;oBACN,OAAO,GAAG,IAAI,CAAC;gBACjB,CAAC;YACH,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/B,IAAI,OAAO,CAAC,IAAI,IAAI,iBAAiB,EAAE,CAAC;oBACtC,OAAO,GAAG,IAAI,CAAC;oBACf,MAAM;gBACR,CAAC;gBAED,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC1B,IAAI,UAAU,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;oBAC1C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAChC,CAAC;qBAAM,CAAC;oBACN,OAAO,GAAG,IAAI,CAAC;gBACjB,CAAC;YACH,CAAC;YAED,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,CAAC,MAAM,GAAG,CAAC,CAAC;QACpB,QAAQ,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;AACnD,CAAC;AAED,SAAS,oBAAoB,CAC3B,EAAW,EACX,MAAyB;IAEzB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,EAAE;SACN,WAAW,CAAY,oBAAoB,CAAC;SAC5C,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,6BAA6B,CACpC,KAAa,EACb,MAAsB;IAEtB,MAAM,aAAa,GAAG,aAAa,KAAK,WAAW,CAAC;IACpD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,aAAa,KAAK,cAAc,CAAC;IAC1C,CAAC;IAED,MAAM,aAAa,GAAG,sBAAsB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAClE,MAAM,UAAU,GAAG,sBAAsB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,SAAS,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,KAAK,IAAI,CAAC;IAEjE,OAAO,aAAa,KAAK,MAAM,aAAa,cAAc,UAAU,SAAS,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAC7G,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAiB,EAAE,EAAW;IAC3D,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,CAAC,YAAY,CACjB,QAAQ,CAAC,IAAI,EACb;QACE,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,WAAW,EAAE,QAAQ,CAAC,WAAuC;QAC7D,YAAY,EAAE,QAAQ,CAAC,YAAyC;QAChE,WAAW,EAAE,QAAQ,CAAC,WAAW;KAClC,EACD,KAAK,EAAE,MAAmB,EAAE,KAAK,EAAE,EAAE;QACnC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;QACxC,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,sBAAsB,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC5D,MAAM,YAAY,GAAG,aAAa,MAAM,CAAC,KAAK,WAAW,KAAK,GAAG,CAAC;QAClE,MAAM,iBAAiB,GAAG,KAAK,GAAG,CAAC,CAAC;QAEpC,MAAM,cAAc,CAAC,KAAK,EAAE;YAC1B,OAAO,EAAE,CAAC;YACV,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,YAAY;SACtB,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,mBAAmB,CACrC,sBAAsB,CAAC,KAAK,CAAC,EAC7B,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CACrB,aAAa,MAAM,CAAC,KAAK,SAAS,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,CAC5F,CAAC;QAEF,MAAM,KAAK,GAAqB,CAAC,GAAW,EAAQ,EAAE;YACpD,WAAW,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAC9D,CAAC,CAAC;QAEF,IAAI,MAAkC,CAAC;QACvC,IAAI,WAAiC,CAAC;QACtC,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM;gBAC1B,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC;gBACnC,CAAC,CAAC,SAAS,CAAC;YAEd,0BAA0B;YAC1B,MAAM,QAAQ,GAAG,oBAAoB,CACnC,EAAE,EACF,MAAM,CAAC,KAAK,EACZ,KAAK,EACL,aAAa,EACb,OAAO,CACR,CAAC;YACF,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAEhE,2CAA2C;YAC3C,MAAM,SAAS,GAAG,MAAM,aAAa,CACnC,EAAE,EACF,SAAS,EACT,KAAK,EACL,KAAK,CAAC,MAAM,EACZ,KAAK,CACN,CAAC;YAEF,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,UAAU,GAAG,oBAAoB,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;YACvD,MAAM,QAAQ,GAAa,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;gBAChD,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;gBACnC,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC3C,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;oBAChB,MAAM,CAAC,SAAS,GAAG,GAAG,CAAC;gBACzB,CAAC;gBACD,OAAO,MAAM,CAAC;YAChB,CAAC,CAAC,CAAC;YAEH,IAAI,UAA8B,CAAC;YACnC,IAAI,OAAO,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpC,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBACjD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAC3B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC;oBAChC,UAAU,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC;YAED,MAAM,YAAY,CAAC,MAAM,EAAE,QAAQ,EAAE;gBACnC,KAAK;gBACL,aAAa,EAAE,SAAS,CAAC,YAAY;gBACrC,UAAU,EAAE,SAAS,CAAC,MAAM;gBAC5B,aAAa,EAAE,SAAS,CAAC,OAAO,CAAC,IAAI;gBACrC,UAAU,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM;gBAClC,OAAO,EAAE,SAAS,CAAC,OAAO;aAC3B,CAAC,CAAC;YAEH,MAAM,GAAG,kBAAkB,CAAC;gBAC1B,QAAQ;gBACR,KAAK,EAAE,SAAS,CAAC,KAAK;gBACtB,aAAa,EAAE,SAAS,CAAC,YAAY;gBACrC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/C,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;gBAC5B,WAAW,GAAG,GAAG,CAAC;YACpB,CAAC;iBAAM,CAAC;gBACN,eAAe,CAAC,GAAG,CAAC,CAAC;gBACrB,MAAM,GAAG,mBAAmB,CAAC,SAAS,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;QAED,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC;QAE1B,MAAM,gBAAgB,GACpB,MAAM,IAAI,mBAAmB,CAAC,SAAS,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC;QAEzE,MAAM,cAAc,CAAC,KAAK,EAAE;YAC1B,OAAO,EAAE,iBAAiB;YAC1B,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,6BAA6B,CAAC,MAAM,CAAC,KAAK,EAAE,gBAAgB,CAAC;SACvE,CAAC,CAAC;QAEH,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,WAAW,CAAC;QACpB,CAAC;QAED,OAAO,gBAAgB,CAAC;IAC1B,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -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;
|
|
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 {
|
|
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 {
|
|
6
|
-
import {
|
|
7
|
-
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
.
|
|
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
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
|
|
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
|
-
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
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
|