@cartisien/engram-mcp 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/LICENSE +21 -0
  2. package/dist/analysis/emotions.d.ts +16 -0
  3. package/dist/analysis/emotions.js +130 -0
  4. package/dist/analysis/emotions.js.map +1 -0
  5. package/dist/analysis/entities.d.ts +15 -0
  6. package/dist/analysis/entities.js +182 -0
  7. package/dist/analysis/entities.js.map +1 -0
  8. package/dist/analysis/themes.d.ts +11 -0
  9. package/dist/analysis/themes.js +151 -0
  10. package/dist/analysis/themes.js.map +1 -0
  11. package/dist/client.d.ts +3 -0
  12. package/dist/client.js +31 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/config.d.ts +13 -0
  15. package/dist/config.js +20 -0
  16. package/dist/config.js.map +1 -0
  17. package/dist/response.d.ts +17 -0
  18. package/dist/response.js +17 -0
  19. package/dist/response.js.map +1 -0
  20. package/dist/server.d.ts +7 -0
  21. package/dist/server.js +104 -0
  22. package/dist/server.js.map +1 -0
  23. package/dist/tools/consolidate.d.ts +41 -0
  24. package/dist/tools/consolidate.js +53 -0
  25. package/dist/tools/consolidate.js.map +1 -0
  26. package/dist/tools/context.d.ts +44 -0
  27. package/dist/tools/context.js +186 -0
  28. package/dist/tools/context.js.map +1 -0
  29. package/dist/tools/detect_changes.d.ts +35 -0
  30. package/dist/tools/detect_changes.js +178 -0
  31. package/dist/tools/detect_changes.js.map +1 -0
  32. package/dist/tools/forget.d.ts +38 -0
  33. package/dist/tools/forget.js +38 -0
  34. package/dist/tools/forget.js.map +1 -0
  35. package/dist/tools/graph.d.ts +40 -0
  36. package/dist/tools/graph.js +74 -0
  37. package/dist/tools/graph.js.map +1 -0
  38. package/dist/tools/impact.d.ts +39 -0
  39. package/dist/tools/impact.js +143 -0
  40. package/dist/tools/impact.js.map +1 -0
  41. package/dist/tools/process_detect.d.ts +49 -0
  42. package/dist/tools/process_detect.js +218 -0
  43. package/dist/tools/process_detect.js.map +1 -0
  44. package/dist/tools/recall.d.ts +81 -0
  45. package/dist/tools/recall.js +134 -0
  46. package/dist/tools/recall.js.map +1 -0
  47. package/dist/tools/remember.d.ts +47 -0
  48. package/dist/tools/remember.js +79 -0
  49. package/dist/tools/remember.js.map +1 -0
  50. package/dist/tools/search.d.ts +72 -0
  51. package/dist/tools/search.js +96 -0
  52. package/dist/tools/search.js.map +1 -0
  53. package/dist/tools/stats.d.ts +23 -0
  54. package/dist/tools/stats.js +47 -0
  55. package/dist/tools/stats.js.map +1 -0
  56. package/package.json +29 -14
  57. package/README.md +0 -114
  58. package/dist/engram.d.ts +0 -99
  59. package/dist/engram.js +0 -283
  60. package/dist/src/index.d.ts +0 -2
  61. package/dist/src/index.js +0 -322
  62. package/engram.ts +0 -385
  63. package/src/index.ts +0 -336
  64. package/tests/mcp.test.ts +0 -274
  65. package/tsconfig.json +0 -17
  66. package/tsconfig.test.json +0 -5
