@codemem/mcp 0.44.1 → 0.45.0-rc.1

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.
@@ -1,857 +0,0 @@
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 _ } from "node:os";
5
- import { join as v } from "node:path";
6
- import { McpServer as y } from "@modelcontextprotocol/sdk/server/mcp.js";
7
- import { z as b } from "zod";
8
- //#region src/canonical-json.ts
9
- function x(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 S(e) {
15
- return e?.trim() || null;
16
- }
17
- function C() {
18
- return S(process.env.CODEMEM_PROJECT) ?? f(process.cwd());
19
- }
20
- function w(e) {
21
- return S(e.project) ?? S(e.envProject) ?? null;
22
- }
23
- function T(e, t = C()) {
24
- let n = {}, r = !1, i = (typeof e.project == "string" ? S(e.project) : void 0) || S(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 E(e) {
57
- return { content: [{
58
- type: "text",
59
- text: JSON.stringify(e)
60
- }] };
61
- }
62
- function D(e) {
63
- return { content: [{
64
- type: "text",
65
- text: JSON.stringify({ error: e })
66
- }] };
67
- }
68
- //#endregion
69
- //#region src/schemas.ts
70
- var O = {
71
- scope_id: b.string().optional().describe("Filter by a single sharing domain scope_id"),
72
- include_scope_ids: b.array(b.string()).optional().describe("Sharing domain scope_ids to include"),
73
- exclude_scope_ids: b.array(b.string()).optional().describe("Sharing domain scope_ids to exclude")
74
- }, k = {
75
- kind: b.string().optional().describe("Filter by memory kind"),
76
- project: b.string().optional().describe("Filter by project scope (matches sessions.project)"),
77
- ...O,
78
- visibility: b.array(b.string()).optional(),
79
- include_visibility: b.array(b.string()).optional(),
80
- exclude_visibility: b.array(b.string()).optional(),
81
- include_workspace_ids: b.array(b.string()).optional(),
82
- exclude_workspace_ids: b.array(b.string()).optional(),
83
- include_workspace_kinds: b.array(b.string()).optional(),
84
- exclude_workspace_kinds: b.array(b.string()).optional(),
85
- include_actor_ids: b.array(b.string()).optional(),
86
- exclude_actor_ids: b.array(b.string()).optional(),
87
- include_trust_states: b.array(b.string()).optional(),
88
- exclude_trust_states: b.array(b.string()).optional(),
89
- ownership_scope: b.string().optional(),
90
- personal_first: b.union([b.boolean(), b.string()]).optional(),
91
- trust_bias: b.string().optional(),
92
- widen_shared_when_weak: b.union([b.boolean(), b.string()]).optional(),
93
- widen_shared_min_personal_results: b.number().int().optional(),
94
- widen_shared_min_personal_score: b.number().optional()
95
- }, A = b.enum(i), j = Object.keys(k).toSorted();
96
- //#endregion
97
- //#region src/tools/distill.ts
98
- function M(e, t, n) {
99
- if (!g(e)) return null;
100
- let r = ee(e, "utf8");
101
- return r.trim() ? {
102
- path: t,
103
- text: r,
104
- scope: n
105
- } : null;
106
- }
107
- function te(e, t = process.cwd()) {
108
- let n = p(t) ?? t;
109
- return [e ? M(v(n, "AGENTS.md"), "AGENTS.md", "project") : null, M(v(_(), ".config", "opencode", "AGENTS.md"), "~/.config/opencode/AGENTS.md", "user")].filter((e) => e != null);
110
- }
111
- function ne(e, t) {
112
- if (e.all_projects) return !1;
113
- let n = f(process.cwd());
114
- if (!n) return !1;
115
- let r = typeof e.project == "string" ? e.project.trim() : "", i = r ? f(process.cwd(), r) : t;
116
- return i ? l(i, n) : !1;
117
- }
118
- function re(e, t) {
119
- if (e.all_projects && typeof e.project == "string" && e.project.trim()) throw Error("project cannot be combined with all_projects");
120
- return T(e, e.all_projects ? null : t);
121
- }
122
- function ie(e, t) {
123
- let { defaultProject: n, store: i } = t;
124
- e.tool("memory_distill_candidates", "Mine recurring memories into reviewable context candidates. Read-only; does not modify context files.", {
125
- limit: b.number().int().min(1).max(50).default(10).describe("Max candidates"),
126
- min_recurrence: b.number().int().min(1).max(50).default(2).describe("Minimum member count per candidate"),
127
- all_projects: b.boolean().default(!1).describe("Mine memories across all projects"),
128
- include_documented: b.boolean().default(!1).describe("Include candidates already represented in context files"),
129
- max_evidence_items: b.number().int().min(1).max(20).default(5).describe("Evidence snippets per candidate"),
130
- judge: b.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)"),
131
- ...k
132
- }, async (e) => {
133
- try {
134
- let t = n(), a = re(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, {
135
- candidate: {
136
- includeDocumented: e.include_documented,
137
- maxEvidenceItems: e.max_evidence_items
138
- },
139
- contextDocuments: te(ne(e, t)),
140
- corpus: {
141
- filters: a ?? null,
142
- kinds: s
143
- },
144
- limit: l,
145
- minRecurrence: e.min_recurrence
146
- });
147
- if (e.judge) {
148
- try {
149
- let e = new r();
150
- u = await c(u, async (t, n) => (await e.observe(t, n)).raw);
151
- } catch (e) {
152
- let t = e instanceof Error ? e.message : String(e);
153
- u = {
154
- ...u,
155
- metadata: {
156
- ...u.metadata,
157
- judged: !1,
158
- judge_error: t
159
- }
160
- };
161
- }
162
- u.candidates.length > e.limit && (u = {
163
- ...u,
164
- candidates: u.candidates.slice(0, e.limit),
165
- metadata: {
166
- ...u.metadata,
167
- candidate_count: e.limit
168
- }
169
- });
170
- }
171
- return E(u);
172
- } catch (e) {
173
- return D(e instanceof Error ? e.message : String(e));
174
- }
175
- });
176
- }
177
- //#endregion
178
- //#region src/mcp-retrieval-ledger.ts
179
- var N = 3e5, P = 2e3, F = /* @__PURE__ */ new WeakMap(), I = 0;
180
- function L(e, t, n) {
181
- if (e.captureRetrievalLedger) try {
182
- let r = d(e.store.db, t);
183
- 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);
184
- } catch {}
185
- }
186
- function R(e) {
187
- if (e == null) return t();
188
- let n = e.slice(0, 32).split("");
189
- n[12] = "5", n[16] = (Number.parseInt(n[16] ?? "0", 16) & 3 | 8).toString(16);
190
- let r = n.join("");
191
- return `${r.slice(0, 8)}-${r.slice(8, 12)}-${r.slice(12, 16)}-${r.slice(16, 20)}-${r.slice(20)}`;
192
- }
193
- function z(t, n) {
194
- if (n.requestId == null) return null;
195
- let r = e("sha256").update(x({
196
- method: "tools/call",
197
- params: {
198
- name: n.toolName,
199
- arguments: n.toolArguments
200
- }
201
- })).digest("hex");
202
- return e("sha256").update(JSON.stringify([
203
- n.sourceSessionId ?? t.retrievalLedgerScopeId,
204
- n.requestId,
205
- r
206
- ])).digest("hex");
207
- }
208
- function B(e) {
209
- let t = F.get(e);
210
- return t || (t = {
211
- byInvocation: /* @__PURE__ */ new WeakMap(),
212
- activeByRequest: /* @__PURE__ */ new Map(),
213
- pendingFailures: /* @__PURE__ */ new Map(),
214
- pendingFailureCount: 0,
215
- nextPendingFailureOrder: 0,
216
- nextInvocationSequence: 0
217
- }, F.set(e, t)), t;
218
- }
219
- function V(e, t) {
220
- for (let [n, r] of e.pendingFailures) {
221
- let i = r.filter((e) => e.expiresAt > t);
222
- e.pendingFailureCount -= r.length - i.length, i.length === 0 ? e.pendingFailures.delete(n) : i.length !== r.length && e.pendingFailures.set(n, i);
223
- }
224
- for (; e.pendingFailureCount > P;) {
225
- let t, n = Infinity;
226
- for (let [r, i] of e.pendingFailures) {
227
- let e = i[0]?.order;
228
- e != null && e < n && (t = r, n = e);
229
- }
230
- if (t === void 0) break;
231
- let r = e.pendingFailures.get(t), i = r?.shift();
232
- if (!r || !i) {
233
- e.pendingFailures.delete(t);
234
- continue;
235
- }
236
- --e.pendingFailureCount, r.length === 0 && e.pendingFailures.delete(t);
237
- }
238
- }
239
- function H(e, t) {
240
- let n = e.pendingFailures.get(t);
241
- if (!n) return;
242
- let r = n.shift();
243
- if (r) return --e.pendingFailureCount, n.length === 0 && e.pendingFailures.delete(t), r.identity;
244
- }
245
- function U(e, t, n) {
246
- let r = e.pendingFailures.get(t), i = r?.findIndex((e) => e.identity.attemptId === n) ?? -1;
247
- !r || i < 0 || (r.splice(i, 1), --e.pendingFailureCount, r.length === 0 && e.pendingFailures.delete(t));
248
- }
249
- function W(e, t, n, r) {
250
- let i = e.pendingFailures.get(t) ?? [];
251
- i.some((e) => e.identity.attemptId === n.attemptId) || (i.push({
252
- identity: n,
253
- expiresAt: r + N,
254
- order: e.nextPendingFailureOrder
255
- }), e.nextPendingFailureOrder += 1, e.pendingFailures.set(t, i), e.pendingFailureCount += 1, V(e, r));
256
- }
257
- function G() {
258
- try {
259
- return {
260
- baseRequestId: null,
261
- requestId: null,
262
- attemptId: t()
263
- };
264
- } catch {
265
- let e = Date.now().toString(16).slice(-8).padStart(8, "0"), t = I.toString(16).slice(-4).padStart(4, "0");
266
- return I = (I + 1) % 65536, {
267
- baseRequestId: null,
268
- requestId: null,
269
- attemptId: `00000000-0000-4000-8000-${e}${t}`
270
- };
271
- }
272
- }
273
- function K(t, n) {
274
- let r = z(t, n);
275
- if (t.retrievalLedgerIdentityMode === "stateless" || r == null) return {
276
- baseRequestId: r,
277
- requestId: r,
278
- attemptId: R(r)
279
- };
280
- let i = B(t);
281
- V(i, Date.now());
282
- let a = n.invocationIdentity ? i.byInvocation.get(n.invocationIdentity) : void 0, o = a?.baseRequestId === r ? a : void 0;
283
- if (!o) {
284
- let a = (i.activeByRequest.get(r) ?? 0) === 0 ? H(i, r) : void 0;
285
- if (a) o = a;
286
- else {
287
- let n = i.nextInvocationSequence;
288
- i.nextInvocationSequence += 1;
289
- let a = e("sha256").update(JSON.stringify([
290
- r,
291
- t.retrievalLedgerScopeId,
292
- n
293
- ])).digest("hex");
294
- o = {
295
- baseRequestId: r,
296
- requestId: a,
297
- attemptId: R(a)
298
- };
299
- }
300
- n.invocationIdentity && i.byInvocation.set(n.invocationIdentity, o);
301
- }
302
- return i.activeByRequest.set(r, (i.activeByRequest.get(r) ?? 0) + 1), o;
303
- }
304
- function q(e, t) {
305
- try {
306
- return K(e, t);
307
- } catch {
308
- return G();
309
- }
310
- }
311
- function J(e, t, n) {
312
- if (e.retrievalLedgerIdentityMode === "stateless" || t.baseRequestId == null) return;
313
- let r = B(e), i = r.activeByRequest.get(t.baseRequestId) ?? 0;
314
- i <= 1 ? r.activeByRequest.delete(t.baseRequestId) : r.activeByRequest.set(t.baseRequestId, i - 1), n === "failed" ? W(r, t.baseRequestId, t, Date.now()) : U(r, t.baseRequestId, t.attemptId);
315
- }
316
- function Y(e, t, n) {
317
- try {
318
- J(e, t, n);
319
- } catch {}
320
- }
321
- async function X(e, t, n) {
322
- let r = q(e, t), i = r.requestId, a = r.attemptId, o = /* @__PURE__ */ new Date(), s;
323
- try {
324
- s = t.resolveFilters?.();
325
- let c = await n(s), l = /* @__PURE__ */ new Date(), u = c.error ? D(c.error) : E(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";
326
- return L(e, {
327
- attemptId: a,
328
- surface: t.surface,
329
- trigger: "explicit",
330
- startedAt: o.toISOString(),
331
- completedAt: l.toISOString(),
332
- retrievalStatus: m ? "failed" : f ? g : "no_results",
333
- deliveryStatus: m || !f ? "not_attempted" : "handed_off",
334
- candidateIds: h,
335
- selectedIds: h,
336
- candidateCount: f && !m ? c.candidateCount : 0,
337
- recorderVersion: "mcp-retrieval-v1",
338
- source: "mcp",
339
- streamId: d,
340
- sourceSessionId: t.sourceSessionId ?? null,
341
- requestId: i,
342
- latencyMs: Math.max(0, l.getTime() - o.getTime()),
343
- filters: c.filters ?? s,
344
- query: t.query,
345
- limitRequested: t.limit,
346
- failureCode: m ? "tool_failed" : void 0,
347
- failureStage: m ? "retrieval" : void 0
348
- }, !m), Y(e, r, m ? "failed" : "completed"), u;
349
- } catch (n) {
350
- let c = /* @__PURE__ */ new Date(), l = t.sourceSessionId ?? e.retrievalLedgerScopeId;
351
- return L(e, {
352
- attemptId: a,
353
- surface: t.surface,
354
- trigger: "explicit",
355
- startedAt: o.toISOString(),
356
- completedAt: c.toISOString(),
357
- retrievalStatus: "failed",
358
- deliveryStatus: "not_attempted",
359
- candidateIds: [],
360
- selectedIds: [],
361
- recorderVersion: "mcp-retrieval-v1",
362
- source: "mcp",
363
- streamId: l,
364
- sourceSessionId: t.sourceSessionId ?? null,
365
- requestId: i,
366
- latencyMs: Math.max(0, c.getTime() - o.getTime()),
367
- query: t.query,
368
- limitRequested: t.limit,
369
- filters: s,
370
- failureCode: "tool_failed",
371
- failureStage: "retrieval"
372
- }, !1), Y(e, r, "failed"), D(n instanceof Error ? n.message : String(n));
373
- }
374
- }
375
- //#endregion
376
- //#region src/memory-access.ts
377
- function Z(e, t, n) {
378
- return e.timeline(null, t, 0, 0, n ?? null).find((e) => e.id === t) ?? null;
379
- }
380
- function Q(e, t, n) {
381
- if (t.length === 0) return [];
382
- let r = [];
383
- for (let i of t) {
384
- let t = Z(e, i, n);
385
- t && r.push(t);
386
- }
387
- return r;
388
- }
389
- function ae(e, t, n) {
390
- return Z(e, t, n) ? (e.forget(t), !0) : !1;
391
- }
392
- function oe(e, t, n = {}) {
393
- return e.db.transaction(() => {
394
- let r = n.now?.() ?? (/* @__PURE__ */ new Date()).toISOString(), i = n.user ?? process.env.USER ?? "unknown", a = n.cwd ?? process.cwd(), o = w({
395
- project: t.project,
396
- envProject: n.envProject
397
- }), 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);
398
- if (!Z(e, l)) throw Error("unauthorized_scope");
399
- return e.db.prepare("UPDATE sessions SET ended_at = ?, metadata_json = ? WHERE id = ?").run(n.now?.() ?? (/* @__PURE__ */ new Date()).toISOString(), h({ mcp: !0 }), c), {
400
- memId: l,
401
- title: t.title,
402
- body: t.body
403
- };
404
- })();
405
- }
406
- //#endregion
407
- //#region src/tools/items.ts
408
- function se(e, t) {
409
- let { envProject: n, store: r } = t;
410
- e.tool("memory_get", "Fetch a single memory item by ID.", {
411
- memory_id: b.number().int().describe("Memory ID"),
412
- ...k
413
- }, async (e, n) => X(t, {
414
- surface: "mcp_get",
415
- toolName: "memory_get",
416
- toolArguments: e,
417
- limit: 1,
418
- resolveFilters: () => T(e, null),
419
- requestId: n?.requestId,
420
- sourceSessionId: n?.sessionId,
421
- invocationIdentity: n?.signal
422
- }, (t) => {
423
- let n = Z(r, e.memory_id, t);
424
- return n ? {
425
- value: n,
426
- memoryIds: [n.id],
427
- filters: t
428
- } : {
429
- value: null,
430
- memoryIds: [],
431
- error: "not_found",
432
- filters: t
433
- };
434
- })), e.tool("memory_get_observations", "Fetch multiple memory items by their IDs.", {
435
- ids: b.array(b.number().int()).max(200).describe("Memory IDs to fetch"),
436
- ...k
437
- }, async (e, n) => X(t, {
438
- surface: "mcp_get_observations",
439
- toolName: "memory_get_observations",
440
- toolArguments: e,
441
- limit: e.ids.length,
442
- resolveFilters: () => T(e, null),
443
- requestId: n?.requestId,
444
- sourceSessionId: n?.sessionId,
445
- invocationIdentity: n?.signal
446
- }, (t) => {
447
- let n = Q(r, e.ids, t);
448
- return {
449
- value: { items: n },
450
- memoryIds: n.map((e) => e.id),
451
- filters: t
452
- };
453
- })), e.tool("memory_remember", "Create a new memory. Use for milestones, decisions, and notable facts.", {
454
- kind: A.describe("Memory kind"),
455
- title: b.string().describe("Short title"),
456
- body: b.string().describe("Body text (high-signal content)"),
457
- confidence: b.number().min(0).max(1).default(.5).describe("Confidence 0-1"),
458
- project: b.string().optional().describe("Project identifier")
459
- }, async (e) => {
460
- try {
461
- let t = oe(r, e, { envProject: n() });
462
- try {
463
- await m(r.db, t.memId, t.title, t.body);
464
- } catch {}
465
- return E({ id: t.memId });
466
- } catch (e) {
467
- return D(e instanceof Error ? e.message : String(e));
468
- }
469
- }), e.tool("memory_forget", "Soft-delete a memory item. Use for incorrect or sensitive data.", {
470
- memory_id: b.number().int().describe("Memory ID to forget"),
471
- ...k
472
- }, async (e) => {
473
- try {
474
- return ae(r, e.memory_id, T(e, null)) ? E({ status: "ok" }) : D("not_found");
475
- } catch (e) {
476
- return D(e instanceof Error ? e.message : String(e));
477
- }
478
- });
479
- }
480
- //#endregion
481
- //#region src/tools/learn.ts
482
- function ce(e) {
483
- e.tool("memory_learn", "Learn how to use codemem memory tools. Call this first if unfamiliar.", {}, async () => E({
484
- intro: "Use this tool when you're new to codemem or unsure when to recall/persist.",
485
- client_hint: "If you are unfamiliar with codemem, call memory.learn first.",
486
- recall: {
487
- when: ["Start of a task or when the user references prior work.", "When you need background context, decisions, or recent changes."],
488
- how: [
489
- "Use memory.search_index to get compact candidates.",
490
- "Use memory.timeline to expand around a promising memory.",
491
- "Use memory.get_observations for full details only when needed.",
492
- "Use memory.pack for quick one-shot context blocks.",
493
- "Use the project filter unless the user requests cross-project context."
494
- ],
495
- examples: [
496
- "memory.search_index(\"billing cache bug\", limit=5)",
497
- "memory.timeline(memory_id=123)",
498
- "memory.get_observations([123, 456])"
499
- ]
500
- },
501
- persistence: {
502
- when: ["Milestones (task done, key decision, new facts learned).", "Notable regressions or follow-ups that should be remembered."],
503
- how: [
504
- "Use memory.remember with kind decision/discovery/change/exploration.",
505
- "Keep titles short and bodies high-signal.",
506
- "ALWAYS pass the project parameter if known."
507
- ],
508
- 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\")"]
509
- },
510
- forget: {
511
- when: ["Accidental or sensitive data stored in memory items.", "Obsolete or incorrect items that should no longer surface."],
512
- how: ["Call memory.forget(id) to mark the item inactive.", "Prefer forgetting over overwriting to preserve auditability."],
513
- examples: ["memory.forget(123)"]
514
- },
515
- prompt_hint: "At task start: call memory.search_index; during work: memory.timeline + memory.get_observations; at milestones: memory.remember.",
516
- recommended_system_prompt: [
517
- "Trigger policy (1-liner): If the user references prior work or starts a task,",
518
- "immediately call memory.search_index; then use memory.timeline + memory.get_observations;",
519
- "at milestones, call memory.remember; use memory.forget for incorrect/sensitive items.",
520
- "",
521
- "System prompt:",
522
- "You have access to codemem MCP tools. If unfamiliar, call memory.learn first.",
523
- "",
524
- "Recall:",
525
- "- Start of any task: call memory.search_index with a concise task query.",
526
- "- If prior work is referenced (\"as before\", \"last time\", \"we already did…\", \"regression\"),",
527
- " call memory.search_index or memory.timeline.",
528
- "- Use memory.get_observations only after filtering IDs.",
529
- "- Prefer project-scoped queries unless the user asks for cross-project.",
530
- "",
531
- "Persistence:",
532
- "- On milestones (task done, key decision, new facts learned), call memory.remember.",
533
- "- Use kind=decision for tradeoffs, kind=change for outcomes, kind=discovery/exploration for useful findings.",
534
- "- Keep titles short and bodies high-signal.",
535
- "- ALWAYS pass the project parameter if known.",
536
- "",
537
- "Safety:",
538
- "- Use memory.forget(id) for incorrect or sensitive items.",
539
- "",
540
- "Examples:",
541
- "- memory.search_index(\"billing cache bug\")",
542
- "- memory.timeline(memory_id=123)",
543
- "- memory.get_observations([123, 456])",
544
- "- memory.remember(kind=\"decision\", title=\"Use async cache\", body=\"Chose async cache to avoid lock contention in X.\", project=\"my-service\")",
545
- "- memory.remember(kind=\"change\", title=\"Fixed retry loop\", body=\"Root cause was Y; added guard in Z.\", project=\"my-service\")",
546
- "- memory.forget(123)"
547
- ].join("\n")
548
- }));
549
- }
550
- //#endregion
551
- //#region src/tools/schema.ts
552
- function le(e) {
553
- e.tool("memory_schema", "Return the memory schema — kinds, fields, and available filters.", {}, async () => E({
554
- kinds: Object.keys(n),
555
- kind_descriptions: n,
556
- fields: {
557
- title: "short text",
558
- body: "long text",
559
- subtitle: "short text",
560
- facts: "list<string>",
561
- narrative: "long text",
562
- concepts: "list<string>",
563
- files_read: "list<string>",
564
- files_modified: "list<string>",
565
- prompt_number: "int"
566
- },
567
- filters: j
568
- }));
569
- }
570
- //#endregion
571
- //#region src/tools/search.ts
572
- function $(e, t) {
573
- let { defaultProject: n, store: r } = t;
574
- e.tool("memory_search", "Search memories by text query. Returns full body text for each match.", {
575
- query: b.string().describe("Search query"),
576
- limit: b.number().int().min(1).max(50).default(5).describe("Max results"),
577
- ...k
578
- }, async (e, i) => X(t, {
579
- surface: "mcp_search",
580
- toolName: "memory_search",
581
- toolArguments: e,
582
- query: e.query,
583
- limit: e.limit,
584
- resolveFilters: () => T(e, n()),
585
- requestId: i?.requestId,
586
- sourceSessionId: i?.sessionId,
587
- invocationIdentity: i?.signal
588
- }, (t) => {
589
- let n = r.search(e.query, e.limit, t);
590
- return {
591
- value: { items: n.map((e) => ({
592
- id: e.id,
593
- title: e.title,
594
- kind: e.kind,
595
- body: e.body_text,
596
- confidence: e.confidence,
597
- score: e.score,
598
- session_id: e.session_id,
599
- metadata: e.metadata
600
- })) },
601
- memoryIds: n.map((e) => e.id),
602
- filters: t
603
- };
604
- })), e.tool("memory_search_index", "Search memories by text query. Returns compact index entries (no body) for browsing.", {
605
- query: b.string().describe("Search query"),
606
- limit: b.number().int().min(1).max(50).default(8).describe("Max results"),
607
- ...k
608
- }, async (e, i) => X(t, {
609
- surface: "mcp_search_index",
610
- toolName: "memory_search_index",
611
- toolArguments: e,
612
- query: e.query,
613
- limit: e.limit,
614
- resolveFilters: () => T(e, n()),
615
- requestId: i?.requestId,
616
- sourceSessionId: i?.sessionId,
617
- invocationIdentity: i?.signal
618
- }, (t) => {
619
- let n = r.search(e.query, e.limit, t);
620
- return {
621
- value: { items: n.map((e) => ({
622
- id: e.id,
623
- kind: e.kind,
624
- title: e.title,
625
- score: e.score,
626
- created_at: e.created_at,
627
- session_id: e.session_id,
628
- metadata: e.metadata
629
- })) },
630
- memoryIds: n.map((e) => e.id),
631
- filters: t
632
- };
633
- })), e.tool("memory_explain", "Explain search results with detailed scoring breakdown.", {
634
- query: b.string().optional().describe("Search query"),
635
- ids: b.array(b.number().int()).max(200).optional().describe("Specific memory IDs to explain"),
636
- limit: b.number().int().min(1).max(50).default(10).describe("Max results"),
637
- include_pack_context: b.boolean().default(!1).describe("Include formatted pack context"),
638
- ...k
639
- }, async (e, i) => X(t, {
640
- surface: "mcp_explain",
641
- toolName: "memory_explain",
642
- toolArguments: e,
643
- query: e.query,
644
- limit: e.limit,
645
- resolveFilters: () => T(e, n()),
646
- requestId: i?.requestId,
647
- sourceSessionId: i?.sessionId,
648
- invocationIdentity: i?.signal
649
- }, (t) => {
650
- 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");
651
- return {
652
- value: n,
653
- memoryIds: n.items.map((e) => e.id),
654
- filters: t,
655
- retrievalStatus: i ? "failed" : void 0
656
- };
657
- })), e.tool("memory_recent", "Return recent memories, newest first.", {
658
- limit: b.number().int().min(1).max(100).default(8).describe("Max results"),
659
- ...k
660
- }, async (e, i) => X(t, {
661
- surface: "mcp_recent",
662
- toolName: "memory_recent",
663
- toolArguments: e,
664
- limit: e.limit,
665
- resolveFilters: () => T(e, n()),
666
- requestId: i?.requestId,
667
- sourceSessionId: i?.sessionId,
668
- invocationIdentity: i?.signal
669
- }, (t) => {
670
- let n = r.recent(e.limit, t);
671
- return {
672
- value: { items: n },
673
- memoryIds: n.map((e) => e.id),
674
- filters: t
675
- };
676
- })), e.tool("memory_pack", "Build a formatted memory pack from search results — quick one-shot context block.", {
677
- context: b.string().describe("Context description to search for"),
678
- limit: b.number().int().min(1).max(50).optional().describe("Max items to include"),
679
- compact: b.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."),
680
- compact_detail_count: b.number().int().min(0).max(50).optional().describe("Number of items to show in full detail in compact mode (default 3)"),
681
- compression_mode: b.enum([
682
- "off",
683
- "compact",
684
- "ids"
685
- ]).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."),
686
- ...k
687
- }, async (e, i) => X(t, {
688
- surface: "mcp_pack",
689
- toolName: "memory_pack",
690
- toolArguments: e,
691
- query: e.context,
692
- limit: e.limit ?? null,
693
- resolveFilters: () => T(e, n()),
694
- requestId: i?.requestId,
695
- sourceSessionId: i?.sessionId,
696
- invocationIdentity: i?.signal
697
- }, async (t) => {
698
- let n = e.compact || e.compact_detail_count != null || e.compression_mode != null ? {
699
- compact: e.compact ?? (e.compact_detail_count != null || void 0),
700
- compactDetailCount: e.compact_detail_count,
701
- compressionMode: e.compression_mode
702
- } : void 0, i = await r.buildMemoryPackAsync(e.context, e.limit ?? void 0, null, t, n), { rendered_items: a, ...o } = i;
703
- return {
704
- value: o,
705
- memoryIds: i.item_ids,
706
- filters: t
707
- };
708
- }));
709
- }
710
- //#endregion
711
- //#region src/tools/timeline.ts
712
- function ue(e, t) {
713
- let { defaultProject: n, store: r } = t;
714
- e.tool("memory_timeline", "Get a chronological window of memories around an anchor (by ID or query).", {
715
- query: b.string().optional().describe("Search query to find anchor"),
716
- memory_id: b.number().int().optional().describe("Anchor memory ID"),
717
- depth_before: b.number().int().min(0).default(3).describe("Items before anchor"),
718
- depth_after: b.number().int().min(0).default(3).describe("Items after anchor"),
719
- ...k
720
- }, async (e, i) => X(t, {
721
- surface: "mcp_timeline",
722
- toolName: "memory_timeline",
723
- toolArguments: e,
724
- query: e.query,
725
- limit: e.depth_before + e.depth_after + 1,
726
- resolveFilters: () => T(e, n()),
727
- requestId: i?.requestId,
728
- sourceSessionId: i?.sessionId,
729
- invocationIdentity: i?.signal
730
- }, (t) => {
731
- let n = r.timeline(e.query ?? null, e.memory_id ?? null, e.depth_before, e.depth_after, t);
732
- return {
733
- value: { items: n },
734
- memoryIds: n.map((e) => e.id),
735
- filters: t
736
- };
737
- })), e.tool("memory_expand", "Fetch memories by ID with surrounding timeline context.", {
738
- ids: b.array(b.union([b.number(), b.string()])).max(200).describe("Memory IDs to expand"),
739
- depth_before: b.number().int().min(0).default(3).describe("Timeline items before"),
740
- depth_after: b.number().int().min(0).default(3).describe("Timeline items after"),
741
- include_observations: b.boolean().default(!1).describe("Include full observation details"),
742
- ...k
743
- }, async (e, i) => X(t, {
744
- surface: "mcp_expand",
745
- toolName: "memory_expand",
746
- toolArguments: e,
747
- limit: e.ids.length,
748
- resolveFilters: () => T(e, e.project !== void 0 && !e.project.trim() ? null : n()),
749
- requestId: i?.requestId,
750
- sourceSessionId: i?.sessionId,
751
- invocationIdentity: i?.signal
752
- }, (t) => {
753
- let n = t?.project ?? null, { ordered: i, invalid: a } = s(e.ids), o = [];
754
- a.length > 0 && o.push({
755
- code: "INVALID_ARGUMENT",
756
- field: "ids",
757
- message: "some ids are not valid integers",
758
- ids: a
759
- });
760
- let c = [], u = [], d = [], f = [], p = [], m = /* @__PURE__ */ new Set(), h = /* @__PURE__ */ new Map();
761
- for (let a of i) {
762
- let i = r.get(a);
763
- if (!i?.active) {
764
- c.push(a);
765
- continue;
766
- }
767
- let o = i.session_id;
768
- if (n && o > 0) {
769
- if (!h.has(o)) {
770
- let e = r.db.prepare("SELECT project FROM sessions WHERE id = ? LIMIT 1").get(o);
771
- h.set(o, typeof e?.project == "string" ? e.project : null);
772
- }
773
- if (!l(n, h.get(o) ?? null)) {
774
- u.push(a);
775
- continue;
776
- }
777
- } else if (n && o <= 0) {
778
- u.push(a);
779
- continue;
780
- }
781
- let s = r.timeline(null, a, e.depth_before, e.depth_after, t), g = s.find((e) => e.id === a);
782
- if (!g) {
783
- d.push(a);
784
- continue;
785
- }
786
- f.push(g);
787
- for (let e of s) {
788
- let t = e.id;
789
- t <= 0 || m.has(t) || (m.add(t), p.push(e));
790
- }
791
- }
792
- c.length > 0 && o.push({
793
- code: "NOT_FOUND",
794
- field: "ids",
795
- message: "some requested ids were not found",
796
- ids: c
797
- }), u.length > 0 && o.push({
798
- code: "PROJECT_MISMATCH",
799
- field: "project",
800
- message: "some requested ids are outside the requested project scope",
801
- ids: u
802
- }), d.length > 0 && o.push({
803
- code: "FILTER_MISMATCH",
804
- field: "filters",
805
- message: "some requested ids are outside the requested filters",
806
- ids: d
807
- });
808
- let g = [];
809
- if (e.include_observations) {
810
- let e = /* @__PURE__ */ new Set(), n = [];
811
- for (let t of [...f, ...p]) t.id > 0 && !e.has(t.id) && (e.add(t.id), n.push(t.id));
812
- g = Q(r, n, t);
813
- }
814
- return {
815
- value: {
816
- anchors: f,
817
- timeline: p,
818
- observations: g,
819
- missing_ids: i.filter((e) => c.includes(e) || u.includes(e) || d.includes(e)),
820
- errors: o,
821
- metadata: {
822
- project: n,
823
- requested_ids_count: i.length,
824
- returned_anchor_count: f.length,
825
- timeline_count: p.length,
826
- include_observations: e.include_observations
827
- }
828
- },
829
- memoryIds: [...new Set([
830
- ...f,
831
- ...p,
832
- ...g
833
- ].map((e) => e.id))],
834
- filters: t
835
- };
836
- }));
837
- }
838
- //#endregion
839
- //#region src/server.ts
840
- function de(e, n = {}) {
841
- let r = new y({
842
- name: "codemem",
843
- version: a
844
- }), i = {
845
- store: e,
846
- defaultProject: () => n.resolveDefaultProject ? n.resolveDefaultProject() : n.defaultProject === void 0 ? C() : n.defaultProject,
847
- envProject: () => n.envProject === void 0 ? process.env.CODEMEM_PROJECT ?? null : n.envProject,
848
- captureRetrievalLedger: n.captureRetrievalLedger !== !1,
849
- retrievalLedgerScopeId: n.retrievalLedgerScopeId ?? t(),
850
- retrievalLedgerIdentityMode: n.retrievalLedgerIdentityMode ?? "session"
851
- };
852
- return $(r, i), ue(r, i), ie(r, i), se(r, i), le(r), ce(r), r;
853
- }
854
- //#endregion
855
- export { x as n, de as t };
856
-
857
- //# sourceMappingURL=server-D-jxqflv.js.map