@gethmy/mcp 2.3.2 → 2.3.3

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,388 +0,0 @@
1
- import { createRequire } from "node:module";
2
- var __create = Object.create;
3
- var __getProtoOf = Object.getPrototypeOf;
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __toESM = (mod, isNodeMode, target) => {
8
- target = mod != null ? __create(__getProtoOf(mod)) : {};
9
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
- for (let key of __getOwnPropNames(mod))
11
- if (!__hasOwnProp.call(to, key))
12
- __defProp(to, key, {
13
- get: () => mod[key],
14
- enumerable: true
15
- });
16
- return to;
17
- };
18
- var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
19
- var __export = (target, all) => {
20
- for (var name in all)
21
- __defProp(target, name, {
22
- get: all[name],
23
- enumerable: true,
24
- configurable: true,
25
- set: (newValue) => all[name] = () => newValue
26
- });
27
- };
28
- var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
29
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
30
-
31
- // src/graph-expansion.ts
32
- async function autoExpandGraph(client, entityId, title, content, _tags, workspaceId, projectId, maxRelations = 5) {
33
- try {
34
- const contentSnippet = content.slice(0, 200).trim();
35
- const query = [title, contentSnippet].filter(Boolean).join(" ");
36
- let candidates = [];
37
- const { entities } = await client.searchMemoryEntities(workspaceId, query, {
38
- project_id: projectId,
39
- limit: 20
40
- });
41
- candidates = entities.filter((e) => e.id !== entityId).slice(0, maxRelations);
42
- if (candidates.length === 0) {
43
- await new Promise((resolve) => setTimeout(resolve, 2000));
44
- const retry = await client.searchMemoryEntities(workspaceId, query, {
45
- project_id: projectId,
46
- limit: 20
47
- });
48
- candidates = retry.entities.filter((e) => e.id !== entityId).slice(0, maxRelations);
49
- }
50
- let relationsCreated = 0;
51
- for (const candidate of candidates) {
52
- try {
53
- await client.createMemoryRelation({
54
- source_id: entityId,
55
- target_id: candidate.id,
56
- relation_type: "relates_to",
57
- confidence: 0.6
58
- });
59
- relationsCreated++;
60
- } catch (err) {
61
- const status = err?.status;
62
- if (status !== 409) {}
63
- }
64
- }
65
- return { relationsCreated };
66
- } catch {
67
- return { relationsCreated: 0 };
68
- }
69
- }
70
- async function findSimilarEntities(client, title, content, workspaceId, options) {
71
- const contentSnippet = content.slice(0, 200).trim();
72
- const query = [title, contentSnippet].filter(Boolean).join(" ");
73
- try {
74
- const { entities } = await client.searchMemoryEntities(workspaceId, query, {
75
- project_id: options?.projectId,
76
- limit: options?.limit ?? 20,
77
- type: options?.type
78
- });
79
- const minScore = options?.minRrfScore ?? 0;
80
- const excludeSet = new Set(options?.excludeIds || []);
81
- return entities.filter((e) => {
82
- if (excludeSet.has(e.id))
83
- return false;
84
- if (minScore > 0 && (e.rrf_score ?? 0) < minScore)
85
- return false;
86
- return true;
87
- });
88
- } catch {
89
- return [];
90
- }
91
- }
92
- var CAUSAL_LOOKUP = [
93
- {
94
- sourceType: "error",
95
- targetType: "solution",
96
- relation: "resolved_by",
97
- direction: "forward"
98
- },
99
- {
100
- sourceType: "solution",
101
- targetType: "error",
102
- relation: "resolved_by",
103
- direction: "reverse"
104
- },
105
- {
106
- sourceType: "lesson",
107
- targetType: "error",
108
- relation: "learned_from",
109
- direction: "forward"
110
- }
111
- ];
112
- async function linkCrossTypeNeighbors(client, entityId, entityType, title, content, workspaceId, projectId) {
113
- const rules = CAUSAL_LOOKUP.filter((r) => r.sourceType === entityType);
114
- if (rules.length === 0)
115
- return { relationsCreated: 0 };
116
- let relationsCreated = 0;
117
- for (const rule of rules) {
118
- try {
119
- const matches = await findSimilarEntities(client, title, content, workspaceId, {
120
- projectId,
121
- limit: 10,
122
- minRrfScore: 0.04,
123
- excludeIds: [entityId],
124
- type: rule.targetType
125
- });
126
- for (const match of matches.slice(0, 3)) {
127
- const sourceId = rule.direction === "forward" ? entityId : match.id;
128
- const targetId = rule.direction === "forward" ? match.id : entityId;
129
- try {
130
- await client.createMemoryRelation({
131
- source_id: sourceId,
132
- target_id: targetId,
133
- relation_type: rule.relation,
134
- confidence: 0.65
135
- });
136
- relationsCreated++;
137
- } catch {}
138
- }
139
- } catch {}
140
- }
141
- return { relationsCreated };
142
- }
143
-
144
- // src/consolidation.ts
145
- async function consolidateMemories(client, workspaceId, projectId, options) {
146
- const dryRun = options?.dryRun !== false;
147
- const minClusterSize = options?.minClusterSize ?? 3;
148
- const result = {
149
- consolidated: 0,
150
- clustersFound: 0,
151
- entitiesProcessed: 0,
152
- details: []
153
- };
154
- const listResult = await client.listMemoryEntities({
155
- workspace_id: workspaceId,
156
- project_id: projectId,
157
- limit: 100
158
- });
159
- const allEntities = (listResult.entities || []).filter((e) => e.memory_tier === "draft" || e.memory_tier === "episode");
160
- result.entitiesProcessed = allEntities.length;
161
- if (allEntities.length < minClusterSize)
162
- return result;
163
- const typeGroups = new Map;
164
- for (const entity of allEntities) {
165
- const group = typeGroups.get(entity.type) || [];
166
- group.push(entity);
167
- typeGroups.set(entity.type, group);
168
- }
169
- for (const [type, entities] of typeGroups) {
170
- if (entities.length < minClusterSize)
171
- continue;
172
- const clustered = new Set;
173
- const clusters = [];
174
- for (const entity of entities) {
175
- if (clustered.has(entity.id))
176
- continue;
177
- const similar = await findSimilarEntities(client, entity.title, entity.content, workspaceId, {
178
- projectId,
179
- limit: 20,
180
- minRrfScore: 0.01,
181
- excludeIds: [...clustered]
182
- });
183
- const entityIdSet = new Set(entities.map((e) => e.id));
184
- const clusterMembers = similar.filter((s) => entityIdSet.has(s.id) && !clustered.has(s.id) && s.id !== entity.id && s.type === type);
185
- if (clusterMembers.length >= minClusterSize - 1) {
186
- const cluster = [
187
- entity,
188
- ...clusterMembers.slice(0, 5).map((s) => {
189
- return entities.find((e) => e.id === s.id) || entity;
190
- })
191
- ];
192
- const uniqueCluster = [];
193
- const seen = new Set;
194
- for (const member of cluster) {
195
- if (!seen.has(member.id)) {
196
- seen.add(member.id);
197
- uniqueCluster.push(member);
198
- }
199
- }
200
- if (uniqueCluster.length >= minClusterSize) {
201
- clusters.push(uniqueCluster);
202
- for (const member of uniqueCluster) {
203
- clustered.add(member.id);
204
- }
205
- }
206
- }
207
- }
208
- for (const cluster of clusters) {
209
- result.clustersFound++;
210
- const mergedTitle = deriveClusterTitle(cluster, type);
211
- const memberTitles = cluster.map((e) => e.title);
212
- const mergedContent = synthesizeClusterContent(cluster, type);
213
- const maxConfidence = Math.max(...cluster.map((e) => e.confidence));
214
- const allTags = [...new Set(cluster.flatMap((e) => e.tags || []))];
215
- const detail = {
216
- clusterSize: cluster.length,
217
- mergedTitle,
218
- memberTitles
219
- };
220
- if (!dryRun) {
221
- try {
222
- const createResult = await client.createMemoryEntity({
223
- workspace_id: workspaceId,
224
- project_id: projectId,
225
- type,
226
- scope: "project",
227
- memory_tier: "reference",
228
- title: mergedTitle,
229
- content: mergedContent,
230
- confidence: maxConfidence,
231
- tags: [...allTags.slice(0, 15), "consolidated"],
232
- metadata: {
233
- source: "consolidation",
234
- member_ids: cluster.map((e) => e.id),
235
- consolidated_at: new Date().toISOString()
236
- }
237
- });
238
- const newEntity = createResult.entity;
239
- if (newEntity?.id) {
240
- detail.entityId = newEntity.id;
241
- for (const member of cluster) {
242
- try {
243
- await client.createMemoryRelation({
244
- source_id: member.id,
245
- target_id: newEntity.id,
246
- relation_type: "part_of",
247
- confidence: 0.8
248
- });
249
- } catch {}
250
- }
251
- for (const member of cluster) {
252
- try {
253
- const newConf = Math.max(member.confidence - 0.3, 0.1);
254
- await client.updateMemoryEntity(member.id, {
255
- confidence: newConf,
256
- metadata: {
257
- consolidated_into: newEntity.id,
258
- original_confidence: member.confidence
259
- }
260
- });
261
- } catch {}
262
- }
263
- result.consolidated++;
264
- }
265
- } catch {}
266
- } else {
267
- result.consolidated++;
268
- }
269
- result.details.push(detail);
270
- }
271
- }
272
- return result;
273
- }
274
- function synthesizeClusterContent(cluster, type) {
275
- const SKIP_PATTERNS = [
276
- /^##\s/,
277
- /^Agent:/,
278
- /^Duration:/,
279
- /^Labels:/,
280
- /^Progress:/,
281
- /^Session status:/,
282
- /^Completed at/,
283
- /^Final state:/,
284
- /^Related:/,
285
- /^When working on:/,
286
- /^\d+\.\s+.+\(\d+%,\s*\+\d+%\)/,
287
- /^Last updated:/,
288
- /^Recurring pattern:/,
289
- /^Consolidated from/
290
- ];
291
- const seenLines = new Set;
292
- const knowledgeLines = [];
293
- for (const entity of cluster) {
294
- const lines = entity.content.split(`
295
- `).map((l) => l.trim());
296
- for (const line of lines) {
297
- if (!line || line.length < 20)
298
- continue;
299
- if (SKIP_PATTERNS.some((p) => p.test(line)))
300
- continue;
301
- const normalized = line.toLowerCase().replace(/[*_`#[\]]/g, "").trim();
302
- if (seenLines.has(normalized))
303
- continue;
304
- seenLines.add(normalized);
305
- knowledgeLines.push(line);
306
- }
307
- }
308
- if (knowledgeLines.length === 0) {
309
- return `${cluster.length} related ${type} entities consolidated. Original titles:
310
- ${cluster.map((e) => `- ${e.title}`).join(`
311
- `)}`;
312
- }
313
- const MAX_CHARS = 1600;
314
- const result = [
315
- `Consolidated knowledge from ${cluster.length} ${type} entities:
316
- `
317
- ];
318
- let charCount = result[0].length;
319
- for (const line of knowledgeLines) {
320
- if (charCount + line.length + 3 > MAX_CHARS)
321
- break;
322
- result.push(`- ${line}`);
323
- charCount += line.length + 3;
324
- }
325
- return result.join(`
326
- `);
327
- }
328
- function deriveClusterTitle(cluster, type) {
329
- const stopWords = new Set([
330
- "the",
331
- "a",
332
- "an",
333
- "is",
334
- "are",
335
- "was",
336
- "were",
337
- "be",
338
- "been",
339
- "being",
340
- "have",
341
- "has",
342
- "had",
343
- "do",
344
- "does",
345
- "did",
346
- "will",
347
- "shall",
348
- "would",
349
- "should",
350
- "may",
351
- "might",
352
- "can",
353
- "could",
354
- "of",
355
- "in",
356
- "to",
357
- "for",
358
- "with",
359
- "on",
360
- "at",
361
- "from",
362
- "by",
363
- "and",
364
- "or",
365
- "but",
366
- "not",
367
- "session",
368
- "blocker",
369
- "pattern",
370
- "solution",
371
- "error",
372
- "task",
373
- "mid-session"
374
- ]);
375
- const wordCounts = new Map;
376
- for (const entity of cluster) {
377
- const words = entity.title.toLowerCase().split(/\W+/).filter((w) => w.length > 2 && !stopWords.has(w));
378
- for (const word of words) {
379
- wordCounts.set(word, (wordCounts.get(word) || 0) + 1);
380
- }
381
- }
382
- const topWords = [...wordCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 4).map(([word]) => word[0].toUpperCase() + word.slice(1));
383
- const suffix = topWords.length > 0 ? topWords.join(" / ") : "Various";
384
- return `${type[0].toUpperCase() + type.slice(1)}: ${suffix}`;
385
- }
386
- export {
387
- consolidateMemories
388
- };