mindlore 0.6.9 → 0.7.1

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 (152) hide show
  1. package/README.md +31 -4
  2. package/dist/scripts/bundle-hooks.d.ts +2 -0
  3. package/dist/scripts/bundle-hooks.d.ts.map +1 -0
  4. package/dist/scripts/bundle-hooks.js +68 -0
  5. package/dist/scripts/bundle-hooks.js.map +1 -0
  6. package/dist/scripts/cc-memory-bulk-sync.d.ts.map +1 -1
  7. package/dist/scripts/cc-memory-bulk-sync.js +2 -1
  8. package/dist/scripts/cc-memory-bulk-sync.js.map +1 -1
  9. package/dist/scripts/cc-session-sync.d.ts.map +1 -1
  10. package/dist/scripts/cc-session-sync.js +3 -2
  11. package/dist/scripts/cc-session-sync.js.map +1 -1
  12. package/dist/scripts/init.js +4 -4
  13. package/dist/scripts/init.js.map +1 -1
  14. package/dist/scripts/lib/constants.d.ts +1 -2
  15. package/dist/scripts/lib/constants.d.ts.map +1 -1
  16. package/dist/scripts/lib/constants.js +2 -22
  17. package/dist/scripts/lib/constants.js.map +1 -1
  18. package/dist/scripts/lib/err-msg.d.ts +2 -0
  19. package/dist/scripts/lib/err-msg.d.ts.map +1 -0
  20. package/dist/scripts/lib/err-msg.js +7 -0
  21. package/dist/scripts/lib/err-msg.js.map +1 -0
  22. package/dist/scripts/lib/mcp-namespace.d.ts +2 -0
  23. package/dist/scripts/lib/mcp-namespace.d.ts.map +1 -0
  24. package/dist/scripts/lib/mcp-namespace.js +21 -0
  25. package/dist/scripts/lib/mcp-namespace.js.map +1 -0
  26. package/dist/scripts/lib/mcp-telemetry.d.ts +11 -0
  27. package/dist/scripts/lib/mcp-telemetry.d.ts.map +1 -0
  28. package/dist/scripts/lib/mcp-telemetry.js +37 -0
  29. package/dist/scripts/lib/mcp-telemetry.js.map +1 -0
  30. package/dist/scripts/lib/mcp-tools.d.ts +10 -0
  31. package/dist/scripts/lib/mcp-tools.d.ts.map +1 -0
  32. package/dist/scripts/lib/mcp-tools.js +121 -0
  33. package/dist/scripts/lib/mcp-tools.js.map +1 -0
  34. package/dist/scripts/lib/rrf.d.ts.map +1 -1
  35. package/dist/scripts/lib/rrf.js +2 -1
  36. package/dist/scripts/lib/rrf.js.map +1 -1
  37. package/dist/scripts/lib/search-engine.d.ts +1 -0
  38. package/dist/scripts/lib/search-engine.d.ts.map +1 -1
  39. package/dist/scripts/lib/search-engine.js +9 -5
  40. package/dist/scripts/lib/search-engine.js.map +1 -1
  41. package/dist/scripts/lib/slugify.d.ts +2 -0
  42. package/dist/scripts/lib/slugify.d.ts.map +1 -0
  43. package/dist/scripts/lib/slugify.js +13 -0
  44. package/dist/scripts/lib/slugify.js.map +1 -0
  45. package/dist/scripts/lib/smart-snippet.d.ts +9 -0
  46. package/dist/scripts/lib/smart-snippet.d.ts.map +1 -0
  47. package/dist/scripts/lib/smart-snippet.js +47 -0
  48. package/dist/scripts/lib/smart-snippet.js.map +1 -0
  49. package/dist/scripts/lib/tool-adapters/brief-adapter.d.ts +15 -0
  50. package/dist/scripts/lib/tool-adapters/brief-adapter.d.ts.map +1 -0
  51. package/dist/scripts/lib/tool-adapters/brief-adapter.js +66 -0
  52. package/dist/scripts/lib/tool-adapters/brief-adapter.js.map +1 -0
  53. package/dist/scripts/lib/tool-adapters/decide-adapter.d.ts +31 -0
  54. package/dist/scripts/lib/tool-adapters/decide-adapter.d.ts.map +1 -0
  55. package/dist/scripts/lib/tool-adapters/decide-adapter.js +71 -0
  56. package/dist/scripts/lib/tool-adapters/decide-adapter.js.map +1 -0
  57. package/dist/scripts/lib/tool-adapters/ingest-adapter.d.ts +16 -0
  58. package/dist/scripts/lib/tool-adapters/ingest-adapter.d.ts.map +1 -0
  59. package/dist/scripts/lib/tool-adapters/ingest-adapter.js +58 -0
  60. package/dist/scripts/lib/tool-adapters/ingest-adapter.js.map +1 -0
  61. package/dist/scripts/lib/tool-adapters/recall-adapter.d.ts +20 -0
  62. package/dist/scripts/lib/tool-adapters/recall-adapter.d.ts.map +1 -0
  63. package/dist/scripts/lib/tool-adapters/recall-adapter.js +69 -0
  64. package/dist/scripts/lib/tool-adapters/recall-adapter.js.map +1 -0
  65. package/dist/scripts/lib/tool-adapters/search-adapter.d.ts +22 -0
  66. package/dist/scripts/lib/tool-adapters/search-adapter.d.ts.map +1 -0
  67. package/dist/scripts/lib/tool-adapters/search-adapter.js +32 -0
  68. package/dist/scripts/lib/tool-adapters/search-adapter.js.map +1 -0
  69. package/dist/scripts/lib/tool-adapters/stats-adapter.d.ts +15 -0
  70. package/dist/scripts/lib/tool-adapters/stats-adapter.d.ts.map +1 -0
  71. package/dist/scripts/lib/tool-adapters/stats-adapter.js +66 -0
  72. package/dist/scripts/lib/tool-adapters/stats-adapter.js.map +1 -0
  73. package/dist/scripts/maintain-cleanup.d.ts.map +1 -1
  74. package/dist/scripts/maintain-cleanup.js +3 -2
  75. package/dist/scripts/maintain-cleanup.js.map +1 -1
  76. package/dist/scripts/mcp-server.d.ts +3 -0
  77. package/dist/scripts/mcp-server.d.ts.map +1 -0
  78. package/dist/scripts/mcp-server.js +85 -0
  79. package/dist/scripts/mcp-server.js.map +1 -0
  80. package/dist/scripts/mindlore-doctor.d.ts.map +1 -1
  81. package/dist/scripts/mindlore-doctor.js +4 -6
  82. package/dist/scripts/mindlore-doctor.js.map +1 -1
  83. package/dist/scripts/mindlore-fts5-index.js +2 -2
  84. package/dist/scripts/mindlore-fts5-index.js.map +1 -1
  85. package/dist/scripts/mindlore-health-check.d.ts.map +1 -1
  86. package/dist/scripts/mindlore-health-check.js +2 -2
  87. package/dist/scripts/mindlore-health-check.js.map +1 -1
  88. package/dist/scripts/validate-manifest-cli.js +2 -2
  89. package/dist/scripts/validate-manifest-cli.js.map +1 -1
  90. package/dist/tests/err-msg.test.d.ts +2 -0
  91. package/dist/tests/err-msg.test.d.ts.map +1 -0
  92. package/dist/tests/err-msg.test.js +24 -0
  93. package/dist/tests/err-msg.test.js.map +1 -0
  94. package/dist/tests/hook-smoke.test.js +1 -1
  95. package/dist/tests/hook-smoke.test.js.map +1 -1
  96. package/dist/tests/manifest-v2.test.js +0 -7
  97. package/dist/tests/manifest-v2.test.js.map +1 -1
  98. package/dist/tests/mcp-server.test.d.ts +2 -0
  99. package/dist/tests/mcp-server.test.d.ts.map +1 -0
  100. package/dist/tests/mcp-server.test.js +118 -0
  101. package/dist/tests/mcp-server.test.js.map +1 -0
  102. package/dist/tests/mcp-tools.test.d.ts +2 -0
  103. package/dist/tests/mcp-tools.test.d.ts.map +1 -0
  104. package/dist/tests/mcp-tools.test.js +243 -0
  105. package/dist/tests/mcp-tools.test.js.map +1 -0
  106. package/dist/tests/search-hook.test.js +1 -1
  107. package/dist/tests/search-hook.test.js.map +1 -1
  108. package/dist/tests/smart-snippet.test.d.ts +2 -0
  109. package/dist/tests/smart-snippet.test.d.ts.map +1 -0
  110. package/dist/tests/smart-snippet.test.js +67 -0
  111. package/dist/tests/smart-snippet.test.js.map +1 -0
  112. package/hooks/cc-memory-bulk-sync.cjs +592 -0
  113. package/hooks/cc-session-sync.cjs +842 -0
  114. package/hooks/hooks.json +149 -0
  115. package/hooks/lib/mindlore-common.cjs +2 -2
  116. package/hooks/lib/secure-io.cjs +17 -0
  117. package/hooks/mindlore-cwd-changed.cjs +19 -34
  118. package/hooks/mindlore-decision-detector.cjs +40 -31
  119. package/hooks/mindlore-dont-repeat.cjs +57 -115
  120. package/hooks/mindlore-fts5-sync.cjs +15 -44
  121. package/hooks/mindlore-index.cjs +100 -101
  122. package/hooks/mindlore-model-router.cjs +20 -32
  123. package/hooks/mindlore-post-compact.cjs +26 -42
  124. package/hooks/mindlore-post-read.cjs +35 -60
  125. package/hooks/mindlore-pre-compact.cjs +55 -73
  126. package/hooks/mindlore-read-guard.cjs +28 -51
  127. package/hooks/mindlore-research-guard.cjs +63 -101
  128. package/hooks/mindlore-search.cjs +1142 -93
  129. package/hooks/mindlore-session-end.cjs +155 -276
  130. package/hooks/mindlore-session-focus.cjs +639 -110
  131. package/hooks/src/lib/constants.cjs +15 -0
  132. package/hooks/src/lib/mindlore-common.cjs +975 -0
  133. package/hooks/src/lib/mindlore-common.d.cts +72 -0
  134. package/hooks/src/lib/secure-io.cjs +17 -0
  135. package/hooks/src/lib/types.d.ts +58 -0
  136. package/hooks/src/mindlore-cwd-changed.cjs +57 -0
  137. package/hooks/src/mindlore-decision-detector.cjs +54 -0
  138. package/hooks/src/mindlore-dont-repeat.cjs +222 -0
  139. package/hooks/src/mindlore-fts5-sync.cjs +98 -0
  140. package/hooks/src/mindlore-index.cjs +230 -0
  141. package/hooks/src/mindlore-model-router.cjs +54 -0
  142. package/hooks/src/mindlore-post-compact.cjs +69 -0
  143. package/hooks/src/mindlore-post-read.cjs +106 -0
  144. package/hooks/src/mindlore-pre-compact.cjs +154 -0
  145. package/hooks/src/mindlore-read-guard.cjs +105 -0
  146. package/hooks/src/mindlore-research-guard.cjs +176 -0
  147. package/hooks/src/mindlore-search.cjs +200 -0
  148. package/hooks/src/mindlore-session-end.cjs +511 -0
  149. package/hooks/src/mindlore-session-focus.cjs +256 -0
  150. package/package.json +8 -3
  151. package/plugin.json +7 -1
  152. package/templates/config.json +1 -1
