@vheins/local-memory-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/DASHBOARD.md +129 -0
  2. package/HYBRID_SEARCH.md +204 -0
  3. package/IMPLEMENTATION.md +159 -0
  4. package/README.md +175 -0
  5. package/dist/capabilities.d.ts +22 -0
  6. package/dist/capabilities.d.ts.map +1 -0
  7. package/dist/capabilities.js +23 -0
  8. package/dist/capabilities.js.map +1 -0
  9. package/dist/dashboard/dashboard.test.d.ts +2 -0
  10. package/dist/dashboard/dashboard.test.d.ts.map +1 -0
  11. package/dist/dashboard/dashboard.test.js +362 -0
  12. package/dist/dashboard/dashboard.test.js.map +1 -0
  13. package/dist/dashboard/public/app.js +1187 -0
  14. package/dist/dashboard/public/chart.js +0 -0
  15. package/dist/dashboard/public/index.html +967 -0
  16. package/dist/dashboard/server.d.ts +3 -0
  17. package/dist/dashboard/server.d.ts.map +1 -0
  18. package/dist/dashboard/server.js +297 -0
  19. package/dist/dashboard/server.js.map +1 -0
  20. package/dist/mcp/client.d.ts +34 -0
  21. package/dist/mcp/client.d.ts.map +1 -0
  22. package/dist/mcp/client.js +181 -0
  23. package/dist/mcp/client.js.map +1 -0
  24. package/dist/mcp/client.test.d.ts +2 -0
  25. package/dist/mcp/client.test.d.ts.map +1 -0
  26. package/dist/mcp/client.test.js +130 -0
  27. package/dist/mcp/client.test.js.map +1 -0
  28. package/dist/prompts/registry.d.ts +39 -0
  29. package/dist/prompts/registry.d.ts.map +1 -0
  30. package/dist/prompts/registry.js +90 -0
  31. package/dist/prompts/registry.js.map +1 -0
  32. package/dist/resources/index.d.ts +17 -0
  33. package/dist/resources/index.d.ts.map +1 -0
  34. package/dist/resources/index.js +100 -0
  35. package/dist/resources/index.js.map +1 -0
  36. package/dist/resources/index.test.d.ts +2 -0
  37. package/dist/resources/index.test.d.ts.map +1 -0
  38. package/dist/resources/index.test.js +96 -0
  39. package/dist/resources/index.test.js.map +1 -0
  40. package/dist/router.d.ts +4 -0
  41. package/dist/router.d.ts.map +1 -0
  42. package/dist/router.js +60 -0
  43. package/dist/router.js.map +1 -0
  44. package/dist/router.test.d.ts +2 -0
  45. package/dist/router.test.d.ts.map +1 -0
  46. package/dist/router.test.js +113 -0
  47. package/dist/router.test.js.map +1 -0
  48. package/dist/search_memory_example.d.ts +3 -0
  49. package/dist/search_memory_example.d.ts.map +1 -0
  50. package/dist/search_memory_example.js +56 -0
  51. package/dist/search_memory_example.js.map +1 -0
  52. package/dist/server.d.ts +3 -0
  53. package/dist/server.d.ts.map +1 -0
  54. package/dist/server.js +91 -0
  55. package/dist/server.js.map +1 -0
  56. package/dist/storage/sqlite.d.ts +95 -0
  57. package/dist/storage/sqlite.d.ts.map +1 -0
  58. package/dist/storage/sqlite.js +537 -0
  59. package/dist/storage/sqlite.js.map +1 -0
  60. package/dist/storage/sqlite.test.d.ts +2 -0
  61. package/dist/storage/sqlite.test.d.ts.map +1 -0
  62. package/dist/storage/sqlite.test.js +358 -0
  63. package/dist/storage/sqlite.test.js.map +1 -0
  64. package/dist/storage/vectors.stub.d.ts +12 -0
  65. package/dist/storage/vectors.stub.d.ts.map +1 -0
  66. package/dist/storage/vectors.stub.js +88 -0
  67. package/dist/storage/vectors.stub.js.map +1 -0
  68. package/dist/store_memory_example.d.ts +3 -0
  69. package/dist/store_memory_example.d.ts.map +1 -0
  70. package/dist/store_memory_example.js +69 -0
  71. package/dist/store_memory_example.js.map +1 -0
  72. package/dist/test_quotes_client.d.ts +3 -0
  73. package/dist/test_quotes_client.d.ts.map +1 -0
  74. package/dist/test_quotes_client.js +72 -0
  75. package/dist/test_quotes_client.js.map +1 -0
  76. package/dist/tools/memory.delete.d.ts +9 -0
  77. package/dist/tools/memory.delete.d.ts.map +1 -0
  78. package/dist/tools/memory.delete.js +22 -0
  79. package/dist/tools/memory.delete.js.map +1 -0
  80. package/dist/tools/memory.recap.d.ts +4 -0
  81. package/dist/tools/memory.recap.d.ts.map +1 -0
  82. package/dist/tools/memory.recap.js +42 -0
  83. package/dist/tools/memory.recap.js.map +1 -0
  84. package/dist/tools/memory.search.d.ts +5 -0
  85. package/dist/tools/memory.search.d.ts.map +1 -0
  86. package/dist/tools/memory.search.js +192 -0
  87. package/dist/tools/memory.search.js.map +1 -0
  88. package/dist/tools/memory.search.test.d.ts +2 -0
  89. package/dist/tools/memory.search.test.d.ts.map +1 -0
  90. package/dist/tools/memory.search.test.js +181 -0
  91. package/dist/tools/memory.search.test.js.map +1 -0
  92. package/dist/tools/memory.store.d.ts +5 -0
  93. package/dist/tools/memory.store.d.ts.map +1 -0
  94. package/dist/tools/memory.store.js +41 -0
  95. package/dist/tools/memory.store.js.map +1 -0
  96. package/dist/tools/memory.summarize.d.ts +4 -0
  97. package/dist/tools/memory.summarize.d.ts.map +1 -0
  98. package/dist/tools/memory.summarize.js +13 -0
  99. package/dist/tools/memory.summarize.js.map +1 -0
  100. package/dist/tools/memory.update.d.ts +5 -0
  101. package/dist/tools/memory.update.d.ts.map +1 -0
  102. package/dist/tools/memory.update.js +31 -0
  103. package/dist/tools/memory.update.js.map +1 -0
  104. package/dist/tools/schemas.d.ts +334 -0
  105. package/dist/tools/schemas.d.ts.map +1 -0
  106. package/dist/tools/schemas.js +251 -0
  107. package/dist/tools/schemas.js.map +1 -0
  108. package/dist/types.d.ts +31 -0
  109. package/dist/types.d.ts.map +1 -0
  110. package/dist/types.js +3 -0
  111. package/dist/types.js.map +1 -0
  112. package/dist/utils/git-scope.d.ts +8 -0
  113. package/dist/utils/git-scope.d.ts.map +1 -0
  114. package/dist/utils/git-scope.js +38 -0
  115. package/dist/utils/git-scope.js.map +1 -0
  116. package/dist/utils/logger.d.ts +7 -0
  117. package/dist/utils/logger.d.ts.map +1 -0
  118. package/dist/utils/logger.js +40 -0
  119. package/dist/utils/logger.js.map +1 -0
  120. package/dist/utils/logger.test.d.ts +2 -0
  121. package/dist/utils/logger.test.d.ts.map +1 -0
  122. package/dist/utils/logger.test.js +84 -0
  123. package/dist/utils/logger.test.js.map +1 -0
  124. package/dist/utils/mcp-response.d.ts +44 -0
  125. package/dist/utils/mcp-response.d.ts.map +1 -0
  126. package/dist/utils/mcp-response.js +81 -0
  127. package/dist/utils/mcp-response.js.map +1 -0
  128. package/dist/utils/normalize.d.ts +4 -0
  129. package/dist/utils/normalize.d.ts.map +1 -0
  130. package/dist/utils/normalize.js +51 -0
  131. package/dist/utils/normalize.js.map +1 -0
  132. package/dist/utils/normalize.test.d.ts +2 -0
  133. package/dist/utils/normalize.test.d.ts.map +1 -0
  134. package/dist/utils/normalize.test.js +159 -0
  135. package/dist/utils/normalize.test.js.map +1 -0
  136. package/dist/utils/query-expander.d.ts +2 -0
  137. package/dist/utils/query-expander.d.ts.map +1 -0
  138. package/dist/utils/query-expander.js +50 -0
  139. package/dist/utils/query-expander.js.map +1 -0
  140. package/dist/utils/query-expander.test.d.ts +2 -0
  141. package/dist/utils/query-expander.test.d.ts.map +1 -0
  142. package/dist/utils/query-expander.test.js +35 -0
  143. package/dist/utils/query-expander.test.js.map +1 -0
  144. package/docs/PRD.md +199 -0
  145. package/docs/PROMPT-agent.md +139 -0
  146. package/docs/SPEC-git-scope.md +172 -0
  147. package/docs/SPEC-heuristics.md +199 -0
  148. package/docs/SPEC-server.md +243 -0
  149. package/docs/SPEC-skeleton.md +255 -0
  150. package/docs/SPEC-sqlite-schema.md +183 -0
  151. package/docs/SPEC-tool-schema.md +201 -0
  152. package/docs/SPEC-vector-search.md +198 -0
  153. package/docs/TEST-scenarios.md +179 -0
  154. package/package.json +43 -0
  155. package/scripts/update-null-titles-ai.mjs +272 -0
  156. package/scripts/update-titles-batch.mjs +71 -0
  157. package/scripts/update-titles.mjs +66 -0
  158. package/seed-data.mjs +151 -0
  159. package/src/capabilities.ts +22 -0
  160. package/src/dashboard/dashboard.test.ts +546 -0
  161. package/src/dashboard/public/app.js +1187 -0
  162. package/src/dashboard/public/chart.js +0 -0
  163. package/src/dashboard/public/index.html +967 -0
  164. package/src/dashboard/server.ts +347 -0
  165. package/src/mcp/client.test.ts +164 -0
  166. package/src/mcp/client.ts +212 -0
  167. package/src/prompts/registry.ts +89 -0
  168. package/src/resources/index.test.ts +132 -0
  169. package/src/resources/index.ts +113 -0
  170. package/src/router.test.ts +145 -0
  171. package/src/router.ts +80 -0
  172. package/src/server.ts +99 -0
  173. package/src/storage/sqlite.test.ts +504 -0
  174. package/src/storage/sqlite.ts +688 -0
  175. package/src/storage/vectors.stub.ts +101 -0
  176. package/src/tools/memory.delete.ts +37 -0
  177. package/src/tools/memory.recap.ts +61 -0
  178. package/src/tools/memory.search.test.ts +276 -0
  179. package/src/tools/memory.search.ts +244 -0
  180. package/src/tools/memory.store.ts +56 -0
  181. package/src/tools/memory.summarize.ts +23 -0
  182. package/src/tools/memory.update.ts +46 -0
  183. package/src/tools/schemas.ts +261 -0
  184. package/src/types.ts +36 -0
  185. package/src/utils/git-scope.ts +42 -0
  186. package/src/utils/logger.test.ts +125 -0
  187. package/src/utils/logger.ts +53 -0
  188. package/src/utils/mcp-response.ts +116 -0
  189. package/src/utils/normalize.test.ts +203 -0
  190. package/src/utils/normalize.ts +53 -0
  191. package/src/utils/query-expander.test.ts +40 -0
  192. package/src/utils/query-expander.ts +60 -0
  193. package/storage/.gitkeep +5 -0
  194. package/test.sh +48 -0
  195. package/tsconfig.json +21 -0
  196. package/vitest.config.ts +10 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-response.js","sourceRoot":"","sources":["../../src/utils/mcp-response.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare const STOPWORDS: ReadonlySet<string>;
