@codemem/mcp 0.44.0 → 0.44.2
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/dist/content.d.ts +2 -0
- package/dist/content.d.ts.map +1 -1
- package/dist/http.js +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp-retrieval-ledger.d.ts +7 -0
- package/dist/mcp-retrieval-ledger.d.ts.map +1 -1
- package/dist/server-DmdZAo6k.js +1157 -0
- package/dist/server-DmdZAo6k.js.map +1 -0
- package/dist/stdio.js +1 -1
- package/dist/tool-contracts.d.ts +324 -0
- package/dist/tool-contracts.d.ts.map +1 -0
- package/dist/tools/distill.d.ts.map +1 -1
- package/dist/tools/items.d.ts.map +1 -1
- package/dist/tools/learn.d.ts.map +1 -1
- package/dist/tools/schema.d.ts.map +1 -1
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/timeline.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/server-D-jxqflv.js +0 -857
- package/dist/server-D-jxqflv.js.map +0 -1
|
@@ -0,0 +1,1157 @@
|
|
|
1
|
+
import { createHash as e, randomUUID as t } from "node:crypto";
|
|
2
|
+
import { MEMORY_KIND_DESCRIPTIONS as n, ObserverClient as r, REMEMBER_MEMORY_KINDS as i, VERSION as a, buildDistillReport as o, dedupeOrderedIds as s, judgeDistillReport as c, projectMatchesFilter as l, reconcileFailedRetrievalSurface as u, recordRetrievalSurface as d, resolveProject as f, resolveProjectRoot as p, storeVectors as m, toJson as h } from "@codemem/core";
|
|
3
|
+
import { existsSync as g, readFileSync as ee } from "node:fs";
|
|
4
|
+
import { homedir as te } from "node:os";
|
|
5
|
+
import { join as _ } from "node:path";
|
|
6
|
+
import { McpServer as ne } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
|
+
import { z as v } from "zod";
|
|
8
|
+
//#region src/canonical-json.ts
|
|
9
|
+
function y(e) {
|
|
10
|
+
return JSON.stringify(e, (e, t) => typeof t != "object" || !t || Array.isArray(t) ? t : Object.fromEntries(Object.entries(t).toSorted(([e], [t]) => e < t ? -1 : +(e > t)))) ?? "undefined";
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/project-scope.ts
|
|
14
|
+
function b(e) {
|
|
15
|
+
return e?.trim() || null;
|
|
16
|
+
}
|
|
17
|
+
function x() {
|
|
18
|
+
return b(process.env.CODEMEM_PROJECT) ?? f(process.cwd());
|
|
19
|
+
}
|
|
20
|
+
function re(e) {
|
|
21
|
+
return b(e.project) ?? b(e.envProject) ?? null;
|
|
22
|
+
}
|
|
23
|
+
function S(e, t = x()) {
|
|
24
|
+
let n = {}, r = !1, i = (typeof e.project == "string" ? b(e.project) : void 0) || b(t) || void 0;
|
|
25
|
+
i && (n.project = i, r = !0);
|
|
26
|
+
for (let t of [
|
|
27
|
+
"kind",
|
|
28
|
+
"visibility",
|
|
29
|
+
"scope_id",
|
|
30
|
+
"include_scope_ids",
|
|
31
|
+
"exclude_scope_ids",
|
|
32
|
+
"include_visibility",
|
|
33
|
+
"exclude_visibility",
|
|
34
|
+
"include_workspace_ids",
|
|
35
|
+
"exclude_workspace_ids",
|
|
36
|
+
"include_workspace_kinds",
|
|
37
|
+
"exclude_workspace_kinds",
|
|
38
|
+
"include_actor_ids",
|
|
39
|
+
"exclude_actor_ids",
|
|
40
|
+
"include_trust_states",
|
|
41
|
+
"exclude_trust_states",
|
|
42
|
+
"ownership_scope",
|
|
43
|
+
"personal_first",
|
|
44
|
+
"trust_bias",
|
|
45
|
+
"widen_shared_when_weak",
|
|
46
|
+
"widen_shared_min_personal_results",
|
|
47
|
+
"widen_shared_min_personal_score"
|
|
48
|
+
]) {
|
|
49
|
+
let i = e[t];
|
|
50
|
+
i != null && (n[t] = i, r = !0);
|
|
51
|
+
}
|
|
52
|
+
return r ? n : void 0;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/content.ts
|
|
56
|
+
function ie(e) {
|
|
57
|
+
let t = JSON.parse(e);
|
|
58
|
+
if (!t || typeof t != "object" || Array.isArray(t)) throw TypeError("MCP structured content must be a JSON object");
|
|
59
|
+
return t;
|
|
60
|
+
}
|
|
61
|
+
function C(e) {
|
|
62
|
+
let t = JSON.stringify(e);
|
|
63
|
+
if (t === void 0) throw TypeError("MCP structured content must be JSON serializable");
|
|
64
|
+
return {
|
|
65
|
+
content: [{
|
|
66
|
+
type: "text",
|
|
67
|
+
text: t
|
|
68
|
+
}],
|
|
69
|
+
structuredContent: ie(t)
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function w(e) {
|
|
73
|
+
return {
|
|
74
|
+
content: [{
|
|
75
|
+
type: "text",
|
|
76
|
+
text: JSON.stringify({ error: e })
|
|
77
|
+
}],
|
|
78
|
+
isError: !0
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/schemas.ts
|
|
83
|
+
var T = {
|
|
84
|
+
scope_id: v.string().optional().describe("Filter by a single sharing domain scope_id"),
|
|
85
|
+
include_scope_ids: v.array(v.string()).optional().describe("Sharing domain scope_ids to include"),
|
|
86
|
+
exclude_scope_ids: v.array(v.string()).optional().describe("Sharing domain scope_ids to exclude")
|
|
87
|
+
}, E = {
|
|
88
|
+
kind: v.string().optional().describe("Filter by memory kind"),
|
|
89
|
+
project: v.string().optional().describe("Filter by project scope (matches sessions.project)"),
|
|
90
|
+
...T,
|
|
91
|
+
visibility: v.array(v.string()).optional(),
|
|
92
|
+
include_visibility: v.array(v.string()).optional(),
|
|
93
|
+
exclude_visibility: v.array(v.string()).optional(),
|
|
94
|
+
include_workspace_ids: v.array(v.string()).optional(),
|
|
95
|
+
exclude_workspace_ids: v.array(v.string()).optional(),
|
|
96
|
+
include_workspace_kinds: v.array(v.string()).optional(),
|
|
97
|
+
exclude_workspace_kinds: v.array(v.string()).optional(),
|
|
98
|
+
include_actor_ids: v.array(v.string()).optional(),
|
|
99
|
+
exclude_actor_ids: v.array(v.string()).optional(),
|
|
100
|
+
include_trust_states: v.array(v.string()).optional(),
|
|
101
|
+
exclude_trust_states: v.array(v.string()).optional(),
|
|
102
|
+
ownership_scope: v.string().optional(),
|
|
103
|
+
personal_first: v.union([v.boolean(), v.string()]).optional(),
|
|
104
|
+
trust_bias: v.string().optional(),
|
|
105
|
+
widen_shared_when_weak: v.union([v.boolean(), v.string()]).optional(),
|
|
106
|
+
widen_shared_min_personal_results: v.number().int().optional(),
|
|
107
|
+
widen_shared_min_personal_score: v.number().optional()
|
|
108
|
+
}, ae = v.enum(i), oe = Object.keys(E).toSorted(), D = v.record(v.string(), v.unknown()), O = v.number().nullable(), k = v.object({
|
|
109
|
+
id: v.number().int(),
|
|
110
|
+
kind: v.string(),
|
|
111
|
+
title: v.string(),
|
|
112
|
+
body_text: v.string(),
|
|
113
|
+
session_id: v.number().int().optional(),
|
|
114
|
+
confidence: O.optional(),
|
|
115
|
+
created_at: v.string().optional(),
|
|
116
|
+
updated_at: v.string().optional(),
|
|
117
|
+
metadata_json: D.optional()
|
|
118
|
+
}).passthrough(), se = v.object({
|
|
119
|
+
id: v.number().int(),
|
|
120
|
+
kind: v.string(),
|
|
121
|
+
title: v.string(),
|
|
122
|
+
body: v.string(),
|
|
123
|
+
confidence: O.optional(),
|
|
124
|
+
score: v.number().optional(),
|
|
125
|
+
session_id: v.number().int().optional(),
|
|
126
|
+
metadata: D.optional()
|
|
127
|
+
}).passthrough(), ce = v.object({
|
|
128
|
+
id: v.number().int(),
|
|
129
|
+
kind: v.string(),
|
|
130
|
+
title: v.string(),
|
|
131
|
+
score: v.number(),
|
|
132
|
+
created_at: v.string(),
|
|
133
|
+
session_id: v.number().int(),
|
|
134
|
+
metadata: D
|
|
135
|
+
}).passthrough(), A = v.object({
|
|
136
|
+
code: v.string(),
|
|
137
|
+
field: v.string(),
|
|
138
|
+
message: v.string(),
|
|
139
|
+
ids: v.array(v.union([v.string(), v.number()])).optional()
|
|
140
|
+
}).passthrough(), le = v.object({
|
|
141
|
+
id: v.number().int(),
|
|
142
|
+
kind: v.string(),
|
|
143
|
+
title: v.string(),
|
|
144
|
+
created_at: v.string(),
|
|
145
|
+
project: v.string().nullable(),
|
|
146
|
+
retrieval: v.object({
|
|
147
|
+
source: v.string(),
|
|
148
|
+
rank: v.number().int().nullable()
|
|
149
|
+
}).passthrough(),
|
|
150
|
+
score: v.object({
|
|
151
|
+
total: v.number().nullable(),
|
|
152
|
+
components: v.object({
|
|
153
|
+
base: v.number().nullable(),
|
|
154
|
+
recency: v.number(),
|
|
155
|
+
kind_bonus: v.number(),
|
|
156
|
+
personal_bias: v.number(),
|
|
157
|
+
semantic_boost: v.number().nullable()
|
|
158
|
+
}).passthrough()
|
|
159
|
+
}).passthrough(),
|
|
160
|
+
role: v.object({
|
|
161
|
+
inferred: v.string(),
|
|
162
|
+
reason: v.string()
|
|
163
|
+
}).passthrough(),
|
|
164
|
+
matches: v.object({
|
|
165
|
+
query_terms: v.array(v.string()),
|
|
166
|
+
project_match: v.boolean().nullable()
|
|
167
|
+
}).passthrough(),
|
|
168
|
+
pack_context: v.object({
|
|
169
|
+
included: v.boolean().nullable(),
|
|
170
|
+
section: v.string().nullable()
|
|
171
|
+
}).passthrough().nullable()
|
|
172
|
+
}).passthrough(), ue = v.object({
|
|
173
|
+
id: v.number().int(),
|
|
174
|
+
kind: v.string(),
|
|
175
|
+
title: v.string(),
|
|
176
|
+
body: v.string(),
|
|
177
|
+
confidence: O,
|
|
178
|
+
metadata: D
|
|
179
|
+
}).passthrough(), j = v.object({
|
|
180
|
+
when: v.array(v.string()),
|
|
181
|
+
how: v.array(v.string()),
|
|
182
|
+
examples: v.array(v.string())
|
|
183
|
+
}).passthrough(), M = {
|
|
184
|
+
memory_search: v.object({ items: v.array(se) }),
|
|
185
|
+
memory_search_index: v.object({ items: v.array(ce) }),
|
|
186
|
+
memory_explain: v.object({
|
|
187
|
+
items: v.array(le),
|
|
188
|
+
missing_ids: v.array(v.number().int()),
|
|
189
|
+
errors: v.array(A),
|
|
190
|
+
metadata: v.object({
|
|
191
|
+
query: v.string().nullable(),
|
|
192
|
+
project: v.string().nullable(),
|
|
193
|
+
requested_ids_count: v.number().int(),
|
|
194
|
+
returned_items_count: v.number().int(),
|
|
195
|
+
include_pack_context: v.boolean(),
|
|
196
|
+
sanitized_query: v.string().optional()
|
|
197
|
+
}).passthrough()
|
|
198
|
+
}),
|
|
199
|
+
memory_recent: v.object({ items: v.array(k) }),
|
|
200
|
+
memory_pack: v.object({
|
|
201
|
+
context: v.string(),
|
|
202
|
+
items: v.array(ue),
|
|
203
|
+
item_ids: v.array(v.number().int()),
|
|
204
|
+
pack_text: v.string(),
|
|
205
|
+
metrics: v.object({
|
|
206
|
+
total_items: v.number().int(),
|
|
207
|
+
pack_tokens: v.number().int(),
|
|
208
|
+
fallback_used: v.boolean(),
|
|
209
|
+
limit: v.number().int(),
|
|
210
|
+
project: v.string().nullable(),
|
|
211
|
+
pack_item_ids: v.array(v.number().int())
|
|
212
|
+
}).passthrough()
|
|
213
|
+
}),
|
|
214
|
+
memory_timeline: v.object({ items: v.array(k) }),
|
|
215
|
+
memory_expand: v.object({
|
|
216
|
+
anchors: v.array(k),
|
|
217
|
+
timeline: v.array(k),
|
|
218
|
+
observations: v.array(k),
|
|
219
|
+
missing_ids: v.array(v.number().int()),
|
|
220
|
+
errors: v.array(A),
|
|
221
|
+
metadata: v.object({
|
|
222
|
+
project: v.string().nullable(),
|
|
223
|
+
requested_ids_count: v.number().int(),
|
|
224
|
+
returned_anchor_count: v.number().int(),
|
|
225
|
+
timeline_count: v.number().int(),
|
|
226
|
+
include_observations: v.boolean()
|
|
227
|
+
}).passthrough()
|
|
228
|
+
}),
|
|
229
|
+
memory_get: k,
|
|
230
|
+
memory_get_observations: v.object({ items: v.array(k) }),
|
|
231
|
+
memory_remember: v.object({ id: v.number().int() }),
|
|
232
|
+
memory_forget: v.object({ status: v.literal("ok") }),
|
|
233
|
+
memory_distill_candidates: v.object({
|
|
234
|
+
version: v.literal(1),
|
|
235
|
+
candidates: v.array(v.object({
|
|
236
|
+
scope: v.enum(["project", "user"]),
|
|
237
|
+
suggested_target: v.string().nullable(),
|
|
238
|
+
score: v.number(),
|
|
239
|
+
recurrence: v.number().int(),
|
|
240
|
+
projects: v.array(v.string()),
|
|
241
|
+
member_ids: v.array(v.number().int()),
|
|
242
|
+
representative_id: v.number().int(),
|
|
243
|
+
concepts: v.array(v.string()),
|
|
244
|
+
artifact_kind: v.enum(["context_fact", "skill"]),
|
|
245
|
+
evidence: v.array(v.string()),
|
|
246
|
+
draft_text: v.string().nullable()
|
|
247
|
+
}).passthrough()),
|
|
248
|
+
metadata: v.object({
|
|
249
|
+
candidate_count: v.number().int(),
|
|
250
|
+
cluster_count: v.number().int(),
|
|
251
|
+
context_document_count: v.number().int(),
|
|
252
|
+
corpus_count: v.number().int(),
|
|
253
|
+
corpus_limit: v.number().int(),
|
|
254
|
+
documented_cluster_count: v.number().int(),
|
|
255
|
+
include_documented: v.boolean(),
|
|
256
|
+
min_recurrence: v.number().int()
|
|
257
|
+
}).passthrough()
|
|
258
|
+
}),
|
|
259
|
+
memory_schema: v.object({
|
|
260
|
+
kinds: v.array(v.string()),
|
|
261
|
+
kind_descriptions: v.record(v.string(), v.string()),
|
|
262
|
+
fields: v.record(v.string(), v.string()),
|
|
263
|
+
filters: v.array(v.string())
|
|
264
|
+
}),
|
|
265
|
+
memory_learn: v.object({
|
|
266
|
+
intro: v.string(),
|
|
267
|
+
client_hint: v.string(),
|
|
268
|
+
recall: j,
|
|
269
|
+
persistence: j,
|
|
270
|
+
forget: j,
|
|
271
|
+
prompt_hint: v.string(),
|
|
272
|
+
recommended_system_prompt: v.string()
|
|
273
|
+
})
|
|
274
|
+
}, N = {
|
|
275
|
+
readOnlyHint: !0,
|
|
276
|
+
openWorldHint: !1
|
|
277
|
+
}, P = {
|
|
278
|
+
readOnlyHint: !0,
|
|
279
|
+
openWorldHint: !0
|
|
280
|
+
}, F = {
|
|
281
|
+
memory_search: N,
|
|
282
|
+
memory_search_index: N,
|
|
283
|
+
memory_explain: N,
|
|
284
|
+
memory_recent: N,
|
|
285
|
+
memory_pack: P,
|
|
286
|
+
memory_timeline: N,
|
|
287
|
+
memory_expand: N,
|
|
288
|
+
memory_get: N,
|
|
289
|
+
memory_get_observations: N,
|
|
290
|
+
memory_remember: {
|
|
291
|
+
readOnlyHint: !1,
|
|
292
|
+
destructiveHint: !1,
|
|
293
|
+
idempotentHint: !1,
|
|
294
|
+
openWorldHint: !0
|
|
295
|
+
},
|
|
296
|
+
memory_forget: {
|
|
297
|
+
readOnlyHint: !1,
|
|
298
|
+
destructiveHint: !0,
|
|
299
|
+
idempotentHint: !0,
|
|
300
|
+
openWorldHint: !1
|
|
301
|
+
},
|
|
302
|
+
memory_distill_candidates: P,
|
|
303
|
+
memory_schema: N,
|
|
304
|
+
memory_learn: N
|
|
305
|
+
}, de = {
|
|
306
|
+
limit: v.number().int().min(1).max(50).default(10).describe("Max candidates"),
|
|
307
|
+
min_recurrence: v.number().int().min(1).max(50).default(2).describe("Minimum member count per candidate"),
|
|
308
|
+
all_projects: v.boolean().default(!1).describe("Mine memories across all projects"),
|
|
309
|
+
include_documented: v.boolean().default(!1).describe("Include candidates already represented in context files"),
|
|
310
|
+
max_evidence_items: v.number().int().min(1).max(20).default(5).describe("Evidence snippets per candidate"),
|
|
311
|
+
judge: v.boolean().default(!0).describe("Judge candidates with the observer model and drop routine-activity clusters (on by default; falls back to unjudged output when no observer model is configured)"),
|
|
312
|
+
...E
|
|
313
|
+
};
|
|
314
|
+
function I(e, t, n) {
|
|
315
|
+
if (!g(e)) return null;
|
|
316
|
+
let r = ee(e, "utf8");
|
|
317
|
+
return r.trim() ? {
|
|
318
|
+
path: t,
|
|
319
|
+
text: r,
|
|
320
|
+
scope: n
|
|
321
|
+
} : null;
|
|
322
|
+
}
|
|
323
|
+
function L(e, t = process.cwd()) {
|
|
324
|
+
let n = p(t) ?? t;
|
|
325
|
+
return [e ? I(_(n, "AGENTS.md"), "AGENTS.md", "project") : null, I(_(te(), ".config", "opencode", "AGENTS.md"), "~/.config/opencode/AGENTS.md", "user")].filter((e) => e != null);
|
|
326
|
+
}
|
|
327
|
+
function R(e, t) {
|
|
328
|
+
if (e.all_projects) return !1;
|
|
329
|
+
let n = f(process.cwd());
|
|
330
|
+
if (!n) return !1;
|
|
331
|
+
let r = typeof e.project == "string" ? e.project.trim() : "", i = r ? f(process.cwd(), r) : t;
|
|
332
|
+
return i ? l(i, n) : !1;
|
|
333
|
+
}
|
|
334
|
+
function z(e, t) {
|
|
335
|
+
if (e.all_projects && typeof e.project == "string" && e.project.trim()) throw Error("project cannot be combined with all_projects");
|
|
336
|
+
return S(e, e.all_projects ? null : t);
|
|
337
|
+
}
|
|
338
|
+
function B(e, t) {
|
|
339
|
+
let { defaultProject: n, store: i } = t;
|
|
340
|
+
e.registerTool("memory_distill_candidates", {
|
|
341
|
+
description: "Mine recurring memories into reviewable context candidates. Reads project/user context files without modifying them and can call the optional observer when judge=true.",
|
|
342
|
+
inputSchema: de,
|
|
343
|
+
outputSchema: M.memory_distill_candidates,
|
|
344
|
+
annotations: F.memory_distill_candidates
|
|
345
|
+
}, async (e) => {
|
|
346
|
+
try {
|
|
347
|
+
let t = n(), a = z(e, t), s = e.kind ? [e.kind] : void 0, l = e.judge ? Math.min(e.limit * 3, e.limit + 20) : e.limit, u = await o(i, {
|
|
348
|
+
candidate: {
|
|
349
|
+
includeDocumented: e.include_documented,
|
|
350
|
+
maxEvidenceItems: e.max_evidence_items
|
|
351
|
+
},
|
|
352
|
+
contextDocuments: L(R(e, t)),
|
|
353
|
+
corpus: {
|
|
354
|
+
filters: a ?? null,
|
|
355
|
+
kinds: s
|
|
356
|
+
},
|
|
357
|
+
limit: l,
|
|
358
|
+
minRecurrence: e.min_recurrence
|
|
359
|
+
});
|
|
360
|
+
if (e.judge) {
|
|
361
|
+
try {
|
|
362
|
+
let e = new r();
|
|
363
|
+
u = await c(u, async (t, n) => (await e.observe(t, n)).raw);
|
|
364
|
+
} catch (e) {
|
|
365
|
+
let t = e instanceof Error ? e.message : String(e);
|
|
366
|
+
u = {
|
|
367
|
+
...u,
|
|
368
|
+
metadata: {
|
|
369
|
+
...u.metadata,
|
|
370
|
+
judged: !1,
|
|
371
|
+
judge_error: t
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
u.candidates.length > e.limit && (u = {
|
|
376
|
+
...u,
|
|
377
|
+
candidates: u.candidates.slice(0, e.limit),
|
|
378
|
+
metadata: {
|
|
379
|
+
...u.metadata,
|
|
380
|
+
candidate_count: e.limit
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
return C(u);
|
|
385
|
+
} catch (e) {
|
|
386
|
+
return w(e instanceof Error ? e.message : String(e));
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
//#endregion
|
|
391
|
+
//#region src/mcp-retrieval-ledger.ts
|
|
392
|
+
var V = 3e5, H = 2e3, U = /* @__PURE__ */ new WeakMap(), W = 0;
|
|
393
|
+
function G(e, t, n) {
|
|
394
|
+
if (e.captureRetrievalLedger) try {
|
|
395
|
+
let r = d(e.store.db, t);
|
|
396
|
+
n && !r.ok && r.reason === "idempotency_conflict" && (t.retrievalStatus === "succeeded" && t.deliveryStatus === "handed_off" || t.retrievalStatus === "no_results" && t.deliveryStatus === "not_attempted") && u(e.store.db, t);
|
|
397
|
+
} catch {}
|
|
398
|
+
}
|
|
399
|
+
function K(e) {
|
|
400
|
+
if (e == null) return t();
|
|
401
|
+
let n = e.slice(0, 32).split("");
|
|
402
|
+
n[12] = "5", n[16] = (Number.parseInt(n[16] ?? "0", 16) & 3 | 8).toString(16);
|
|
403
|
+
let r = n.join("");
|
|
404
|
+
return `${r.slice(0, 8)}-${r.slice(8, 12)}-${r.slice(12, 16)}-${r.slice(16, 20)}-${r.slice(20)}`;
|
|
405
|
+
}
|
|
406
|
+
function fe(t, n) {
|
|
407
|
+
if (n.requestId == null) return null;
|
|
408
|
+
let r = e("sha256").update(y({
|
|
409
|
+
method: "tools/call",
|
|
410
|
+
params: {
|
|
411
|
+
name: n.toolName,
|
|
412
|
+
arguments: n.toolArguments
|
|
413
|
+
}
|
|
414
|
+
})).digest("hex");
|
|
415
|
+
return e("sha256").update(JSON.stringify([
|
|
416
|
+
n.sourceSessionId ?? t.retrievalLedgerScopeId,
|
|
417
|
+
n.requestId,
|
|
418
|
+
r
|
|
419
|
+
])).digest("hex");
|
|
420
|
+
}
|
|
421
|
+
function q(e) {
|
|
422
|
+
let t = U.get(e);
|
|
423
|
+
return t || (t = {
|
|
424
|
+
byInvocation: /* @__PURE__ */ new WeakMap(),
|
|
425
|
+
activeByRequest: /* @__PURE__ */ new Map(),
|
|
426
|
+
pendingFailures: /* @__PURE__ */ new Map(),
|
|
427
|
+
pendingFailureCount: 0,
|
|
428
|
+
nextPendingFailureOrder: 0,
|
|
429
|
+
nextInvocationSequence: 0
|
|
430
|
+
}, U.set(e, t)), t;
|
|
431
|
+
}
|
|
432
|
+
function J(e, t) {
|
|
433
|
+
for (let [n, r] of e.pendingFailures) {
|
|
434
|
+
let i = r.filter((e) => e.expiresAt > t);
|
|
435
|
+
e.pendingFailureCount -= r.length - i.length, i.length === 0 ? e.pendingFailures.delete(n) : i.length !== r.length && e.pendingFailures.set(n, i);
|
|
436
|
+
}
|
|
437
|
+
for (; e.pendingFailureCount > H;) {
|
|
438
|
+
let t, n = Infinity;
|
|
439
|
+
for (let [r, i] of e.pendingFailures) {
|
|
440
|
+
let e = i[0]?.order;
|
|
441
|
+
e != null && e < n && (t = r, n = e);
|
|
442
|
+
}
|
|
443
|
+
if (t === void 0) break;
|
|
444
|
+
let r = e.pendingFailures.get(t), i = r?.shift();
|
|
445
|
+
if (!r || !i) {
|
|
446
|
+
e.pendingFailures.delete(t);
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
--e.pendingFailureCount, r.length === 0 && e.pendingFailures.delete(t);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
function Y(e, t) {
|
|
453
|
+
let n = e.pendingFailures.get(t);
|
|
454
|
+
if (!n) return;
|
|
455
|
+
let r = n.shift();
|
|
456
|
+
if (r) return --e.pendingFailureCount, n.length === 0 && e.pendingFailures.delete(t), r.identity;
|
|
457
|
+
}
|
|
458
|
+
function pe(e, t, n) {
|
|
459
|
+
let r = e.pendingFailures.get(t), i = r?.findIndex((e) => e.identity.attemptId === n) ?? -1;
|
|
460
|
+
!r || i < 0 || (r.splice(i, 1), --e.pendingFailureCount, r.length === 0 && e.pendingFailures.delete(t));
|
|
461
|
+
}
|
|
462
|
+
function me(e, t, n, r) {
|
|
463
|
+
let i = e.pendingFailures.get(t) ?? [];
|
|
464
|
+
i.some((e) => e.identity.attemptId === n.attemptId) || (i.push({
|
|
465
|
+
identity: n,
|
|
466
|
+
expiresAt: r + V,
|
|
467
|
+
order: e.nextPendingFailureOrder
|
|
468
|
+
}), e.nextPendingFailureOrder += 1, e.pendingFailures.set(t, i), e.pendingFailureCount += 1, J(e, r));
|
|
469
|
+
}
|
|
470
|
+
function he() {
|
|
471
|
+
try {
|
|
472
|
+
return {
|
|
473
|
+
baseRequestId: null,
|
|
474
|
+
requestId: null,
|
|
475
|
+
attemptId: t()
|
|
476
|
+
};
|
|
477
|
+
} catch {
|
|
478
|
+
let e = Date.now().toString(16).slice(-8).padStart(8, "0"), t = W.toString(16).slice(-4).padStart(4, "0");
|
|
479
|
+
return W = (W + 1) % 65536, {
|
|
480
|
+
baseRequestId: null,
|
|
481
|
+
requestId: null,
|
|
482
|
+
attemptId: `00000000-0000-4000-8000-${e}${t}`
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
function ge(t, n) {
|
|
487
|
+
let r = fe(t, n);
|
|
488
|
+
if (t.retrievalLedgerIdentityMode === "stateless" || r == null) return {
|
|
489
|
+
baseRequestId: r,
|
|
490
|
+
requestId: r,
|
|
491
|
+
attemptId: K(r)
|
|
492
|
+
};
|
|
493
|
+
let i = q(t);
|
|
494
|
+
J(i, Date.now());
|
|
495
|
+
let a = n.invocationIdentity ? i.byInvocation.get(n.invocationIdentity) : void 0, o = a?.baseRequestId === r ? a : void 0;
|
|
496
|
+
if (!o) {
|
|
497
|
+
let a = (i.activeByRequest.get(r) ?? 0) === 0 ? Y(i, r) : void 0;
|
|
498
|
+
if (a) o = a;
|
|
499
|
+
else {
|
|
500
|
+
let n = i.nextInvocationSequence;
|
|
501
|
+
i.nextInvocationSequence += 1;
|
|
502
|
+
let a = e("sha256").update(JSON.stringify([
|
|
503
|
+
r,
|
|
504
|
+
t.retrievalLedgerScopeId,
|
|
505
|
+
n
|
|
506
|
+
])).digest("hex");
|
|
507
|
+
o = {
|
|
508
|
+
baseRequestId: r,
|
|
509
|
+
requestId: a,
|
|
510
|
+
attemptId: K(a)
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
n.invocationIdentity && i.byInvocation.set(n.invocationIdentity, o);
|
|
514
|
+
}
|
|
515
|
+
return i.activeByRequest.set(r, (i.activeByRequest.get(r) ?? 0) + 1), o;
|
|
516
|
+
}
|
|
517
|
+
function _e(e, t) {
|
|
518
|
+
try {
|
|
519
|
+
return ge(e, t);
|
|
520
|
+
} catch {
|
|
521
|
+
return he();
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
function ve(e, t, n) {
|
|
525
|
+
if (e.retrievalLedgerIdentityMode === "stateless" || t.baseRequestId == null) return;
|
|
526
|
+
let r = q(e), i = r.activeByRequest.get(t.baseRequestId) ?? 0;
|
|
527
|
+
i <= 1 ? r.activeByRequest.delete(t.baseRequestId) : r.activeByRequest.set(t.baseRequestId, i - 1), n === "failed" ? me(r, t.baseRequestId, t, Date.now()) : pe(r, t.baseRequestId, t.attemptId);
|
|
528
|
+
}
|
|
529
|
+
function X(e, t, n) {
|
|
530
|
+
try {
|
|
531
|
+
ve(e, t, n);
|
|
532
|
+
} catch {}
|
|
533
|
+
}
|
|
534
|
+
async function Z(e, t, n) {
|
|
535
|
+
let r = _e(e, t), i = r.requestId, a = r.attemptId, o = /* @__PURE__ */ new Date(), s;
|
|
536
|
+
try {
|
|
537
|
+
s = t.resolveFilters?.();
|
|
538
|
+
let c = await n(s), l = /* @__PURE__ */ new Date(), u = c.error ? w(c.error) : C(c.value), d = t.sourceSessionId ?? e.retrievalLedgerScopeId, f = c.memoryIds.length > 0, p = c.error === "not_found" && !f, m = c.error != null && !p || c.retrievalStatus === "failed" && !f, h = m ? [] : c.memoryIds, g = c.retrievalStatus === "unknown" ? "unknown" : "succeeded";
|
|
539
|
+
return G(e, {
|
|
540
|
+
attemptId: a,
|
|
541
|
+
surface: t.surface,
|
|
542
|
+
trigger: "explicit",
|
|
543
|
+
startedAt: o.toISOString(),
|
|
544
|
+
completedAt: l.toISOString(),
|
|
545
|
+
retrievalStatus: m ? "failed" : f ? g : "no_results",
|
|
546
|
+
deliveryStatus: m || !f ? "not_attempted" : "handed_off",
|
|
547
|
+
candidateIds: h,
|
|
548
|
+
selectedIds: h,
|
|
549
|
+
candidateCount: f && !m ? c.candidateCount : 0,
|
|
550
|
+
recorderVersion: "mcp-retrieval-v1",
|
|
551
|
+
source: "mcp",
|
|
552
|
+
streamId: d,
|
|
553
|
+
sourceSessionId: t.sourceSessionId ?? null,
|
|
554
|
+
requestId: i,
|
|
555
|
+
latencyMs: Math.max(0, l.getTime() - o.getTime()),
|
|
556
|
+
filters: c.filters ?? s,
|
|
557
|
+
query: t.query,
|
|
558
|
+
limitRequested: t.limit,
|
|
559
|
+
failureCode: m ? "tool_failed" : void 0,
|
|
560
|
+
failureStage: m ? "retrieval" : void 0
|
|
561
|
+
}, !m), X(e, r, m ? "failed" : "completed"), u;
|
|
562
|
+
} catch (n) {
|
|
563
|
+
let c = /* @__PURE__ */ new Date(), l = t.sourceSessionId ?? e.retrievalLedgerScopeId;
|
|
564
|
+
return G(e, {
|
|
565
|
+
attemptId: a,
|
|
566
|
+
surface: t.surface,
|
|
567
|
+
trigger: "explicit",
|
|
568
|
+
startedAt: o.toISOString(),
|
|
569
|
+
completedAt: c.toISOString(),
|
|
570
|
+
retrievalStatus: "failed",
|
|
571
|
+
deliveryStatus: "not_attempted",
|
|
572
|
+
candidateIds: [],
|
|
573
|
+
selectedIds: [],
|
|
574
|
+
recorderVersion: "mcp-retrieval-v1",
|
|
575
|
+
source: "mcp",
|
|
576
|
+
streamId: l,
|
|
577
|
+
sourceSessionId: t.sourceSessionId ?? null,
|
|
578
|
+
requestId: i,
|
|
579
|
+
latencyMs: Math.max(0, c.getTime() - o.getTime()),
|
|
580
|
+
query: t.query,
|
|
581
|
+
limitRequested: t.limit,
|
|
582
|
+
filters: s,
|
|
583
|
+
failureCode: "tool_failed",
|
|
584
|
+
failureStage: "retrieval"
|
|
585
|
+
}, !1), X(e, r, "failed"), w(n instanceof Error ? n.message : String(n));
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
//#endregion
|
|
589
|
+
//#region src/memory-access.ts
|
|
590
|
+
function Q(e, t, n) {
|
|
591
|
+
return e.timeline(null, t, 0, 0, n ?? null).find((e) => e.id === t) ?? null;
|
|
592
|
+
}
|
|
593
|
+
function $(e, t, n) {
|
|
594
|
+
if (t.length === 0) return [];
|
|
595
|
+
let r = [];
|
|
596
|
+
for (let i of t) {
|
|
597
|
+
let t = Q(e, i, n);
|
|
598
|
+
t && r.push(t);
|
|
599
|
+
}
|
|
600
|
+
return r;
|
|
601
|
+
}
|
|
602
|
+
function ye(e, t, n) {
|
|
603
|
+
return Q(e, t, n) ? (e.forget(t), !0) : !1;
|
|
604
|
+
}
|
|
605
|
+
function be(e, t, n = {}) {
|
|
606
|
+
return e.db.transaction(() => {
|
|
607
|
+
let r = n.now?.() ?? (/* @__PURE__ */ new Date()).toISOString(), i = n.user ?? process.env.USER ?? "unknown", a = n.cwd ?? process.cwd(), o = re({
|
|
608
|
+
project: t.project,
|
|
609
|
+
envProject: n.envProject
|
|
610
|
+
}), s = e.db.prepare("INSERT INTO sessions(started_at, ended_at, cwd, project, user, tool_version, metadata_json)\n VALUES (?, ?, ?, ?, ?, ?, ?)").run(r, r, a, o, i, "mcp-ts", h({ mcp: !0 })), c = Number(s.lastInsertRowid), l = e.remember(c, t.kind, t.title, t.body, t.confidence);
|
|
611
|
+
if (!Q(e, l)) throw Error("unauthorized_scope");
|
|
612
|
+
return e.db.prepare("UPDATE sessions SET ended_at = ?, metadata_json = ? WHERE id = ?").run(n.now?.() ?? (/* @__PURE__ */ new Date()).toISOString(), h({ mcp: !0 }), c), {
|
|
613
|
+
memId: l,
|
|
614
|
+
title: t.title,
|
|
615
|
+
body: t.body
|
|
616
|
+
};
|
|
617
|
+
})();
|
|
618
|
+
}
|
|
619
|
+
//#endregion
|
|
620
|
+
//#region src/tools/items.ts
|
|
621
|
+
var xe = {
|
|
622
|
+
memory_id: v.number().int().describe("Memory ID"),
|
|
623
|
+
...E
|
|
624
|
+
}, Se = {
|
|
625
|
+
ids: v.array(v.number().int()).max(200).describe("Memory IDs to fetch"),
|
|
626
|
+
...E
|
|
627
|
+
}, Ce = {
|
|
628
|
+
kind: ae.describe("Memory kind"),
|
|
629
|
+
title: v.string().describe("Short title"),
|
|
630
|
+
body: v.string().describe("Body text (high-signal content)"),
|
|
631
|
+
confidence: v.number().min(0).max(1).default(.5).describe("Confidence 0-1"),
|
|
632
|
+
project: v.string().optional().describe("Project identifier")
|
|
633
|
+
}, we = {
|
|
634
|
+
memory_id: v.number().int().describe("Memory ID to forget"),
|
|
635
|
+
...E
|
|
636
|
+
};
|
|
637
|
+
function Te(e, t) {
|
|
638
|
+
e.registerTool("memory_get", {
|
|
639
|
+
description: "Fetch one memory by exact ID. Does not inherit the default project; optional filters constrain the lookup, and a mismatch returns not_found.",
|
|
640
|
+
inputSchema: xe,
|
|
641
|
+
outputSchema: M.memory_get,
|
|
642
|
+
annotations: F.memory_get
|
|
643
|
+
}, async (e, n) => Z(t, {
|
|
644
|
+
surface: "mcp_get",
|
|
645
|
+
toolName: "memory_get",
|
|
646
|
+
toolArguments: e,
|
|
647
|
+
limit: 1,
|
|
648
|
+
resolveFilters: () => S(e, null),
|
|
649
|
+
requestId: n?.requestId,
|
|
650
|
+
sourceSessionId: n?.sessionId,
|
|
651
|
+
invocationIdentity: n?.signal
|
|
652
|
+
}, (n) => {
|
|
653
|
+
let r = Q(t.store, e.memory_id, n);
|
|
654
|
+
return r ? {
|
|
655
|
+
value: r,
|
|
656
|
+
memoryIds: [r.id],
|
|
657
|
+
filters: n
|
|
658
|
+
} : {
|
|
659
|
+
value: null,
|
|
660
|
+
memoryIds: [],
|
|
661
|
+
error: "not_found",
|
|
662
|
+
filters: n
|
|
663
|
+
};
|
|
664
|
+
}));
|
|
665
|
+
}
|
|
666
|
+
function Ee(e, t) {
|
|
667
|
+
e.registerTool("memory_get_observations", {
|
|
668
|
+
description: "Fetch multiple memories by exact IDs. Does not inherit the default project. Missing or filtered-out IDs are omitted from results, not reported as not_found.",
|
|
669
|
+
inputSchema: Se,
|
|
670
|
+
outputSchema: M.memory_get_observations,
|
|
671
|
+
annotations: F.memory_get_observations
|
|
672
|
+
}, async (e, n) => Z(t, {
|
|
673
|
+
surface: "mcp_get_observations",
|
|
674
|
+
toolName: "memory_get_observations",
|
|
675
|
+
toolArguments: e,
|
|
676
|
+
limit: e.ids.length,
|
|
677
|
+
resolveFilters: () => S(e, null),
|
|
678
|
+
requestId: n?.requestId,
|
|
679
|
+
sourceSessionId: n?.sessionId,
|
|
680
|
+
invocationIdentity: n?.signal
|
|
681
|
+
}, (n) => {
|
|
682
|
+
let r = $(t.store, e.ids, n);
|
|
683
|
+
return {
|
|
684
|
+
value: { items: r },
|
|
685
|
+
memoryIds: r.map((e) => e.id),
|
|
686
|
+
filters: n
|
|
687
|
+
};
|
|
688
|
+
}));
|
|
689
|
+
}
|
|
690
|
+
function De(e, t) {
|
|
691
|
+
e.registerTool("memory_remember", {
|
|
692
|
+
description: "Create a new memory. Use for milestones, decisions, and notable facts.",
|
|
693
|
+
inputSchema: Ce,
|
|
694
|
+
outputSchema: M.memory_remember,
|
|
695
|
+
annotations: F.memory_remember
|
|
696
|
+
}, async (e) => {
|
|
697
|
+
try {
|
|
698
|
+
let n = be(t.store, e, { envProject: t.envProject() });
|
|
699
|
+
try {
|
|
700
|
+
await m(t.store.db, n.memId, n.title, n.body);
|
|
701
|
+
} catch {}
|
|
702
|
+
return C({ id: n.memId });
|
|
703
|
+
} catch (e) {
|
|
704
|
+
return w(e instanceof Error ? e.message : String(e));
|
|
705
|
+
}
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
function Oe(e, t) {
|
|
709
|
+
e.registerTool("memory_forget", {
|
|
710
|
+
description: "Soft-delete a memory by exact ID so it no longer appears in normal retrieval; this is not secure erasure. Does not inherit the default project; optional filters must match or the tool returns not_found.",
|
|
711
|
+
inputSchema: we,
|
|
712
|
+
outputSchema: M.memory_forget,
|
|
713
|
+
annotations: F.memory_forget
|
|
714
|
+
}, async (e) => {
|
|
715
|
+
try {
|
|
716
|
+
return ye(t.store, e.memory_id, S(e, null)) ? C({ status: "ok" }) : w("not_found");
|
|
717
|
+
} catch (e) {
|
|
718
|
+
return w(e instanceof Error ? e.message : String(e));
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
function ke(e, t) {
|
|
723
|
+
Te(e, t), Ee(e, t), De(e, t), Oe(e, t);
|
|
724
|
+
}
|
|
725
|
+
//#endregion
|
|
726
|
+
//#region src/tools/learn.ts
|
|
727
|
+
var Ae = {
|
|
728
|
+
intro: "Use this tool when you're new to codemem or unsure when to recall/persist.",
|
|
729
|
+
client_hint: "If you are unfamiliar with codemem, call memory_learn first.",
|
|
730
|
+
recall: {
|
|
731
|
+
when: ["Start of a task or when the user references prior work.", "When you need background context, decisions, or recent changes."],
|
|
732
|
+
how: [
|
|
733
|
+
"Use memory_search or memory_search_index for exact terms and identifiers; memory_search returns bodies, while memory_search_index returns compact candidates.",
|
|
734
|
+
"Use memory_pack for conceptually relevant context; it combines keyword and semantic search when embeddings are available and falls back to keyword search when they are not.",
|
|
735
|
+
"Use memory_timeline to expand around a promising memory.",
|
|
736
|
+
"Use memory_get or memory_get_observations for full details only when needed.",
|
|
737
|
+
"Use the project filter unless the user requests cross-project context.",
|
|
738
|
+
"Project, trust, and ownership filters organize and select memories; they are not authentication or tenant-isolation controls."
|
|
739
|
+
],
|
|
740
|
+
examples: [
|
|
741
|
+
"memory_search_index(query=\"billing cache bug\", limit=5)",
|
|
742
|
+
"memory_timeline(memory_id=123)",
|
|
743
|
+
"memory_get_observations(ids=[123, 456])"
|
|
744
|
+
]
|
|
745
|
+
},
|
|
746
|
+
persistence: {
|
|
747
|
+
when: ["Milestones (task done, key decision, new facts learned).", "Notable regressions or follow-ups that should be remembered."],
|
|
748
|
+
how: [
|
|
749
|
+
"Use memory_remember with kind decision/discovery/change/exploration.",
|
|
750
|
+
"Keep titles short and bodies high-signal.",
|
|
751
|
+
"ALWAYS pass the project parameter if known."
|
|
752
|
+
],
|
|
753
|
+
examples: ["memory_remember(kind=\"decision\", title=\"Switch to async cache\", body=\"...why...\", project=\"my-service\")", "memory_remember(kind=\"change\", title=\"Fixed retry loop\", body=\"...impact...\", project=\"my-service\")"]
|
|
754
|
+
},
|
|
755
|
+
forget: {
|
|
756
|
+
when: ["Obsolete or incorrect items that should no longer surface.", "Items that should be soft-deleted; soft deletion is not secure erasure."],
|
|
757
|
+
how: [
|
|
758
|
+
"Call memory_forget(memory_id) to mark the item inactive.",
|
|
759
|
+
"Optional filters constrain the exact-ID lookup; a filter mismatch returns not_found.",
|
|
760
|
+
"Do not treat memory_forget as secure erasure or a user-data erasure guarantee."
|
|
761
|
+
],
|
|
762
|
+
examples: ["memory_forget(memory_id=123)"]
|
|
763
|
+
},
|
|
764
|
+
prompt_hint: "At task start: call memory_search_index for exact terms or memory_pack for conceptual context; during work: memory_timeline + memory_get_observations; at milestones: memory_remember.",
|
|
765
|
+
recommended_system_prompt: [
|
|
766
|
+
"Trigger policy (1-liner): If the user references prior work or starts a task,",
|
|
767
|
+
"call memory_search_index for exact terms or memory_pack for conceptual context; then use",
|
|
768
|
+
"memory_timeline + memory_get_observations; at milestones, call memory_remember.",
|
|
769
|
+
"",
|
|
770
|
+
"System prompt:",
|
|
771
|
+
"You have access to codemem MCP tools. If unfamiliar, call memory_learn first.",
|
|
772
|
+
"",
|
|
773
|
+
"Recall:",
|
|
774
|
+
"- For exact terms or identifiers, use memory_search_index for compact candidates or memory_search for bodies.",
|
|
775
|
+
"- For conceptually relevant context, use memory_pack; it falls back to keyword search without embeddings.",
|
|
776
|
+
"- If prior work is referenced (\"as before\", \"last time\", \"we already did…\", \"regression\"),",
|
|
777
|
+
" call memory_search_index, memory_pack, or memory_timeline as appropriate.",
|
|
778
|
+
"- Use memory_get or memory_get_observations only after filtering IDs.",
|
|
779
|
+
"- Prefer project-scoped queries unless the user asks for cross-project.",
|
|
780
|
+
"- Project, trust, and ownership filters select memories; they do not authenticate or isolate tenants.",
|
|
781
|
+
"",
|
|
782
|
+
"Persistence:",
|
|
783
|
+
"- On milestones (task done, key decision, new facts learned), call memory_remember.",
|
|
784
|
+
"- Use kind=decision for tradeoffs, kind=change for outcomes, kind=discovery/exploration for useful findings.",
|
|
785
|
+
"- Keep titles short and bodies high-signal.",
|
|
786
|
+
"- ALWAYS pass the project parameter if known.",
|
|
787
|
+
"",
|
|
788
|
+
"Safety:",
|
|
789
|
+
"- Use memory_forget(memory_id) to soft-delete incorrect or obsolete items; this is not secure erasure.",
|
|
790
|
+
"",
|
|
791
|
+
"Examples:",
|
|
792
|
+
"- memory_search_index(query=\"billing cache bug\")",
|
|
793
|
+
"- memory_timeline(memory_id=123)",
|
|
794
|
+
"- memory_get_observations(ids=[123, 456])",
|
|
795
|
+
"- memory_remember(kind=\"decision\", title=\"Use async cache\", body=\"Chose async cache to avoid lock contention in X.\", project=\"my-service\")",
|
|
796
|
+
"- memory_remember(kind=\"change\", title=\"Fixed retry loop\", body=\"Root cause was Y; added guard in Z.\", project=\"my-service\")",
|
|
797
|
+
"- memory_forget(memory_id=123)"
|
|
798
|
+
].join("\n")
|
|
799
|
+
};
|
|
800
|
+
function je(e) {
|
|
801
|
+
e.registerTool("memory_learn", {
|
|
802
|
+
description: "Learn how to use codemem memory tools. Call this first if unfamiliar.",
|
|
803
|
+
inputSchema: {},
|
|
804
|
+
outputSchema: M.memory_learn,
|
|
805
|
+
annotations: F.memory_learn
|
|
806
|
+
}, async () => C(Ae));
|
|
807
|
+
}
|
|
808
|
+
//#endregion
|
|
809
|
+
//#region src/tools/schema.ts
|
|
810
|
+
function Me(e) {
|
|
811
|
+
e.registerTool("memory_schema", {
|
|
812
|
+
description: "Return the memory schema — kinds, fields, and available filters.",
|
|
813
|
+
inputSchema: {},
|
|
814
|
+
outputSchema: M.memory_schema,
|
|
815
|
+
annotations: F.memory_schema
|
|
816
|
+
}, async () => C({
|
|
817
|
+
kinds: Object.keys(n),
|
|
818
|
+
kind_descriptions: n,
|
|
819
|
+
fields: {
|
|
820
|
+
title: "short text",
|
|
821
|
+
body: "long text",
|
|
822
|
+
subtitle: "short text",
|
|
823
|
+
facts: "list<string>",
|
|
824
|
+
narrative: "long text",
|
|
825
|
+
concepts: "list<string>",
|
|
826
|
+
files_read: "list<string>",
|
|
827
|
+
files_modified: "list<string>",
|
|
828
|
+
prompt_number: "int"
|
|
829
|
+
},
|
|
830
|
+
filters: oe
|
|
831
|
+
}));
|
|
832
|
+
}
|
|
833
|
+
//#endregion
|
|
834
|
+
//#region src/tools/search.ts
|
|
835
|
+
var Ne = {
|
|
836
|
+
query: v.string().describe("Search query"),
|
|
837
|
+
limit: v.number().int().min(1).max(50).default(5).describe("Max results"),
|
|
838
|
+
...E
|
|
839
|
+
}, Pe = {
|
|
840
|
+
query: v.string().describe("Search query"),
|
|
841
|
+
limit: v.number().int().min(1).max(50).default(8).describe("Max results"),
|
|
842
|
+
...E
|
|
843
|
+
}, Fe = {
|
|
844
|
+
query: v.string().optional().describe("Search query"),
|
|
845
|
+
ids: v.array(v.number().int()).max(200).optional().describe("Specific memory IDs to explain"),
|
|
846
|
+
limit: v.number().int().min(1).max(50).default(10).describe("Max results"),
|
|
847
|
+
include_pack_context: v.boolean().default(!1).describe("Include formatted pack context"),
|
|
848
|
+
...E
|
|
849
|
+
}, Ie = {
|
|
850
|
+
limit: v.number().int().min(1).max(100).default(8).describe("Max results"),
|
|
851
|
+
...E
|
|
852
|
+
}, Le = {
|
|
853
|
+
context: v.string().describe("Context description to search for"),
|
|
854
|
+
limit: v.number().int().min(1).max(50).optional().describe("Max items to include"),
|
|
855
|
+
compact: v.boolean().optional().describe("When true, render a scannable index of all items with full detail only for the top N (default 3). Saves tokens when broad overview matters more than per-item detail."),
|
|
856
|
+
compact_detail_count: v.number().int().min(0).max(50).optional().describe("Number of items to show in full detail in compact mode (default 3)"),
|
|
857
|
+
compression_mode: v.enum([
|
|
858
|
+
"off",
|
|
859
|
+
"compact",
|
|
860
|
+
"ids"
|
|
861
|
+
]).optional().describe("Near-related compression mode: off disables it, compact applies only to compact rendering, ids applies in all modes. Defaults to CODEMEM_PACK_COMPRESSION or compact."),
|
|
862
|
+
...E
|
|
863
|
+
};
|
|
864
|
+
function Re(e, t) {
|
|
865
|
+
let { defaultProject: n, store: r } = t;
|
|
866
|
+
e.registerTool("memory_search", {
|
|
867
|
+
description: "Keyword-search memories when you know exact terms or identifiers. Returns full body text for each match; use memory_search_index when you only need compact candidates.",
|
|
868
|
+
inputSchema: Ne,
|
|
869
|
+
outputSchema: M.memory_search,
|
|
870
|
+
annotations: F.memory_search
|
|
871
|
+
}, async (e, i) => Z(t, {
|
|
872
|
+
surface: "mcp_search",
|
|
873
|
+
toolName: "memory_search",
|
|
874
|
+
toolArguments: e,
|
|
875
|
+
query: e.query,
|
|
876
|
+
limit: e.limit,
|
|
877
|
+
resolveFilters: () => S(e, n()),
|
|
878
|
+
requestId: i?.requestId,
|
|
879
|
+
sourceSessionId: i?.sessionId,
|
|
880
|
+
invocationIdentity: i?.signal
|
|
881
|
+
}, (t) => {
|
|
882
|
+
let n = r.search(e.query, e.limit, t);
|
|
883
|
+
return {
|
|
884
|
+
value: { items: n.map((e) => ({
|
|
885
|
+
id: e.id,
|
|
886
|
+
title: e.title,
|
|
887
|
+
kind: e.kind,
|
|
888
|
+
body: e.body_text,
|
|
889
|
+
confidence: e.confidence,
|
|
890
|
+
score: e.score,
|
|
891
|
+
session_id: e.session_id,
|
|
892
|
+
metadata: e.metadata
|
|
893
|
+
})) },
|
|
894
|
+
memoryIds: n.map((e) => e.id),
|
|
895
|
+
filters: t
|
|
896
|
+
};
|
|
897
|
+
})), e.registerTool("memory_search_index", {
|
|
898
|
+
description: "Keyword-search memories when you know exact terms or identifiers. Returns compact entries with IDs and titles, without bodies; expand selected IDs with memory_get or memory_get_observations.",
|
|
899
|
+
inputSchema: Pe,
|
|
900
|
+
outputSchema: M.memory_search_index,
|
|
901
|
+
annotations: F.memory_search_index
|
|
902
|
+
}, async (e, i) => Z(t, {
|
|
903
|
+
surface: "mcp_search_index",
|
|
904
|
+
toolName: "memory_search_index",
|
|
905
|
+
toolArguments: e,
|
|
906
|
+
query: e.query,
|
|
907
|
+
limit: e.limit,
|
|
908
|
+
resolveFilters: () => S(e, n()),
|
|
909
|
+
requestId: i?.requestId,
|
|
910
|
+
sourceSessionId: i?.sessionId,
|
|
911
|
+
invocationIdentity: i?.signal
|
|
912
|
+
}, (t) => {
|
|
913
|
+
let n = r.search(e.query, e.limit, t);
|
|
914
|
+
return {
|
|
915
|
+
value: { items: n.map((e) => ({
|
|
916
|
+
id: e.id,
|
|
917
|
+
kind: e.kind,
|
|
918
|
+
title: e.title,
|
|
919
|
+
score: e.score,
|
|
920
|
+
created_at: e.created_at,
|
|
921
|
+
session_id: e.session_id,
|
|
922
|
+
metadata: e.metadata
|
|
923
|
+
})) },
|
|
924
|
+
memoryIds: n.map((e) => e.id),
|
|
925
|
+
filters: t
|
|
926
|
+
};
|
|
927
|
+
})), e.registerTool("memory_explain", {
|
|
928
|
+
description: "Explain search results with detailed scoring breakdown.",
|
|
929
|
+
inputSchema: Fe,
|
|
930
|
+
outputSchema: M.memory_explain,
|
|
931
|
+
annotations: F.memory_explain
|
|
932
|
+
}, async (e, i) => Z(t, {
|
|
933
|
+
surface: "mcp_explain",
|
|
934
|
+
toolName: "memory_explain",
|
|
935
|
+
toolArguments: e,
|
|
936
|
+
query: e.query,
|
|
937
|
+
limit: e.limit,
|
|
938
|
+
resolveFilters: () => S(e, n()),
|
|
939
|
+
requestId: i?.requestId,
|
|
940
|
+
sourceSessionId: i?.sessionId,
|
|
941
|
+
invocationIdentity: i?.signal
|
|
942
|
+
}, (t) => {
|
|
943
|
+
let n = r.explain(e.query ?? null, e.ids ?? null, e.limit, t, { includePackContext: e.include_pack_context }), i = n.errors.some((e) => e.code === "INVALID_ARGUMENT" && e.field === "query");
|
|
944
|
+
return {
|
|
945
|
+
value: n,
|
|
946
|
+
memoryIds: n.items.map((e) => e.id),
|
|
947
|
+
filters: t,
|
|
948
|
+
retrievalStatus: i ? "failed" : void 0
|
|
949
|
+
};
|
|
950
|
+
})), e.registerTool("memory_recent", {
|
|
951
|
+
description: "Return recent memories, newest first.",
|
|
952
|
+
inputSchema: Ie,
|
|
953
|
+
outputSchema: M.memory_recent,
|
|
954
|
+
annotations: F.memory_recent
|
|
955
|
+
}, async (e, i) => Z(t, {
|
|
956
|
+
surface: "mcp_recent",
|
|
957
|
+
toolName: "memory_recent",
|
|
958
|
+
toolArguments: e,
|
|
959
|
+
limit: e.limit,
|
|
960
|
+
resolveFilters: () => S(e, n()),
|
|
961
|
+
requestId: i?.requestId,
|
|
962
|
+
sourceSessionId: i?.sessionId,
|
|
963
|
+
invocationIdentity: i?.signal
|
|
964
|
+
}, (t) => {
|
|
965
|
+
let n = r.recent(e.limit, t);
|
|
966
|
+
return {
|
|
967
|
+
value: { items: n },
|
|
968
|
+
memoryIds: n.map((e) => e.id),
|
|
969
|
+
filters: t
|
|
970
|
+
};
|
|
971
|
+
})), e.registerTool("memory_pack", {
|
|
972
|
+
description: "Build a formatted context block for a concept or task using keyword and semantic search when embeddings are available, with automatic keyword-only fallback. Use for conceptually relevant context; use memory_search or memory_search_index for exact identifiers.",
|
|
973
|
+
inputSchema: Le,
|
|
974
|
+
outputSchema: M.memory_pack,
|
|
975
|
+
annotations: F.memory_pack
|
|
976
|
+
}, async (e, i) => Z(t, {
|
|
977
|
+
surface: "mcp_pack",
|
|
978
|
+
toolName: "memory_pack",
|
|
979
|
+
toolArguments: e,
|
|
980
|
+
query: e.context,
|
|
981
|
+
limit: e.limit ?? null,
|
|
982
|
+
resolveFilters: () => S(e, n()),
|
|
983
|
+
requestId: i?.requestId,
|
|
984
|
+
sourceSessionId: i?.sessionId,
|
|
985
|
+
invocationIdentity: i?.signal
|
|
986
|
+
}, async (t) => {
|
|
987
|
+
let n = e.compact || e.compact_detail_count != null || e.compression_mode != null ? {
|
|
988
|
+
compact: e.compact ?? (e.compact_detail_count != null || void 0),
|
|
989
|
+
compactDetailCount: e.compact_detail_count,
|
|
990
|
+
compressionMode: e.compression_mode
|
|
991
|
+
} : void 0, i = await r.buildMemoryPackAsync(e.context, e.limit ?? void 0, null, t, n), { rendered_items: a, ...o } = i;
|
|
992
|
+
return {
|
|
993
|
+
value: o,
|
|
994
|
+
memoryIds: i.item_ids,
|
|
995
|
+
filters: t
|
|
996
|
+
};
|
|
997
|
+
}));
|
|
998
|
+
}
|
|
999
|
+
//#endregion
|
|
1000
|
+
//#region src/tools/timeline.ts
|
|
1001
|
+
var ze = {
|
|
1002
|
+
query: v.string().optional().describe("Search query to find anchor"),
|
|
1003
|
+
memory_id: v.number().int().optional().describe("Anchor memory ID"),
|
|
1004
|
+
depth_before: v.number().int().min(0).default(3).describe("Items before anchor"),
|
|
1005
|
+
depth_after: v.number().int().min(0).default(3).describe("Items after anchor"),
|
|
1006
|
+
...E
|
|
1007
|
+
}, Be = {
|
|
1008
|
+
ids: v.array(v.union([v.number(), v.string()])).max(200).describe("Memory IDs to expand"),
|
|
1009
|
+
depth_before: v.number().int().min(0).default(3).describe("Timeline items before"),
|
|
1010
|
+
depth_after: v.number().int().min(0).default(3).describe("Timeline items after"),
|
|
1011
|
+
include_observations: v.boolean().default(!1).describe("Include full observation details"),
|
|
1012
|
+
...E
|
|
1013
|
+
};
|
|
1014
|
+
function Ve(e, t) {
|
|
1015
|
+
let { defaultProject: n, store: r } = t;
|
|
1016
|
+
e.registerTool("memory_timeline", {
|
|
1017
|
+
description: "Get a chronological window of memories around an anchor (by ID or query).",
|
|
1018
|
+
inputSchema: ze,
|
|
1019
|
+
outputSchema: M.memory_timeline,
|
|
1020
|
+
annotations: F.memory_timeline
|
|
1021
|
+
}, async (e, i) => Z(t, {
|
|
1022
|
+
surface: "mcp_timeline",
|
|
1023
|
+
toolName: "memory_timeline",
|
|
1024
|
+
toolArguments: e,
|
|
1025
|
+
query: e.query,
|
|
1026
|
+
limit: e.depth_before + e.depth_after + 1,
|
|
1027
|
+
resolveFilters: () => S(e, n()),
|
|
1028
|
+
requestId: i?.requestId,
|
|
1029
|
+
sourceSessionId: i?.sessionId,
|
|
1030
|
+
invocationIdentity: i?.signal
|
|
1031
|
+
}, (t) => {
|
|
1032
|
+
let n = r.timeline(e.query ?? null, e.memory_id ?? null, e.depth_before, e.depth_after, t);
|
|
1033
|
+
return {
|
|
1034
|
+
value: { items: n },
|
|
1035
|
+
memoryIds: n.map((e) => e.id),
|
|
1036
|
+
filters: t
|
|
1037
|
+
};
|
|
1038
|
+
})), e.registerTool("memory_expand", {
|
|
1039
|
+
description: "Fetch memories by ID with surrounding timeline context.",
|
|
1040
|
+
inputSchema: Be,
|
|
1041
|
+
outputSchema: M.memory_expand,
|
|
1042
|
+
annotations: F.memory_expand
|
|
1043
|
+
}, async (e, i) => Z(t, {
|
|
1044
|
+
surface: "mcp_expand",
|
|
1045
|
+
toolName: "memory_expand",
|
|
1046
|
+
toolArguments: e,
|
|
1047
|
+
limit: e.ids.length,
|
|
1048
|
+
resolveFilters: () => S(e, e.project !== void 0 && !e.project.trim() ? null : n()),
|
|
1049
|
+
requestId: i?.requestId,
|
|
1050
|
+
sourceSessionId: i?.sessionId,
|
|
1051
|
+
invocationIdentity: i?.signal
|
|
1052
|
+
}, (t) => {
|
|
1053
|
+
let n = t?.project ?? null, { ordered: i, invalid: a } = s(e.ids), o = [];
|
|
1054
|
+
a.length > 0 && o.push({
|
|
1055
|
+
code: "INVALID_ARGUMENT",
|
|
1056
|
+
field: "ids",
|
|
1057
|
+
message: "some ids are not valid integers",
|
|
1058
|
+
ids: a
|
|
1059
|
+
});
|
|
1060
|
+
let c = [], u = [], d = [], f = [], p = [], m = /* @__PURE__ */ new Set(), h = /* @__PURE__ */ new Map();
|
|
1061
|
+
for (let a of i) {
|
|
1062
|
+
let i = r.get(a);
|
|
1063
|
+
if (!i?.active) {
|
|
1064
|
+
c.push(a);
|
|
1065
|
+
continue;
|
|
1066
|
+
}
|
|
1067
|
+
let o = i.session_id;
|
|
1068
|
+
if (n && o > 0) {
|
|
1069
|
+
if (!h.has(o)) {
|
|
1070
|
+
let e = r.db.prepare("SELECT project FROM sessions WHERE id = ? LIMIT 1").get(o);
|
|
1071
|
+
h.set(o, typeof e?.project == "string" ? e.project : null);
|
|
1072
|
+
}
|
|
1073
|
+
if (!l(n, h.get(o) ?? null)) {
|
|
1074
|
+
u.push(a);
|
|
1075
|
+
continue;
|
|
1076
|
+
}
|
|
1077
|
+
} else if (n && o <= 0) {
|
|
1078
|
+
u.push(a);
|
|
1079
|
+
continue;
|
|
1080
|
+
}
|
|
1081
|
+
let s = r.timeline(null, a, e.depth_before, e.depth_after, t), g = s.find((e) => e.id === a);
|
|
1082
|
+
if (!g) {
|
|
1083
|
+
d.push(a);
|
|
1084
|
+
continue;
|
|
1085
|
+
}
|
|
1086
|
+
f.push(g);
|
|
1087
|
+
for (let e of s) {
|
|
1088
|
+
let t = e.id;
|
|
1089
|
+
t <= 0 || m.has(t) || (m.add(t), p.push(e));
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
c.length > 0 && o.push({
|
|
1093
|
+
code: "NOT_FOUND",
|
|
1094
|
+
field: "ids",
|
|
1095
|
+
message: "some requested ids were not found",
|
|
1096
|
+
ids: c
|
|
1097
|
+
}), u.length > 0 && o.push({
|
|
1098
|
+
code: "PROJECT_MISMATCH",
|
|
1099
|
+
field: "project",
|
|
1100
|
+
message: "some requested ids are outside the requested project scope",
|
|
1101
|
+
ids: u
|
|
1102
|
+
}), d.length > 0 && o.push({
|
|
1103
|
+
code: "FILTER_MISMATCH",
|
|
1104
|
+
field: "filters",
|
|
1105
|
+
message: "some requested ids are outside the requested filters",
|
|
1106
|
+
ids: d
|
|
1107
|
+
});
|
|
1108
|
+
let g = [];
|
|
1109
|
+
if (e.include_observations) {
|
|
1110
|
+
let e = /* @__PURE__ */ new Set(), n = [];
|
|
1111
|
+
for (let t of [...f, ...p]) t.id > 0 && !e.has(t.id) && (e.add(t.id), n.push(t.id));
|
|
1112
|
+
g = $(r, n, t);
|
|
1113
|
+
}
|
|
1114
|
+
return {
|
|
1115
|
+
value: {
|
|
1116
|
+
anchors: f,
|
|
1117
|
+
timeline: p,
|
|
1118
|
+
observations: g,
|
|
1119
|
+
missing_ids: i.filter((e) => c.includes(e) || u.includes(e) || d.includes(e)),
|
|
1120
|
+
errors: o,
|
|
1121
|
+
metadata: {
|
|
1122
|
+
project: n,
|
|
1123
|
+
requested_ids_count: i.length,
|
|
1124
|
+
returned_anchor_count: f.length,
|
|
1125
|
+
timeline_count: p.length,
|
|
1126
|
+
include_observations: e.include_observations
|
|
1127
|
+
}
|
|
1128
|
+
},
|
|
1129
|
+
memoryIds: [...new Set([
|
|
1130
|
+
...f,
|
|
1131
|
+
...p,
|
|
1132
|
+
...g
|
|
1133
|
+
].map((e) => e.id))],
|
|
1134
|
+
filters: t
|
|
1135
|
+
};
|
|
1136
|
+
}));
|
|
1137
|
+
}
|
|
1138
|
+
//#endregion
|
|
1139
|
+
//#region src/server.ts
|
|
1140
|
+
function He(e, n = {}) {
|
|
1141
|
+
let r = new ne({
|
|
1142
|
+
name: "codemem",
|
|
1143
|
+
version: a
|
|
1144
|
+
}), i = {
|
|
1145
|
+
store: e,
|
|
1146
|
+
defaultProject: () => n.resolveDefaultProject ? n.resolveDefaultProject() : n.defaultProject === void 0 ? x() : n.defaultProject,
|
|
1147
|
+
envProject: () => n.envProject === void 0 ? process.env.CODEMEM_PROJECT ?? null : n.envProject,
|
|
1148
|
+
captureRetrievalLedger: n.captureRetrievalLedger !== !1,
|
|
1149
|
+
retrievalLedgerScopeId: n.retrievalLedgerScopeId ?? t(),
|
|
1150
|
+
retrievalLedgerIdentityMode: n.retrievalLedgerIdentityMode ?? "session"
|
|
1151
|
+
};
|
|
1152
|
+
return Re(r, i), Ve(r, i), B(r, i), ke(r, i), Me(r), je(r), r;
|
|
1153
|
+
}
|
|
1154
|
+
//#endregion
|
|
1155
|
+
export { y as n, He as t };
|
|
1156
|
+
|
|
1157
|
+
//# sourceMappingURL=server-DmdZAo6k.js.map
|