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.
Files changed (45) hide show
  1. package/README.md +58 -16
  2. package/dist/adapters/opencode/index.d.ts.map +1 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +129 -60
  5. package/dist/memory/classifier.d.ts.map +1 -1
  6. package/dist/memory/negative-patterns.d.ts +22 -0
  7. package/dist/memory/negative-patterns.d.ts.map +1 -1
  8. package/dist/memory/patterns.d.ts +11 -0
  9. package/dist/memory/patterns.d.ts.map +1 -1
  10. package/dist/utils/toast.d.ts +6 -0
  11. package/dist/utils/toast.d.ts.map +1 -0
  12. package/dist/utils/version.d.ts +6 -0
  13. package/dist/utils/version.d.ts.map +1 -0
  14. package/package.json +2 -1
  15. package/dist/adapters/opencode/index.js +0 -676
  16. package/dist/adapters/opencode/index.js.map +0 -1
  17. package/dist/adapters/opencode/injection.js +0 -93
  18. package/dist/adapters/opencode/injection.js.map +0 -1
  19. package/dist/config.js +0 -61
  20. package/dist/config.js.map +0 -1
  21. package/dist/extraction/queue.js +0 -75
  22. package/dist/extraction/queue.js.map +0 -1
  23. package/dist/index.js.map +0 -1
  24. package/dist/logger.js +0 -30
  25. package/dist/logger.js.map +0 -1
  26. package/dist/memory/classifier.js +0 -363
  27. package/dist/memory/classifier.js.map +0 -1
  28. package/dist/memory/embeddings.js +0 -98
  29. package/dist/memory/embeddings.js.map +0 -1
  30. package/dist/memory/negative-patterns.js +0 -71
  31. package/dist/memory/negative-patterns.js.map +0 -1
  32. package/dist/memory/patterns.js +0 -623
  33. package/dist/memory/patterns.js.map +0 -1
  34. package/dist/memory/reconsolidate.js +0 -96
  35. package/dist/memory/reconsolidate.js.map +0 -1
  36. package/dist/memory/role-patterns.js +0 -188
  37. package/dist/memory/role-patterns.js.map +0 -1
  38. package/dist/shutdown.js +0 -120
  39. package/dist/shutdown.js.map +0 -1
  40. package/dist/storage/database.js +0 -590
  41. package/dist/storage/database.js.map +0 -1
  42. package/dist/storage/sqlite-adapter.js +0 -99
  43. package/dist/storage/sqlite-adapter.js.map +0 -1
  44. package/dist/types.js +0 -63
  45. 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
- ## Installation
77
+ ## Noise Filtering
82
78
 
83
- ```bash
84
- npm install true-mem
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
- Then add to your `~/.config/opencode/opencode.jsonc`:
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 "Ricorda questo:" to force storage:
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. Negative Patterns | Filter known false positives |
186
- | 2. Multi-Keyword Scoring | Require 2+ signals |
187
- | 3. Confidence Threshold | Store only if score >= 0.6 |
188
- | 4. Role Validation | Human-only for user-level memories |
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;AAylBD,eAAe,sBAAsB,CAAC"}
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"}
@@ -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;AAkBzD,QAAA,MAAM,UAAU,EAAE,MAgGjB,CAAC;AAEF,eAAe,UAAU,CAAC;AAG1B,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,YAAY,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
- var EXPLICIT_REMEMBER, EMPHASIS_CUE, CORRECTION, PREFERENCE, DECISION, CONSTRAINT, BUG_FIX, LEARNING, ALL_PATTERNS;
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 isUserLevel = userLevelClassifications.includes(classification) || isExplicitIntent;
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
- // package.json
2913
- var package_default = {
2914
- name: "true-mem",
2915
- version: "1.0.2",
2916
- description: "Persistent memory plugin for OpenCode with cognitive psychology-based memory management",
2917
- main: "dist/index.js",
2918
- types: "dist/index.d.ts",
2919
- type: "module",
2920
- exports: {
2921
- ".": {
2922
- types: "./dist/index.d.ts",
2923
- import: "./dist/index.js"
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,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"}
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;AAGD,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,CAUpF;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,CAkB1F"}
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,6 @@
1
+ /**
2
+ * Read version from package.json at RUNTIME.
3
+ * This ensures the version is always current, even after npm version bump.
4
+ */
5
+ export declare function getVersion(): string;
6
+ //# sourceMappingURL=version.d.ts.map
@@ -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.2",
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"