true-mem 1.0.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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +217 -0
  3. package/dist/adapters/opencode/index.d.ts +11 -0
  4. package/dist/adapters/opencode/index.d.ts.map +1 -0
  5. package/dist/adapters/opencode/index.js +676 -0
  6. package/dist/adapters/opencode/index.js.map +1 -0
  7. package/dist/adapters/opencode/injection.d.ts +52 -0
  8. package/dist/adapters/opencode/injection.d.ts.map +1 -0
  9. package/dist/adapters/opencode/injection.js +93 -0
  10. package/dist/adapters/opencode/injection.js.map +1 -0
  11. package/dist/config.d.ts +9 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +61 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/extraction/queue.d.ts +35 -0
  16. package/dist/extraction/queue.d.ts.map +1 -0
  17. package/dist/extraction/queue.js +75 -0
  18. package/dist/extraction/queue.js.map +1 -0
  19. package/dist/index.d.ts +14 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +2900 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/logger.d.ts +6 -0
  24. package/dist/logger.d.ts.map +1 -0
  25. package/dist/logger.js +30 -0
  26. package/dist/logger.js.map +1 -0
  27. package/dist/memory/classifier.d.ts +78 -0
  28. package/dist/memory/classifier.d.ts.map +1 -0
  29. package/dist/memory/classifier.js +363 -0
  30. package/dist/memory/classifier.js.map +1 -0
  31. package/dist/memory/embeddings.d.ts +41 -0
  32. package/dist/memory/embeddings.d.ts.map +1 -0
  33. package/dist/memory/embeddings.js +98 -0
  34. package/dist/memory/embeddings.js.map +1 -0
  35. package/dist/memory/negative-patterns.d.ts +32 -0
  36. package/dist/memory/negative-patterns.d.ts.map +1 -0
  37. package/dist/memory/negative-patterns.js +71 -0
  38. package/dist/memory/negative-patterns.js.map +1 -0
  39. package/dist/memory/patterns.d.ts +110 -0
  40. package/dist/memory/patterns.d.ts.map +1 -0
  41. package/dist/memory/patterns.js +623 -0
  42. package/dist/memory/patterns.js.map +1 -0
  43. package/dist/memory/reconsolidate.d.ts +57 -0
  44. package/dist/memory/reconsolidate.d.ts.map +1 -0
  45. package/dist/memory/reconsolidate.js +96 -0
  46. package/dist/memory/reconsolidate.js.map +1 -0
  47. package/dist/memory/role-patterns.d.ts +50 -0
  48. package/dist/memory/role-patterns.d.ts.map +1 -0
  49. package/dist/memory/role-patterns.js +188 -0
  50. package/dist/memory/role-patterns.js.map +1 -0
  51. package/dist/shutdown.d.ts +31 -0
  52. package/dist/shutdown.d.ts.map +1 -0
  53. package/dist/shutdown.js +120 -0
  54. package/dist/shutdown.js.map +1 -0
  55. package/dist/storage/database.d.ts +77 -0
  56. package/dist/storage/database.d.ts.map +1 -0
  57. package/dist/storage/database.js +590 -0
  58. package/dist/storage/database.js.map +1 -0
  59. package/dist/storage/sqlite-adapter.d.ts +35 -0
  60. package/dist/storage/sqlite-adapter.d.ts.map +1 -0
  61. package/dist/storage/sqlite-adapter.js +99 -0
  62. package/dist/storage/sqlite-adapter.js.map +1 -0
  63. package/dist/types.d.ts +266 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/dist/types.js +63 -0
  66. package/dist/types.js.map +1 -0
  67. package/package.json +54 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * True-Mem Logger