@@ -1,116 +1,1175 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+
29
+ // dist/scripts/lib/constants.js
30
+ var require_constants = __commonJS({
31
+ "dist/scripts/lib/constants.js"(exports2) {
32
+ "use strict";
33
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
34
+ return mod && mod.__esModule ? mod : { "default": mod };
35
+ };
36
+ Object.defineProperty(exports2, "__esModule", { value: true });
37
+ exports2.CONSOLIDATION_THRESHOLD = exports2.STALE_THRESHOLD = exports2.DECAY_HALF_LIFE_DAYS = exports2.DEFAULT_TOKEN_BUDGET = exports2.CC_MEMORY_BOOST = exports2.CC_SUBAGENT_CATEGORY = exports2.CC_SESSION_CATEGORY = exports2.CC_MEMORY_CATEGORY = exports2.CC_MEMORY_DIR = exports2.CC_MEMORY_PATH_MARKER = exports2.TYPE_TO_DIR = exports2.QUALITY_HEURISTICS = exports2.QUALITY_VALUES = exports2.FRONTMATTER_TYPES = exports2.FTS5_COLUMNS = exports2.STOP_WORDS = exports2.TURKISH_WORD_RE = exports2.STOP_WORDS_MIN_LENGTH = exports2.SESSION_CATEGORIES = exports2.CATEGORIES = exports2.SCHEMA_VERSION = exports2.DEFAULT_MODELS = exports2.CONFIG_FILE = exports2.MCP_BUSY_TIMEOUT_MS = exports2.DB_BUSY_TIMEOUT_MS = exports2.SKIP_FILES = exports2.DIRECTORIES = exports2.DB_NAME = exports2.GLOBAL_MINDLORE_DIR = exports2.MINDLORE_DIR = exports2.KNOWN_HOOK_EVENTS = void 0;
38
+ exports2.isKnownHookEvent = isKnownHookEvent;
39
+ exports2.isSessionCategory = isSessionCategory;
40
+ exports2.fixVersionTokens = fixVersionTokens;
41
+ exports2.homedir = homedir;
42
+ exports2.getActiveMindloreDir = getActiveMindloreDir;
43
+ exports2.getAllDbs = getAllDbs2;
44
+ exports2.getProjectName = getProjectName;
45
+ exports2.log = log;
46
+ exports2.isContentFile = isContentFile;
47
+ exports2.resolveHookCommon = resolveHookCommon;
48
+ exports2.hasYoutubeTranscript = hasYoutubeTranscript;
49
+ var os_1 = __importDefault(require("os"));
50
+ var fs_1 = __importDefault(require("fs"));
51
+ var path_1 = __importDefault(require("path"));
52
+ exports2.KNOWN_HOOK_EVENTS = [
53
+ "SessionStart",
54
+ "SessionEnd",
55
+ "UserPromptSubmit",
56
+ "FileChanged",
57
+ "PreToolUse",
58
+ "PostToolUse",
59
+ "PreCompact",
60
+ "PostCompact",
61
+ "CwdChanged"
62
+ ];
63
+ function isKnownHookEvent(s) {
64
+ return exports2.KNOWN_HOOK_EVENTS.includes(s);
65
+ }
66
+ exports2.MINDLORE_DIR = ".mindlore";
67
+ exports2.GLOBAL_MINDLORE_DIR = process.env.MINDLORE_HOME ?? path_1.default.join(os_1.default.homedir(), exports2.MINDLORE_DIR);
68
+ exports2.DB_NAME = "mindlore.db";
69
+ exports2.DIRECTORIES = [
70
+ "raw",
71
+ "sources",
72
+ "domains",
73
+ "analyses",
74
+ "insights",
75
+ "connections",
76
+ "learnings",
77
+ "diary",
78
+ "decisions",
79
+ "logs",
80
+ "memory"
81
+ ];
82
+ exports2.SKIP_FILES = /* @__PURE__ */ new Set(["INDEX.md", "SCHEMA.md", "log.md"]);
83
+ exports2.DB_BUSY_TIMEOUT_MS = 2e3;
84
+ exports2.MCP_BUSY_TIMEOUT_MS = 5e3;
85
+ exports2.CONFIG_FILE = "config.json";
86
+ exports2.DEFAULT_MODELS = {
87
+ ingest: "haiku",
88
+ evolve: "sonnet",
89
+ explore: "sonnet",
90
+ default: "haiku"
91
+ };
92
+ exports2.SCHEMA_VERSION = 1;
93
+ exports2.CATEGORIES = ["sources", "analyses", "domains", "episodes", "decisions", "raw", "sessions", "cc_memory", "cc-session", "cc-subagent", "diary", "insights", "connections", "learnings", "memory"];
94
+ exports2.SESSION_CATEGORIES = ["cc-subagent", "cc-session"];
95
+ function isSessionCategory(category) {
96
+ return exports2.SESSION_CATEGORIES.includes(category);
97
+ }
98
+ exports2.STOP_WORDS_MIN_LENGTH = 2;
99
+ exports2.TURKISH_WORD_RE = /[^\w\sçğıöşüÇĞİÖŞÜ-]/g;
100
+ exports2.STOP_WORDS = /* @__PURE__ */ new Set([
101
+ // English
102
+ "the",
103
+ "a",
104
+ "an",
105
+ "is",
106
+ "are",
107
+ "was",
108
+ "were",
109
+ "be",
110
+ "been",
111
+ "being",
112
+ "have",
113
+ "has",
114
+ "had",
115
+ "do",
116
+ "does",
117
+ "did",
118
+ "will",
119
+ "would",
120
+ "could",
121
+ "should",
122
+ "may",
123
+ "might",
124
+ "can",
125
+ "shall",
126
+ "to",
127
+ "of",
128
+ "in",
129
+ "for",
130
+ "on",
131
+ "with",
132
+ "at",
133
+ "by",
134
+ "from",
135
+ "as",
136
+ "into",
137
+ "through",
138
+ "during",
139
+ "it",
140
+ "its",
141
+ "this",
142
+ "that",
143
+ "these",
144
+ "those",
145
+ "what",
146
+ "which",
147
+ "who",
148
+ "whom",
149
+ "how",
150
+ "when",
151
+ "where",
152
+ "why",
153
+ "not",
154
+ "no",
155
+ "nor",
156
+ "so",
157
+ "if",
158
+ "or",
159
+ "but",
160
+ "all",
161
+ "each",
162
+ "every",
163
+ "both",
164
+ "few",
165
+ "more",
166
+ "most",
167
+ "other",
168
+ "some",
169
+ "such",
170
+ "only",
171
+ "own",
172
+ "same",
173
+ "than",
174
+ "and",
175
+ "about",
176
+ "between",
177
+ "after",
178
+ "before",
179
+ "above",
180
+ "below",
181
+ "up",
182
+ "down",
183
+ "out",
184
+ "very",
185
+ "just",
186
+ "also",
187
+ "now",
188
+ "then",
189
+ "here",
190
+ "there",
191
+ "too",
192
+ "yet",
193
+ "my",
194
+ "your",
195
+ "his",
196
+ "her",
197
+ "our",
198
+ "their",
199
+ "me",
200
+ "him",
201
+ "us",
202
+ "them",
203
+ "i",
204
+ "you",
205
+ "he",
206
+ "she",
207
+ "we",
208
+ "they",
209
+ // Turkish
210
+ "bir",
211
+ "bu",
212
+ "su",
213
+ "ne",
214
+ "nas\u0131l",
215
+ "neden",
216
+ "var",
217
+ "yok",
218
+ "mi",
219
+ "mu",
220
+ "m\u0131",
221
+ "ile",
222
+ "i\xE7in",
223
+ "de",
224
+ "da",
225
+ "ve",
226
+ "veya",
227
+ "ama",
228
+ "ise",
229
+ "hem",
230
+ "bakal\u0131m",
231
+ "gel",
232
+ "git",
233
+ "yap",
234
+ "et",
235
+ "al",
236
+ "ver",
237
+ "evet",
238
+ "hay\u0131r",
239
+ "tamam",
240
+ "ok",
241
+ "oldu",
242
+ "olur",
243
+ "dur",
244
+ "\u015Fimdi",
245
+ "sonra",
246
+ "\xF6nce",
247
+ "hemen",
248
+ "biraz",
249
+ "lan",
250
+ "ya",
251
+ "ki",
252
+ "abi",
253
+ "hadi",
254
+ "hey",
255
+ "selam",
256
+ "olarak",
257
+ "olan",
258
+ "gibi",
259
+ "kadar",
260
+ "daha",
261
+ "\xE7ok",
262
+ "en",
263
+ "bunu",
264
+ "buna",
265
+ "i\xE7inde",
266
+ "\xFCzerinde",
267
+ "aras\u0131nda",
268
+ "sonucu",
269
+ "taraf\u0131ndan",
270
+ "zaten",
271
+ "gayet",
272
+ "acaba",
273
+ "nedir",
274
+ "midir",
275
+ "mudur",
276
+ // Generic technical
277
+ "hook",
278
+ "file",
279
+ "dosya",
280
+ "kullan",
281
+ "ekle",
282
+ "yaz",
283
+ "oku",
284
+ "\xE7al\u0131\u015Ft\u0131r",
285
+ "kontrol",
286
+ "test",
287
+ "check",
288
+ "run",
289
+ "add",
290
+ "update",
291
+ "config",
292
+ "setup",
293
+ "install",
294
+ "start",
295
+ "stop",
296
+ "create",
297
+ "delete",
298
+ "remove",
299
+ "set",
300
+ "get",
301
+ "list",
302
+ "show",
303
+ "view",
304
+ "open",
305
+ "close",
306
+ "save",
307
+ "load"
308
+ ]);
309
+ var VERSION_RE = /v(\d+)\.(\d+)(?:\.(\d+))?/g;
310
+ function fixVersionTokens(query) {
311
+ return query.replace(VERSION_RE, (_m, a, b, c) => c ? `"v${a} ${b} ${c}"` : `"v${a} ${b}"`);
312
+ }
313
+ exports2.FTS5_COLUMNS = ["path", "slug", "description", "type", "category", "title", "content", "tags", "quality", "date_captured", "project"];
314
+ exports2.FRONTMATTER_TYPES = ["raw", "source", "domain", "analysis", "diary", "decision", "insight", "connection", "learning", "feedback", "user", "project", "reference", "note"];
315
+ exports2.QUALITY_VALUES = ["high", "medium", "low"];
316
+ exports2.QUALITY_HEURISTICS = {
317
+ "github-repo": "high",
318
+ "docs": "high",
319
+ "blog": "medium",
320
+ "video": "medium",
321
+ "x-thread": "medium",
322
+ "text-paste": "low",
323
+ "snippet": "low",
324
+ "forum": "low",
325
+ "cc-session": "low",
326
+ "cc-subagent": "low"
327
+ };
328
+ exports2.TYPE_TO_DIR = {
329
+ raw: "raw",
330
+ source: "sources",
331
+ domain: "domains",
332
+ analysis: "analyses",
333
+ insight: "insights",
334
+ connection: "connections",
335
+ learning: "learnings",
336
+ decision: "decisions",
337
+ diary: "diary",
338
+ feedback: "memory",
339
+ user: "memory",
340
+ project: "memory",
341
+ reference: "memory",
342
+ note: "memory"
343
+ };
344
+ exports2.CC_MEMORY_PATH_MARKER = path_1.default.join(".claude", "projects");
345
+ exports2.CC_MEMORY_DIR = "memory";
346
+ exports2.CC_MEMORY_CATEGORY = "cc-memory";
347
+ exports2.CC_SESSION_CATEGORY = "cc-session";
348
+ exports2.CC_SUBAGENT_CATEGORY = "cc-subagent";
349
+ exports2.CC_MEMORY_BOOST = 1.2;
350
+ function homedir() {
351
+ return os_1.default.homedir();
352
+ }
353
+ function getActiveMindloreDir() {
354
+ return exports2.GLOBAL_MINDLORE_DIR;
355
+ }
356
+ function getAllDbs2() {
357
+ const dbPath = path_1.default.join(exports2.GLOBAL_MINDLORE_DIR, exports2.DB_NAME);
358
+ if (fs_1.default.existsSync(dbPath))
359
+ return [dbPath];
360
+ return [];
361
+ }
362
+ function getProjectName() {
363
+ return path_1.default.basename(process.cwd());
364
+ }
365
+ function log(msg) {
366
+ console.log(` ${msg}`);
367
+ }
368
+ function isContentFile(filePath) {
369
+ return !exports2.SKIP_FILES.has(path_1.default.basename(filePath));
370
+ }
371
+ function resolveHookCommon(callerDir) {
372
+ let dir = callerDir;
373
+ for (let i = 0; i < 5; i++) {
374
+ const target = path_1.default.join(dir, "hooks", "lib", "mindlore-common.cjs");
375
+ if (fs_1.default.existsSync(target))
376
+ return target;
377
+ const parent = path_1.default.dirname(dir);
378
+ if (parent === dir)
379
+ break;
380
+ dir = parent;
381
+ }
382
+ return path_1.default.resolve(callerDir, "..", "..", "hooks", "lib", "mindlore-common.cjs");
383
+ }
384
+ function hasYoutubeTranscript() {
385
+ try {
386
+ require.resolve("youtube-transcript");
387
+ return true;
388
+ } catch (_err) {
389
+ return false;
390
+ }
391
+ }
392
+ exports2.DEFAULT_TOKEN_BUDGET = {
393
+ sessionInject: 2e3,
394
+ searchResults: 1500,
395
+ perResult: 500
396
+ };
397
+ exports2.DECAY_HALF_LIFE_DAYS = 30;
398
+ exports2.STALE_THRESHOLD = 0.3;
399
+ exports2.CONSOLIDATION_THRESHOLD = 50;
400
+ }
401
+ });
402
+
403
+ // dist/scripts/lib/db-helpers.js
404
+ var require_db_helpers = __commonJS({
405
+ "dist/scripts/lib/db-helpers.js"(exports2) {
406
+ "use strict";
407
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
408
+ return mod && mod.__esModule ? mod : { "default": mod };
409
+ };
410
+ Object.defineProperty(exports2, "__esModule", { value: true });
411
+ exports2.dbGet = dbGet;
412
+ exports2.dbAll = dbAll;
413
+ exports2.dbPragma = dbPragma;
414
+ exports2.withReadonlyDb = withReadonlyDb;
415
+ exports2.openDatabaseTs = openDatabaseTs;
416
+ var better_sqlite3_1 = __importDefault(require("better-sqlite3"));
417
+ var fs_1 = __importDefault(require("fs"));
418
+ var constants_js_1 = require_constants();
419
+ function dbGet(db, sql, ...params) {
420
+ const result = db.prepare(sql).get(...params);
421
+ if (result === void 0)
422
+ return void 0;
423
+ if (typeof result !== "object" || result === null) {
424
+ throw new TypeError(`Expected object from query, got ${typeof result}`);
425
+ }
426
+ return result;
427
+ }
428
+ function dbAll(db, sql, ...params) {
429
+ const results = db.prepare(sql).all(...params);
430
+ return results;
431
+ }
432
+ function dbPragma(db, pragma) {
433
+ const result = db.pragma(pragma);
434
+ return result;
435
+ }
436
+ function withReadonlyDb(dbPath, fn) {
437
+ let db = null;
438
+ try {
439
+ db = new better_sqlite3_1.default(dbPath, { readonly: true });
440
+ return fn(db);
441
+ } catch {
442
+ return void 0;
443
+ } finally {
444
+ db?.close();
445
+ }
446
+ }
447
+ function openDatabaseTs(dbPath, options) {
448
+ try {
449
+ if (!fs_1.default.existsSync(dbPath))
450
+ return null;
451
+ const readonly = options?.readonly ?? false;
452
+ const db = new better_sqlite3_1.default(dbPath, { readonly });
453
+ if (!readonly) {
454
+ db.pragma("journal_mode = WAL");
455
+ db.pragma(`busy_timeout = ${constants_js_1.DB_BUSY_TIMEOUT_MS}`);
456
+ }
457
+ return db;
458
+ } catch {
459
+ return null;
460
+ }
461
+ }
462
+ }
463
+ });
464
+
465
+ // dist/scripts/lib/err-msg.js
466
+ var require_err_msg = __commonJS({
467
+ "dist/scripts/lib/err-msg.js"(exports2) {
468
+ "use strict";
469
+ Object.defineProperty(exports2, "__esModule", { value: true });
470
+ exports2.errMsg = errMsg;
471
+ function errMsg(err) {
472
+ return err instanceof Error ? err.message : String(err);
473
+ }
474
+ }
475
+ });
476
+
477
+ // dist/scripts/lib/rrf.js
478
+ var require_rrf = __commonJS({
479
+ "dist/scripts/lib/rrf.js"(exports2) {
480
+ "use strict";
481
+ Object.defineProperty(exports2, "__esModule", { value: true });
482
+ exports2.sanitizeFtsQuery = sanitizeFtsQuery;
483
+ exports2.computeRRF = computeRRF;
484
+ exports2.searchPorter = searchPorter;
485
+ exports2.searchTrigram = searchTrigram;
486
+ var db_helpers_js_1 = require_db_helpers();
487
+ var err_msg_js_1 = require_err_msg();
488
+ function sanitizeFtsQuery(query) {
489
+ return query.replace(/["*(){}[\]^~:-]/g, " ").replace(/\s+/g, " ").trim();
490
+ }
491
+ var BM25_RANK_EXPR = "bm25(mindlore_fts, 1, 1, 1, 5.0, 1, 1) as bm";
492
+ function computeRRF(porterResults, trigramResults, options = {}) {
493
+ const k = options.k ?? 60;
494
+ const scores = /* @__PURE__ */ new Map();
495
+ for (const list of [porterResults, trigramResults]) {
496
+ for (const r of list) {
497
+ const existing = scores.get(r.slug);
498
+ const rrfScore = 1 / (k + r.rank);
499
+ if (existing) {
500
+ existing.score += rrfScore;
501
+ } else {
502
+ scores.set(r.slug, { ...r, score: rrfScore });
503
+ }
504
+ }
505
+ }
506
+ let results = Array.from(scores.values()).sort((a, b) => b.score - a.score);
507
+ if (options.dedupByPath) {
508
+ const seen = /* @__PURE__ */ new Set();
509
+ results = results.filter((r) => {
510
+ if (seen.has(r.path))
511
+ return false;
512
+ seen.add(r.path);
513
+ return true;
514
+ });
515
+ }
516
+ return results;
517
+ }
518
+ function _searchFts(db, p) {
519
+ const sql = p.project ? `SELECT path, slug, description, title, category, tags, content, ${p.rankExpr} FROM ${p.table} WHERE ${p.table} MATCH ? AND project = ? ORDER BY ${p.orderBy} LIMIT ?` : `SELECT path, slug, description, title, category, tags, content, ${p.rankExpr} FROM ${p.table} WHERE ${p.table} MATCH ? ORDER BY ${p.orderBy} LIMIT ?`;
520
+ const params = p.project ? [p.query, p.project, p.limit] : [p.query, p.limit];
521
+ return (0, db_helpers_js_1.dbAll)(db, sql, ...params).map((r, i) => ({ ...r, rank: i + 1, score: 0 }));
522
+ }
523
+ function searchPorter(db, options) {
524
+ const sanitized = sanitizeFtsQuery(options.query);
525
+ if (!sanitized)
526
+ return [];
527
+ return _searchFts(db, { table: "mindlore_fts", rankExpr: BM25_RANK_EXPR, orderBy: "bm", query: sanitized, project: options.project, limit: options.limit });
528
+ }
529
+ function searchTrigram(db, options) {
530
+ const sanitized = sanitizeFtsQuery(options.query);
531
+ if (!sanitized)
532
+ return [];
533
+ try {
534
+ return _searchFts(db, { table: "mindlore_fts_trigram", rankExpr: "rank", orderBy: "rank", query: sanitized, project: options.project, limit: options.limit });
535
+ } catch (err) {
536
+ const msg = (0, err_msg_js_1.errMsg)(err);
537
+ if (!msg.includes("no such table")) {
538
+ console.warn(`searchTrigram: ${msg}`);
539
+ }
540
+ return [];
541
+ }
542
+ }
543
+ }
544
+ });
545
+
546
+ // dist/scripts/lib/fuzzy.js
547
+ var require_fuzzy = __commonJS({
548
+ "dist/scripts/lib/fuzzy.js"(exports2) {
549
+ "use strict";
550
+ Object.defineProperty(exports2, "__esModule", { value: true });
551
+ exports2.levenshtein = levenshtein;
552
+ exports2.findClosestWords = findClosestWords;
553
+ exports2.loadVocabulary = loadVocabulary;
554
+ exports2.invalidateVocabCache = invalidateVocabCache;
555
+ exports2.populateVocabulary = populateVocabulary;
556
+ exports2.correctQuery = correctQuery;
557
+ var db_helpers_js_1 = require_db_helpers();
558
+ var constants_js_1 = require_constants();
559
+ function levenshtein(a, b) {
560
+ const m = a.length, n = b.length;
561
+ const prev = new Int32Array(n + 1);
562
+ const curr = new Int32Array(n + 1);
563
+ for (let j = 0; j <= n; j++)
564
+ prev[j] = j;
565
+ for (let i = 1; i <= m; i++) {
566
+ curr[0] = i;
567
+ for (let j = 1; j <= n; j++) {
568
+ curr[j] = a[i - 1] === b[j - 1] ? prev[j - 1] : 1 + Math.min(prev[j], curr[j - 1], prev[j - 1]);
569
+ }
570
+ for (let j = 0; j <= n; j++)
571
+ prev[j] = curr[j];
572
+ }
573
+ return prev[n];
574
+ }
575
+ function maxDistance(wordLen) {
576
+ if (wordLen <= 4)
577
+ return 1;
578
+ if (wordLen <= 7)
579
+ return 2;
580
+ return 3;
581
+ }
582
+ function findClosestWords(word, vocabulary, limit = 3) {
583
+ const maxDist = maxDistance(word.length);
584
+ const lower = word.toLowerCase();
585
+ const candidates = [];
586
+ for (const v of vocabulary) {
587
+ if (Math.abs(v.length - lower.length) > maxDist)
588
+ continue;
589
+ const dist = levenshtein(lower, v.toLowerCase());
590
+ if (dist > 0 && dist <= maxDist) {
591
+ candidates.push({ word: v, dist });
592
+ }
593
+ }
594
+ return candidates.sort((a, b) => a.dist - b.dist).slice(0, limit).map((c) => c.word);
595
+ }
596
+ var vocabCache = null;
597
+ function loadVocabulary(db) {
598
+ const dbName = db.name;
599
+ if (vocabCache && vocabCache.dbName === dbName)
600
+ return vocabCache.words;
601
+ const words = (0, db_helpers_js_1.dbAll)(db, "SELECT word FROM vocabulary").map((r) => r.word);
602
+ vocabCache = { dbName, words };
603
+ return words;
604
+ }
605
+ function invalidateVocabCache() {
606
+ vocabCache = null;
607
+ }
608
+ function populateVocabulary(db, content) {
609
+ const words = content.replace(constants_js_1.TURKISH_WORD_RE, " ").split(/\s+/).filter((w) => w.length >= 3).map((w) => w.toLowerCase());
610
+ const unique = [...new Set(words)];
611
+ const stmt = db.prepare("INSERT OR IGNORE INTO vocabulary (word) VALUES (?)");
612
+ for (const w of unique)
613
+ stmt.run(w);
614
+ }
615
+ function correctQuery(db, keywords) {
616
+ const vocab = loadVocabulary(db);
617
+ if (vocab.length === 0)
618
+ return null;
619
+ let corrected = false;
620
+ const result = keywords.map((kw) => {
621
+ const closest = findClosestWords(kw, vocab, 1);
622
+ const match = closest[0];
623
+ if (match !== void 0 && match !== kw) {
624
+ corrected = true;
625
+ return match;
626
+ }
627
+ return kw;
628
+ });
629
+ return corrected ? result : null;
630
+ }
631
+ }
632
+ });
633
+
634
+ // dist/scripts/lib/proximity.js
635
+ var require_proximity = __commonJS({
636
+ "dist/scripts/lib/proximity.js"(exports2) {
637
+ "use strict";
638
+ Object.defineProperty(exports2, "__esModule", { value: true });
639
+ exports2.rerankByProximity = rerankByProximity;
640
+ function findMinSpan(content, terms) {
641
+ const lower = content.toLowerCase();
642
+ const positions = terms.map((t) => {
643
+ const pos = [];
644
+ let idx = lower.indexOf(t);
645
+ while (idx !== -1) {
646
+ pos.push(idx);
647
+ idx = lower.indexOf(t, idx + 1);
648
+ }
649
+ return pos;
650
+ });
651
+ if (positions.some((p) => p.length === 0))
652
+ return Infinity;
653
+ let minSpan = Infinity;
654
+ for (let i = 0; i < positions[0].length; i++) {
655
+ let maxPos = positions[0][i];
656
+ let minPos = positions[0][i];
657
+ for (let t = 1; t < terms.length; t++) {
658
+ let bestDist = Infinity;
659
+ let bestPos = 0;
660
+ for (let j = 0; j < positions[t].length; j++) {
661
+ const dist = Math.abs(positions[t][j] - positions[0][i]);
662
+ if (dist < bestDist) {
663
+ bestDist = dist;
664
+ bestPos = positions[t][j];
665
+ }
666
+ }
667
+ if (bestPos > maxPos)
668
+ maxPos = bestPos;
669
+ if (bestPos < minPos)
670
+ minPos = bestPos;
671
+ }
672
+ const span = maxPos - minPos;
673
+ if (span < minSpan)
674
+ minSpan = span;
675
+ }
676
+ return minSpan;
677
+ }
678
+ function rerankByProximity(results, terms) {
679
+ if (terms.length < 2)
680
+ return results;
681
+ return results.map((r) => {
682
+ const span = findMinSpan(r.content ?? "", terms);
683
+ const boost = span === Infinity ? 1 : 1 + 1 / (1 + span / 50);
684
+ return { ...r, score: r.score * boost };
685
+ }).sort((a, b) => b.score - a.score);
686
+ }
687
+ }
688
+ });
689
+
690
+ // dist/scripts/lib/snippet.js
691
+ var require_snippet = __commonJS({
692
+ "dist/scripts/lib/snippet.js"(exports2) {
693
+ "use strict";
694
+ Object.defineProperty(exports2, "__esModule", { value: true });
695
+ exports2.extractSnippet = extractSnippet;
696
+ function extractSnippet(content, terms, maxLen = 300) {
697
+ if (!content || content.length <= maxLen)
698
+ return content;
699
+ const lower = content.toLowerCase();
700
+ let bestPos = 0;
701
+ let bestScore = 0;
702
+ for (const term of terms) {
703
+ const idx = lower.indexOf(term.toLowerCase());
704
+ if (idx !== -1) {
705
+ const windowStart = Math.max(0, idx - Math.floor(maxLen / 2));
706
+ const windowEnd = Math.min(lower.length, idx + Math.floor(maxLen / 2));
707
+ const window = lower.slice(windowStart, windowEnd);
708
+ const termCount = terms.filter((t) => window.includes(t.toLowerCase())).length;
709
+ if (termCount > bestScore) {
710
+ bestScore = termCount;
711
+ bestPos = idx;
712
+ }
713
+ }
714
+ }
715
+ const start = Math.max(0, bestPos - Math.floor(maxLen / 3));
716
+ const end = Math.min(content.length, start + maxLen);
717
+ let snippet = content.slice(start, end);
718
+ if (start > 0)
719
+ snippet = "..." + snippet;
720
+ if (end < content.length)
721
+ snippet = snippet + "...";
722
+ return snippet;
723
+ }
724
+ }
725
+ });
3
726
 
4
- /**
5
- * mindlore-search — UserPromptSubmit hook
6
- *
7
- * Thin wrapper over search-engine.ts pipeline.
8
- * Extracts keywords from user prompt, delegates search to modular engine,
9
- * injects top results with description + headings.
10
- */
727
+ // dist/scripts/lib/chunker.js
728
+ var require_chunker = __commonJS({
729
+ "dist/scripts/lib/chunker.js"(exports2) {
730
+ "use strict";
731
+ Object.defineProperty(exports2, "__esModule", { value: true });
732
+ exports2.chunkMarkdown = chunkMarkdown;
733
+ function chunkMarkdown(markdown, options = {}) {
734
+ const maxChunkChars = options.maxChunkChars ?? 1e4;
735
+ const lines = markdown.split("\n");
736
+ const chunks = [];
737
+ let currentLines = [];
738
+ let currentHeading = null;
739
+ const headingStack = [];
740
+ let inCodeBlock = false;
741
+ function flush() {
742
+ const content = currentLines.join("\n").trim();
743
+ if (content.length === 0)
744
+ return;
745
+ const breadcrumb = headingStack.length > 0 ? headingStack.join(" > ") : "";
746
+ const chunk = {
747
+ index: 0,
748
+ heading: currentHeading,
749
+ breadcrumb,
750
+ content,
751
+ charCount: content.length
752
+ };
753
+ if (chunk.charCount > maxChunkChars) {
754
+ for (const c of splitOversized(chunk, maxChunkChars))
755
+ chunks.push(c);
756
+ } else {
757
+ chunks.push(chunk);
758
+ }
759
+ currentLines = [];
760
+ }
761
+ for (const line of lines) {
762
+ if (line.startsWith("```")) {
763
+ inCodeBlock = !inCodeBlock;
764
+ currentLines.push(line);
765
+ continue;
766
+ }
767
+ if (inCodeBlock) {
768
+ currentLines.push(line);
769
+ continue;
770
+ }
771
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)/);
772
+ if (headingMatch) {
773
+ flush();
774
+ currentHeading = line;
775
+ const level = headingMatch[1].length;
776
+ while (headingStack.length > 0) {
777
+ const top = headingStack[headingStack.length - 1];
778
+ const topLevel = (top.match(/^#+/) ?? [""])[0].length;
779
+ if (topLevel >= level)
780
+ headingStack.pop();
781
+ else
782
+ break;
783
+ }
784
+ headingStack.push(line);
785
+ }
786
+ currentLines.push(line);
787
+ }
788
+ flush();
789
+ return chunks.map((c, i) => ({ ...c, index: i }));
790
+ }
791
+ function splitOversized(chunk, maxChars) {
792
+ const lines = chunk.content.split("\n");
793
+ const result = [];
794
+ let buffer = [];
795
+ let bufLen = 0;
796
+ for (const line of lines) {
797
+ if (bufLen + line.length > maxChars && buffer.length > 0) {
798
+ result.push({
799
+ index: 0,
800
+ heading: result.length === 0 ? chunk.heading : null,
801
+ breadcrumb: chunk.breadcrumb,
802
+ content: buffer.join("\n"),
803
+ charCount: bufLen
804
+ });
805
+ buffer = [];
806
+ bufLen = 0;
807
+ }
808
+ buffer.push(line);
809
+ bufLen += line.length + 1;
810
+ }
811
+ if (buffer.length > 0) {
812
+ result.push({
813
+ index: 0,
814
+ heading: result.length === 0 ? chunk.heading : null,
815
+ breadcrumb: chunk.breadcrumb,
816
+ content: buffer.join("\n"),
817
+ charCount: bufLen
818
+ });
819
+ }
820
+ return result;
821
+ }
822
+ }
823
+ });
11
824
 
12
- const fs = require('fs');
13
- const path = require('path');
14
- const { getAllDbs, openDatabase, extractHeadings, readHookStdin, readConfig, hookLog, incrementRecallCount, withTelemetry } = require('./lib/mindlore-common.cjs');
825
+ // dist/scripts/lib/smart-snippet.js
826
+ var require_smart_snippet = __commonJS({
827
+ "dist/scripts/lib/smart-snippet.js"(exports2) {
828
+ "use strict";
829
+ Object.defineProperty(exports2, "__esModule", { value: true });
830
+ exports2.extractSmartSnippet = extractSmartSnippet;
831
+ var snippet_js_1 = require_snippet();
832
+ var chunker_js_1 = require_chunker();
833
+ function extractSmartSnippet(db, sourcePath, fullContent, terms, maxLen = 500) {
834
+ if (!fullContent || fullContent.length <= maxLen) {
835
+ return { snippet: fullContent, heading: null };
836
+ }
837
+ let chunks;
838
+ try {
839
+ chunks = db.prepare("SELECT chunk_index, heading, breadcrumb, char_count FROM chunks WHERE source_path = ? ORDER BY chunk_index").all(sourcePath);
840
+ } catch {
841
+ return { snippet: (0, snippet_js_1.extractSnippet)(fullContent, terms, maxLen), heading: null };
842
+ }
843
+ if (chunks.length === 0) {
844
+ return { snippet: (0, snippet_js_1.extractSnippet)(fullContent, terms, maxLen), heading: null };
845
+ }
846
+ const parsedChunks = (0, chunker_js_1.chunkMarkdown)(fullContent);
847
+ const lowerTerms = terms.map((t) => t.toLowerCase());
848
+ let bestChunkIdx = -1;
849
+ let bestScore = 0;
850
+ for (let i = 0; i < parsedChunks.length; i++) {
851
+ const parsed = parsedChunks[i];
852
+ if (!parsed)
853
+ continue;
854
+ const chunkLower = parsed.content.toLowerCase();
855
+ const score = lowerTerms.filter((t) => chunkLower.includes(t)).length;
856
+ if (score > bestScore) {
857
+ bestScore = score;
858
+ bestChunkIdx = i;
859
+ }
860
+ }
861
+ if (bestChunkIdx === -1) {
862
+ return { snippet: (0, snippet_js_1.extractSnippet)(fullContent, terms, maxLen), heading: null };
863
+ }
864
+ const bestParsed = parsedChunks[bestChunkIdx];
865
+ if (!bestParsed) {
866
+ return { snippet: (0, snippet_js_1.extractSnippet)(fullContent, terms, maxLen), heading: null };
867
+ }
868
+ const chunkSnippet = (0, snippet_js_1.extractSnippet)(bestParsed.content, terms, maxLen);
869
+ const heading = chunks[bestChunkIdx]?.heading ?? bestParsed.heading ?? null;
870
+ return { snippet: chunkSnippet, heading };
871
+ }
872
+ }
873
+ });
874
+
875
+ // dist/scripts/lib/search-engine.js
876
+ var require_search_engine = __commonJS({
877
+ "dist/scripts/lib/search-engine.js"(exports2) {
878
+ "use strict";
879
+ Object.defineProperty(exports2, "__esModule", { value: true });
880
+ exports2.extractKeywords = extractKeywords;
881
+ exports2.search = search;
882
+ var rrf_js_1 = require_rrf();
883
+ var fuzzy_js_1 = require_fuzzy();
884
+ var proximity_js_1 = require_proximity();
885
+ var smart_snippet_js_1 = require_smart_snippet();
886
+ var constants_js_1 = require_constants();
887
+ function extractKeywords(text, maxKeywords) {
888
+ const keywords = text.replace(constants_js_1.TURKISH_WORD_RE, " ").split(/\s+/).filter((w) => w.length >= constants_js_1.STOP_WORDS_MIN_LENGTH && !constants_js_1.STOP_WORDS.has(w.toLowerCase())).map((w) => w.toLowerCase());
889
+ return maxKeywords ? keywords.slice(0, maxKeywords) : keywords;
890
+ }
891
+ function expandWithSynonyms(keywords, synonyms) {
892
+ if (!synonyms)
893
+ return keywords;
894
+ const expanded = [...keywords];
895
+ for (const kw of keywords) {
896
+ const syns = synonyms[kw];
897
+ if (syns)
898
+ expanded.push(...syns);
899
+ }
900
+ return expanded;
901
+ }
902
+ var CATEGORY_WEIGHTS = {
903
+ sources: 1.2,
904
+ analyses: 1.15,
905
+ domains: 1.1,
906
+ episodes: 1,
907
+ decisions: 1,
908
+ raw: 0.9,
909
+ sessions: 0.85,
910
+ cc_memory: 1.3
911
+ };
912
+ var INTENT_CONFIG = {
913
+ debug: {
914
+ keywords: ["debug", "fix", "hata", "bug", "error", "crash", "fail"],
915
+ boosts: { episodes: 1.3, raw: 1.1 }
916
+ },
917
+ research: {
918
+ keywords: ["ara\u015Ft\u0131r", "bul", "search", "nedir", "nas\u0131l", "compare"],
919
+ boosts: { sources: 1.3, analyses: 1.2 }
920
+ },
921
+ implementation: {
922
+ keywords: [],
923
+ boosts: { domains: 1.2, sessions: 1.1 }
924
+ }
925
+ };
926
+ var INTENT_KEYS = Object.keys(INTENT_CONFIG);
927
+ function detectIntent(query) {
928
+ const lower = query.toLowerCase();
929
+ for (const intent of INTENT_KEYS) {
930
+ if (INTENT_CONFIG[intent].keywords.some((k) => lower.includes(k)))
931
+ return intent;
932
+ }
933
+ return "implementation";
934
+ }
935
+ function search(db, query, options) {
936
+ const maxResults = options.maxResults ?? 3;
937
+ const keywords = extractKeywords(query);
938
+ if (keywords.length === 0)
939
+ return [];
940
+ const expanded = expandWithSynonyms(keywords, options.synonyms);
941
+ const queryStr = (0, constants_js_1.fixVersionTokens)(expanded.join(" "));
942
+ const limit = 20;
943
+ function fusedSearch(q) {
944
+ return (0, rrf_js_1.computeRRF)((0, rrf_js_1.searchPorter)(db, { query: q, limit, project: options.project }), (0, rrf_js_1.searchTrigram)(db, { query: q, limit, project: options.project }), { dedupByPath: true });
945
+ }
946
+ let fused = fusedSearch(queryStr);
947
+ if (fused.length === 0) {
948
+ const corrected = (0, fuzzy_js_1.correctQuery)(db, keywords);
949
+ if (corrected) {
950
+ fused = fusedSearch((0, constants_js_1.fixVersionTokens)(corrected.join(" ")));
951
+ }
952
+ }
953
+ const intent = detectIntent(query);
954
+ const intentBoosts = INTENT_CONFIG[intent].boosts;
955
+ for (const r of fused) {
956
+ r.score *= CATEGORY_WEIGHTS[r.category] ?? 1;
957
+ r.score *= intentBoosts[r.category] ?? 1;
958
+ }
959
+ fused.sort((a, b) => b.score - a.score);
960
+ const ranked = (0, proximity_js_1.rerankByProximity)(fused.map((r) => ({
961
+ slug: r.slug,
962
+ path: r.path,
963
+ title: r.title ?? "",
964
+ description: r.description ?? "",
965
+ category: r.category ?? "",
966
+ tags: r.tags ?? "",
967
+ score: r.score,
968
+ content: r.content
969
+ })), keywords);
970
+ return ranked.slice(0, maxResults).map((r) => {
971
+ const smart = r.content ? (0, smart_snippet_js_1.extractSmartSnippet)(db, r.path, r.content, keywords) : void 0;
972
+ return {
973
+ ...r,
974
+ snippet: smart?.snippet,
975
+ heading: smart?.heading ?? null
976
+ };
977
+ });
978
+ }
979
+ }
980
+ });
15
981
 
16
- const MAX_RESULTS = 3;
17
- const MIN_QUERY_WORDS = 3;
982
+ // dist/scripts/lib/search-cache.js
983
+ var require_search_cache = __commonJS({
984
+ "dist/scripts/lib/search-cache.js"(exports2) {
985
+ "use strict";
986
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
987
+ return mod && mod.__esModule ? mod : { "default": mod };
988
+ };
989
+ Object.defineProperty(exports2, "__esModule", { value: true });
990
+ exports2.SearchThrottle = exports2.SearchCache = void 0;
991
+ var crypto_1 = __importDefault(require("crypto"));
992
+ var CLEANUP_INTERVAL_MS = 6e4;
993
+ var SearchCache = class {
994
+ db;
995
+ ttlMs;
996
+ statsReady = false;
997
+ stmtHit = null;
998
+ stmtMiss = null;
999
+ lastCleanup = 0;
1000
+ constructor(db, options = {}) {
1001
+ this.db = db;
1002
+ this.ttlMs = options.ttlMs ?? 3e5;
1003
+ }
1004
+ hash(query) {
1005
+ return crypto_1.default.createHash("sha256").update(query).digest("hex").slice(0, 16);
1006
+ }
1007
+ ensureStatsTable() {
1008
+ if (this.statsReady)
1009
+ return;
1010
+ this.db.exec(`
1011
+ CREATE TABLE IF NOT EXISTS search_cache_stats (
1012
+ id INTEGER PRIMARY KEY CHECK (id = 1),
1013
+ hits INTEGER NOT NULL DEFAULT 0,
1014
+ misses INTEGER NOT NULL DEFAULT 0
1015
+ )
1016
+ `);
1017
+ this.db.prepare("INSERT OR IGNORE INTO search_cache_stats (id, hits, misses) VALUES (1, 0, 0)").run();
1018
+ this.stmtHit = this.db.prepare("UPDATE search_cache_stats SET hits = hits + 1 WHERE id = 1");
1019
+ this.stmtMiss = this.db.prepare("UPDATE search_cache_stats SET misses = misses + 1 WHERE id = 1");
1020
+ this.statsReady = true;
1021
+ }
1022
+ getStats() {
1023
+ this.ensureStatsTable();
1024
+ const row = this.db.prepare("SELECT hits, misses FROM search_cache_stats WHERE id = 1").get();
1025
+ const total = row.hits + row.misses;
1026
+ return { hits: row.hits, misses: row.misses, hitRate: total > 0 ? row.hits / total : 0 };
1027
+ }
1028
+ resetStats() {
1029
+ this.ensureStatsTable();
1030
+ this.db.prepare("UPDATE search_cache_stats SET hits = 0, misses = 0 WHERE id = 1").run();
1031
+ }
1032
+ get(query) {
1033
+ const h = this.hash(query);
1034
+ const row = this.db.prepare("SELECT results_json FROM search_cache WHERE query_hash = ? AND expires_at > ?").get(h, (/* @__PURE__ */ new Date()).toISOString());
1035
+ if (!row) {
1036
+ this.ensureStatsTable();
1037
+ this.stmtMiss.run();
1038
+ this.cleanup();
1039
+ return null;
1040
+ }
1041
+ this.ensureStatsTable();
1042
+ this.stmtHit.run();
1043
+ return JSON.parse(row.results_json);
1044
+ }
1045
+ set(query, results) {
1046
+ const h = this.hash(query);
1047
+ const expiresAt = new Date(Date.now() + this.ttlMs).toISOString();
1048
+ this.db.prepare("INSERT OR REPLACE INTO search_cache (query_hash, results_json, expires_at) VALUES (?, ?, ?)").run(h, JSON.stringify(results), expiresAt);
1049
+ }
1050
+ invalidate() {
1051
+ this.db.exec("DELETE FROM search_cache");
1052
+ }
1053
+ cleanup() {
1054
+ const now = Date.now();
1055
+ if (now - this.lastCleanup < CLEANUP_INTERVAL_MS)
1056
+ return;
1057
+ this.lastCleanup = now;
1058
+ this.db.prepare("DELETE FROM search_cache WHERE expires_at < ?").run((/* @__PURE__ */ new Date()).toISOString());
1059
+ }
1060
+ };
1061
+ exports2.SearchCache = SearchCache;
1062
+ var SearchThrottle = class {
1063
+ db;
1064
+ constructor(db) {
1065
+ this.db = db;
1066
+ }
1067
+ incrementCallCount(sessionId) {
1068
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1069
+ const row = this.db.prepare(`
1070
+ INSERT INTO search_throttle (session_id, call_count, last_call)
1071
+ VALUES (?, 1, ?)
1072
+ ON CONFLICT(session_id) DO UPDATE SET call_count = call_count + 1, last_call = ?
1073
+ RETURNING call_count
1074
+ `).get(sessionId, now, now);
1075
+ return row?.call_count ?? 1;
1076
+ }
1077
+ getMaxResults(callCount) {
1078
+ if (callCount <= 10)
1079
+ return 3;
1080
+ if (callCount <= 20)
1081
+ return 1;
1082
+ return 0;
1083
+ }
1084
+ };
1085
+ exports2.SearchThrottle = SearchThrottle;
1086
+ }
1087
+ });
18
1088
 
19
- let searchEngineMod;
1089
+ // hooks/src/mindlore-search.cjs
1090
+ var fs = require("fs");
1091
+ var path = require("path");
1092
+ var { getAllDbs, openDatabase, extractHeadings, readHookStdin, readConfig, hookLog, incrementRecallCount, withTelemetry } = require("./lib/mindlore-common.cjs");
1093
+ var MAX_RESULTS = 3;
1094
+ var MIN_QUERY_WORDS = 3;
1095
+ var searchEngineMod;
20
1096
  try {
21
- searchEngineMod = require('../dist/scripts/lib/search-engine.js');
1097
+ searchEngineMod = require_search_engine();
22
1098
  } catch (_err) {
23
- // search-engine not built yet
24
1099
  }
25
-
26
- let SearchCacheMod;
1100
+ var SearchCacheMod;
27
1101
  try {
28
- SearchCacheMod = require('../dist/scripts/lib/search-cache.js');
1102
+ SearchCacheMod = require_search_cache();
29
1103
  } catch (_err) {
30
- // search-cache not built yet
31
1104
  }
32
-
33
1105
  function main() {
34
- const userMessage = readHookStdin(['prompt', 'content', 'message', 'query']);
1106
+ const userMessage = readHookStdin(["prompt", "content", "message", "query"]);
35
1107
  if (!userMessage || userMessage.length < MIN_QUERY_WORDS) return;
36
-
37
1108
  const dbPaths = getAllDbs();
38
1109
  if (dbPaths.length === 0) return;
39
-
40
1110
  if (!searchEngineMod) {
41
- hookLog('search', 'warn', 'search-engine module not available skipping');
1111
+ hookLog("search", "warn", "search-engine module not available \u2014 skipping");
42
1112
  return;
43
1113
  }
44
-
45
1114
  const project = path.basename(process.cwd());
46
1115
  const config = readConfig(path.dirname(dbPaths[0]));
47
- const synonyms = (config && config.synonyms) ? config.synonyms : {};
48
-
49
- // Read session_id from stdin for throttling
1116
+ const synonyms = config && config.synonyms ? config.synonyms : {};
50
1117
  let sessionId;
51
1118
  try {
52
- const stdinData = JSON.parse(process.env.CLAUDE_HOOK_STDIN || '{}');
53
- sessionId = stdinData.session_id || 'unknown';
1119
+ const stdinData = JSON.parse(process.env.CLAUDE_HOOK_STDIN || "{}");
1120
+ sessionId = stdinData.session_id || "unknown";
54
1121
  } catch (_) {
55
- sessionId = 'unknown';
1122
+ sessionId = "unknown";
56
1123
  }
57
-
58
1124
  const allResults = [];
59
1125
  for (const dbPath of dbPaths) {
60
1126
  const db = openDatabase(dbPath);
61
1127
  if (!db) continue;
62
1128
  try {
63
- // Cache + throttle
64
1129
  let cache;
65
1130
  let effectiveMax = MAX_RESULTS;
66
1131
  if (SearchCacheMod) {
67
- cache = new SearchCacheMod.SearchCache(db, { ttlMs: 300000 });
1132
+ cache = new SearchCacheMod.SearchCache(db, { ttlMs: 3e5 });
68
1133
  const throttle = new SearchCacheMod.SearchThrottle(db);
69
1134
  const callCount = throttle.incrementCallCount(sessionId);
70
1135
  effectiveMax = throttle.getMaxResults(callCount);
71
1136
  if (effectiveMax === 0) {
72
- hookLog('search', 'info', `Throttled (call #${callCount})`);
1137
+ hookLog("search", "info", `Throttled (call #${callCount})`);
73
1138
  db.close();
74
1139
  continue;
75
1140
  }
76
1141
  const cached = cache.get(userMessage);
77
1142
  if (cached) {
78
- const baseDir = path.dirname(dbPath);
79
- for (const r of cached) allResults.push({ ...r, baseDir });
1143
+ const baseDir2 = path.dirname(dbPath);
1144
+ for (const r of cached) allResults.push({ ...r, baseDir: baseDir2 });
80
1145
  db.close();
81
1146
  continue;
82
1147
  }
83
1148
  }
84
-
85
1149
  const results = searchEngineMod.search(db, userMessage, {
86
1150
  project,
87
1151
  maxResults: effectiveMax,
88
- synonyms,
1152
+ synonyms
89
1153
  });
90
-
91
1154
  if (cache) cache.set(userMessage, results);
92
-
93
1155
  const baseDir = path.dirname(dbPath);
94
1156
  for (const r of results) {
95
1157
  allResults.push({ ...r, baseDir });
96
1158
  }
97
-
98
- // Recall count inside loop — avoid reopening DB
99
1159
  try {
100
1160
  const txn = db.transaction(() => {
101
1161
  for (const r of results) incrementRecallCount(db, r.path);
102
1162
  });
103
1163
  txn();
104
- } catch (_e) { /* graceful */ }
1164
+ } catch (_e) {
1165
+ }
105
1166
  } catch (err) {
106
- hookLog('search', 'warn', `Search error: ${err?.message || err}`);
1167
+ hookLog("search", "warn", `Search error: ${err?.message || err}`);
107
1168
  } finally {
108
1169
  db.close();
109
1170
  }
110
1171
  }
111
-
112
- // Deduplicate by full path
113
- const seen = new Set();
1172
+ const seen = /* @__PURE__ */ new Set();
114
1173
  const unique = [];
115
1174
  for (const r of allResults) {
116
1175
  const normalized = path.resolve(r.path);
@@ -119,82 +1178,72 @@ function main() {
119
1178
  unique.push(r);
120
1179
  }
121
1180
  }
122
-
123
- // Sort by score descending, take top N
124
1181
  unique.sort((a, b) => b.score - a.score);
125
1182
  const relevant = unique.slice(0, MAX_RESULTS);
126
1183
  if (relevant.length === 0) return;
127
-
128
- // Token budget from config
129
- const budget = (config && config.tokenBudget) || {};
130
- const perResultChars = ((budget.perResult || 500) * 4);
131
- const totalChars = ((budget.searchResults || 1500) * 4);
132
-
133
- // Build output
1184
+ const budget = config && config.tokenBudget || {};
1185
+ const perResultChars = (budget.perResult || 500) * 4;
1186
+ const totalChars = (budget.searchResults || 1500) * 4;
134
1187
  const output = [];
135
1188
  let totalUsed = 0;
136
1189
  for (const r of relevant) {
137
1190
  if (totalUsed >= totalChars) break;
138
- const relativePath = path.relative(r.baseDir, r.path).replace(/\\/g, '/');
139
-
1191
+ const relativePath = path.relative(r.baseDir, r.path).replace(/\\/g, "/");
140
1192
  let headings = [];
141
- const contentStr = r.content || '';
1193
+ const contentStr = r.content || "";
142
1194
  if (contentStr) {
143
1195
  try {
144
1196
  headings = extractHeadings(contentStr, 3);
145
- } catch (_err) { /* skip */ }
1197
+ } catch (_err) {
1198
+ }
146
1199
  }
147
-
148
- const category = r.category || path.dirname(relativePath).split('/')[0];
149
- const title = r.title || r.slug || path.basename(r.path, '.md');
150
- const description = r.description || '';
151
-
152
- const headingStr = headings.length > 0 ? `\nBasliklar: ${headings.join(', ')}` : '';
153
- const tagsStr = r.tags ? `\nTags: ${r.tags}` : '';
1200
+ const category = r.category || path.dirname(relativePath).split("/")[0];
1201
+ const title = r.title || r.slug || path.basename(r.path, ".md");
1202
+ const description = r.description || "";
1203
+ const headingStr = headings.length > 0 ? `
1204
+ Basliklar: ${headings.join(", ")}` : "";
1205
+ const tagsStr = r.tags ? `
1206
+ Tags: ${r.tags}` : "";
154
1207
  const snippetOrDesc = r.snippet || description;
155
- const entry = `[Mindlore: ${category}/${title}] ${snippetOrDesc}\nDosya: ${relativePath}${tagsStr}${headingStr}`;
1208
+ const entry = `[Mindlore: ${category}/${title}] ${snippetOrDesc}
1209
+ Dosya: ${relativePath}${tagsStr}${headingStr}`;
156
1210
  const truncated = entry.slice(0, perResultChars);
157
1211
  totalUsed += truncated.length;
158
1212
  output.push(truncated);
159
1213
  }