2
+ export declare function normalize(text: string): string;
3
+ export declare function tokenize(text: string): string[];
4
+ //# sourceMappingURL=normalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/utils/normalize.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,SAAS,EAAE,WAAW,CAAC,MAAM,CAiCxC,CAAC;AAEH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO9C;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAI/C"}
@@ -0,0 +1,51 @@
1
+ // Normalization layer for text processing
2
+ // Requirements: 4.1, 5.1, 17.4
3
+ // Combined English + Indonesian stopwords (all lowercase, no duplicates)
4
+ export const STOPWORDS = new Set([
5
+ // English stopwords
6
+ "a", "an", "the", "and", "or", "but", "in", "on", "at", "to", "for",
7
+ "of", "with", "by", "from", "up", "about", "into", "through", "during",
8
+ "is", "are", "was", "were", "be", "been", "being", "have", "has", "had",
9
+ "do", "does", "did", "will", "would", "could", "should", "may", "might",
10
+ "shall", "can", "need", "dare", "ought", "used",
11
+ "i", "me", "my", "myself", "we", "our", "ours", "ourselves",
12
+ "you", "your", "yours", "yourself", "yourselves",
13
+ "he", "him", "his", "himself", "she", "her", "hers", "herself",
14
+ "it", "its", "itself", "they", "them", "their", "theirs", "themselves",
15
+ "what", "which", "who", "whom", "this", "that", "these", "those",
16
+ "am", "if", "then", "else", "when", "where", "why", "how",
17
+ "all", "both", "each", "few", "more", "most", "other", "some", "such",
18
+ "no", "not", "only", "same", "so", "than", "too", "very",
19
+ "just", "because", "as", "until", "while", "although", "though",
20
+ "after", "before", "since", "between", "out", "off", "over", "under",
21
+ "again", "further", "once", "here", "there", "any", "also",
22
+ // Indonesian stopwords
23
+ "yang", "dan", "di", "ke", "dari", "ini", "itu", "dengan", "untuk",
24
+ "pada", "adalah", "dalam", "tidak", "akan", "juga", "ada", "saya",
25
+ "kita", "kami", "mereka", "dia", "ia", "anda", "kamu", "aku",
26
+ "bisa", "dapat", "harus", "sudah", "telah", "sedang", "masih",
27
+ "lebih", "sangat", "paling", "hanya", "jika", "kalau", "karena",
28
+ "sehingga", "namun", "tetapi", "tapi", "atau", "maupun", "bahwa",
29
+ "oleh", "seperti", "antara", "setelah", "sebelum", "ketika", "saat",
30
+ "semua", "setiap", "beberapa", "banyak", "sedikit", "lain", "lainnya",
31
+ "tersebut", "nya", "pun", "lah", "kah", "dah",
32
+ "agar", "supaya", "maka", "meski", "walaupun", "meskipun",
33
+ "selain", "selama", "sejak", "hingga", "sampai", "tentang",
34
+ "terhadap", "melalui", "tanpa", "bagi", "atas", "bawah",
35
+ "depan", "belakang", "kiri", "kanan", "sini", "sana", "situ",
36
+ "begitu", "begini", "demikian", "hal", "cara", "waktu", "tempat",
37
+ ]);
38
+ export function normalize(text) {
39
+ return text
40
+ .toLowerCase()
41
+ // Keep alphanumeric characters and spaces, including Unicode letters (for Indonesian, etc.)
42
+ .replace(/[^\w\s\u00C0-\u017F]/g, " ")
43
+ .replace(/\s+/g, " ")
44
+ .trim();
45
+ }
46
+ export function tokenize(text) {
47
+ return normalize(text)
48
+ .split(" ")
49
+ .filter((token) => token.length > 0 && !STOPWORDS.has(token));
50
+ }
51
+ //# sourceMappingURL=normalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/utils/normalize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=normalize.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.test.d.ts","sourceRoot":"","sources":["../../src/utils/normalize.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,159 @@
1
+ // Feature: memory-mcp-optimization
2
+ // Unit + Property tests for normalize(), tokenize(), and STOPWORDS
3
+ // Requirements: 5.4, 5.5, 17.3, 17.4, 17.7
4
+ import { describe, it, expect } from "vitest";
5
+ import * as fc from "fast-check";
6
+ import { normalize, tokenize, STOPWORDS } from "./normalize.js";
7
+ // ─── Unit Tests: normalize() ─────────────────────────────────────────────────
8
+ describe("normalize() — unit tests", () => {
9
+ it("converts text to lowercase", () => {
10
+ expect(normalize("Hello World")).toBe("hello world");
11
+ expect(normalize("TYPESCRIPT")).toBe("typescript");
12
+ expect(normalize("CamelCase")).toBe("camelcase");
13
+ });
14
+ it("trims leading and trailing whitespace", () => {
15
+ expect(normalize(" hello ")).toBe("hello");
16
+ expect(normalize("\t text \n")).toBe("text");
17
+ });
18
+ it("replaces special characters with spaces", () => {
19
+ const result = normalize("hello!world@test#value");
20
+ // Special chars replaced by spaces, then collapsed
21
+ expect(result).not.toContain("!");
22
+ expect(result).not.toContain("@");
23
+ expect(result).not.toContain("#");
24
+ });
25
+ it("collapses multiple spaces into one", () => {
26
+ expect(normalize("hello world")).toBe("hello world");
27
+ expect(normalize("a b c")).toBe("a b c");
28
+ });
29
+ it("handles empty string", () => {
30
+ expect(normalize("")).toBe("");
31
+ });
32
+ it("handles string with only special characters", () => {
33
+ expect(normalize("!!!@@@###")).toBe("");
34
+ });
35
+ it("preserves alphanumeric characters", () => {
36
+ expect(normalize("abc123")).toBe("abc123");
37
+ });
38
+ });
39
+ // ─── Unit Tests: tokenize() ──────────────────────────────────────────────────
40
+ describe("tokenize() — unit tests", () => {
41
+ it("removes stopwords from output", () => {
42
+ const tokens = tokenize("the quick brown fox");
43
+ expect(tokens).not.toContain("the");
44
+ expect(tokens).toContain("quick");
45
+ expect(tokens).toContain("brown");
46
+ expect(tokens).toContain("fox");
47
+ });
48
+ it("removes short words (length <= 0 after normalize)", () => {
49
+ // tokenize filters tokens with length > 0 and not in STOPWORDS
50
+ const tokens = tokenize("a b c hello");
51
+ // "a", "b", "c" are stopwords or single chars
52
+ expect(tokens).toContain("hello");
53
+ });
54
+ it("returns empty array for all-stopword input", () => {
55
+ const tokens = tokenize("the and or but");
56
+ expect(tokens).toEqual([]);
57
+ });
58
+ it("handles empty string", () => {
59
+ expect(tokenize("")).toEqual([]);
60
+ });
61
+ it("normalizes before tokenizing (lowercase, trim)", () => {
62
+ const tokens1 = tokenize("TypeScript");
63
+ const tokens2 = tokenize("typescript");
64
+ expect(tokens1).toEqual(tokens2);
65
+ });
66
+ it("removes Indonesian stopwords", () => {
67
+ const tokens = tokenize("yang dan di ke dari ini itu coding");
68
+ expect(tokens).not.toContain("yang");
69
+ expect(tokens).not.toContain("dan");
70
+ expect(tokens).toContain("coding");
71
+ });
72
+ });
73
+ // ─── Property 4: Tokenisasi konsisten antara SQLiteStore dan StubVectorStore ──
74
+ // Feature: memory-mcp-optimization, Property 4: Tokenisasi konsisten
75
+ // Validates: Requirements 4.4, 5.2, 5.3
76
+ describe("Property 4: Tokenisasi konsisten antara SQLiteStore dan StubVectorStore", () => {
77
+ it("tokenize() is deterministic — same input always produces same output", () => {
78
+ fc.assert(fc.property(fc.string({ minLength: 0, maxLength: 100 }), (text) => {
79
+ // Both SQLiteStore and StubVectorStore use tokenize() from normalize.ts
80
+ // So testing tokenize() determinism validates consistency between them
81
+ const result1 = tokenize(text);
82
+ const result2 = tokenize(text);
83
+ expect(result1).toEqual(result2);
84
+ }), { numRuns: 200 });
85
+ });
86
+ it("tokenize() output is a subset of normalize() tokens", () => {
87
+ fc.assert(fc.property(fc.string({ minLength: 0, maxLength: 100 }), (text) => {
88
+ const normalized = normalize(text);
89
+ const allTokens = normalized.split(" ").filter((t) => t.length > 0);
90
+ const filtered = tokenize(text);
91
+ // Every token in filtered must appear in allTokens
92
+ for (const token of filtered) {
93
+ expect(allTokens).toContain(token);
94
+ }
95
+ }), { numRuns: 200 });
96
+ });
97
+ });
98
+ // ─── Property 5: normalize() idempoten ganda ─────────────────────────────────
99
+ // Feature: memory-mcp-optimization, Property 5: normalize() idempoten ganda
100
+ // Validates: Requirements 5.4, 5.5
101
+ describe("Property 5: normalize() idempoten ganda", () => {
102
+ it("normalize(normalize(text)) === normalize(text) for 100+ random inputs", () => {
103
+ fc.assert(fc.property(fc.string({ minLength: 0, maxLength: 200 }), (text) => {
104
+ const once = normalize(text);
105
+ const twice = normalize(once);
106
+ expect(twice).toBe(once);
107
+ }), { numRuns: 200 });
108
+ });
109
+ it("normalize is idempotent for specific edge cases", () => {
110
+ const cases = [
111
+ "",
112
+ " ",
113
+ "Hello World!",
114
+ "UPPERCASE",
115
+ "already normalized",
116
+ "multiple spaces",
117
+ "special!@#chars",
118
+ "123numbers456",
119
+ ];
120
+ for (const text of cases) {
121
+ const once = normalize(text);
122
+ const twice = normalize(once);
123
+ expect(twice).toBe(once);
124
+ }
125
+ });
126
+ });
127
+ // ─── Property 21: Stopword list tidak mengandung duplikat ────────────────────
128
+ // Feature: memory-mcp-optimization, Property 21: Stopword no duplicates
129
+ // Validates: Requirement 17.4
130
+ describe("Property 21: Stopword list tidak mengandung duplikat", () => {
131
+ it("STOPWORDS has no duplicate entries", () => {
132
+ // Since STOPWORDS is a Set, duplicates are automatically removed.
133
+ // We verify the source array (before Set construction) has no duplicates
134
+ // by checking that Set size equals the number of unique entries.
135
+ // The Set itself guarantees uniqueness, so we verify the exported Set is consistent.
136
+ const stopwordsArray = Array.from(STOPWORDS);
137
+ const uniqueSet = new Set(stopwordsArray);
138
+ expect(uniqueSet.size).toBe(stopwordsArray.length);
139
+ });
140
+ it("all STOPWORDS entries are lowercase strings", () => {
141
+ for (const word of STOPWORDS) {
142
+ expect(typeof word).toBe("string");
143
+ expect(word).toBe(word.toLowerCase());
144
+ }
145
+ });
146
+ it("STOPWORDS is non-empty", () => {
147
+ expect(STOPWORDS.size).toBeGreaterThan(0);
148
+ });
149
+ it("property: no string appears more than once in STOPWORDS", () => {
150
+ // This is a structural property — verified once (not random inputs needed)
151
+ // since STOPWORDS is a constant Set
152
+ const seen = new Set();
153
+ for (const word of STOPWORDS) {
154
+ expect(seen.has(word)).toBe(false);
155
+ seen.add(word);
156
+ }
157
+ });
158
+ });
159
+ //# sourceMappingURL=normalize.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.test.js","sourceRoot":"","sources":["../../src/utils/normalize.test.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,mEAAmE;AACnE,2CAA2C;AAE3C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhE,gFAAgF;AAEhF,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrD,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACnD,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,MAAM,GAAG,SAAS,CAAC,wBAAwB,CAAC,CAAC;QACnD,mDAAmD;QACnD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACvD,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,gFAAgF;AAEhF,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,+DAA+D;QAC/D,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;QACvC,8CAA8C;QAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,MAAM,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,oCAAoC,CAAC,CAAC;QAC9D,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,iFAAiF;AACjF,qEAAqE;AACrE,wCAAwC;AAExC,QAAQ,CAAC,yEAAyE,EAAE,GAAG,EAAE;IACvF,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,EAAE,CAAC,MAAM,CACP,EAAE,CAAC,QAAQ,CACT,EAAE,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,EAC3C,CAAC,IAAY,EAAE,EAAE;YACf,wEAAwE;YACxE,uEAAuE;YACvE,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC,CACF,EACD,EAAE,OAAO,EAAE,GAAG,EAAE,CACjB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,EAAE,CAAC,MAAM,CACP,EAAE,CAAC,QAAQ,CACT,EAAE,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,EAC3C,CAAC,IAAY,EAAE,EAAE;YACf,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACpE,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAChC,mDAAmD;YACnD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;gBAC7B,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACrC,CAAC;QACH,CAAC,CACF,EACD,EAAE,OAAO,EAAE,GAAG,EAAE,CACjB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,gFAAgF;AAChF,4EAA4E;AAC5E,mCAAmC;AAEnC,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACvD,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,EAAE,CAAC,MAAM,CACP,EAAE,CAAC,QAAQ,CACT,EAAE,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,EAC3C,CAAC,IAAY,EAAE,EAAE;YACf,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC7B,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC,CACF,EACD,EAAE,OAAO,EAAE,GAAG,EAAE,CACjB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,KAAK,GAAG;YACZ,EAAE;YACF,KAAK;YACL,cAAc;YACd,WAAW;YACX,oBAAoB;YACpB,mBAAmB;YACnB,iBAAiB;YACjB,eAAe;SAChB,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC7B,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,gFAAgF;AAChF,wEAAwE;AACxE,8BAA8B;AAE9B,QAAQ,CAAC,sDAAsD,EAAE,GAAG,EAAE;IACpE,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,kEAAkE;QAClE,yEAAyE;QACzE,iEAAiE;QACjE,qFAAqF;QACrF,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;QAC1C,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,2EAA2E;QAC3E,oCAAoC;QACpC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function expandQuery(query: string, prompt?: string): string;
2
+ //# sourceMappingURL=query-expander.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-expander.d.ts","sourceRoot":"","sources":["../../src/utils/query-expander.ts"],"names":[],"mappings":"AA4CA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAelE"}
@@ -0,0 +1,50 @@
1
+ import { tokenize, normalize } from "./normalize.js";
2
+ const KEYWORD_EXPANSION = {
3
+ database: ["sql", "orm", "query", "migration", "schema", "postgresql", "mysql"],
4
+ auth: ["authentication", "login", "password", "jwt", "token", "session", "oauth"],
5
+ login: ["auth", "authentication", "password", "jwt", "session", "credential"],
6
+ api: ["rest", "endpoint", "controller", "route", "request", "response"],
7
+ test: ["testing", "unit", "integration", "vitest", "jest", "mock"],
8
+ model: ["entity", "schema", "relation", "eloquent", "migration"],
9
+ frontend: ["ui", "react", "vue", "component", "tailwind", "css"],
10
+ backend: ["server", "api", "controller", "service", "database"],
11
+ security: ["encryption", "hash", "csrf", "xss", "sanitize", "validation"],
12
+ performance: ["cache", "optimization", "index", "query", "lazy", "eager"],
13
+ deployment: ["docker", "nginx", "ci", "cd", "pipeline", "deploy"],
14
+ };
15
+ function expandKeyword(keyword) {
16
+ const normalized = normalize(keyword).toLowerCase();
17
+ return KEYWORD_EXPANSION[normalized] || [];
18
+ }
19
+ function extractIntentKeywords(prompt) {
20
+ const tokens = tokenize(prompt);
21
+ const important = tokens.filter((t) => {
22
+ if (t.length < 3)
23
+ return false;
24
+ const stopWords = [
25
+ "need", "want", "how", "what", "when", "where", "why",
26
+ "using", "with", "implement", "create", "build", "make",
27
+ "have", "get", "find", "look", "search", "trying",
28
+ ];
29
+ return !stopWords.includes(t);
30
+ });
31
+ const expanded = [];
32
+ for (const token of important) {
33
+ expanded.push(token);
34
+ const expansions = expandKeyword(token);
35
+ expanded.push(...expansions);
36
+ }
37
+ return [...new Set(expanded)];
38
+ }
39
+ export function expandQuery(query, prompt) {
40
+ const normalizedQuery = normalize(query);
41
+ const queryTokens = normalizedQuery.split(/\s+/).filter((t) => t.length > 0);
42
+ if (!prompt) {
43
+ return queryTokens.join(" ");
44
+ }
45
+ const intentKeywords = extractIntentKeywords(prompt);
46
+ const combined = new Set([...queryTokens, ...intentKeywords]);
47
+ const result = Array.from(combined).slice(0, 10).join(" ");
48
+ return result.length > 3 ? result : queryTokens.join(" ");
49
+ }
50
+ //# sourceMappingURL=query-expander.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-expander.js","sourceRoot":"","sources":["../../src/utils/query-expander.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=query-expander.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-expander.test.d.ts","sourceRoot":"","sources":["../../src/utils/query-expander.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,35 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { expandQuery } from "../utils/query-expander.js";
3
+ describe("expandQuery", () => {
4
+ it("returns original query when no prompt provided", () => {
5
+ expect(expandQuery("database")).toBe("database");
6
+ expect(expandQuery("api endpoint")).toBe("api endpoint");
7
+ });
8
+ it("expands query with prompt keywords", () => {
9
+ const result = expandQuery("database", "user authentication implementation");
10
+ expect(result).toContain("database");
11
+ expect(result).toContain("user");
12
+ expect(result).toContain("auth");
13
+ });
14
+ it("expands known keywords", () => {
15
+ const result = expandQuery("auth", "login system");
16
+ expect(result).toContain("auth");
17
+ expect(result).toContain("login");
18
+ expect(result).toContain("password");
19
+ });
20
+ it("limits to 10 keywords", () => {
21
+ const result = expandQuery("api", "building a rest endpoint with controller and route handling");
22
+ const words = result.split(" ");
23
+ expect(words.length).toBeLessThanOrEqual(10);
24
+ });
25
+ it("removes duplicates", () => {
26
+ const result = expandQuery("database", "database query optimization");
27
+ const words = result.split(" ");
28
+ const unique = new Set(words);
29
+ expect(words.length).toBe(unique.size);
30
+ });
31
+ it("handles empty prompt gracefully", () => {
32
+ expect(expandQuery("test", "")).toBe("test");
33
+ });
34
+ });
35
+ //# sourceMappingURL=query-expander.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-expander.test.js","sourceRoot":"","sources":["../../src/utils/query-expander.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACjD,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,MAAM,GAAG,WAAW,CAAC,UAAU,EAAE,oCAAoC,CAAC,CAAC;QAC7E,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,EAAE,6DAA6D,CAAC,CAAC;QACjG,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,MAAM,GAAG,WAAW,CAAC,UAAU,EAAE,6BAA6B,CAAC,CAAC;QACtE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/docs/PRD.md ADDED
@@ -0,0 +1,199 @@
1
+ # PRD – MCP Local Memory Service
2
+
3
+ ## TL;DR
4
+
5
+ Membangun **MCP Local Memory Service** berbasis Node.js yang menyediakan *long-term, high-signal memory* untuk coding copilot & antigravity agent. Sistem ini menyimpan keputusan, fakta kode, kesalahan, dan pola penting menggunakan SQLite + vector similarity search, sehingga agent tetap konsisten, tidak mengulang kesalahan, dan tahan terhadap typo / variasi query.
6
+
7
+ ---
8
+
9
+ ## Problem Statement
10
+
11
+ Coding copilot dan agent saat ini:
12
+ - Mudah kehilangan konteks keputusan sebelumnya
13
+ - Mengulang kesalahan yang sama
14
+ - Overfit ke prompt terakhir (*gravity problem*)
15
+ - Lemah terhadap typo atau phrasing berbeda
16
+
17
+ Tanpa memory terstruktur, agent terasa "pintar sesaat" tapi tidak reliable untuk penggunaan jangka panjang.
18
+
19
+ ---
20
+
21
+ ## Goals
22
+
23
+ ### Business Goals
24
+ - Meningkatkan kualitas dan konsistensi output coding copilot
25
+ - Mengurangi user correction berulang
26
+ - Menjadikan agent usable untuk long-running projects
27
+
28
+ ### User Goals
29
+ - Agent mengingat keputusan & constraint penting
30
+ - Agent tidak mengulang kesalahan lama
31
+ - Agent tetap relevan walau prompt berubah atau typo
32
+
33
+ ### Non-Goals
34
+ - Bukan chat history logger
35
+ - Bukan audit trail
36
+ - Tidak mendukung distributed / cloud sync (local-first)
37
+
38
+ ---
39
+
40
+ ## Target Users
41
+ - Developer menggunakan coding copilot lokal
42
+ - Power user / engineer yang menginginkan agent “punya ingatan”
43
+ - Pengguna MCP-based agent system
44
+
45
+ ---
46
+
47
+ ## User Stories
48
+ 1. **Sebagai developer**, saya ingin agent mengingat keputusan arsitektur agar tidak perlu menjelaskannya berulang kali.
49
+ 2. **Sebagai developer**, saya ingin agent tidak mengulang kesalahan yang sudah saya koreksi sebelumnya.
50
+ 3. **Sebagai developer**, saya ingin agent tetap menemukan memory relevan walau saya salah ketik atau pakai istilah berbeda.
51
+ 4. **Sebagai agent**, saya ingin memory yang ringkas dan relevan agar tidak membanjiri prompt.
52
+
53
+ ---
54
+
55
+ ## Memory Types (Core Concept)
56
+
57
+ ### 1. code_fact
58
+ Fakta stabil tentang codebase.
59
+ *Contoh:*
60
+ - Project pakai clean architecture
61
+ - Semua API pakai zod validation
62
+
63
+ ### 2. decision
64
+ Keputusan desain atau arsitektur.
65
+ *Contoh:*
66
+ - Tidak menggunakan ORM
67
+ - Menggunakan raw SQL demi performa
68
+
69
+ ### 3. mistake
70
+ Kesalahan yang tidak boleh diulang.
71
+ *Contoh:*
72
+ - Jangan pakai default export
73
+ - Jangan gunakan `any` di domain layer
74
+
75
+ ### 4. pattern
76
+ Pola kode atau konvensi yang sering dipakai.
77
+ *Contoh:*
78
+ - Struktur handler
79
+ - Pola error handling
80
+
81
+ ---
82
+
83
+ ## User Experience (End-to-End Flow)
84
+
85
+ ### 1. Normal Interaction
86
+ 1. User meminta agent generate / modify code
87
+ 2. Agent membaca project summary (jika ada)
88
+ 3. Agent mencari memory relevan via semantic search
89
+ 4. Memory terpilih diinjeksi ke prompt
90
+ 5. Agent menghasilkan code sesuai constraint
91
+
92
+ ### 2. Memory Creation Flow
93
+ 1. User memberi constraint / koreksi penting
94
+ 2. Agent mendeteksi sinyal *memory-worthy*
95
+ 3. Agent menyimpan memory via MCP tool
96
+ 4. Agent (opsional) update project summary
97
+
98
+ ---
99
+
100
+ ## Narrative (Executive Story)
101
+
102
+ Bayangkan seorang developer bekerja di codebase selama berminggu-minggu. Ia sudah menetapkan aturan: arsitektur tertentu, larangan tertentu, dan pola kode yang disepakati.
103
+
104
+ Tanpa memory, setiap hari agent kembali seperti "intern baru" — pintar, tapi lupa segalanya.
105
+
106
+ Dengan **MCP Local Memory Service**, agent berubah menjadi rekan tim yang belajar:
107
+ - Mengingat keputusan
108
+ - Menghindari kesalahan lama
109
+ - Berpikir di level arsitektur
110
+
111
+ Ini bukan soal membuat agent lebih pintar — tapi membuatnya lebih dapat dipercaya.
112
+
113
+ ---
114
+
115
+ ## Functional Requirements
116
+
117
+ ### Memory Storage
118
+ - Menyimpan memory bertipe: `code_fact`, `decision`, `mistake`, `pattern`
119
+ - Mendukung metadata scope (repo, language, folder)
120
+ - Mendukung importance score (1–5)
121
+
122
+ ### Memory Retrieval
123
+ - Semantic similarity search (vector-based)
124
+ - Tahan typo & variasi bahasa
125
+ - Mendukung filtering by type, scope, importance
126
+
127
+ ### Memory Summary
128
+ - Ringkasan high-level per repo
129
+ - Digunakan sebagai *antigravity anchor*
130
+
131
+ ---
132
+
133
+ ## MCP Interface
134
+
135
+ ### Resources
136
+ - `memory://entries`
137
+ - `memory://summary`
138
+
139
+ ### Tools
140
+ - `memory.search`
141
+ - `memory.store`
142
+ - `memory.summarize`
143
+
144
+ Agent tidak mengetahui detail database atau vector engine.
145
+
146
+ ---
147
+
148
+ ## Success Metrics
149
+
150
+ ### Quantitative
151
+ - Penurunan jumlah user correction berulang
152
+ - Peningkatan reuse memory dalam prompt
153
+ - Latency memory search < 100ms (local)
154
+
155
+ ### Qualitative
156
+ - Agent terasa konsisten
157
+ - Agent tidak mengulang kesalahan lama
158
+ - User trust meningkat
159
+
160
+ ---
161
+
162
+ ## Technical Considerations
163
+ - Node.js MCP server
164
+ - SQLite sebagai primary storage
165
+ - Vector similarity via sqlite extension atau embedded index
166
+ - Local embedding model (via Ollama / llama.cpp)
167
+ - Normalization layer untuk typo handling
168
+
169
+ ---
170
+
171
+ ## Milestones & Sequencing
172
+ 1. MCP contract & interface definition (XX weeks)
173
+ 2. SQLite schema + vector indexing (XX weeks)
174
+ 3. Memory search & ranking logic (XX weeks)
175
+ 4. Agent prompt integration (XX weeks)
176
+ 5. Heuristic-based auto memory rules (XX weeks)
177
+
178
+ ---
179
+
180
+ ## Risks & Mitigations
181
+ - **Risk: Memory pollution**
182
+ - *Mitigasi:* strict store rules + importance threshold
183
+ - **Risk: Prompt bloat**
184
+ - *Mitigasi:* limit memory injection + summary usage
185
+ - **Risk: Overfitting memory**
186
+ - *Mitigasi:* relevance threshold + scope filtering
187
+
188
+ ---
189
+
190
+ ## Open Questions
191
+ - Perlu manual memory deletion UI?
192
+ - Perlu memory versioning?
193
+ - Perlu cross-repo inference di masa depan?
194
+
195
+ ---
196
+
197
+ ## Final Take
198
+ Produk ini bukan tentang database atau vector search.
199
+ Ini tentang mendisiplinkan ingatan agent agar ia benar-benar berguna untuk kerja nyata.