3
+ * File-based logging to avoid SDK crashes
4
+ */
5
+ export declare function log(message: string, data?: unknown): void;
6
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAiBzD"}
package/dist/logger.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * True-Memory Logger
3
+ * File-based logging to avoid SDK crashes
4
+ */
5
+ import { appendFileSync, existsSync, mkdirSync, statSync, renameSync } from 'fs';
6
+ import { homedir } from 'os';
7
+ import { join } from 'path';
8
+ const LOG_DIR = join(homedir(), '.true-memory');
9
+ const LOG_FILE = join(LOG_DIR, 'plugin-debug.log');
10
+ const LOG_MAX_BYTES = 10 * 1024 * 1024; // 10 MB
11
+ export function log(message, data) {
12
+ try {
13
+ if (!existsSync(LOG_DIR))
14
+ mkdirSync(LOG_DIR, { recursive: true });
15
+ // Rotate if log exceeds 10 MB
16
+ try {
17
+ if (existsSync(LOG_FILE) && statSync(LOG_FILE).size >= LOG_MAX_BYTES) {
18
+ renameSync(LOG_FILE, join(LOG_DIR, 'plugin-debug.log.1'));
19
+ }
20
+ }
21
+ catch { /* ignore */ }
22
+ const timestamp = new Date().toISOString();
23
+ const entry = `[${timestamp}] ${message}${data ? ' ' + JSON.stringify(data) : ''}\n`;
24
+ appendFileSync(LOG_FILE, entry);
25
+ }
26
+ catch {
27
+ // Silently ignore logging errors
28
+ }
29
+ }
30
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;AACnD,MAAM,aAAa,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,QAAQ;AAEhD,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,IAAc;IACjD,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAElE,8BAA8B;QAC9B,IAAI,CAAC;YACH,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,IAAI,aAAa,EAAE,CAAC;gBACrE,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAExB,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,IAAI,SAAS,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QACrF,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,iCAAiC;IACnC,CAAC;AACH,CAAC"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Memory Classifier with Three-Layer Defense + Role Awareness
3
+ *
4
+ * Layer 1: Negative Patterns (filter out known false positives)
5
+ * Layer 2: Multi-Keyword Scoring (require 2+ signals)
6
+ * Layer 3: Confidence Threshold (store only if score >= 0.6)
7
+ * Layer 4: Role Validation (Human-only for preferences, constraints, decisions, learnings)
8
+ */
9
+ import type { MessageRole, RoleAwareContext } from '../types.js';
10
+ export declare const CONFIDENCE_THRESHOLD = 0.6;
11
+ /**
12
+ * Calculate classification score based on keyword presence
13
+ * Returns 0-1 score where higher is more confident
14
+ */
15
+ export declare function calculateClassificationScore(text: string, classification: string): number;
16
+ /**
17
+ * Three-layer defense: decide if memory should be stored
18
+ *
19
+ * SPECIAL CASE: When classification is 'semantic' (assigned by explicit intent fallback),
20
+ * bypass keyword checking - the user explicitly asked to remember this.
21
+ */
22
+ export declare function shouldStoreMemory(text: string, classification: string, baseSignalScore: number): {
23
+ store: boolean;
24
+ confidence: number;
25
+ reason: string;
26
+ };
27
+ /**
28
+ * Infer classification from text content
29
+ * Returns the most likely classification or null
30
+ */
31
+ export declare function inferClassification(text: string): string | null;
32
+ /**
33
+ * Classify content with explicit intent detection.
34
+ * If explicit_remember signal is present, isolate the sentence and classify it.
35
+ */
36
+ export declare function classifyWithExplicitIntent(text: string, signals: any[]): {
37
+ classification: string | null;
38
+ confidence: number;
39
+ isolatedContent: string;
40
+ };
41
+ /**
42
+ * Validate if a memory should be stored based on role rules
43
+ *
44
+ * Returns:
45
+ * - store: whether to store the memory
46
+ * - reason: human-readable reason for decision
47
+ */
48
+ export declare function shouldStoreMemoryWithRole(text: string, classification: string, primaryRole: MessageRole): {
49
+ store: boolean;
50
+ reason: string;
51
+ };
52
+ /**
53
+ * Classify content with role-aware context
54
+ *
55
+ * Takes into account:
56
+ * - Primary role of the message (Human vs Assistant)
57
+ * - Human intent signals (10x weight for Human messages)
58
+ * - Role validation rules (user-level classifications must be from Human)
59
+ *
60
+ * Returns:
61
+ * - classification: the inferred classification
62
+ * - confidence: 0-1 score
63
+ * - isolatedContent: the extracted content
64
+ * - roleValidated: whether the role validation passed
65
+ */
66
+ export declare function classifyWithRoleAwareness(text: string, signals: any[], roleAwareContext: RoleAwareContext | null): {
67
+ classification: string | null;
68
+ confidence: number;
69
+ isolatedContent: string;
70
+ roleValidated: boolean;
71
+ validationReason: string;
72
+ };
73
+ /**
74
+ * Calculate role-weighted score for signals
75
+ * Human messages get 10x weight for their signals
76
+ */
77
+ export declare function calculateRoleWeightedScore(baseSignalScore: number, primaryRole: MessageRole, text: string): number;
78
+ //# sourceMappingURL=classifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifier.d.ts","sourceRoot":"","sources":["../../src/memory/classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoCjE,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAsBzF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,GACtB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAiDxD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc/D;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,GAAG,EAAE,GACb;IAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CA4FhF;AAMD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,WAAW,GACvB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CA8CpC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,GAAG,EAAE,EACd,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,GACxC;IACD,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAsEA;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,eAAe,EAAE,MAAM,EACvB,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,MAAM,GACX,MAAM,CAWR"}
@@ -0,0 +1,363 @@
1
+ /**
2
+ * Memory Classifier with Three-Layer Defense + Role Awareness
3
+ *
4
+ * Layer 1: Negative Patterns (filter out known false positives)
5
+ * Layer 2: Multi-Keyword Scoring (require 2+ signals)
6
+ * Layer 3: Confidence Threshold (store only if score >= 0.6)
7
+ * Layer 4: Role Validation (Human-only for preferences, constraints, decisions, learnings)
8
+ */
9
+ import { matchesNegativePattern } from './negative-patterns.js';
10
+ import { log } from '../logger.js';
11
+ import { HUMAN_MESSAGE_WEIGHT_MULTIPLIER } from '../types.js';
12
+ import { scoreHumanIntent, hasAssistantListPattern, } from './role-patterns.js';
13
+ // Classification keywords for multi-keyword scoring
14
+ const CLASSIFICATION_KEYWORDS = {
15
+ bugfix: {
16
+ primary: ['error', 'bug', 'crash', 'exception', 'fail', 'broken', 'issue', 'problem', 'errore', 'guasto', 'fallimento'],
17
+ boosters: ['fixed', 'resolved', 'patched', 'solved', 'corrected', 'repaired', 'debugged', 'risolto', 'corretto', 'sistemato', 'patchato'],
18
+ },
19
+ decision: {
20
+ primary: ['decided', 'chose', 'selected', 'picked', 'opted', 'went with', 'deciso', 'scelto', 'selezionato'],
21
+ boosters: ['because', 'since', 'reason', 'rationale', 'due to', 'as', 'perché', 'poiché', 'motivo', 'ragione'],
22
+ },
23
+ learning: {
24
+ primary: ['learned', 'discovered', 'found out', 'realized', 'figured out', 'imparato', 'scoperto', 'capito'],
25
+ boosters: ['today', 'just', 'finally', 'interesting', 'surprising', 'oggi', 'appena'],
26
+ },
27
+ constraint: {
28
+ primary: ["can't", 'cannot', 'must not', 'never', 'forbidden', 'prohibited', 'not allowed', 'non posso', 'vietato', 'proibito', 'obbligatorio'],
29
+ boosters: ['always', 'require', 'mandatory', 'enforce', 'strict', 'mai', 'necessario'],
30
+ },
31
+ preference: {
32
+ primary: ['prefer', 'like', 'want', 'favor', 'rather', 'preferisco', 'mi piace', 'voglio', 'prediligo'],
33
+ boosters: ['better', 'best', 'instead', 'over', 'more than', 'meglio', 'ottimo', 'invece', 'rispetto a', 'sempre'],
34
+ },
35
+ procedural: {
36
+ primary: ['step', 'workflow', 'process', 'procedure', 'instructions', 'guide'],
37
+ boosters: ['first', 'then', 'next', 'finally', 'after', 'before'],
38
+ },
39
+ };
40
+ // Confidence threshold for storing memories
41
+ export const CONFIDENCE_THRESHOLD = 0.6;
42
+ /**
43
+ * Calculate classification score based on keyword presence
44
+ * Returns 0-1 score where higher is more confident
45
+ */
46
+ export function calculateClassificationScore(text, classification) {
47
+ const keywords = CLASSIFICATION_KEYWORDS[classification];
48
+ if (!keywords)
49
+ return 0;
50
+ const textLower = text.toLowerCase();
51
+ const { primary, boosters } = keywords;
52
+ const primaryMatches = primary.filter(k => textLower.includes(k.toLowerCase())).length;
53
+ const boosterMatches = boosters.filter(k => textLower.includes(k.toLowerCase())).length;
54
+ // No primary keywords = not this classification
55
+ if (primaryMatches === 0)
56
+ return 0;
57
+ // Single primary, no boosters = low confidence (likely false positive)
58
+ if (primaryMatches === 1 && boosterMatches === 0)
59
+ return 0.4;
60
+ // Calculate score
61
+ // More primaries and boosters = higher confidence
62
+ const primaryScore = Math.min(0.5, primaryMatches * 0.2);
63
+ const boosterScore = Math.min(0.3, boosterMatches * 0.15);
64
+ return Math.min(1, 0.3 + primaryScore + boosterScore);
65
+ }
66
+ /**
67
+ * Three-layer defense: decide if memory should be stored
68
+ *
69
+ * SPECIAL CASE: When classification is 'semantic' (assigned by explicit intent fallback),
70
+ * bypass keyword checking - the user explicitly asked to remember this.
71
+ */
72
+ export function shouldStoreMemory(text, classification, baseSignalScore) {
73
+ // Layer 1: Check negative patterns
74
+ if (matchesNegativePattern(text, classification)) {
75
+ return {
76
+ store: false,
77
+ confidence: 0,
78
+ reason: 'matches_negative_pattern',
79
+ };
80
+ }
81
+ // SPECIAL CASE: semantic classification from explicit intent
82
+ // Bypass keyword checking - user explicitly said "Ricordati che..."
83
+ if (classification === 'semantic') {
84
+ // Use high confidence for explicit intent memories
85
+ return {
86
+ store: true,
87
+ confidence: 0.85,
88
+ reason: 'explicit_intent_semantic',
89
+ };
90
+ }
91
+ // Layer 2: Calculate multi-keyword score
92
+ const keywordScore = calculateClassificationScore(text, classification);
93
+ // No keywords found for this classification
94
+ if (keywordScore === 0) {
95
+ return {
96
+ store: false,
97
+ confidence: 0,
98
+ reason: 'no_classification_keywords',
99
+ };
100
+ }
101
+ // Layer 3: Combined score must exceed threshold
102
+ const finalScore = (baseSignalScore + keywordScore) / 2;
103
+ if (finalScore < CONFIDENCE_THRESHOLD) {
104
+ return {
105
+ store: false,
106
+ confidence: finalScore,
107
+ reason: 'below_confidence_threshold',
108
+ };
109
+ }
110
+ return {
111
+ store: true,
112
+ confidence: finalScore,
113
+ reason: 'passed_all_layers',
114
+ };
115
+ }
116
+ /**
117
+ * Infer classification from text content
118
+ * Returns the most likely classification or null
119
+ */
120
+ export function inferClassification(text) {
121
+ const textLower = text.toLowerCase();
122
+ let bestClassification = null;
123
+ let bestScore = 0;
124
+ for (const [classification, keywords] of Object.entries(CLASSIFICATION_KEYWORDS)) {
125
+ const score = calculateClassificationScore(text, classification);
126
+ if (score > bestScore) {
127
+ bestScore = score;
128
+ bestClassification = classification;
129
+ }
130
+ }
131
+ return bestScore >= 0.4 ? bestClassification : null;
132
+ }
133
+ /**
134
+ * Classify content with explicit intent detection.
135
+ * If explicit_remember signal is present, isolate the sentence and classify it.
136
+ */
137
+ export function classifyWithExplicitIntent(text, signals) {
138
+ // Check if explicit_remember signal is present
139
+ const hasExplicitRemember = signals.some(s => s.type === 'explicit_remember');
140
+ if (hasExplicitRemember) {
141
+ log('Debug: Explicit intent signal found, isolating sentence...');
142
+ }
143
+ if (!hasExplicitRemember) {
144
+ // Fall back to normal classification
145
+ const classification = inferClassification(text);
146
+ const confidence = classification ? calculateClassificationScore(text, classification) : 0;
147
+ return { classification, confidence, isolatedContent: text };
148
+ }
149
+ // Extract explicit remember marker patterns with word boundaries and optional colon/whitespace
150
+ const markerPatterns = [
151
+ /\bricorda questo\b:?\s*/gi,
152
+ /\bremember this\b:?\s*/gi,
153
+ /\bricordati che\b:?\s*/gi,
154
+ /\bricorda che\b:?\s*/gi,
155
+ /\bmemorizza questo\b:?\s*/gi,
156
+ /\bmemorizza che\b:?\s*/gi,
157
+ /\bmemorizziamo\b:?\s*/gi,
158
+ /\bricordiamoci che\b:?\s*/gi,
159
+ /\bricordiamoci di\b:?\s*/gi,
160
+ /\bricorda\b:?\s*/gi,
161
+ /\bremember\b:?\s*/gi,
162
+ /\btieni a mente\b:?\s*/gi,
163
+ /\bkeep in mind\b:?\s*/gi,
164
+ /\bnota che\b:?\s*/gi,
165
+ /\bnote that\b:?\s*/gi,
166
+ ];
167
+ // Find the LAST sentence containing the explicit marker
168
+ const sentences = text.match(/[^.!?]*[.!?]/g) || [];
169
+ let lastMatchingSentence = '';
170
+ let isolatedContent = '';
171
+ for (const sentence of sentences) {
172
+ const trimmed = sentence.trim();
173
+ // Check each pattern with lastIndex reset for regex safety
174
+ for (const pattern of markerPatterns) {
175
+ pattern.lastIndex = 0; // Reset regex lastIndex before testing
176
+ if (pattern.test(trimmed)) {
177
+ lastMatchingSentence = trimmed;
178
+ // Extract content AFTER the marker
179
+ pattern.lastIndex = 0; // Reset again for exec
180
+ const match = pattern.exec(trimmed);
181
+ if (match && match.index !== undefined) {
182
+ isolatedContent = trimmed.substring(match.index + match[0].length).trim();
183
+ }
184
+ break; // Move to next sentence after finding match
185
+ }
186
+ }
187
+ }
188
+ // If no content isolated, fall back to normal classification
189
+ if (!isolatedContent) {
190
+ log('Debug: No content isolated, falling back to normal classification');
191
+ const classification = inferClassification(text);
192
+ const confidence = classification ? calculateClassificationScore(text, classification) : 0;
193
+ return { classification, confidence, isolatedContent: text };
194
+ }
195
+ log('Debug: Isolated content for classification:', isolatedContent);
196
+ // Score ONLY the isolated content for all classifications
197
+ let bestClassification = null;
198
+ let bestScore = 0;
199
+ for (const [classification] of Object.entries(CLASSIFICATION_KEYWORDS)) {
200
+ const score = calculateClassificationScore(isolatedContent, classification);
201
+ if (score > bestScore) {
202
+ bestScore = score;
203
+ bestClassification = classification;
204
+ }
205
+ }
206
+ // If classification found with score >= 0.4, return with boosted confidence (min 0.85)
207
+ if (bestScore >= 0.4 && bestClassification) {
208
+ const boostedConfidence = Math.max(0.85, bestScore);
209
+ log(`Debug: Explicit intent classification: ${bestClassification}, score: ${bestScore}, boosted: ${boostedConfidence}`);
210
+ return { classification: bestClassification, confidence: boostedConfidence, isolatedContent };
211
+ }
212
+ // If explicit intent detected but no specific classification found,
213
+ // assign semantic classification with high confidence (0.85)
214
+ // This ensures "Ricordati che [fatto generico]" is always stored
215
+ log('Debug: No specific classification found for explicit intent, assigning semantic classification');
216
+ return {
217
+ classification: 'semantic',
218
+ confidence: 0.85,
219
+ isolatedContent
220
+ };
221
+ }
222
+ // =============================================================================
223
+ // Role-Aware Classification
224
+ // =============================================================================
225
+ /**
226
+ * Validate if a memory should be stored based on role rules
227
+ *
228
+ * Returns:
229
+ * - store: whether to store the memory
230
+ * - reason: human-readable reason for decision
231
+ */
232
+ export function shouldStoreMemoryWithRole(text, classification, primaryRole) {
233
+ // Check if this classification has role validation rules
234
+ const validationRules = {
235
+ constraint: { validRoles: ['user'], requiresPrimary: true },
236
+ preference: { validRoles: ['user'], requiresPrimary: true },
237
+ learning: { validRoles: ['user'], requiresPrimary: true },
238
+ procedural: { validRoles: ['user'], requiresPrimary: true },
239
+ decision: { validRoles: ['user', 'assistant'], requiresPrimary: false },
240
+ bugfix: { validRoles: ['user', 'assistant'], requiresPrimary: false },
241
+ semantic: { validRoles: ['user', 'assistant'], requiresPrimary: false },
242
+ episodic: { validRoles: ['user', 'assistant'], requiresPrimary: false },
243
+ };
244
+ const rule = validationRules[classification];
245
+ // If no rule, allow storage (backward compatibility)
246
+ if (!rule) {
247
+ return { store: true, reason: 'no_role_validation_rule' };
248
+ }
249
+ // Check if primary role is valid
250
+ if (!rule.validRoles.includes(primaryRole)) {
251
+ return {
252
+ store: false,
253
+ reason: `invalid_role_${primaryRole}_for_${classification}`,
254
+ };
255
+ }
256
+ // Check if requires primary Human source
257
+ if (rule.requiresPrimary && primaryRole !== 'user') {
258
+ return {
259
+ store: false,
260
+ reason: `classification_${classification}_requires_human_primary`,
261
+ };
262
+ }
263
+ // Additional check: down-weight Assistant-generated list patterns for user-level classifications
264
+ if (rule.requiresPrimary && hasAssistantListPattern(text)) {
265
+ log('Debug: Detected Assistant list pattern, filtering out as potential false positive');
266
+ return {
267
+ store: false,
268
+ reason: 'assistant_list_pattern_detected',
269
+ };
270
+ }
271
+ return { store: true, reason: 'role_validation_passed' };
272
+ }
273
+ /**
274
+ * Classify content with role-aware context
275
+ *
276
+ * Takes into account:
277
+ * - Primary role of the message (Human vs Assistant)
278
+ * - Human intent signals (10x weight for Human messages)
279
+ * - Role validation rules (user-level classifications must be from Human)
280
+ *
281
+ * Returns:
282
+ * - classification: the inferred classification
283
+ * - confidence: 0-1 score
284
+ * - isolatedContent: the extracted content
285
+ * - roleValidated: whether the role validation passed
286
+ */
287
+ export function classifyWithRoleAwareness(text, signals, roleAwareContext) {
288
+ // First, do the standard classification with explicit intent detection
289
+ const baseResult = classifyWithExplicitIntent(text, signals);
290
+ const { classification, confidence, isolatedContent } = baseResult;
291
+ // If no classification found, return early
292
+ if (!classification) {
293
+ return {
294
+ classification: null,
295
+ confidence: 0,
296
+ isolatedContent: text,
297
+ roleValidated: true,
298
+ validationReason: 'no_classification_found',
299
+ };
300
+ }
301
+ // If no role-aware context provided, allow storage (backward compatibility)
302
+ if (!roleAwareContext) {
303
+ log('Debug: No role-aware context, skipping role validation');
304
+ return {
305
+ classification,
306
+ confidence,
307
+ isolatedContent,
308
+ roleValidated: true,
309
+ validationReason: 'no_role_context',
310
+ };
311
+ }
312
+ // Apply role validation
313
+ const roleValidation = shouldStoreMemoryWithRole(isolatedContent, classification, roleAwareContext.primaryRole);
314
+ if (!roleValidation.store) {
315
+ log(`Debug: Role validation failed: ${roleValidation.reason} for ${classification}`);
316
+ return {
317
+ classification,
318
+ confidence,
319
+ isolatedContent,
320
+ roleValidated: false,
321
+ validationReason: roleValidation.reason,
322
+ };
323
+ }
324
+ // Boost confidence for Human messages with high intent scores
325
+ if (roleAwareContext.primaryRole === 'user') {
326
+ const humanIntentScore = scoreHumanIntent(isolatedContent);
327
+ if (humanIntentScore > 0.6) {
328
+ // Apply 10x weight multiplier for Human messages with clear intent
329
+ const boostedConfidence = Math.min(1, confidence * HUMAN_MESSAGE_WEIGHT_MULTIPLIER);
330
+ log(`Debug: Applied Human weight multiplier: ${confidence.toFixed(2)} -> ${boostedConfidence.toFixed(2)}`);
331
+ return {
332
+ classification,
333
+ confidence: boostedConfidence,
334
+ isolatedContent,
335
+ roleValidated: true,
336
+ validationReason: 'human_intent_boosted',
337
+ };
338
+ }
339
+ }
340
+ return {
341
+ classification,
342
+ confidence,
343
+ isolatedContent,
344
+ roleValidated: true,
345
+ validationReason: 'standard_role_aware',
346
+ };
347
+ }
348
+ /**
349
+ * Calculate role-weighted score for signals
350
+ * Human messages get 10x weight for their signals
351
+ */
352
+ export function calculateRoleWeightedScore(baseSignalScore, primaryRole, text) {
353
+ if (primaryRole === 'user') {
354
+ // Apply 10x weight for Human messages
355
+ // Also consider human intent patterns
356
+ const humanIntentScore = scoreHumanIntent(text);
357
+ const intentMultiplier = 1 + (humanIntentScore * 2); // Up to 3x based on intent strength
358
+ return Math.min(1, baseSignalScore * HUMAN_MESSAGE_WEIGHT_MULTIPLIER * intentMultiplier);
359
+ }
360
+ // Assistant messages get normal weight (can be boosted by acknowledgment patterns)
361
+ return baseSignalScore;
362
+ }
363
+ //# sourceMappingURL=classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifier.js","sourceRoot":"","sources":["../../src/memory/classifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * True-Mem Embeddings (Stub - Jaccard Similarity)
3
+ * Replaced Transformers.js with Jaccard similarity (word overlap)
4
+ */
5
+ /**
6
+ * Calculate Jaccard similarity between two texts
7
+ * Jaccard = |intersection| / |union|
8
+ *
9
+ * @param text1 - First text
10
+ * @param text2 - Second text
11
+ * @returns number - Jaccard similarity (0 to 1)
12
+ */
13
+ export declare function jaccardSimilarity(text1: string, text2: string): number;
14
+ /**
15
+ * Stub: Generate embedding (not used - returns empty array)
16
+ * @deprecated Use jaccardSimilarity instead
17
+ */
18
+ export declare function embed(text: string): Promise<Float32Array>;
19
+ /**
20
+ * Stub: Dispose function (no-op)
21
+ * @deprecated No resources to clean up
22
+ */
23
+ export declare function disposeEmbeddings(): void;
24
+ /**
25
+ * Stub: Get embedding pipeline (not used)
26
+ * @deprecated Use jaccardSimilarity instead
27
+ */
28
+ export declare function getEmbeddingPipeline(): any;
29
+ /**
30
+ * @deprecated Use jaccardSimilarity instead
31
+ */
32
+ export declare function vectorToBuffer(vector: Float32Array): Buffer;
33
+ /**
34
+ * @deprecated Use jaccardSimilarity instead
35
+ */
36
+ export declare function bufferToVector(buffer: Buffer): Float32Array;
37
+ /**
38
+ * @deprecated Use jaccardSimilarity instead
39
+ */
40
+ export declare function cosineSimilarity(a: Float32Array, b: Float32Array): number;
41
+ //# sourceMappingURL=embeddings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../src/memory/embeddings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAsCtE;AAED;;;GAGG;AACH,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAG/D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,GAAG,CAG1C;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAG3D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAG3D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAGzE"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * True-Memory Embeddings (Stub - Jaccard Similarity)
3
+ * Replaced Transformers.js with Jaccard similarity (word overlap)
4
+ */
5
+ import { log } from '../logger.js';
6
+ // =============================================================================
7
+ // Stub Functions (No Vector Embeddings)
8
+ // =============================================================================
9
+ /**
10
+ * Calculate Jaccard similarity between two texts
11
+ * Jaccard = |intersection| / |union|
12
+ *
13
+ * @param text1 - First text
14
+ * @param text2 - Second text
15
+ * @returns number - Jaccard similarity (0 to 1)
16
+ */
17
+ export function jaccardSimilarity(text1, text2) {
18
+ try {
19
+ // Tokenize into lowercase words (remove punctuation)
20
+ const tokenize = (text) => {
21
+ const words = text
22
+ .toLowerCase()
23
+ .replace(/[^\w\s]/g, '')
24
+ .split(/\s+/)
25
+ .filter(w => w.length > 0);
26
+ return new Set(words);
27
+ };
28
+ const set1 = tokenize(text1);
29
+ const set2 = tokenize(text2);
30
+ if (set1.size === 0 || set2.size === 0) {
31
+ return 0;
32
+ }
33
+ // Calculate intersection and union
34
+ const intersection = new Set([...set1].filter(x => set2.has(x)));
35
+ const union = new Set([...set1, ...set2]);
36
+ const similarity = intersection.size / union.size;
37
+ log('Jaccard similarity calculated', {
38
+ similarity: similarity.toFixed(4),
39
+ text1Words: set1.size,
40
+ text2Words: set2.size,
41
+ intersectionWords: intersection.size,
42
+ });
43
+ return similarity;
44
+ }
45
+ catch (error) {
46
+ const errorMessage = error instanceof Error ? error.message : String(error);
47
+ log('Jaccard similarity calculation failed', { error: errorMessage });
48
+ return 0;
49
+ }
50
+ }
51
+ /**
52
+ * Stub: Generate embedding (not used - returns empty array)
53
+ * @deprecated Use jaccardSimilarity instead
54
+ */
55
+ export async function embed(text) {
56
+ log('Embeddings: embed() called, returning empty array (use jaccardSimilarity instead)');
57
+ return new Float32Array(0);
58
+ }
59
+ /**
60
+ * Stub: Dispose function (no-op)
61
+ * @deprecated No resources to clean up
62
+ */
63
+ export function disposeEmbeddings() {
64
+ log('Embeddings: disposeEmbeddings() called (no-op in Jaccard mode)');
65
+ }
66
+ /**
67
+ * Stub: Get embedding pipeline (not used)
68
+ * @deprecated Use jaccardSimilarity instead
69
+ */
70
+ export function getEmbeddingPipeline() {
71
+ log('Embeddings: getEmbeddingPipeline() called (no-op in Jaccard mode)');
72
+ return null;
73
+ }
74
+ // =============================================================================
75
+ // Legacy functions (for backward compatibility, do not use)
76
+ // =============================================================================
77
+ /**
78
+ * @deprecated Use jaccardSimilarity instead
79
+ */
80
+ export function vectorToBuffer(vector) {
81
+ log('Warning: vectorToBuffer called (no-op in Jaccard mode)');
82
+ return Buffer.alloc(0);
83
+ }
84
+ /**
85
+ * @deprecated Use jaccardSimilarity instead
86
+ */
87
+ export function bufferToVector(buffer) {
88
+ log('Warning: bufferToVector called (no-op in Jaccard mode)');
89
+ return new Float32Array(0);
90
+ }
91
+ /**
92
+ * @deprecated Use jaccardSimilarity instead
93
+ */
94
+ export function cosineSimilarity(a, b) {
95
+ log('Warning: cosineSimilarity called (no-op in Jaccard mode, returning 0)');
96
+ return 0;
97
+ }
98
+ //# sourceMappingURL=embeddings.js.map