true-mem 1.0.2 → 1.0.9
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/README.md +58 -16
- package/dist/adapters/opencode/index.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +129 -60
- package/dist/memory/classifier.d.ts.map +1 -1
- package/dist/memory/negative-patterns.d.ts +22 -0
- package/dist/memory/negative-patterns.d.ts.map +1 -1
- package/dist/memory/patterns.d.ts +11 -0
- package/dist/memory/patterns.d.ts.map +1 -1
- package/dist/utils/toast.d.ts +6 -0
- package/dist/utils/toast.d.ts.map +1 -0
- package/dist/utils/version.d.ts +6 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/package.json +2 -1
- package/dist/adapters/opencode/index.js +0 -676
- package/dist/adapters/opencode/index.js.map +0 -1
- package/dist/adapters/opencode/injection.js +0 -93
- package/dist/adapters/opencode/injection.js.map +0 -1
- package/dist/config.js +0 -61
- package/dist/config.js.map +0 -1
- package/dist/extraction/queue.js +0 -75
- package/dist/extraction/queue.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/logger.js +0 -30
- package/dist/logger.js.map +0 -1
- package/dist/memory/classifier.js +0 -363
- package/dist/memory/classifier.js.map +0 -1
- package/dist/memory/embeddings.js +0 -98
- package/dist/memory/embeddings.js.map +0 -1
- package/dist/memory/negative-patterns.js +0 -71
- package/dist/memory/negative-patterns.js.map +0 -1
- package/dist/memory/patterns.js +0 -623
- package/dist/memory/patterns.js.map +0 -1
- package/dist/memory/reconsolidate.js +0 -96
- package/dist/memory/reconsolidate.js.map +0 -1
- package/dist/memory/role-patterns.js +0 -188
- package/dist/memory/role-patterns.js.map +0 -1
- package/dist/shutdown.js +0 -120
- package/dist/shutdown.js.map +0 -1
- package/dist/storage/database.js +0 -590
- package/dist/storage/database.js.map +0 -1
- package/dist/storage/sqlite-adapter.js +0 -99
- package/dist/storage/sqlite-adapter.js.map +0 -1
- package/dist/types.js +0 -63
- package/dist/types.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,17 +7,13 @@
|
|
|
7
7
|
## Table of Contents
|
|
8
8
|
|
|
9
9
|
- [Overview](#overview)
|
|
10
|
-
- [The Problem](#the-problem)
|
|
11
|
-
- [The Solution](#the-solution)
|
|
12
|
-
- [The Psychology Behind It](#the-psychology-behind-it)
|
|
13
10
|
- [Key Features](#key-features)
|
|
11
|
+
- [Noise Filtering](#noise-filtering)
|
|
14
12
|
- [Installation](#installation)
|
|
15
13
|
- [Usage](#usage)
|
|
16
14
|
- [Architecture](#architecture)
|
|
17
15
|
- [Memory Classifications](#memory-classifications)
|
|
18
16
|
- [Technical Details](#technical-details)
|
|
19
|
-
- [Inspiration](#inspiration)
|
|
20
|
-
- [Debug](#debug)
|
|
21
17
|
|
|
22
18
|
---
|
|
23
19
|
|
|
@@ -78,13 +74,36 @@ What makes True-Mem different from a simple database? It's modeled after how hum
|
|
|
78
74
|
|
|
79
75
|
---
|
|
80
76
|
|
|
81
|
-
##
|
|
77
|
+
## Noise Filtering
|
|
82
78
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
79
|
+
What truly sets True-Mem apart is its ability to distinguish **signal from noise**. Unlike simpler memory plugins that store everything matching a keyword, True-Mem understands context and intent:
|
|
80
|
+
|
|
81
|
+
**What gets filtered OUT:**
|
|
82
|
+
|
|
83
|
+
| Pattern Type | Example | Why filtered |
|
|
84
|
+
|--------------|---------|--------------|
|
|
85
|
+
| Questions | "Do you remember this?" | It's a question, not a statement |
|
|
86
|
+
| 1st person recall | "I remember when we fixed that" | Recounting, not requesting storage |
|
|
87
|
+
| Remind-me recall | "Remind me how we did this" | Asking AI to recall info, not store |
|
|
88
|
+
| AI meta-talk | "Goal: The user is trying to..." | AI-generated, not user content |
|
|
89
|
+
| List selections | "I prefer option 3" | Context-specific choice, not general preference |
|
|
90
|
+
|
|
91
|
+
**What gets stored:**
|
|
92
|
+
|
|
93
|
+
| Pattern Type | Example | Why stored |
|
|
94
|
+
|--------------|---------|------------|
|
|
95
|
+
| Imperatives | "Remember this: always run tests" | Explicit storage request |
|
|
96
|
+
| Preferences | "I prefer TypeScript over JavaScript" | General, reusable preference |
|
|
97
|
+
| Decisions | "We decided to use SQLite" | Project-level decision |
|
|
98
|
+
| Constraints | "Never use var keyword" | Permanent rule |
|
|
99
|
+
|
|
100
|
+
All filtering patterns support **10 languages**: English, Italian, Spanish, French, German, Portuguese, Dutch, Polish, Turkish, and Russian.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Installation
|
|
86
105
|
|
|
87
|
-
|
|
106
|
+
Add to your `~/.config/opencode/opencode.jsonc`:
|
|
88
107
|
|
|
89
108
|
```jsonc
|
|
90
109
|
{
|
|
@@ -94,6 +113,8 @@ Then add to your `~/.config/opencode/opencode.jsonc`:
|
|
|
94
113
|
}
|
|
95
114
|
```
|
|
96
115
|
|
|
116
|
+
OpenCode will automatically download the plugin from npm.
|
|
117
|
+
|
|
97
118
|
---
|
|
98
119
|
|
|
99
120
|
## Usage
|
|
@@ -111,13 +132,34 @@ Just have conversations with OpenCode. True-Mem extracts relevant info in the ba
|
|
|
111
132
|
|
|
112
133
|
### Explicit Memory Storage
|
|
113
134
|
|
|
114
|
-
Use phrases like "Remember this:" or "
|
|
135
|
+
Use phrases like "Remember this:" or "Remember that ..." to force storage:
|
|
115
136
|
|
|
116
137
|
```
|
|
117
|
-
"Ricorda questo: preferisco sempre usare TypeScript per i miei progetti"
|
|
118
138
|
"Remember this: never commit without running tests first"
|
|
139
|
+
"Remember that I prefer to use TypeScript in my projects"
|
|
119
140
|
```
|
|
120
141
|
|
|
142
|
+
**Scope Behavior**:
|
|
143
|
+
|
|
144
|
+
By default, explicit intent memories are stored at **project scope** (only visible in the current project). To make them **global** (available in all projects), include a global scope keyword anywhere in your phrase:
|
|
145
|
+
|
|
146
|
+
| Language | Global Scope Keywords |
|
|
147
|
+
|----------|---------------------|
|
|
148
|
+
| **English** | "always", "everywhere", "for all projects", "in every project", "globally" |
|
|
149
|
+
| **Italian** | "sempre", "ovunque", "per tutti i progetti", "in ogni progetto", "globalmente" |
|
|
150
|
+
| **Spanish** | "siempre", "en todas partes", "para todos los proyectos" |
|
|
151
|
+
| **French** | "toujours", "partout", "pour tous les projets" |
|
|
152
|
+
| **German** | "immer", "überall", "für alle projekte" |
|
|
153
|
+
| **Portuguese** | "sempre", "em todos os projetos" |
|
|
154
|
+
|
|
155
|
+
**Examples**:
|
|
156
|
+
|
|
157
|
+
| Memory | Scope | Phrase |
|
|
158
|
+
|---------|---------|---------|
|
|
159
|
+
| **Project** | `project_scope = current_project` | "Remember that we use REST for the API" |
|
|
160
|
+
| **Global** | `project_scope = null` | "Remember to _always_ run tests before committing" |
|
|
161
|
+
| **Global** | `project_scope = null` | "Remember that I _always_ use Typescript _in every project_" |
|
|
162
|
+
|
|
121
163
|
---
|
|
122
164
|
|
|
123
165
|
## Architecture
|
|
@@ -182,10 +224,10 @@ true-mem/
|
|
|
182
224
|
|
|
183
225
|
| Layer | Purpose |
|
|
184
226
|
|-------|---------|
|
|
185
|
-
| 1.
|
|
186
|
-
| 2.
|
|
187
|
-
| 3.
|
|
188
|
-
| 4.
|
|
227
|
+
| 1. Question Detection | Filter questions before classification |
|
|
228
|
+
| 2. Negative Patterns | AI meta-talk, list selections, 1st person recall, remind-me recall (10 languages) |
|
|
229
|
+
| 3. Multi-Keyword + Sentence-Level | Require 2+ signals in the same sentence |
|
|
230
|
+
| 4. Confidence Threshold | Store only if score >= 0.6 |
|
|
189
231
|
|
|
190
232
|
### Decay Strategy
|
|
191
233
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/opencode/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAwB,MAAM,gBAAgB,CAAC;AAC/E,OAAO,KAAK,EAAE,cAAc,EAA4D,MAAM,gBAAgB,CAAC;AA4F/G;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,WAAW,EAChB,eAAe,GAAE,OAAO,CAAC,cAAc,CAAM,GAC5C,OAAO,CAAC,KAAK,CAAC,CAwKhB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/opencode/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAwB,MAAM,gBAAgB,CAAC;AAC/E,OAAO,KAAK,EAAE,cAAc,EAA4D,MAAM,gBAAgB,CAAC;AA4F/G;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,WAAW,EAChB,eAAe,GAAE,OAAO,CAAC,cAAc,CAAM,GAC5C,OAAO,CAAC,KAAK,CAAC,CAwKhB;AAwlBD,eAAe,sBAAsB,CAAC"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAS,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAS,MAAM,qBAAqB,CAAC;AAmBzD,QAAA,MAAM,UAAU,EAAE,MAqGjB,CAAC;AAEF,eAAe,UAAU,CAAC;AAG1B,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -858,12 +858,18 @@ function matchesNegativePattern(text, classification) {
|
|
|
858
858
|
if (isAIMetaTalk(text)) {
|
|
859
859
|
return true;
|
|
860
860
|
}
|
|
861
|
+
if (FIRST_PERSON_RECALL_PATTERNS.some((pattern) => pattern.test(text))) {
|
|
862
|
+
return true;
|
|
863
|
+
}
|
|
864
|
+
if (REMIND_RECALL_PATTERNS.some((pattern) => pattern.test(text))) {
|
|
865
|
+
return true;
|
|
866
|
+
}
|
|
861
867
|
const patterns = NEGATIVE_PATTERNS[classification];
|
|
862
868
|
if (!patterns)
|
|
863
869
|
return false;
|
|
864
870
|
return patterns.some((pattern) => pattern.test(text));
|
|
865
871
|
}
|
|
866
|
-
var AI_META_TALK_PATTERNS, NEGATIVE_PATTERNS;
|
|
872
|
+
var AI_META_TALK_PATTERNS, FIRST_PERSON_RECALL_PATTERNS, REMIND_RECALL_PATTERNS, NEGATIVE_PATTERNS;
|
|
867
873
|
var init_negative_patterns = __esm(() => {
|
|
868
874
|
AI_META_TALK_PATTERNS = [
|
|
869
875
|
/^(Goal|Summary|Context|Analysis|Note|Overview|Background):\s+The user/i,
|
|
@@ -886,6 +892,45 @@ var init_negative_patterns = __esm(() => {
|
|
|
886
892
|
/\|\w+\|.*\.\.\./i,
|
|
887
893
|
/^\|.+\|$/i
|
|
888
894
|
];
|
|
895
|
+
FIRST_PERSON_RECALL_PATTERNS = [
|
|
896
|
+
/\bI\s+(remember|recall|recollect|don'?t\s+forget)\b/i,
|
|
897
|
+
/\bwe\s+(remember|recall|recollect)\b/i,
|
|
898
|
+
/\bI\s+can\s+remember\b/i,
|
|
899
|
+
/\b(io\s+)?ricordo\b/i,
|
|
900
|
+
/\bmi\s+ricordo\b/i,
|
|
901
|
+
/\bho\s+ricordato\b/i,
|
|
902
|
+
/\b(ci\s+)?ricordiamo\s+(che|di|quando|come|perch)\b/i,
|
|
903
|
+
/\b(yo\s+)?recuerdo\b/i,
|
|
904
|
+
/\bme\s+acuerdo\b/i,
|
|
905
|
+
/\brecordamos\b/i,
|
|
906
|
+
/\bje\s+(me\s+)?souviens\b/i,
|
|
907
|
+
/\bnous\s+(nous\s+)?souvenons\b/i,
|
|
908
|
+
/\bich\s+erinnere(\s+mich)?\b/i,
|
|
909
|
+
/\bwir\s+erinnern(\s+uns)?\b/i,
|
|
910
|
+
/\b(eu\s+)?(me\s+)?lembro\b/i,
|
|
911
|
+
/\bnos\s+lembramos\b/i,
|
|
912
|
+
/\bik\s+herinner(\s+me)?\b/i,
|
|
913
|
+
/\bwe\s+herinneren(\s+ons)?\b/i,
|
|
914
|
+
/\bpami\u0119tam\b/i,
|
|
915
|
+
/\bpami\u0119tamy\b/i,
|
|
916
|
+
/\bhat\u0131rl\u0131yorum\b/i,
|
|
917
|
+
/\bhat\u0131rl\u0131yoruz\b/i
|
|
918
|
+
];
|
|
919
|
+
REMIND_RECALL_PATTERNS = [
|
|
920
|
+
/\bremind\s+me\s+(how|what|when|where|why|who|which)\b/i,
|
|
921
|
+
/\bremind\s+me\s+of\s+(the|what|how|when|where|why)\b/i,
|
|
922
|
+
/\bricordami\s+(come|cosa|quando|dove|perch[e\u00E9]|chi|quale|quanto)\b/i,
|
|
923
|
+
/\bricordami\s+che\s+(cosa|tipo|ragione)\b/i,
|
|
924
|
+
/\brec[u\u00FA]rdame\s+(c[o\u00F3]mo|qu[e\u00E9]|cu[a\u00E1]ndo|d[o\u00F3]nde|por\s*qu[e\u00E9]|qui[e\u00E9]n|cu[a\u00E1]l)\b/i,
|
|
925
|
+
/\brappelle[s]?\s*-?\s*moi\s+(comment|quand|o[u\u00F9]|pourquoi|qui|quel)\b/i,
|
|
926
|
+
/\brappelle[s]?\s*-?\s*moi\s+ce\s+que\b/i,
|
|
927
|
+
/\berinner\s+(mich|uns)\s+(wie|was|wann|wo|warum|wer|welche[ns]?)\b/i,
|
|
928
|
+
/\blembre\s*-?\s*me\s+(como|quando|onde|por\s*que|quem|qual)\b/i,
|
|
929
|
+
/\blembre\s*-?\s*me\s+o\s+que\b/i,
|
|
930
|
+
/\bherinner\s+(me|ons)\s+(hoe|wat|wanneer|waar|waarom|wie|welke)\b/i,
|
|
931
|
+
/\bprzypomnij\s+mi\s+(jak|co|kiedy|gdzie|dlaczego|kto|kt[o\u00F3]ry)\b/i,
|
|
932
|
+
/\bhat[\u0131i]rlat\s+(bana)\s+(nas[\u0131i]l|ne|ne\s+zaman|nere[dy]e|neden|kim|hangi)\b/i
|
|
933
|
+
];
|
|
889
934
|
NEGATIVE_PATTERNS = {
|
|
890
935
|
bugfix: [
|
|
891
936
|
/resolve\s+(dns|ip|address|hostname|url|uri|path)/i,
|
|
@@ -1086,8 +1131,6 @@ function classifyWithExplicitIntent(text, signals) {
|
|
|
1086
1131
|
/\bmemorizziamo\b:?\s*/gi,
|
|
1087
1132
|
/\bricordiamoci che\b:?\s*/gi,
|
|
1088
1133
|
/\bricordiamoci di\b:?\s*/gi,
|
|
1089
|
-
/\bricorda\b:?\s*/gi,
|
|
1090
|
-
/\bremember\b:?\s*/gi,
|
|
1091
1134
|
/\btieni a mente\b:?\s*/gi,
|
|
1092
1135
|
/\bkeep in mind\b:?\s*/gi,
|
|
1093
1136
|
/\bnota che\b:?\s*/gi,
|
|
@@ -1320,7 +1363,11 @@ function matchAllPatterns(text) {
|
|
|
1320
1363
|
}
|
|
1321
1364
|
return signals;
|
|
1322
1365
|
}
|
|
1323
|
-
|
|
1366
|
+
function hasGlobalScopeKeyword(text) {
|
|
1367
|
+
const lowerText = text.toLowerCase();
|
|
1368
|
+
return GLOBAL_SCOPE_KEYWORDS.latin.some((keyword) => lowerText.includes(keyword.toLowerCase()));
|
|
1369
|
+
}
|
|
1370
|
+
var EXPLICIT_REMEMBER, EMPHASIS_CUE, CORRECTION, PREFERENCE, DECISION, CONSTRAINT, BUG_FIX, LEARNING, ALL_PATTERNS, GLOBAL_SCOPE_KEYWORDS;
|
|
1324
1371
|
var init_patterns = __esm(() => {
|
|
1325
1372
|
EXPLICIT_REMEMBER = {
|
|
1326
1373
|
signalType: "explicit_remember",
|
|
@@ -2223,6 +2270,56 @@ var init_patterns = __esm(() => {
|
|
|
2223
2270
|
BUG_FIX,
|
|
2224
2271
|
LEARNING
|
|
2225
2272
|
];
|
|
2273
|
+
GLOBAL_SCOPE_KEYWORDS = {
|
|
2274
|
+
latin: [
|
|
2275
|
+
"always",
|
|
2276
|
+
"everywhere",
|
|
2277
|
+
"for all projects",
|
|
2278
|
+
"in every project",
|
|
2279
|
+
"globally",
|
|
2280
|
+
"in all my projects",
|
|
2281
|
+
"across all projects",
|
|
2282
|
+
"in all projects",
|
|
2283
|
+
"sempre",
|
|
2284
|
+
"ovunque",
|
|
2285
|
+
"per tutti i progetti",
|
|
2286
|
+
"in ogni progetto",
|
|
2287
|
+
"globalmente",
|
|
2288
|
+
"in tutti i miei progetti",
|
|
2289
|
+
"in tutti i progetti",
|
|
2290
|
+
"per ogni progetto",
|
|
2291
|
+
"siempre",
|
|
2292
|
+
"en todas partes",
|
|
2293
|
+
"para todos los proyectos",
|
|
2294
|
+
"en todos los proyectos",
|
|
2295
|
+
"en todos mis proyectos",
|
|
2296
|
+
"toujours",
|
|
2297
|
+
"partout",
|
|
2298
|
+
"pour tous les projets",
|
|
2299
|
+
"dans tous les projets",
|
|
2300
|
+
"dans tous mes projets",
|
|
2301
|
+
"immer",
|
|
2302
|
+
"uberall",
|
|
2303
|
+
"fur alle projekte",
|
|
2304
|
+
"in allen projekten",
|
|
2305
|
+
"in allen meinen projekten",
|
|
2306
|
+
"sempre",
|
|
2307
|
+
"em todos os projetos",
|
|
2308
|
+
"para todos os projetos",
|
|
2309
|
+
"em todos os meus projetos",
|
|
2310
|
+
"altijd",
|
|
2311
|
+
"overal",
|
|
2312
|
+
"voor alle projecten",
|
|
2313
|
+
"in al mijn projecten",
|
|
2314
|
+
"her zaman",
|
|
2315
|
+
"her yerde",
|
|
2316
|
+
"tum projelerde",
|
|
2317
|
+
"zawsze",
|
|
2318
|
+
"wszedzie",
|
|
2319
|
+
"dla wszystkich projektow",
|
|
2320
|
+
"we wszystkich moich projektach"
|
|
2321
|
+
]
|
|
2322
|
+
};
|
|
2226
2323
|
});
|
|
2227
2324
|
|
|
2228
2325
|
// src/extraction/queue.ts
|
|
@@ -2654,7 +2751,8 @@ async function processSessionIdle(state, sessionId) {
|
|
|
2654
2751
|
if (result.store) {
|
|
2655
2752
|
const userLevelClassifications = ["constraint", "preference", "learning", "procedural"];
|
|
2656
2753
|
const isExplicitIntent = confidence >= 0.85;
|
|
2657
|
-
const
|
|
2754
|
+
const hasGlobalKeyword = hasGlobalScopeKeyword(isolatedContent);
|
|
2755
|
+
const isUserLevel = userLevelClassifications.includes(classification) || isExplicitIntent && hasGlobalKeyword;
|
|
2658
2756
|
const scope = isUserLevel ? null : state.worktree;
|
|
2659
2757
|
const autoPromoteClassifications = ["bugfix", "learning", "decision"];
|
|
2660
2758
|
const shouldPromoteToLtm = isExplicitIntent || autoPromoteClassifications.includes(classification);
|
|
@@ -2909,61 +3007,29 @@ var init_opencode = __esm(() => {
|
|
|
2909
3007
|
|
|
2910
3008
|
// src/index.ts
|
|
2911
3009
|
init_logger();
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
scripts: {
|
|
2927
|
-
build: "bun build src/index.ts --outdir dist --target bun --format esm && tsc --emitDeclarationOnly",
|
|
2928
|
-
dev: "bun build src/index.ts --outdir dist --target bun --format esm --watch",
|
|
2929
|
-
typecheck: "tsc --noEmit"
|
|
2930
|
-
},
|
|
2931
|
-
keywords: [
|
|
2932
|
-
"opencode",
|
|
2933
|
-
"ai",
|
|
2934
|
-
"memory",
|
|
2935
|
-
"plugin",
|
|
2936
|
-
"persistent",
|
|
2937
|
-
"cognitive",
|
|
2938
|
-
"coding-assistant"
|
|
2939
|
-
],
|
|
2940
|
-
author: "rizal72",
|
|
2941
|
-
license: "MIT",
|
|
2942
|
-
repository: {
|
|
2943
|
-
type: "git",
|
|
2944
|
-
url: "git+https://github.com/rizal72/true-mem.git"
|
|
2945
|
-
},
|
|
2946
|
-
bugs: {
|
|
2947
|
-
url: "https://github.com/rizal72/true-mem/issues"
|
|
2948
|
-
},
|
|
2949
|
-
homepage: "https://github.com/rizal72/true-mem#readme",
|
|
2950
|
-
files: [
|
|
2951
|
-
"dist/",
|
|
2952
|
-
"README.md",
|
|
2953
|
-
"LICENSE"
|
|
2954
|
-
],
|
|
2955
|
-
dependencies: {
|
|
2956
|
-
"@opencode-ai/plugin": "^1.2.6",
|
|
2957
|
-
"@opencode-ai/sdk": "^1.2.6",
|
|
2958
|
-
uuid: "^13.0.0"
|
|
2959
|
-
},
|
|
2960
|
-
devDependencies: {
|
|
2961
|
-
"@types/node": "^25.0.0",
|
|
2962
|
-
"@types/uuid": "^10.0.0",
|
|
2963
|
-
"bun-types": "^1.3.0",
|
|
2964
|
-
typescript: "^5.9.3"
|
|
3010
|
+
|
|
3011
|
+
// src/utils/version.ts
|
|
3012
|
+
import fs from "fs";
|
|
3013
|
+
import path from "path";
|
|
3014
|
+
var __dirname = "/home/runner/work/true-mem/true-mem/src/utils";
|
|
3015
|
+
function getVersion() {
|
|
3016
|
+
try {
|
|
3017
|
+
const distDir = __dirname;
|
|
3018
|
+
const pkgPath = path.join(distDir, "..", "package.json");
|
|
3019
|
+
const content = fs.readFileSync(pkgPath, "utf-8");
|
|
3020
|
+
const pkg = JSON.parse(content);
|
|
3021
|
+
return pkg.version ?? "unknown";
|
|
3022
|
+
} catch {
|
|
3023
|
+
return "unknown";
|
|
2965
3024
|
}
|
|
2966
|
-
}
|
|
3025
|
+
}
|
|
3026
|
+
|
|
3027
|
+
// src/utils/toast.ts
|
|
3028
|
+
function showToast(ctx, title, message, variant = "info", duration = 3000) {
|
|
3029
|
+
ctx.client.tui.showToast({
|
|
3030
|
+
body: { title, message, variant, duration }
|
|
3031
|
+
}).catch(() => {});
|
|
3032
|
+
}
|
|
2967
3033
|
|
|
2968
3034
|
// src/index.ts
|
|
2969
3035
|
var state = {
|
|
@@ -2973,7 +3039,6 @@ var state = {
|
|
|
2973
3039
|
realHooks: null
|
|
2974
3040
|
};
|
|
2975
3041
|
var TrueMemory = async (ctx) => {
|
|
2976
|
-
console.log(`True-Mem v${package_default.version}: Plugin loading...`);
|
|
2977
3042
|
state.ctx = ctx;
|
|
2978
3043
|
state.initPromise = (async () => {
|
|
2979
3044
|
log("Phase 1: Initializing plugin (lightweight)...");
|
|
@@ -2995,6 +3060,10 @@ var TrueMemory = async (ctx) => {
|
|
|
2995
3060
|
log("True-Mem: Plugin registered (immediate init mode)");
|
|
2996
3061
|
return {
|
|
2997
3062
|
event: async ({ event }) => {
|
|
3063
|
+
if (event.type === "session.created" && state.ctx) {
|
|
3064
|
+
const version = getVersion();
|
|
3065
|
+
showToast(state.ctx, `True-Mem v${version}`, "Persistent memory plugin active.", "info");
|
|
3066
|
+
}
|
|
2998
3067
|
const silentEvents = new Set(["message.part.delta", "message.part.updated", "session.diff"]);
|
|
2999
3068
|
if (silentEvents.has(event.type))
|
|
3000
3069
|
return;
|
|
@@ -1 +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,CAkCzF;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,CA0DxD;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,
|
|
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,CAkCzF;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,CA0DxD;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,CA0FhF;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"}
|
|
@@ -23,6 +23,28 @@ export declare function isAIMetaTalk(text: string): boolean;
|
|
|
23
23
|
* Check if text is a question (should NOT be stored as a statement)
|
|
24
24
|
*/
|
|
25
25
|
export declare function isQuestion(text: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* First Person Recall Patterns
|
|
28
|
+
*
|
|
29
|
+
* These patterns detect when the user is recounting/recalling something
|
|
30
|
+
* (1st person indicative) rather than requesting storage (imperative).
|
|
31
|
+
*
|
|
32
|
+
* "I remember when..." = recounting, NOT storage request
|
|
33
|
+
* "Remember this!" = imperative, storage request
|
|
34
|
+
*/
|
|
35
|
+
export declare const FIRST_PERSON_RECALL_PATTERNS: RegExp[];
|
|
36
|
+
/**
|
|
37
|
+
* Remind Recall Patterns
|
|
38
|
+
*
|
|
39
|
+
* These patterns detect when "remind me" is used to request INFORMATION
|
|
40
|
+
* (recall) rather than to store something (imperative).
|
|
41
|
+
*
|
|
42
|
+
* "Remind me how we did this" = asking AI to recall → DON'T store
|
|
43
|
+
* "Remind me to commit" = imperative to store → STORE
|
|
44
|
+
*
|
|
45
|
+
* Key distinction: question word vs. preposition/demonstrative after "remind me"
|
|
46
|
+
*/
|
|
47
|
+
export declare const REMIND_RECALL_PATTERNS: RegExp[];
|
|
26
48
|
export declare const NEGATIVE_PATTERNS: Record<string, RegExp[]>;
|
|
27
49
|
/**
|
|
28
50
|
* Check if text matches any negative pattern for the given classification
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"negative-patterns.d.ts","sourceRoot":"","sources":["../../src/memory/negative-patterns.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,EAmCzC,CAAC;AAEF;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAahD;
|
|
1
|
+
{"version":3,"file":"negative-patterns.d.ts","sourceRoot":"","sources":["../../src/memory/negative-patterns.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,EAmCzC,CAAC;AAEF;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAahD;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,EAAE,MAAM,EA0ChD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,EA+B1C,CAAC;AAGF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CA0DtD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAoBpF;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,CA4B1F"}
|
|
@@ -103,6 +103,17 @@ export declare function matchAllPatterns(text: string): ImportanceSignal[];
|
|
|
103
103
|
* Returns the best-matching MemoryClassification.
|
|
104
104
|
*/
|
|
105
105
|
export declare function classifyByPatterns(text: string): string | null;
|
|
106
|
+
/**
|
|
107
|
+
* Global scope keywords - indicate memory should apply to all projects
|
|
108
|
+
* Must appear ANYWHERE in the text (not just after "ricordati")
|
|
109
|
+
*/
|
|
110
|
+
export declare const GLOBAL_SCOPE_KEYWORDS: {
|
|
111
|
+
latin: string[];
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Check if text contains global scope keywords
|
|
115
|
+
*/
|
|
116
|
+
export declare function hasGlobalScopeKeyword(text: string): boolean;
|
|
106
117
|
/**
|
|
107
118
|
* Get all classification types supported by patterns
|
|
108
119
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/memory/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAM1E,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,oBAAoB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,eA0C/B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,eA8C1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,eA+CxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,eA8CxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,eAuCtB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,eAwCxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,eA0CrB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,eAgDtB,CAAC;AAMF,eAAO,MAAM,YAAY,EAAE,eAAe,EASzC,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;CAyFnC,CAAC;AAqCF;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,gBAAgB,GAAG,IAAI,CA2B7F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAWjE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA6B9D;AAMD;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,EAAE,CAEtD"}
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/memory/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAM1E,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,oBAAoB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,eA0C/B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,eA8C1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,eA+CxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,eA8CxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,eAuCtB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,eAwCxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,eA0CrB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,eAgDtB,CAAC;AAMF,eAAO,MAAM,YAAY,EAAE,eAAe,EASzC,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;CAyFnC,CAAC;AAqCF;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,gBAAgB,GAAG,IAAI,CA2B7F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAWjE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA6B9D;AAMD;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;CA6BjC,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK3D;AAMD;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,EAAE,CAEtD"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
2
|
+
/**
|
|
3
|
+
* Show a toast notification in the OpenCode TUI.
|
|
4
|
+
*/
|
|
5
|
+
export declare function showToast(ctx: PluginInput, title: string, message: string, variant?: 'info' | 'success' | 'error', duration?: number): void;
|
|
6
|
+
//# sourceMappingURL=toast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../../src/utils/toast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;GAEG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,MAAM,GAAG,SAAS,GAAG,OAAgB,EAC9C,QAAQ,SAAO,GACd,IAAI,CAMN"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/utils/version.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAWnC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "true-mem",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "Persistent memory plugin for OpenCode with cognitive psychology-based memory management",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
+
"preversion": "bun run build",
|
|
15
16
|
"build": "bun build src/index.ts --outdir dist --target bun --format esm && tsc --emitDeclarationOnly",
|
|
16
17
|
"dev": "bun build src/index.ts --outdir dist --target bun --format esm --watch",
|
|
17
18
|
"typecheck": "tsc --noEmit"
|