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.
- package/LICENSE +21 -0
- package/README.md +217 -0
- package/dist/adapters/opencode/index.d.ts +11 -0
- package/dist/adapters/opencode/index.d.ts.map +1 -0
- package/dist/adapters/opencode/index.js +676 -0
- package/dist/adapters/opencode/index.js.map +1 -0
- package/dist/adapters/opencode/injection.d.ts +52 -0
- package/dist/adapters/opencode/injection.d.ts.map +1 -0
- package/dist/adapters/opencode/injection.js +93 -0
- package/dist/adapters/opencode/injection.js.map +1 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +61 -0
- package/dist/config.js.map +1 -0
- package/dist/extraction/queue.d.ts +35 -0
- package/dist/extraction/queue.d.ts.map +1 -0
- package/dist/extraction/queue.js +75 -0
- package/dist/extraction/queue.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2900 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +6 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +30 -0
- package/dist/logger.js.map +1 -0
- package/dist/memory/classifier.d.ts +78 -0
- package/dist/memory/classifier.d.ts.map +1 -0
- package/dist/memory/classifier.js +363 -0
- package/dist/memory/classifier.js.map +1 -0
- package/dist/memory/embeddings.d.ts +41 -0
- package/dist/memory/embeddings.d.ts.map +1 -0
- package/dist/memory/embeddings.js +98 -0
- package/dist/memory/embeddings.js.map +1 -0
- package/dist/memory/negative-patterns.d.ts +32 -0
- package/dist/memory/negative-patterns.d.ts.map +1 -0
- package/dist/memory/negative-patterns.js +71 -0
- package/dist/memory/negative-patterns.js.map +1 -0
- package/dist/memory/patterns.d.ts +110 -0
- package/dist/memory/patterns.d.ts.map +1 -0
- package/dist/memory/patterns.js +623 -0
- package/dist/memory/patterns.js.map +1 -0
- package/dist/memory/reconsolidate.d.ts +57 -0
- package/dist/memory/reconsolidate.d.ts.map +1 -0
- package/dist/memory/reconsolidate.js +96 -0
- package/dist/memory/reconsolidate.js.map +1 -0
- package/dist/memory/role-patterns.d.ts +50 -0
- package/dist/memory/role-patterns.d.ts.map +1 -0
- package/dist/memory/role-patterns.js +188 -0
- package/dist/memory/role-patterns.js.map +1 -0
- package/dist/shutdown.d.ts +31 -0
- package/dist/shutdown.d.ts.map +1 -0
- package/dist/shutdown.js +120 -0
- package/dist/shutdown.js.map +1 -0
- package/dist/storage/database.d.ts +77 -0
- package/dist/storage/database.d.ts.map +1 -0
- package/dist/storage/database.js +590 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/sqlite-adapter.d.ts +35 -0
- package/dist/storage/sqlite-adapter.d.ts.map +1 -0
- package/dist/storage/sqlite-adapter.js +99 -0
- package/dist/storage/sqlite-adapter.js.map +1 -0
- package/dist/types.d.ts +266 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +63 -0
- package/dist/types.js.map +1 -0
- 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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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -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
|