@@ -0,0 +1,218 @@
1
+ import { extractEntities } from '../analysis/entities.js';
2
+ import { themeNames } from '../analysis/themes.js';
3
+ import { scoreEmotion } from '../analysis/emotions.js';
4
+ import { ok, fail } from '../response.js';
5
+ import { defaultSession } from '../client.js';
6
+ export async function toolProcessDetect(engram, input) {
7
+ const start = Date.now();
8
+ const sessionId = input.session_id ?? defaultSession();
9
+ const processType = input.process_type ?? 'all';
10
+ const minOccurrences = input.min_occurrences ?? 2;
11
+ try {
12
+ // Fetch a broad set of memories to detect patterns
13
+ const memories = await engram.recall(sessionId, input.entity_focus ?? undefined, {
14
+ limit: 100,
15
+ threshold: input.entity_focus ? 0.5 : 0,
16
+ tiers: ['working', 'long_term'],
17
+ after: input.time_range?.start ? new Date(input.time_range.start) : undefined,
18
+ before: input.time_range?.end ? new Date(input.time_range.end) : undefined,
19
+ });
20
+ if (memories.length < minOccurrences) {
21
+ return ok({ processes: [], insights: [], memory_count: memories.length }, sessionId, start, [
22
+ `Only ${memories.length} memories found — store more to enable pattern detection`,
23
+ ]);
24
+ }
25
+ const processes = [];
26
+ if (processType === 'decision' || processType === 'all') {
27
+ const decisions = detectDecisionPatterns(memories, minOccurrences);
28
+ processes.push(...decisions);
29
+ }
30
+ if (processType === 'planning' || processType === 'all') {
31
+ const planning = detectPlanningPatterns(memories, minOccurrences);
32
+ processes.push(...planning);
33
+ }
34
+ if (processType === 'learning' || processType === 'all') {
35
+ const learning = detectLearningPatterns(memories, minOccurrences);
36
+ processes.push(...learning);
37
+ }
38
+ if (processType === 'conflict' || processType === 'all') {
39
+ const conflicts = detectConflictPatterns(memories, minOccurrences);
40
+ processes.push(...conflicts);
41
+ }
42
+ // Generate insights
43
+ const insights = generateInsights(memories, processes);
44
+ return ok({
45
+ processes,
46
+ insights,
47
+ memory_count: memories.length,
48
+ time_range_analyzed: {
49
+ from: memories[memories.length - 1]?.timestamp.toISOString() ?? null,
50
+ to: memories[0]?.timestamp.toISOString() ?? null,
51
+ },
52
+ }, sessionId, start);
53
+ }
54
+ catch (err) {
55
+ return fail('PROCESS_DETECT_FAILED', String(err), sessionId, start);
56
+ }
57
+ }
58
+ const DECISION_KEYWORDS = ['decided', 'decision', 'chose', 'choice', 'option', 'will go with',
59
+ 'going with', 'pick', 'select', 'prefer', 'instead', 'rather', 'pivot', 'switch to'];
60
+ const PLANNING_KEYWORDS = ['plan', 'schedule', 'next step', 'todo', 'will do', 'need to',
61
+ 'should', 'going to', 'agenda', 'roadmap', 'milestone', 'deadline', 'by end of'];
62
+ const LEARNING_KEYWORDS = ['learned', 'realized', 'discovered', 'found out', 'understand',
63
+ 'figured out', 'now know', 'insight', 'aha', 'interesting', 'turns out'];
64
+ const CONFLICT_KEYWORDS = ['frustrated', 'problem', 'issue', 'conflict', 'disagree',
65
+ 'not working', 'broken', 'stuck', 'blocked', 'challenge', 'difficulty'];
66
+ function detectDecisionPatterns(memories, minOcc) {
67
+ const relevant = memories.filter(m => DECISION_KEYWORDS.some(kw => m.content.toLowerCase().includes(kw)));
68
+ if (relevant.length < minOcc)
69
+ return [];
70
+ const entities = topEntities(relevant);
71
+ const themes = topThemes(relevant);
72
+ const emotionalArc = buildEmotionalArcString(relevant);
73
+ return [{
74
+ id: `proc_decision_${Date.now()}`,
75
+ name: 'Decision-Making Loop',
76
+ type: 'decision',
77
+ occurrences: relevant.length,
78
+ entities_involved: entities,
79
+ common_themes: themes,
80
+ typical_emotional_arc: emotionalArc,
81
+ last_occurrence: relevant[0]?.timestamp.toISOString() ?? '',
82
+ related_memories: relevant.slice(0, 5).map(m => m.id),
83
+ }];
84
+ }
85
+ function detectPlanningPatterns(memories, minOcc) {
86
+ const relevant = memories.filter(m => PLANNING_KEYWORDS.some(kw => m.content.toLowerCase().includes(kw)));
87
+ if (relevant.length < minOcc)
88
+ return [];
89
+ return [{
90
+ id: `proc_planning_${Date.now()}`,
91
+ name: 'Planning Session',
92
+ type: 'planning',
93
+ occurrences: relevant.length,
94
+ entities_involved: topEntities(relevant),
95
+ common_themes: topThemes(relevant),
96
+ typical_emotional_arc: buildEmotionalArcString(relevant),
97
+ last_occurrence: relevant[0]?.timestamp.toISOString() ?? '',
98
+ related_memories: relevant.slice(0, 5).map(m => m.id),
99
+ }];
100
+ }
101
+ function detectLearningPatterns(memories, minOcc) {
102
+ const relevant = memories.filter(m => LEARNING_KEYWORDS.some(kw => m.content.toLowerCase().includes(kw)));
103
+ if (relevant.length < minOcc)
104
+ return [];
105
+ return [{
106
+ id: `proc_learning_${Date.now()}`,
107
+ name: 'Learning / Discovery',
108
+ type: 'learning',
109
+ occurrences: relevant.length,
110
+ entities_involved: topEntities(relevant),
111
+ common_themes: topThemes(relevant),
112
+ typical_emotional_arc: buildEmotionalArcString(relevant),
113
+ last_occurrence: relevant[0]?.timestamp.toISOString() ?? '',
114
+ related_memories: relevant.slice(0, 5).map(m => m.id),
115
+ }];
116
+ }
117
+ function detectConflictPatterns(memories, minOcc) {
118
+ const relevant = memories.filter(m => CONFLICT_KEYWORDS.some(kw => m.content.toLowerCase().includes(kw)));
119
+ if (relevant.length < minOcc)
120
+ return [];
121
+ return [{
122
+ id: `proc_conflict_${Date.now()}`,
123
+ name: 'Friction / Conflict Pattern',
124
+ type: 'conflict',
125
+ occurrences: relevant.length,
126
+ entities_involved: topEntities(relevant),
127
+ common_themes: topThemes(relevant),
128
+ typical_emotional_arc: buildEmotionalArcString(relevant),
129
+ last_occurrence: relevant[0]?.timestamp.toISOString() ?? '',
130
+ related_memories: relevant.slice(0, 5).map(m => m.id),
131
+ }];
132
+ }
133
+ function topEntities(memories) {
134
+ const counts = {};
135
+ for (const m of memories) {
136
+ for (const e of extractEntities(m.content)) {
137
+ const k = e.name.toLowerCase();
138
+ counts[k] = (counts[k] ?? 0) + 1;
139
+ }
140
+ }
141
+ return Object.entries(counts)
142
+ .sort(([, a], [, b]) => b - a)
143
+ .slice(0, 5)
144
+ .map(([name]) => name);
145
+ }
146
+ function topThemes(memories) {
147
+ const counts = {};
148
+ for (const m of memories) {
149
+ for (const t of themeNames(m.content, 3)) {
150
+ counts[t] = (counts[t] ?? 0) + 1;
151
+ }
152
+ }
153
+ return Object.entries(counts)
154
+ .sort(([, a], [, b]) => b - a)
155
+ .slice(0, 3)
156
+ .map(([t]) => t);
157
+ }
158
+ function buildEmotionalArcString(memories) {
159
+ if (memories.length === 0)
160
+ return 'unknown';
161
+ const sorted = [...memories].sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
162
+ const tones = sorted.map(m => scoreEmotion(m.content).tone);
163
+ // Deduplicate consecutive same tones
164
+ const deduped = [];
165
+ for (const t of tones) {
166
+ if (deduped[deduped.length - 1] !== t)
167
+ deduped.push(t);
168
+ }
169
+ return deduped.slice(0, 5).join(' → ');
170
+ }
171
+ function generateInsights(memories, processes) {
172
+ const insights = [];
173
+ if (processes.length === 0) {
174
+ insights.push('No recurring patterns detected yet — more memories needed');
175
+ return insights;
176
+ }
177
+ // Check for high decision frequency
178
+ const decisionProc = processes.find(p => p.type === 'decision');
179
+ if (decisionProc && decisionProc.occurrences > 5) {
180
+ insights.push(`High decision frequency (${decisionProc.occurrences} instances) — consider documenting decision criteria`);
181
+ }
182
+ // Check for conflict patterns without resolution
183
+ const conflictProc = processes.find(p => p.type === 'conflict');
184
+ const learningProc = processes.find(p => p.type === 'learning');
185
+ if (conflictProc && !learningProc) {
186
+ insights.push('Friction patterns detected without corresponding learning moments — consider reflection');
187
+ }
188
+ if (learningProc && learningProc.occurrences > 3) {
189
+ insights.push(`Active learning phase detected — ${learningProc.occurrences} discovery moments`);
190
+ }
191
+ // Most active entities
192
+ const allEntities = topEntities(memories);
193
+ if (allEntities.length > 0) {
194
+ insights.push(`Most referenced entity: '${allEntities[0]}' — appears central to current work`);
195
+ }
196
+ return insights;
197
+ }
198
+ export const PROCESS_DETECT_SCHEMA = {
199
+ name: 'process_detect',
200
+ description: 'Identify recurring conversation and behavior patterns: decision loops, planning sessions, learning moments, and conflict patterns.',
201
+ inputSchema: {
202
+ type: 'object',
203
+ properties: {
204
+ process_type: { type: 'string', enum: ['decision', 'learning', 'conflict', 'planning', 'all'], default: 'all' },
205
+ session_id: { type: 'string' },
206
+ entity_focus: { type: 'string', description: 'Focus pattern detection on a specific entity' },
207
+ min_occurrences: { type: 'number', default: 2, description: 'Minimum occurrences to consider a pattern' },
208
+ time_range: {
209
+ type: 'object',
210
+ properties: {
211
+ start: { type: 'string' },
212
+ end: { type: 'string' },
213
+ },
214
+ },
215
+ },
216
+ },
217
+ };
218
+ //# sourceMappingURL=process_detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process_detect.js","sourceRoot":"","sources":["../../src/tools/process_detect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import type { Engram } from '@cartisien/engram';
2
+ export interface RecallInput {
3
+ query: string;
4
+ session_id?: string;
5
+ limit?: number;
6
+ min_relevance?: number;
7
+ include_context?: boolean;
8
+ time_range?: {
9
+ start?: string;
10
+ end?: string;
11
+ };
12
+ entity_filter?: string[];
13
+ theme_filter?: string[];
14
+ tiers?: string[];
15
+ }
16
+ export declare function toolRecall(engram: Engram, input: RecallInput): Promise<import("../response.js").McpResponse<unknown>>;
17
+ export declare const RECALL_SCHEMA: {
18
+ readonly name: "recall";
19
+ readonly description: "Retrieve relevant memories with entity, theme, and emotional context. Returns 360° relational intelligence around the query.";
20
+ readonly inputSchema: {
21
+ readonly type: "object";
22
+ readonly properties: {
23
+ readonly query: {
24
+ readonly type: "string";
25
+ readonly description: "What to search for";
26
+ };
27
+ readonly session_id: {
28
+ readonly type: "string";
29
+ };
30
+ readonly limit: {
31
+ readonly type: "number";
32
+ readonly default: 5;
33
+ readonly description: "Max results (default: 5, max: 50)";
34
+ };
35
+ readonly min_relevance: {
36
+ readonly type: "number";
37
+ readonly default: 0.7;
38
+ readonly description: "Minimum relevance score 0-1";
39
+ };
40
+ readonly include_context: {
41
+ readonly type: "boolean";
42
+ readonly default: true;
43
+ };
44
+ readonly time_range: {
45
+ readonly type: "object";
46
+ readonly properties: {
47
+ readonly start: {
48
+ readonly type: "string";
49
+ readonly description: "ISO8601 start date";
50
+ };
51
+ readonly end: {
52
+ readonly type: "string";
53
+ readonly description: "ISO8601 end date";
54
+ };
55
+ };
56
+ };
57
+ readonly entity_filter: {
58
+ readonly type: "array";
59
+ readonly items: {
60
+ readonly type: "string";
61
+ };
62
+ readonly description: "Only return memories mentioning these entities";
63
+ };
64
+ readonly theme_filter: {
65
+ readonly type: "array";
66
+ readonly items: {
67
+ readonly type: "string";
68
+ };
69
+ readonly description: "Only return memories matching these themes";
70
+ };
71
+ readonly tiers: {
72
+ readonly type: "array";
73
+ readonly items: {
74
+ readonly type: "string";
75
+ };
76
+ readonly description: "Memory tiers to search: working, long_term, archived";
77
+ };
78
+ };
79
+ readonly required: readonly ["query"];
80
+ };
81
+ };
@@ -0,0 +1,134 @@
1
+ import { extractEntities } from '../analysis/entities.js';
2
+ import { themeNames } from '../analysis/themes.js';
3
+ import { scoreEmotion, emotionalTrajectory } from '../analysis/emotions.js';
4
+ import { ok, fail } from '../response.js';
5
+ import { defaultSession } from '../client.js';
6
+ export async function toolRecall(engram, input) {
7
+ const start = Date.now();
8
+ const sessionId = input.session_id ?? defaultSession();
9
+ if (!input.query?.trim()) {
10
+ return fail('INVALID_INPUT', 'query is required', sessionId, start);
11
+ }
12
+ const limit = Math.min(input.limit ?? 5, 50);
13
+ const threshold = input.min_relevance ?? 0.7;
14
+ const tiers = input.tiers ?? ['working', 'long_term'];
15
+ try {
16
+ const memories = await engram.recall(sessionId, input.query, {
17
+ limit: limit * 3, // over-fetch to allow post-filtering
18
+ threshold,
19
+ tiers,
20
+ after: input.time_range?.start ? new Date(input.time_range.start) : undefined,
21
+ before: input.time_range?.end ? new Date(input.time_range.end) : undefined,
22
+ });
23
+ // Post-filter by entity
24
+ let filtered = memories;
25
+ if (input.entity_filter?.length) {
26
+ const ef = input.entity_filter.map(e => e.toLowerCase());
27
+ filtered = memories.filter(m => {
28
+ const mLower = m.content.toLowerCase();
29
+ return ef.some(e => mLower.includes(e));
30
+ });
31
+ }
32
+ // Post-filter by theme
33
+ if (input.theme_filter?.length) {
34
+ const tf = new Set(input.theme_filter);
35
+ filtered = filtered.filter(m => {
36
+ const themes = themeNames(m.content, 5);
37
+ return themes.some(t => tf.has(t));
38
+ });
39
+ }
40
+ const results = filtered.slice(0, limit);
41
+ // Enrich each memory with context
42
+ const enriched = results.map(m => enrichMemory(m, input.query));
43
+ // Build summary
44
+ const allThemes = enriched.flatMap(m => m.themes);
45
+ const themeCounts = countItems(allThemes);
46
+ const dominantThemes = Object.entries(themeCounts)
47
+ .sort(([, a], [, b]) => b - a)
48
+ .slice(0, 3)
49
+ .map(([t]) => t);
50
+ const tones = enriched.map(m => m.emotional_tone);
51
+ const trajectory = emotionalTrajectory(tones.reverse()); // oldest first
52
+ const timeSpan = calcTimeSpanDays(results);
53
+ const suggestions = [];
54
+ if (filtered.length > limit) {
55
+ suggestions.push(`${filtered.length - limit} more results available — increase 'limit' or narrow filters`);
56
+ }
57
+ if (dominantThemes[0]) {
58
+ suggestions.push(`Try 'context' with target_type='theme' for '${dominantThemes[0]}'`);
59
+ }
60
+ return ok({
61
+ memories: enriched,
62
+ summary: {
63
+ total_found: memories.length,
64
+ returned: results.length,
65
+ time_span_days: timeSpan,
66
+ dominant_themes: dominantThemes,
67
+ emotional_trajectory: trajectory,
68
+ },
69
+ }, sessionId, start, suggestions);
70
+ }
71
+ catch (err) {
72
+ return fail('RECALL_FAILED', String(err), sessionId, start);
73
+ }
74
+ }
75
+ function enrichMemory(m, query) {
76
+ const entities = extractEntities(m.content).slice(0, 5);
77
+ const themes = themeNames(m.content, 3);
78
+ const emotion = scoreEmotion(m.content);
79
+ return {
80
+ id: m.id,
81
+ content: m.content,
82
+ relevance_score: m.similarity ?? 0,
83
+ retrieval_method: m.similarity && m.similarity > 0 ? 'hybrid' : 'fts',
84
+ timestamp: m.timestamp.toISOString(),
85
+ session_id: m.sessionId,
86
+ role: m.role,
87
+ tier: m.tier,
88
+ importance: m.importance,
89
+ entities: entities.map(e => ({ name: e.name, type: e.type, confidence: e.confidence })),
90
+ themes,
91
+ emotional_tone: emotion.tone,
92
+ };
93
+ }
94
+ function countItems(items) {
95
+ const counts = {};
96
+ for (const item of items) {
97
+ counts[item] = (counts[item] ?? 0) + 1;
98
+ }
99
+ return counts;
100
+ }
101
+ function calcTimeSpanDays(memories) {
102
+ if (memories.length < 2)
103
+ return 0;
104
+ const times = memories.map(m => m.timestamp.getTime());
105
+ const min = Math.min(...times);
106
+ const max = Math.max(...times);
107
+ return Math.round((max - min) / (1000 * 60 * 60 * 24));
108
+ }
109
+ export const RECALL_SCHEMA = {
110
+ name: 'recall',
111
+ description: 'Retrieve relevant memories with entity, theme, and emotional context. Returns 360° relational intelligence around the query.',
112
+ inputSchema: {
113
+ type: 'object',
114
+ properties: {
115
+ query: { type: 'string', description: 'What to search for' },
116
+ session_id: { type: 'string' },
117
+ limit: { type: 'number', default: 5, description: 'Max results (default: 5, max: 50)' },
118
+ min_relevance: { type: 'number', default: 0.7, description: 'Minimum relevance score 0-1' },
119
+ include_context: { type: 'boolean', default: true },
120
+ time_range: {
121
+ type: 'object',
122
+ properties: {
123
+ start: { type: 'string', description: 'ISO8601 start date' },
124
+ end: { type: 'string', description: 'ISO8601 end date' },
125
+ },
126
+ },
127
+ entity_filter: { type: 'array', items: { type: 'string' }, description: 'Only return memories mentioning these entities' },
128
+ theme_filter: { type: 'array', items: { type: 'string' }, description: 'Only return memories matching these themes' },
129
+ tiers: { type: 'array', items: { type: 'string' }, description: 'Memory tiers to search: working, long_term, archived' },
130
+ },
131
+ required: ['query'],
132
+ },
133
+ };
134
+ //# sourceMappingURL=recall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recall.js","sourceRoot":"","sources":["../../src/tools/recall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { Engram } from '@cartisien/engram';
2
+ export interface RememberInput {
3
+ content: string;
4
+ role?: string;
5
+ session_id?: string;
6
+ timestamp?: string;
7
+ metadata?: Record<string, unknown>;
8
+ extract_entities?: boolean;
9
+ link_to_session?: boolean;
10
+ }
11
+ export declare function toolRemember(engram: Engram, input: RememberInput): Promise<import("../response.js").McpResponse<unknown>>;
12
+ export declare const REMEMBER_SCHEMA: {
13
+ readonly name: "remember";
14
+ readonly description: "Store a new memory with automatic entity extraction, theme detection, and relationship mapping.";
15
+ readonly inputSchema: {
16
+ readonly type: "object";
17
+ readonly properties: {
18
+ readonly content: {
19
+ readonly type: "string";
20
+ readonly description: "The memory text to store";
21
+ };
22
+ readonly role: {
23
+ readonly type: "string";
24
+ readonly enum: readonly ["user", "assistant", "system"];
25
+ readonly default: "user";
26
+ };
27
+ readonly session_id: {
28
+ readonly type: "string";
29
+ readonly description: "Session identifier (defaults to ENGRAM_SESSION_ID)";
30
+ };
31
+ readonly timestamp: {
32
+ readonly type: "string";
33
+ readonly description: "ISO8601 timestamp (defaults to now)";
34
+ };
35
+ readonly metadata: {
36
+ readonly type: "object";
37
+ readonly description: "Arbitrary key-value metadata";
38
+ };
39
+ readonly extract_entities: {
40
+ readonly type: "boolean";
41
+ readonly default: true;
42
+ readonly description: "Auto-extract entities and store in graph";
43
+ };
44
+ };
45
+ readonly required: readonly ["content"];
46
+ };
47
+ };
@@ -0,0 +1,79 @@
1
+ import { extractEntities, entityRelation } from '../analysis/entities.js';
2
+ import { themeNames } from '../analysis/themes.js';
3
+ import { scoreEmotion } from '../analysis/emotions.js';
4
+ import { ok, fail } from '../response.js';
5
+ import { defaultSession } from '../client.js';
6
+ export async function toolRemember(engram, input) {
7
+ const start = Date.now();
8
+ const sessionId = input.session_id ?? defaultSession();
9
+ if (!input.content?.trim()) {
10
+ return fail('INVALID_INPUT', 'content is required', sessionId, start);
11
+ }
12
+ const role = (input.role ?? 'user');
13
+ const extractEntitiesFlag = input.extract_entities !== false;
14
+ const meta = { ...(input.metadata ?? {}) };
15
+ if (input.timestamp)
16
+ meta.original_timestamp = input.timestamp;
17
+ try {
18
+ const entry = await engram.remember(sessionId, input.content, role, meta);
19
+ // Entity extraction + graph storage
20
+ let extractedEntities = [];
21
+ if (extractEntitiesFlag) {
22
+ extractedEntities = extractEntities(input.content);
23
+ // Store additional semantic edges beyond what Engram's extractGraph does
24
+ const memoryEntity = `memory:${entry.id}`;
25
+ for (const entity of extractedEntities) {
26
+ const relation = entityRelation(entity.type);
27
+ await engram.storeEdge(sessionId, memoryEntity, relation, entity.name.toLowerCase(), entity.confidence, entry.id);
28
+ // Entity-to-entity: link co-occurring entities
29
+ for (const other of extractedEntities) {
30
+ if (other.name !== entity.name) {
31
+ await engram.storeEdge(sessionId, entity.name.toLowerCase(), 'co_occurs_with', other.name.toLowerCase(), 0.6, entry.id);
32
+ }
33
+ }
34
+ }
35
+ }
36
+ // Theme + emotion analysis
37
+ const themes = themeNames(input.content);
38
+ const emotion = scoreEmotion(input.content);
39
+ // Find linked memories (recent from same session)
40
+ const linked = await engram.recall(sessionId, input.content, { limit: 3, threshold: 0.75 });
41
+ const linkedIds = linked
42
+ .filter(m => m.id !== entry.id)
43
+ .map(m => m.id)
44
+ .slice(0, 3);
45
+ const suggestions = [];
46
+ if (themes.length > 0)
47
+ suggestions.push(`Try 'recall' with theme_filter: [\"${themes[0]}\"]`);
48
+ if (extractedEntities.length > 0)
49
+ suggestions.push(`Try 'context' for entity \"${extractedEntities[0].name}\"`);
50
+ return ok({
51
+ memory_id: entry.id,
52
+ extracted_entities: extractedEntities.slice(0, 10),
53
+ linked_memories: linkedIds,
54
+ themes_detected: themes,
55
+ emotional_tone: emotion.tone,
56
+ tier: entry.tier,
57
+ }, sessionId, start, suggestions);
58
+ }
59
+ catch (err) {
60
+ return fail('STORE_FAILED', String(err), sessionId, start);
61
+ }
62
+ }
63
+ export const REMEMBER_SCHEMA = {
64
+ name: 'remember',
65
+ description: 'Store a new memory with automatic entity extraction, theme detection, and relationship mapping.',
66
+ inputSchema: {
67
+ type: 'object',
68
+ properties: {
69
+ content: { type: 'string', description: 'The memory text to store' },
70
+ role: { type: 'string', enum: ['user', 'assistant', 'system'], default: 'user' },
71
+ session_id: { type: 'string', description: 'Session identifier (defaults to ENGRAM_SESSION_ID)' },
72
+ timestamp: { type: 'string', description: 'ISO8601 timestamp (defaults to now)' },
73
+ metadata: { type: 'object', description: 'Arbitrary key-value metadata' },
74
+ extract_entities: { type: 'boolean', default: true, description: 'Auto-extract entities and store in graph' },
75
+ },
76
+ required: ['content'],
77
+ },
78
+ };
79
+ //# sourceMappingURL=remember.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remember.js","sourceRoot":"","sources":["../../src/tools/remember.ts"],"names":[],"mappings":"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"}