160
-
161
1214
  if (output.length > 0) {
162
- let outputStr = output.join('\n\n') + '\n';
163
-
1215
+ let outputStr = output.join("\n\n") + "\n";
164
1216
  const OFFLOAD_THRESHOLD = 10240;
165
1217
  if (outputStr.length > OFFLOAD_THRESHOLD) {
166
1218
  const baseDir = path.dirname(dbPaths[0]);
167
- const tmpDir = path.join(baseDir, 'tmp');
1219
+ const tmpDir = path.join(baseDir, "tmp");
168
1220
  fs.mkdirSync(tmpDir, { recursive: true });
169
-
170
1221
  try {
171
- const oneHourAgo = Date.now() - 3600000;
172
- const files = fs.readdirSync(tmpDir)
173
- .filter(f => f.startsWith('search-'))
174
- .map(f => ({ name: f, mtime: fs.statSync(path.join(tmpDir, f)).mtimeMs }))
175
- .sort((a, b) => b.mtime - a.mtime);
1222
+ const oneHourAgo = Date.now() - 36e5;
1223
+ const files = fs.readdirSync(tmpDir).filter((f) => f.startsWith("search-")).map((f) => ({ name: f, mtime: fs.statSync(path.join(tmpDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
176
1224
  for (let i = 0; i < files.length; i++) {
177
1225
  if (i >= 20 || files[i].mtime < oneHourAgo) {
178
- try { fs.unlinkSync(path.join(tmpDir, files[i].name)); } catch { /* ignore */ }
1226
+ try {
1227
+ fs.unlinkSync(path.join(tmpDir, files[i].name));
1228
+ } catch {
1229
+ }
179
1230
  }
180
1231
  }
181
- } catch { /* cleanup is best-effort */ }
1232
+ } catch {
1233
+ }
182
1234
  const fileName = `search-${Date.now()}.md`;
183
1235
  const filePath = path.join(tmpDir, fileName);
184
- fs.writeFileSync(filePath, outputStr, 'utf8');
185
-
186
- const summary = outputStr.slice(0, 500).replace(/\n/g, ' ').trim();
187
- outputStr = `[Mindlore Search: ${outputStr.length} chars offloaded to ${filePath}]\n` +
188
- `Summary: ${summary}...\n` +
189
- `[Read full results: ${filePath}]`;
190
- hookLog('search', 'info', 'offloaded to tmp/ (' + outputStr.length + ' chars)');
1236
+ fs.writeFileSync(filePath, outputStr, "utf8");
1237
+ const summary = outputStr.slice(0, 500).replace(/\n/g, " ").trim();
1238
+ outputStr = `[Mindlore Search: ${outputStr.length} chars offloaded to ${filePath}]
1239
+ Summary: ${summary}...
1240
+ [Read full results: ${filePath}]`;
1241
+ hookLog("search", "info", "offloaded to tmp/ (" + outputStr.length + " chars)");
191
1242
  }
192
-
193
1243
  process.stdout.write(outputStr);
194
1244
  }
195
1245
  }
196
-
197
- withTelemetry('mindlore-search', main).catch(err => {
198
- hookLog('mindlore-search', 'error', err?.message ?? String(err));
1246
+ withTelemetry("mindlore-search", main).catch((err) => {
1247
+ hookLog("mindlore-search", "error", err?.message ?? String(err));
199
1248
  process.exit(0);
200
1249
  });