specmem-hardwicksoftware 3.5.99

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 (1473) hide show
  1. package/CHANGELOG.md +299 -0
  2. package/LICENSE.md +6406 -0
  3. package/README.md +539 -0
  4. package/bin/AegisTheme.cjs +1022 -0
  5. package/bin/AnsiRenderer.cjs +1055 -0
  6. package/bin/BoxRenderer.cjs +605 -0
  7. package/bin/ClaudeLiveScreen.cjs +1299 -0
  8. package/bin/DashboardModules.cjs +733 -0
  9. package/bin/LiveScreenCapture.cjs +1012 -0
  10. package/bin/MemoryBrowserScreen.cjs +1595 -0
  11. package/bin/TabManager.cjs +1414 -0
  12. package/bin/checkAgentStatus-fix.patch +30 -0
  13. package/bin/mcp-socket-client.cjs +462 -0
  14. package/bin/screen-utils.cjs +106 -0
  15. package/bin/specmem-autoclaude.cjs +663 -0
  16. package/bin/specmem-cleanup.cjs +421 -0
  17. package/bin/specmem-cli.cjs +794 -0
  18. package/bin/specmem-console-teamcomms-class.cjs +428 -0
  19. package/bin/specmem-console.cjs +8104 -0
  20. package/bin/specmem-statusbar.cjs +530 -0
  21. package/bootstrap.cjs +5065 -0
  22. package/claude-hooks/agent-chooser-hook.js +179 -0
  23. package/claude-hooks/agent-chooser-inject.js +121 -0
  24. package/claude-hooks/agent-loading-hook.js +990 -0
  25. package/claude-hooks/agent-output-fader.cjs +542 -0
  26. package/claude-hooks/agent-output-interceptor.js +193 -0
  27. package/claude-hooks/agent-type-matcher.js +419 -0
  28. package/claude-hooks/auto-bypass.py +74 -0
  29. package/claude-hooks/background-completion-silencer.js +134 -0
  30. package/claude-hooks/bash-auto-background.js +182 -0
  31. package/claude-hooks/build-cedict-dictionary.mjs +167 -0
  32. package/claude-hooks/bullshit-radar.cjs +323 -0
  33. package/claude-hooks/cedict-codes.json +270 -0
  34. package/claude-hooks/cedict-extracted.json +22632 -0
  35. package/claude-hooks/claude-watchdog.sh +401 -0
  36. package/claude-hooks/context-dedup.cjs +144 -0
  37. package/claude-hooks/context-yeeter.cjs +244 -0
  38. package/claude-hooks/debug-suffix.cjs +15 -0
  39. package/claude-hooks/debug2.cjs +7 -0
  40. package/claude-hooks/drilldown-enforcer.js +242 -0
  41. package/claude-hooks/english-morphology-standalone.cjs +149 -0
  42. package/claude-hooks/english-morphology.cjs +152 -0
  43. package/claude-hooks/extract-translations.mjs +193 -0
  44. package/claude-hooks/file-claim-enforcer.cjs +293 -0
  45. package/claude-hooks/file-claim-enforcer.js +293 -0
  46. package/claude-hooks/find-collisions.cjs +39 -0
  47. package/claude-hooks/fix-abbreviations.cjs +60 -0
  48. package/claude-hooks/fix-collisions.cjs +60 -0
  49. package/claude-hooks/fix-decompressor.cjs +79 -0
  50. package/claude-hooks/fix-suffixes.cjs +66 -0
  51. package/claude-hooks/grammar-engine.cjs +159 -0
  52. package/claude-hooks/input-aware-improver.js +231 -0
  53. package/claude-hooks/is-agent.cjs +64 -0
  54. package/claude-hooks/mega-test.cjs +213 -0
  55. package/claude-hooks/merge-dictionaries.mjs +207 -0
  56. package/claude-hooks/merged-codes.cjs +22675 -0
  57. package/claude-hooks/merged-codes.json +22676 -0
  58. package/claude-hooks/output-cleaner.cjs +388 -0
  59. package/claude-hooks/post-write-memory-hook.cjs +430 -0
  60. package/claude-hooks/quick-test.cjs +24 -0
  61. package/claude-hooks/quick-test2.cjs +24 -0
  62. package/claude-hooks/remove-bad-codes.cjs +23 -0
  63. package/claude-hooks/search-reminder-hook.js +90 -0
  64. package/claude-hooks/semantic-test.cjs +93 -0
  65. package/claude-hooks/settings.json +445 -0
  66. package/claude-hooks/smart-context-hook.cjs +547 -0
  67. package/claude-hooks/smart-context-hook.js +539 -0
  68. package/claude-hooks/smart-search-interceptor.js +364 -0
  69. package/claude-hooks/socket-connect-helper.cjs +235 -0
  70. package/claude-hooks/specmem/sockets/session-start.lock +1 -0
  71. package/claude-hooks/specmem-context-hook.cjs +357 -0
  72. package/claude-hooks/specmem-context-hook.js +357 -0
  73. package/claude-hooks/specmem-drilldown-hook.cjs +480 -0
  74. package/claude-hooks/specmem-drilldown-hook.js +480 -0
  75. package/claude-hooks/specmem-drilldown-setter.js +210 -0
  76. package/claude-hooks/specmem-paths.cjs +213 -0
  77. package/claude-hooks/specmem-precompact.js +183 -0
  78. package/claude-hooks/specmem-session-init.sh +33 -0
  79. package/claude-hooks/specmem-session-start.cjs +498 -0
  80. package/claude-hooks/specmem-stop-hook.cjs +73 -0
  81. package/claude-hooks/specmem-stop-hook.js +5 -0
  82. package/claude-hooks/specmem-team-comms.cjs +434 -0
  83. package/claude-hooks/specmem-team-member-inject.js +271 -0
  84. package/claude-hooks/specmem-unified-hook.py +670 -0
  85. package/claude-hooks/subagent-loading-hook.js +194 -0
  86. package/claude-hooks/sysprompt-squisher.cjs +167 -0
  87. package/claude-hooks/task-progress-hook.js +204 -0
  88. package/claude-hooks/team-comms-enforcer.cjs +585 -0
  89. package/claude-hooks/test-accuracy.cjs +27 -0
  90. package/claude-hooks/test-big.cjs +28 -0
  91. package/claude-hooks/test-inflectors.cjs +39 -0
  92. package/claude-hooks/test-pluralize.cjs +37 -0
  93. package/claude-hooks/test-quick.cjs +8 -0
  94. package/claude-hooks/test-wink.cjs +20 -0
  95. package/claude-hooks/token-compressor.cjs +940 -0
  96. package/claude-hooks/use-code-pointers.cjs +279 -0
  97. package/commands/COMMAND_TOOL_MAP.md +299 -0
  98. package/commands/specmem-agents.md +412 -0
  99. package/commands/specmem-autoclaude.md +295 -0
  100. package/commands/specmem-changes.md +247 -0
  101. package/commands/specmem-code.md +103 -0
  102. package/commands/specmem-configteammembercomms.md +322 -0
  103. package/commands/specmem-drilldown.md +208 -0
  104. package/commands/specmem-find.md +195 -0
  105. package/commands/specmem-getdashboard.md +243 -0
  106. package/commands/specmem-hooks.md +219 -0
  107. package/commands/specmem-pointers.md +149 -0
  108. package/commands/specmem-progress.md +287 -0
  109. package/commands/specmem-remember.md +123 -0
  110. package/commands/specmem-service.md +349 -0
  111. package/commands/specmem-stats.md +189 -0
  112. package/commands/specmem-team-member.md +409 -0
  113. package/commands/specmem-webdev.md +583 -0
  114. package/commands/specmem.md +363 -0
  115. package/dist/autoStart/index.d.ts +214 -0
  116. package/dist/autoStart/index.d.ts.map +1 -0
  117. package/dist/autoStart/index.js +883 -0
  118. package/dist/autoStart/index.js.map +1 -0
  119. package/dist/claude-sessions/contextRestorationParser.d.ts +74 -0
  120. package/dist/claude-sessions/contextRestorationParser.d.ts.map +1 -0
  121. package/dist/claude-sessions/contextRestorationParser.js +570 -0
  122. package/dist/claude-sessions/contextRestorationParser.js.map +1 -0
  123. package/dist/claude-sessions/index.d.ts +13 -0
  124. package/dist/claude-sessions/index.d.ts.map +1 -0
  125. package/dist/claude-sessions/index.js +11 -0
  126. package/dist/claude-sessions/index.js.map +1 -0
  127. package/dist/claude-sessions/sessionIntegration.d.ts +48 -0
  128. package/dist/claude-sessions/sessionIntegration.d.ts.map +1 -0
  129. package/dist/claude-sessions/sessionIntegration.js +146 -0
  130. package/dist/claude-sessions/sessionIntegration.js.map +1 -0
  131. package/dist/claude-sessions/sessionParser.d.ts +293 -0
  132. package/dist/claude-sessions/sessionParser.d.ts.map +1 -0
  133. package/dist/claude-sessions/sessionParser.js +1028 -0
  134. package/dist/claude-sessions/sessionParser.js.map +1 -0
  135. package/dist/claude-sessions/sessionWatcher.d.ts +139 -0
  136. package/dist/claude-sessions/sessionWatcher.d.ts.map +1 -0
  137. package/dist/claude-sessions/sessionWatcher.js +722 -0
  138. package/dist/claude-sessions/sessionWatcher.js.map +1 -0
  139. package/dist/cli/deploy-to-claude.d.ts +56 -0
  140. package/dist/cli/deploy-to-claude.d.ts.map +1 -0
  141. package/dist/cli/deploy-to-claude.js +576 -0
  142. package/dist/cli/deploy-to-claude.js.map +1 -0
  143. package/dist/code-explanations/explainCode.d.ts +86 -0
  144. package/dist/code-explanations/explainCode.d.ts.map +1 -0
  145. package/dist/code-explanations/explainCode.js +286 -0
  146. package/dist/code-explanations/explainCode.js.map +1 -0
  147. package/dist/code-explanations/feedback.d.ts +87 -0
  148. package/dist/code-explanations/feedback.d.ts.map +1 -0
  149. package/dist/code-explanations/feedback.js +212 -0
  150. package/dist/code-explanations/feedback.js.map +1 -0
  151. package/dist/code-explanations/getRelatedCode.d.ts +80 -0
  152. package/dist/code-explanations/getRelatedCode.d.ts.map +1 -0
  153. package/dist/code-explanations/getRelatedCode.js +262 -0
  154. package/dist/code-explanations/getRelatedCode.js.map +1 -0
  155. package/dist/code-explanations/index.d.ts +284 -0
  156. package/dist/code-explanations/index.d.ts.map +1 -0
  157. package/dist/code-explanations/index.js +249 -0
  158. package/dist/code-explanations/index.js.map +1 -0
  159. package/dist/code-explanations/linkCodeToPrompt.d.ts +79 -0
  160. package/dist/code-explanations/linkCodeToPrompt.d.ts.map +1 -0
  161. package/dist/code-explanations/linkCodeToPrompt.js +213 -0
  162. package/dist/code-explanations/linkCodeToPrompt.js.map +1 -0
  163. package/dist/code-explanations/recallExplanation.d.ts +88 -0
  164. package/dist/code-explanations/recallExplanation.d.ts.map +1 -0
  165. package/dist/code-explanations/recallExplanation.js +218 -0
  166. package/dist/code-explanations/recallExplanation.js.map +1 -0
  167. package/dist/code-explanations/schema.d.ts +32 -0
  168. package/dist/code-explanations/schema.d.ts.map +1 -0
  169. package/dist/code-explanations/schema.js +221 -0
  170. package/dist/code-explanations/schema.js.map +1 -0
  171. package/dist/code-explanations/semanticSearch.d.ts +75 -0
  172. package/dist/code-explanations/semanticSearch.d.ts.map +1 -0
  173. package/dist/code-explanations/semanticSearch.js +203 -0
  174. package/dist/code-explanations/semanticSearch.js.map +1 -0
  175. package/dist/code-explanations/types.d.ts +328 -0
  176. package/dist/code-explanations/types.d.ts.map +1 -0
  177. package/dist/code-explanations/types.js +122 -0
  178. package/dist/code-explanations/types.js.map +1 -0
  179. package/dist/codebase/codeAnalyzer.d.ts +272 -0
  180. package/dist/codebase/codeAnalyzer.d.ts.map +1 -0
  181. package/dist/codebase/codeAnalyzer.js +1353 -0
  182. package/dist/codebase/codeAnalyzer.js.map +1 -0
  183. package/dist/codebase/codebaseIndexer.d.ts +360 -0
  184. package/dist/codebase/codebaseIndexer.d.ts.map +1 -0
  185. package/dist/codebase/codebaseIndexer.js +1735 -0
  186. package/dist/codebase/codebaseIndexer.js.map +1 -0
  187. package/dist/codebase/codebaseTools.d.ts +853 -0
  188. package/dist/codebase/codebaseTools.d.ts.map +1 -0
  189. package/dist/codebase/codebaseTools.js +1279 -0
  190. package/dist/codebase/codebaseTools.js.map +1 -0
  191. package/dist/codebase/exclusions.d.ts +111 -0
  192. package/dist/codebase/exclusions.d.ts.map +1 -0
  193. package/dist/codebase/exclusions.js +771 -0
  194. package/dist/codebase/exclusions.js.map +1 -0
  195. package/dist/codebase/fileWatcher.d.ts +135 -0
  196. package/dist/codebase/fileWatcher.d.ts.map +1 -0
  197. package/dist/codebase/fileWatcher.js +309 -0
  198. package/dist/codebase/fileWatcher.js.map +1 -0
  199. package/dist/codebase/index.d.ts +33 -0
  200. package/dist/codebase/index.d.ts.map +1 -0
  201. package/dist/codebase/index.js +77 -0
  202. package/dist/codebase/index.js.map +1 -0
  203. package/dist/codebase/ingestion.d.ts +177 -0
  204. package/dist/codebase/ingestion.d.ts.map +1 -0
  205. package/dist/codebase/ingestion.js +690 -0
  206. package/dist/codebase/ingestion.js.map +1 -0
  207. package/dist/codebase/languageDetection.d.ts +75 -0
  208. package/dist/codebase/languageDetection.d.ts.map +1 -0
  209. package/dist/codebase/languageDetection.js +768 -0
  210. package/dist/codebase/languageDetection.js.map +1 -0
  211. package/dist/commands/codebaseCommands.d.ts +101 -0
  212. package/dist/commands/codebaseCommands.d.ts.map +1 -0
  213. package/dist/commands/codebaseCommands.js +911 -0
  214. package/dist/commands/codebaseCommands.js.map +1 -0
  215. package/dist/commands/commandHandler.d.ts +126 -0
  216. package/dist/commands/commandHandler.d.ts.map +1 -0
  217. package/dist/commands/commandHandler.js +296 -0
  218. package/dist/commands/commandHandler.js.map +1 -0
  219. package/dist/commands/commandLoader.d.ts +103 -0
  220. package/dist/commands/commandLoader.d.ts.map +1 -0
  221. package/dist/commands/commandLoader.js +223 -0
  222. package/dist/commands/commandLoader.js.map +1 -0
  223. package/dist/commands/contextCommands.d.ts +83 -0
  224. package/dist/commands/contextCommands.d.ts.map +1 -0
  225. package/dist/commands/contextCommands.js +512 -0
  226. package/dist/commands/contextCommands.js.map +1 -0
  227. package/dist/commands/index.d.ts +24 -0
  228. package/dist/commands/index.d.ts.map +1 -0
  229. package/dist/commands/index.js +28 -0
  230. package/dist/commands/index.js.map +1 -0
  231. package/dist/commands/mcpResources.d.ts +50 -0
  232. package/dist/commands/mcpResources.d.ts.map +1 -0
  233. package/dist/commands/mcpResources.js +372 -0
  234. package/dist/commands/mcpResources.js.map +1 -0
  235. package/dist/commands/memoryCommands.d.ts +74 -0
  236. package/dist/commands/memoryCommands.d.ts.map +1 -0
  237. package/dist/commands/memoryCommands.js +609 -0
  238. package/dist/commands/memoryCommands.js.map +1 -0
  239. package/dist/commands/promptCommands.d.ts +91 -0
  240. package/dist/commands/promptCommands.d.ts.map +1 -0
  241. package/dist/commands/promptCommands.js +801 -0
  242. package/dist/commands/promptCommands.js.map +1 -0
  243. package/dist/commands/teamMemberCommands.d.ts +21 -0
  244. package/dist/commands/teamMemberCommands.d.ts.map +1 -0
  245. package/dist/commands/teamMemberCommands.js +137 -0
  246. package/dist/commands/teamMemberCommands.js.map +1 -0
  247. package/dist/comms/fileCommsTransport.d.ts +91 -0
  248. package/dist/comms/fileCommsTransport.d.ts.map +1 -0
  249. package/dist/comms/fileCommsTransport.js +244 -0
  250. package/dist/comms/fileCommsTransport.js.map +1 -0
  251. package/dist/comms/index.d.ts +7 -0
  252. package/dist/comms/index.d.ts.map +1 -0
  253. package/dist/comms/index.js +7 -0
  254. package/dist/comms/index.js.map +1 -0
  255. package/dist/config/apiKeyDetection.d.ts +41 -0
  256. package/dist/config/apiKeyDetection.d.ts.map +1 -0
  257. package/dist/config/apiKeyDetection.js +211 -0
  258. package/dist/config/apiKeyDetection.js.map +1 -0
  259. package/dist/config/autoConfig.d.ts +188 -0
  260. package/dist/config/autoConfig.d.ts.map +1 -0
  261. package/dist/config/autoConfig.js +850 -0
  262. package/dist/config/autoConfig.js.map +1 -0
  263. package/dist/config/configSync.d.ts +119 -0
  264. package/dist/config/configSync.d.ts.map +1 -0
  265. package/dist/config/configSync.js +878 -0
  266. package/dist/config/configSync.js.map +1 -0
  267. package/dist/config/embeddingTimeouts.d.ts +145 -0
  268. package/dist/config/embeddingTimeouts.d.ts.map +1 -0
  269. package/dist/config/embeddingTimeouts.js +255 -0
  270. package/dist/config/embeddingTimeouts.js.map +1 -0
  271. package/dist/config/index.d.ts +5 -0
  272. package/dist/config/index.d.ts.map +1 -0
  273. package/dist/config/index.js +7 -0
  274. package/dist/config/index.js.map +1 -0
  275. package/dist/config/languageConfig.d.ts +68 -0
  276. package/dist/config/languageConfig.d.ts.map +1 -0
  277. package/dist/config/languageConfig.js +473 -0
  278. package/dist/config/languageConfig.js.map +1 -0
  279. package/dist/config/password.d.ts +145 -0
  280. package/dist/config/password.d.ts.map +1 -0
  281. package/dist/config/password.js +428 -0
  282. package/dist/config/password.js.map +1 -0
  283. package/dist/config.d.ts +338 -0
  284. package/dist/config.d.ts.map +1 -0
  285. package/dist/config.js +1177 -0
  286. package/dist/config.js.map +1 -0
  287. package/dist/consolidation.d.ts +44 -0
  288. package/dist/consolidation.d.ts.map +1 -0
  289. package/dist/consolidation.js +447 -0
  290. package/dist/consolidation.js.map +1 -0
  291. package/dist/constants.d.ts +371 -0
  292. package/dist/constants.d.ts.map +1 -0
  293. package/dist/constants.js +552 -0
  294. package/dist/constants.js.map +1 -0
  295. package/dist/coordination/TeamMemberRegistry.d.ts +192 -0
  296. package/dist/coordination/TeamMemberRegistry.d.ts.map +1 -0
  297. package/dist/coordination/TeamMemberRegistry.js +415 -0
  298. package/dist/coordination/TeamMemberRegistry.js.map +1 -0
  299. package/dist/coordination/events.d.ts +369 -0
  300. package/dist/coordination/events.d.ts.map +1 -0
  301. package/dist/coordination/events.js +232 -0
  302. package/dist/coordination/events.js.map +1 -0
  303. package/dist/coordination/handlers.d.ts +116 -0
  304. package/dist/coordination/handlers.d.ts.map +1 -0
  305. package/dist/coordination/handlers.js +400 -0
  306. package/dist/coordination/handlers.js.map +1 -0
  307. package/dist/coordination/index.d.ts +14 -0
  308. package/dist/coordination/index.d.ts.map +1 -0
  309. package/dist/coordination/index.js +31 -0
  310. package/dist/coordination/index.js.map +1 -0
  311. package/dist/coordination/integration.d.ts +260 -0
  312. package/dist/coordination/integration.d.ts.map +1 -0
  313. package/dist/coordination/integration.js +472 -0
  314. package/dist/coordination/integration.js.map +1 -0
  315. package/dist/coordination/server.d.ts +266 -0
  316. package/dist/coordination/server.d.ts.map +1 -0
  317. package/dist/coordination/server.js +995 -0
  318. package/dist/coordination/server.js.map +1 -0
  319. package/dist/coordination/serviceProvider.d.ts +70 -0
  320. package/dist/coordination/serviceProvider.d.ts.map +1 -0
  321. package/dist/coordination/serviceProvider.js +273 -0
  322. package/dist/coordination/serviceProvider.js.map +1 -0
  323. package/dist/dashboard/api/claudeControl.d.ts +44 -0
  324. package/dist/dashboard/api/claudeControl.d.ts.map +1 -0
  325. package/dist/dashboard/api/claudeControl.js +650 -0
  326. package/dist/dashboard/api/claudeControl.js.map +1 -0
  327. package/dist/dashboard/api/claudeHistory.d.ts +4 -0
  328. package/dist/dashboard/api/claudeHistory.d.ts.map +1 -0
  329. package/dist/dashboard/api/claudeHistory.js +319 -0
  330. package/dist/dashboard/api/claudeHistory.js.map +1 -0
  331. package/dist/dashboard/api/dataExport.d.ts +23 -0
  332. package/dist/dashboard/api/dataExport.d.ts.map +1 -0
  333. package/dist/dashboard/api/dataExport.js +509 -0
  334. package/dist/dashboard/api/dataExport.js.map +1 -0
  335. package/dist/dashboard/api/fileManager.d.ts +39 -0
  336. package/dist/dashboard/api/fileManager.d.ts.map +1 -0
  337. package/dist/dashboard/api/fileManager.js +814 -0
  338. package/dist/dashboard/api/fileManager.js.map +1 -0
  339. package/dist/dashboard/api/hooks.d.ts +16 -0
  340. package/dist/dashboard/api/hooks.d.ts.map +1 -0
  341. package/dist/dashboard/api/hooks.js +342 -0
  342. package/dist/dashboard/api/hooks.js.map +1 -0
  343. package/dist/dashboard/api/hotReload.d.ts +14 -0
  344. package/dist/dashboard/api/hotReload.d.ts.map +1 -0
  345. package/dist/dashboard/api/hotReload.js +219 -0
  346. package/dist/dashboard/api/hotReload.js.map +1 -0
  347. package/dist/dashboard/api/liveSessionStream.d.ts +19 -0
  348. package/dist/dashboard/api/liveSessionStream.d.ts.map +1 -0
  349. package/dist/dashboard/api/liveSessionStream.js +430 -0
  350. package/dist/dashboard/api/liveSessionStream.js.map +1 -0
  351. package/dist/dashboard/api/memoryRecall.d.ts +20 -0
  352. package/dist/dashboard/api/memoryRecall.d.ts.map +1 -0
  353. package/dist/dashboard/api/memoryRecall.js +524 -0
  354. package/dist/dashboard/api/memoryRecall.js.map +1 -0
  355. package/dist/dashboard/api/promptSend.d.ts +33 -0
  356. package/dist/dashboard/api/promptSend.d.ts.map +1 -0
  357. package/dist/dashboard/api/promptSend.js +544 -0
  358. package/dist/dashboard/api/promptSend.js.map +1 -0
  359. package/dist/dashboard/api/settings.d.ts +10 -0
  360. package/dist/dashboard/api/settings.d.ts.map +1 -0
  361. package/dist/dashboard/api/settings.js +656 -0
  362. package/dist/dashboard/api/settings.js.map +1 -0
  363. package/dist/dashboard/api/setup.d.ts +21 -0
  364. package/dist/dashboard/api/setup.d.ts.map +1 -0
  365. package/dist/dashboard/api/setup.js +663 -0
  366. package/dist/dashboard/api/setup.js.map +1 -0
  367. package/dist/dashboard/api/specmemTools.d.ts +14 -0
  368. package/dist/dashboard/api/specmemTools.d.ts.map +1 -0
  369. package/dist/dashboard/api/specmemTools.js +1059 -0
  370. package/dist/dashboard/api/specmemTools.js.map +1 -0
  371. package/dist/dashboard/api/taskTeamMembers.d.ts +8 -0
  372. package/dist/dashboard/api/taskTeamMembers.d.ts.map +1 -0
  373. package/dist/dashboard/api/taskTeamMembers.js +136 -0
  374. package/dist/dashboard/api/taskTeamMembers.js.map +1 -0
  375. package/dist/dashboard/api/teamMemberDeploy.d.ts +15 -0
  376. package/dist/dashboard/api/teamMemberDeploy.d.ts.map +1 -0
  377. package/dist/dashboard/api/teamMemberDeploy.js +421 -0
  378. package/dist/dashboard/api/teamMemberDeploy.js.map +1 -0
  379. package/dist/dashboard/api/teamMemberHistory.d.ts +38 -0
  380. package/dist/dashboard/api/teamMemberHistory.d.ts.map +1 -0
  381. package/dist/dashboard/api/teamMemberHistory.js +583 -0
  382. package/dist/dashboard/api/teamMemberHistory.js.map +1 -0
  383. package/dist/dashboard/api/terminal.d.ts +12 -0
  384. package/dist/dashboard/api/terminal.d.ts.map +1 -0
  385. package/dist/dashboard/api/terminal.js +344 -0
  386. package/dist/dashboard/api/terminal.js.map +1 -0
  387. package/dist/dashboard/api/terminalInject.d.ts +17 -0
  388. package/dist/dashboard/api/terminalInject.d.ts.map +1 -0
  389. package/dist/dashboard/api/terminalInject.js +322 -0
  390. package/dist/dashboard/api/terminalInject.js.map +1 -0
  391. package/dist/dashboard/api/terminalStream.d.ts +12 -0
  392. package/dist/dashboard/api/terminalStream.d.ts.map +1 -0
  393. package/dist/dashboard/api/terminalStream.js +482 -0
  394. package/dist/dashboard/api/terminalStream.js.map +1 -0
  395. package/dist/dashboard/index.d.ts +7 -0
  396. package/dist/dashboard/index.d.ts.map +1 -0
  397. package/dist/dashboard/index.js +7 -0
  398. package/dist/dashboard/index.js.map +1 -0
  399. package/dist/dashboard/ptyStreamer.d.ts +173 -0
  400. package/dist/dashboard/ptyStreamer.d.ts.map +1 -0
  401. package/dist/dashboard/ptyStreamer.js +661 -0
  402. package/dist/dashboard/ptyStreamer.js.map +1 -0
  403. package/dist/dashboard/public/DASHBOARD-README.md +378 -0
  404. package/dist/dashboard/public/INTEGRATION-GUIDE.md +395 -0
  405. package/dist/dashboard/public/codebase-config.html +1247 -0
  406. package/dist/dashboard/public/dashboard-v2.html +1942 -0
  407. package/dist/dashboard/public/data-export.html +819 -0
  408. package/dist/dashboard/public/example-page.html +164 -0
  409. package/dist/dashboard/public/file-explorer.html +1023 -0
  410. package/dist/dashboard/public/hooks.html +1103 -0
  411. package/dist/dashboard/public/index-improvements.css +499 -0
  412. package/dist/dashboard/public/index.html +5534 -0
  413. package/dist/dashboard/public/memory-controls.html +1959 -0
  414. package/dist/dashboard/public/memory-recall.html +1495 -0
  415. package/dist/dashboard/public/previews/skeleton-memory-graph.html +361 -0
  416. package/dist/dashboard/public/previews/skeleton-memory-list.html +366 -0
  417. package/dist/dashboard/public/previews/skeleton-search-results.html +609 -0
  418. package/dist/dashboard/public/previews/skeleton-stats-dashboard.html +556 -0
  419. package/dist/dashboard/public/prompt-console.html +2763 -0
  420. package/dist/dashboard/public/react-dist/assets/index-CkjobT5B.js +871 -0
  421. package/dist/dashboard/public/react-dist/assets/index-iRclxMst.css +1 -0
  422. package/dist/dashboard/public/react-dist/index.html +16 -0
  423. package/dist/dashboard/public/shared-header.js +325 -0
  424. package/dist/dashboard/public/shared-language-selector.js +626 -0
  425. package/dist/dashboard/public/shared-logger.js +66 -0
  426. package/dist/dashboard/public/shared-nav.js +325 -0
  427. package/dist/dashboard/public/shared-theme-blue.css +331 -0
  428. package/dist/dashboard/public/shared-theme.css +813 -0
  429. package/dist/dashboard/public/shared-toast.js +415 -0
  430. package/dist/dashboard/public/team-member-history.html +1291 -0
  431. package/dist/dashboard/public/team-member-spy.html +1199 -0
  432. package/dist/dashboard/public/team-members.html +3756 -0
  433. package/dist/dashboard/public/terminal-output.html +1013 -0
  434. package/dist/dashboard/public/terminal.html +372 -0
  435. package/dist/dashboard/sessionStore.d.ts +86 -0
  436. package/dist/dashboard/sessionStore.d.ts.map +1 -0
  437. package/dist/dashboard/sessionStore.js +262 -0
  438. package/dist/dashboard/sessionStore.js.map +1 -0
  439. package/dist/dashboard/standalone.d.ts +27 -0
  440. package/dist/dashboard/standalone.d.ts.map +1 -0
  441. package/dist/dashboard/standalone.js +380 -0
  442. package/dist/dashboard/standalone.js.map +1 -0
  443. package/dist/dashboard/webServer.d.ts +390 -0
  444. package/dist/dashboard/webServer.d.ts.map +1 -0
  445. package/dist/dashboard/webServer.js +4297 -0
  446. package/dist/dashboard/webServer.js.map +1 -0
  447. package/dist/dashboard/websocket/teamMemberStream.d.ts +87 -0
  448. package/dist/dashboard/websocket/teamMemberStream.d.ts.map +1 -0
  449. package/dist/dashboard/websocket/teamMemberStream.js +366 -0
  450. package/dist/dashboard/websocket/teamMemberStream.js.map +1 -0
  451. package/dist/dashboard/websocket/terminalStream.d.ts +130 -0
  452. package/dist/dashboard/websocket/terminalStream.d.ts.map +1 -0
  453. package/dist/dashboard/websocket/terminalStream.js +456 -0
  454. package/dist/dashboard/websocket/terminalStream.js.map +1 -0
  455. package/dist/database/embeddedPostgres.d.ts +187 -0
  456. package/dist/database/embeddedPostgres.d.ts.map +1 -0
  457. package/dist/database/embeddedPostgres.js +763 -0
  458. package/dist/database/embeddedPostgres.js.map +1 -0
  459. package/dist/database/index.d.ts +12 -0
  460. package/dist/database/index.d.ts.map +1 -0
  461. package/dist/database/index.js +20 -0
  462. package/dist/database/index.js.map +1 -0
  463. package/dist/database/initEmbeddedPostgres.d.ts +124 -0
  464. package/dist/database/initEmbeddedPostgres.d.ts.map +1 -0
  465. package/dist/database/initEmbeddedPostgres.js +855 -0
  466. package/dist/database/initEmbeddedPostgres.js.map +1 -0
  467. package/dist/database.d.ts +256 -0
  468. package/dist/database.d.ts.map +1 -0
  469. package/dist/database.js +1209 -0
  470. package/dist/database.js.map +1 -0
  471. package/dist/db/apiDataManager.d.ts +334 -0
  472. package/dist/db/apiDataManager.d.ts.map +1 -0
  473. package/dist/db/apiDataManager.js +631 -0
  474. package/dist/db/apiDataManager.js.map +1 -0
  475. package/dist/db/batchOperations.d.ts +154 -0
  476. package/dist/db/batchOperations.d.ts.map +1 -0
  477. package/dist/db/batchOperations.js +564 -0
  478. package/dist/db/batchOperations.js.map +1 -0
  479. package/dist/db/bigBrainMigrations.d.ts +48 -0
  480. package/dist/db/bigBrainMigrations.d.ts.map +1 -0
  481. package/dist/db/bigBrainMigrations.js +4266 -0
  482. package/dist/db/bigBrainMigrations.js.map +1 -0
  483. package/dist/db/connectionPoolGoBrrr.d.ts +94 -0
  484. package/dist/db/connectionPoolGoBrrr.d.ts.map +1 -0
  485. package/dist/db/connectionPoolGoBrrr.js +548 -0
  486. package/dist/db/connectionPoolGoBrrr.js.map +1 -0
  487. package/dist/db/dashboardQueries.d.ts +182 -0
  488. package/dist/db/dashboardQueries.d.ts.map +1 -0
  489. package/dist/db/dashboardQueries.js +821 -0
  490. package/dist/db/dashboardQueries.js.map +1 -0
  491. package/dist/db/deploymentBootstrap.d.ts +43 -0
  492. package/dist/db/deploymentBootstrap.d.ts.map +1 -0
  493. package/dist/db/deploymentBootstrap.js +329 -0
  494. package/dist/db/deploymentBootstrap.js.map +1 -0
  495. package/dist/db/dimensionService.d.ts +140 -0
  496. package/dist/db/dimensionService.d.ts.map +1 -0
  497. package/dist/db/dimensionService.js +261 -0
  498. package/dist/db/dimensionService.js.map +1 -0
  499. package/dist/db/embeddingOverflow.d.ts +69 -0
  500. package/dist/db/embeddingOverflow.d.ts.map +1 -0
  501. package/dist/db/embeddingOverflow.js +332 -0
  502. package/dist/db/embeddingOverflow.js.map +1 -0
  503. package/dist/db/embeddingOverflow.sql +221 -0
  504. package/dist/db/findThatShit.d.ts +145 -0
  505. package/dist/db/findThatShit.d.ts.map +1 -0
  506. package/dist/db/findThatShit.js +782 -0
  507. package/dist/db/findThatShit.js.map +1 -0
  508. package/dist/db/hotPathManager.d.ts +187 -0
  509. package/dist/db/hotPathManager.d.ts.map +1 -0
  510. package/dist/db/hotPathManager.js +504 -0
  511. package/dist/db/hotPathManager.js.map +1 -0
  512. package/dist/db/index.d.ts +85 -0
  513. package/dist/db/index.d.ts.map +1 -0
  514. package/dist/db/index.js +219 -0
  515. package/dist/db/index.js.map +1 -0
  516. package/dist/db/memoryDrilldown.sql +99 -0
  517. package/dist/db/migrate.d.ts +3 -0
  518. package/dist/db/migrate.d.ts.map +1 -0
  519. package/dist/db/migrate.js +97 -0
  520. package/dist/db/migrate.js.map +1 -0
  521. package/dist/db/migrateJsonToPostgres.d.ts +43 -0
  522. package/dist/db/migrateJsonToPostgres.d.ts.map +1 -0
  523. package/dist/db/migrateJsonToPostgres.js +465 -0
  524. package/dist/db/migrateJsonToPostgres.js.map +1 -0
  525. package/dist/db/nukeFromOrbit.d.ts +63 -0
  526. package/dist/db/nukeFromOrbit.d.ts.map +1 -0
  527. package/dist/db/nukeFromOrbit.js +499 -0
  528. package/dist/db/nukeFromOrbit.js.map +1 -0
  529. package/dist/db/processedTraining.sql +60 -0
  530. package/dist/db/projectNamespacing.d.ts +258 -0
  531. package/dist/db/projectNamespacing.d.ts.map +1 -0
  532. package/dist/db/projectNamespacing.js +920 -0
  533. package/dist/db/projectNamespacing.js.map +1 -0
  534. package/dist/db/projectNamespacing.sql +374 -0
  535. package/dist/db/projectSchemaInit.sql +271 -0
  536. package/dist/db/spatialMemory.d.ts +296 -0
  537. package/dist/db/spatialMemory.d.ts.map +1 -0
  538. package/dist/db/spatialMemory.js +818 -0
  539. package/dist/db/spatialMemory.js.map +1 -0
  540. package/dist/db/streamingQuery.d.ts +143 -0
  541. package/dist/db/streamingQuery.d.ts.map +1 -0
  542. package/dist/db/streamingQuery.js +350 -0
  543. package/dist/db/streamingQuery.js.map +1 -0
  544. package/dist/db/teamComms.sql +224 -0
  545. package/dist/db/yeetStuffInDb.d.ts +72 -0
  546. package/dist/db/yeetStuffInDb.d.ts.map +1 -0
  547. package/dist/db/yeetStuffInDb.js +473 -0
  548. package/dist/db/yeetStuffInDb.js.map +1 -0
  549. package/dist/embedding-providers/index.d.ts +10 -0
  550. package/dist/embedding-providers/index.d.ts.map +1 -0
  551. package/dist/embedding-providers/index.js +12 -0
  552. package/dist/embedding-providers/index.js.map +1 -0
  553. package/dist/embeddings/projectionLayer.d.ts +114 -0
  554. package/dist/embeddings/projectionLayer.d.ts.map +1 -0
  555. package/dist/embeddings/projectionLayer.js +345 -0
  556. package/dist/embeddings/projectionLayer.js.map +1 -0
  557. package/dist/events/Publisher.d.ts +193 -0
  558. package/dist/events/Publisher.d.ts.map +1 -0
  559. package/dist/events/Publisher.js +439 -0
  560. package/dist/events/Publisher.js.map +1 -0
  561. package/dist/events/config.d.ts +139 -0
  562. package/dist/events/config.d.ts.map +1 -0
  563. package/dist/events/config.js +266 -0
  564. package/dist/events/config.js.map +1 -0
  565. package/dist/events/index.d.ts +19 -0
  566. package/dist/events/index.d.ts.map +1 -0
  567. package/dist/events/index.js +31 -0
  568. package/dist/events/index.js.map +1 -0
  569. package/dist/events/integration.d.ts +206 -0
  570. package/dist/events/integration.d.ts.map +1 -0
  571. package/dist/events/integration.js +348 -0
  572. package/dist/events/integration.js.map +1 -0
  573. package/dist/events/metrics.d.ts +147 -0
  574. package/dist/events/metrics.d.ts.map +1 -0
  575. package/dist/events/metrics.js +343 -0
  576. package/dist/events/metrics.js.map +1 -0
  577. package/dist/hooks/cli.d.ts +28 -0
  578. package/dist/hooks/cli.d.ts.map +1 -0
  579. package/dist/hooks/cli.js +118 -0
  580. package/dist/hooks/cli.js.map +1 -0
  581. package/dist/hooks/contextInjectionHook.d.ts +60 -0
  582. package/dist/hooks/contextInjectionHook.d.ts.map +1 -0
  583. package/dist/hooks/contextInjectionHook.js +294 -0
  584. package/dist/hooks/contextInjectionHook.js.map +1 -0
  585. package/dist/hooks/drilldownHook.d.ts +125 -0
  586. package/dist/hooks/drilldownHook.d.ts.map +1 -0
  587. package/dist/hooks/drilldownHook.js +181 -0
  588. package/dist/hooks/drilldownHook.js.map +1 -0
  589. package/dist/hooks/hookManager.d.ts +180 -0
  590. package/dist/hooks/hookManager.d.ts.map +1 -0
  591. package/dist/hooks/hookManager.js +782 -0
  592. package/dist/hooks/hookManager.js.map +1 -0
  593. package/dist/hooks/index.d.ts +62 -0
  594. package/dist/hooks/index.d.ts.map +1 -0
  595. package/dist/hooks/index.js +66 -0
  596. package/dist/hooks/index.js.map +1 -0
  597. package/dist/hooks/lowContextHook.d.ts +71 -0
  598. package/dist/hooks/lowContextHook.d.ts.map +1 -0
  599. package/dist/hooks/lowContextHook.js +258 -0
  600. package/dist/hooks/lowContextHook.js.map +1 -0
  601. package/dist/hooks/simpleContextHook.d.ts +65 -0
  602. package/dist/hooks/simpleContextHook.d.ts.map +1 -0
  603. package/dist/hooks/simpleContextHook.js +194 -0
  604. package/dist/hooks/simpleContextHook.js.map +1 -0
  605. package/dist/hooks/teamFramingCli.d.ts +56 -0
  606. package/dist/hooks/teamFramingCli.d.ts.map +1 -0
  607. package/dist/hooks/teamFramingCli.js +264 -0
  608. package/dist/hooks/teamFramingCli.js.map +1 -0
  609. package/dist/hooks/teamMemberPrepromptHook.d.ts +150 -0
  610. package/dist/hooks/teamMemberPrepromptHook.d.ts.map +1 -0
  611. package/dist/hooks/teamMemberPrepromptHook.js +308 -0
  612. package/dist/hooks/teamMemberPrepromptHook.js.map +1 -0
  613. package/dist/index.d.ts +42 -0
  614. package/dist/index.d.ts.map +1 -0
  615. package/dist/index.js +4433 -0
  616. package/dist/index.js.map +1 -0
  617. package/dist/init/claudeConfigInjector.d.ts +116 -0
  618. package/dist/init/claudeConfigInjector.d.ts.map +1 -0
  619. package/dist/init/claudeConfigInjector.js +1154 -0
  620. package/dist/init/claudeConfigInjector.js.map +1 -0
  621. package/dist/installer/autoInstall.d.ts +72 -0
  622. package/dist/installer/autoInstall.d.ts.map +1 -0
  623. package/dist/installer/autoInstall.js +617 -0
  624. package/dist/installer/autoInstall.js.map +1 -0
  625. package/dist/installer/dbSetup.d.ts +84 -0
  626. package/dist/installer/dbSetup.d.ts.map +1 -0
  627. package/dist/installer/dbSetup.js +350 -0
  628. package/dist/installer/dbSetup.js.map +1 -0
  629. package/dist/installer/firstRun.d.ts +49 -0
  630. package/dist/installer/firstRun.d.ts.map +1 -0
  631. package/dist/installer/firstRun.js +207 -0
  632. package/dist/installer/firstRun.js.map +1 -0
  633. package/dist/installer/index.d.ts +10 -0
  634. package/dist/installer/index.d.ts.map +1 -0
  635. package/dist/installer/index.js +10 -0
  636. package/dist/installer/index.js.map +1 -0
  637. package/dist/installer/silentAutoInstall.d.ts +99 -0
  638. package/dist/installer/silentAutoInstall.d.ts.map +1 -0
  639. package/dist/installer/silentAutoInstall.js +491 -0
  640. package/dist/installer/silentAutoInstall.js.map +1 -0
  641. package/dist/installer/systemDeps.d.ts +54 -0
  642. package/dist/installer/systemDeps.d.ts.map +1 -0
  643. package/dist/installer/systemDeps.js +322 -0
  644. package/dist/installer/systemDeps.js.map +1 -0
  645. package/dist/mcp/cliNotifications.d.ts +133 -0
  646. package/dist/mcp/cliNotifications.d.ts.map +1 -0
  647. package/dist/mcp/cliNotifications.js +289 -0
  648. package/dist/mcp/cliNotifications.js.map +1 -0
  649. package/dist/mcp/embeddingServerManager.d.ts +307 -0
  650. package/dist/mcp/embeddingServerManager.d.ts.map +1 -0
  651. package/dist/mcp/embeddingServerManager.js +2081 -0
  652. package/dist/mcp/embeddingServerManager.js.map +1 -0
  653. package/dist/mcp/healthMonitor.d.ts +196 -0
  654. package/dist/mcp/healthMonitor.d.ts.map +1 -0
  655. package/dist/mcp/healthMonitor.js +685 -0
  656. package/dist/mcp/healthMonitor.js.map +1 -0
  657. package/dist/mcp/hotReloadManager.d.ts +101 -0
  658. package/dist/mcp/hotReloadManager.d.ts.map +1 -0
  659. package/dist/mcp/hotReloadManager.js +251 -0
  660. package/dist/mcp/hotReloadManager.js.map +1 -0
  661. package/dist/mcp/index.d.ts +16 -0
  662. package/dist/mcp/index.d.ts.map +1 -0
  663. package/dist/mcp/index.js +22 -0
  664. package/dist/mcp/index.js.map +1 -0
  665. package/dist/mcp/mcpProtocolHandler.d.ts +64 -0
  666. package/dist/mcp/mcpProtocolHandler.d.ts.map +1 -0
  667. package/dist/mcp/mcpProtocolHandler.js +253 -0
  668. package/dist/mcp/mcpProtocolHandler.js.map +1 -0
  669. package/dist/mcp/miniCOTServerManager.d.ts +336 -0
  670. package/dist/mcp/miniCOTServerManager.d.ts.map +1 -0
  671. package/dist/mcp/miniCOTServerManager.js +1384 -0
  672. package/dist/mcp/miniCOTServerManager.js.map +1 -0
  673. package/dist/mcp/promptExecutor.d.ts +188 -0
  674. package/dist/mcp/promptExecutor.d.ts.map +1 -0
  675. package/dist/mcp/promptExecutor.js +469 -0
  676. package/dist/mcp/promptExecutor.js.map +1 -0
  677. package/dist/mcp/reloadBroadcast.d.ts +127 -0
  678. package/dist/mcp/reloadBroadcast.d.ts.map +1 -0
  679. package/dist/mcp/reloadBroadcast.js +275 -0
  680. package/dist/mcp/reloadBroadcast.js.map +1 -0
  681. package/dist/mcp/resilientTransport.d.ts +249 -0
  682. package/dist/mcp/resilientTransport.d.ts.map +1 -0
  683. package/dist/mcp/resilientTransport.js +931 -0
  684. package/dist/mcp/resilientTransport.js.map +1 -0
  685. package/dist/mcp/samplingHandler.d.ts +129 -0
  686. package/dist/mcp/samplingHandler.d.ts.map +1 -0
  687. package/dist/mcp/samplingHandler.js +276 -0
  688. package/dist/mcp/samplingHandler.js.map +1 -0
  689. package/dist/mcp/specMemServer.d.ts +305 -0
  690. package/dist/mcp/specMemServer.d.ts.map +1 -0
  691. package/dist/mcp/specMemServer.js +2048 -0
  692. package/dist/mcp/specMemServer.js.map +1 -0
  693. package/dist/mcp/toolRegistry.d.ts +122 -0
  694. package/dist/mcp/toolRegistry.d.ts.map +1 -0
  695. package/dist/mcp/toolRegistry.js +609 -0
  696. package/dist/mcp/toolRegistry.js.map +1 -0
  697. package/dist/mcp/tools/embeddingControl.d.ts +114 -0
  698. package/dist/mcp/tools/embeddingControl.d.ts.map +1 -0
  699. package/dist/mcp/tools/embeddingControl.js +222 -0
  700. package/dist/mcp/tools/embeddingControl.js.map +1 -0
  701. package/dist/mcp/tools/index.d.ts +10 -0
  702. package/dist/mcp/tools/index.d.ts.map +1 -0
  703. package/dist/mcp/tools/index.js +17 -0
  704. package/dist/mcp/tools/index.js.map +1 -0
  705. package/dist/mcp/tools/teamComms.d.ts +444 -0
  706. package/dist/mcp/tools/teamComms.d.ts.map +1 -0
  707. package/dist/mcp/tools/teamComms.js +1953 -0
  708. package/dist/mcp/tools/teamComms.js.map +1 -0
  709. package/dist/mcp/triggerSystem.d.ts +129 -0
  710. package/dist/mcp/triggerSystem.d.ts.map +1 -0
  711. package/dist/mcp/triggerSystem.js +363 -0
  712. package/dist/mcp/triggerSystem.js.map +1 -0
  713. package/dist/mcp/watcherIntegration.d.ts +77 -0
  714. package/dist/mcp/watcherIntegration.d.ts.map +1 -0
  715. package/dist/mcp/watcherIntegration.js +428 -0
  716. package/dist/mcp/watcherIntegration.js.map +1 -0
  717. package/dist/mcp/watcherToolWrappers.d.ts +89 -0
  718. package/dist/mcp/watcherToolWrappers.d.ts.map +1 -0
  719. package/dist/mcp/watcherToolWrappers.js +91 -0
  720. package/dist/mcp/watcherToolWrappers.js.map +1 -0
  721. package/dist/memorization/claudeCodeMigration.d.ts +34 -0
  722. package/dist/memorization/claudeCodeMigration.d.ts.map +1 -0
  723. package/dist/memorization/claudeCodeMigration.js +210 -0
  724. package/dist/memorization/claudeCodeMigration.js.map +1 -0
  725. package/dist/memorization/claudeCodeTracker.d.ts +147 -0
  726. package/dist/memorization/claudeCodeTracker.d.ts.map +1 -0
  727. package/dist/memorization/claudeCodeTracker.js +424 -0
  728. package/dist/memorization/claudeCodeTracker.js.map +1 -0
  729. package/dist/memorization/codeMemorizer.d.ts +158 -0
  730. package/dist/memorization/codeMemorizer.d.ts.map +1 -0
  731. package/dist/memorization/codeMemorizer.js +357 -0
  732. package/dist/memorization/codeMemorizer.js.map +1 -0
  733. package/dist/memorization/codeRecall.d.ts +156 -0
  734. package/dist/memorization/codeRecall.d.ts.map +1 -0
  735. package/dist/memorization/codeRecall.js +499 -0
  736. package/dist/memorization/codeRecall.js.map +1 -0
  737. package/dist/memorization/index.d.ts +55 -0
  738. package/dist/memorization/index.d.ts.map +1 -0
  739. package/dist/memorization/index.js +64 -0
  740. package/dist/memorization/index.js.map +1 -0
  741. package/dist/memorization/memorizationTools.d.ts +413 -0
  742. package/dist/memorization/memorizationTools.d.ts.map +1 -0
  743. package/dist/memorization/memorizationTools.js +513 -0
  744. package/dist/memorization/memorizationTools.js.map +1 -0
  745. package/dist/memorization/watcherIntegration.d.ts +100 -0
  746. package/dist/memorization/watcherIntegration.d.ts.map +1 -0
  747. package/dist/memorization/watcherIntegration.js +196 -0
  748. package/dist/memorization/watcherIntegration.js.map +1 -0
  749. package/dist/memory/humanLikeMemory.d.ts +206 -0
  750. package/dist/memory/humanLikeMemory.d.ts.map +1 -0
  751. package/dist/memory/humanLikeMemory.js +603 -0
  752. package/dist/memory/humanLikeMemory.js.map +1 -0
  753. package/dist/memory/index.d.ts +22 -0
  754. package/dist/memory/index.d.ts.map +1 -0
  755. package/dist/memory/index.js +24 -0
  756. package/dist/memory/index.js.map +1 -0
  757. package/dist/memory/memoryEvolutionMigration.d.ts +36 -0
  758. package/dist/memory/memoryEvolutionMigration.d.ts.map +1 -0
  759. package/dist/memory/memoryEvolutionMigration.js +371 -0
  760. package/dist/memory/memoryEvolutionMigration.js.map +1 -0
  761. package/dist/memory/quadrantSearch.d.ts +221 -0
  762. package/dist/memory/quadrantSearch.d.ts.map +1 -0
  763. package/dist/memory/quadrantSearch.js +897 -0
  764. package/dist/memory/quadrantSearch.js.map +1 -0
  765. package/dist/middleware/apiVersioning.d.ts +83 -0
  766. package/dist/middleware/apiVersioning.d.ts.map +1 -0
  767. package/dist/middleware/apiVersioning.js +152 -0
  768. package/dist/middleware/apiVersioning.js.map +1 -0
  769. package/dist/middleware/compression.d.ts +48 -0
  770. package/dist/middleware/compression.d.ts.map +1 -0
  771. package/dist/middleware/compression.js +240 -0
  772. package/dist/middleware/compression.js.map +1 -0
  773. package/dist/middleware/csrf.d.ts +118 -0
  774. package/dist/middleware/csrf.d.ts.map +1 -0
  775. package/dist/middleware/csrf.js +300 -0
  776. package/dist/middleware/csrf.js.map +1 -0
  777. package/dist/middleware/index.d.ts +13 -0
  778. package/dist/middleware/index.d.ts.map +1 -0
  779. package/dist/middleware/index.js +17 -0
  780. package/dist/middleware/index.js.map +1 -0
  781. package/dist/middleware/wsRateLimiter.d.ts +129 -0
  782. package/dist/middleware/wsRateLimiter.d.ts.map +1 -0
  783. package/dist/middleware/wsRateLimiter.js +279 -0
  784. package/dist/middleware/wsRateLimiter.js.map +1 -0
  785. package/dist/migrations/run.d.ts +2 -0
  786. package/dist/migrations/run.d.ts.map +1 -0
  787. package/dist/migrations/run.js +25 -0
  788. package/dist/migrations/run.js.map +1 -0
  789. package/dist/migrations/syncDimensions.d.ts +24 -0
  790. package/dist/migrations/syncDimensions.d.ts.map +1 -0
  791. package/dist/migrations/syncDimensions.js +140 -0
  792. package/dist/migrations/syncDimensions.js.map +1 -0
  793. package/dist/migrations/teamComms.d.ts +16 -0
  794. package/dist/migrations/teamComms.d.ts.map +1 -0
  795. package/dist/migrations/teamComms.js +210 -0
  796. package/dist/migrations/teamComms.js.map +1 -0
  797. package/dist/openapi/index.d.ts +10 -0
  798. package/dist/openapi/index.d.ts.map +1 -0
  799. package/dist/openapi/index.js +10 -0
  800. package/dist/openapi/index.js.map +1 -0
  801. package/dist/openapi/spec.d.ts +902 -0
  802. package/dist/openapi/spec.d.ts.map +1 -0
  803. package/dist/openapi/spec.js +733 -0
  804. package/dist/openapi/spec.js.map +1 -0
  805. package/dist/packages/dependencyHistory.d.ts +113 -0
  806. package/dist/packages/dependencyHistory.d.ts.map +1 -0
  807. package/dist/packages/dependencyHistory.js +360 -0
  808. package/dist/packages/dependencyHistory.js.map +1 -0
  809. package/dist/packages/index.d.ts +30 -0
  810. package/dist/packages/index.d.ts.map +1 -0
  811. package/dist/packages/index.js +65 -0
  812. package/dist/packages/index.js.map +1 -0
  813. package/dist/packages/packageTools.d.ts +255 -0
  814. package/dist/packages/packageTools.d.ts.map +1 -0
  815. package/dist/packages/packageTools.js +242 -0
  816. package/dist/packages/packageTools.js.map +1 -0
  817. package/dist/packages/packageTracker.d.ts +98 -0
  818. package/dist/packages/packageTracker.d.ts.map +1 -0
  819. package/dist/packages/packageTracker.js +268 -0
  820. package/dist/packages/packageTracker.js.map +1 -0
  821. package/dist/packages/packageWatcher.d.ts +62 -0
  822. package/dist/packages/packageWatcher.d.ts.map +1 -0
  823. package/dist/packages/packageWatcher.js +146 -0
  824. package/dist/packages/packageWatcher.js.map +1 -0
  825. package/dist/providers/MiniCOTProvider.d.ts +48 -0
  826. package/dist/providers/MiniCOTProvider.d.ts.map +1 -0
  827. package/dist/providers/MiniCOTProvider.js +98 -0
  828. package/dist/providers/MiniCOTProvider.js.map +1 -0
  829. package/dist/reminders/index.d.ts +5 -0
  830. package/dist/reminders/index.d.ts.map +1 -0
  831. package/dist/reminders/index.js +5 -0
  832. package/dist/reminders/index.js.map +1 -0
  833. package/dist/reminders/skillReminder.d.ts +131 -0
  834. package/dist/reminders/skillReminder.d.ts.map +1 -0
  835. package/dist/reminders/skillReminder.js +386 -0
  836. package/dist/reminders/skillReminder.js.map +1 -0
  837. package/dist/search.d.ts +35 -0
  838. package/dist/search.d.ts.map +1 -0
  839. package/dist/search.js +574 -0
  840. package/dist/search.js.map +1 -0
  841. package/dist/security/localhostOnly.d.ts +36 -0
  842. package/dist/security/localhostOnly.d.ts.map +1 -0
  843. package/dist/security/localhostOnly.js +101 -0
  844. package/dist/security/localhostOnly.js.map +1 -0
  845. package/dist/services/CameraZoomSearch.d.ts +206 -0
  846. package/dist/services/CameraZoomSearch.d.ts.map +1 -0
  847. package/dist/services/CameraZoomSearch.js +669 -0
  848. package/dist/services/CameraZoomSearch.js.map +1 -0
  849. package/dist/services/DataFlowPipeline.d.ts +111 -0
  850. package/dist/services/DataFlowPipeline.d.ts.map +1 -0
  851. package/dist/services/DataFlowPipeline.js +379 -0
  852. package/dist/services/DataFlowPipeline.js.map +1 -0
  853. package/dist/services/DimensionAdapter.d.ts +194 -0
  854. package/dist/services/DimensionAdapter.d.ts.map +1 -0
  855. package/dist/services/DimensionAdapter.js +566 -0
  856. package/dist/services/DimensionAdapter.js.map +1 -0
  857. package/dist/services/DimensionService.d.ts +252 -0
  858. package/dist/services/DimensionService.d.ts.map +1 -0
  859. package/dist/services/DimensionService.js +564 -0
  860. package/dist/services/DimensionService.js.map +1 -0
  861. package/dist/services/EmbeddingQueue.d.ts +71 -0
  862. package/dist/services/EmbeddingQueue.d.ts.map +1 -0
  863. package/dist/services/EmbeddingQueue.js +258 -0
  864. package/dist/services/EmbeddingQueue.js.map +1 -0
  865. package/dist/services/MemoryDrilldown.d.ts +226 -0
  866. package/dist/services/MemoryDrilldown.d.ts.map +1 -0
  867. package/dist/services/MemoryDrilldown.js +479 -0
  868. package/dist/services/MemoryDrilldown.js.map +1 -0
  869. package/dist/services/MiniCOTScorer.d.ts +140 -0
  870. package/dist/services/MiniCOTScorer.d.ts.map +1 -0
  871. package/dist/services/MiniCOTScorer.js +292 -0
  872. package/dist/services/MiniCOTScorer.js.map +1 -0
  873. package/dist/services/ProjectContext.d.ts +342 -0
  874. package/dist/services/ProjectContext.d.ts.map +1 -0
  875. package/dist/services/ProjectContext.js +667 -0
  876. package/dist/services/ProjectContext.js.map +1 -0
  877. package/dist/services/ResponseCompactor.d.ts +135 -0
  878. package/dist/services/ResponseCompactor.d.ts.map +1 -0
  879. package/dist/services/ResponseCompactor.js +501 -0
  880. package/dist/services/ResponseCompactor.js.map +1 -0
  881. package/dist/services/TeamCommsDbService.d.ts +202 -0
  882. package/dist/services/TeamCommsDbService.d.ts.map +1 -0
  883. package/dist/services/TeamCommsDbService.js +526 -0
  884. package/dist/services/TeamCommsDbService.js.map +1 -0
  885. package/dist/services/UnifiedPasswordService.d.ts +166 -0
  886. package/dist/services/UnifiedPasswordService.d.ts.map +1 -0
  887. package/dist/services/UnifiedPasswordService.js +587 -0
  888. package/dist/services/UnifiedPasswordService.js.map +1 -0
  889. package/dist/services/adaptiveSearchConfig.d.ts +64 -0
  890. package/dist/services/adaptiveSearchConfig.d.ts.map +1 -0
  891. package/dist/services/adaptiveSearchConfig.js +187 -0
  892. package/dist/services/adaptiveSearchConfig.js.map +1 -0
  893. package/dist/skills/index.d.ts +8 -0
  894. package/dist/skills/index.d.ts.map +1 -0
  895. package/dist/skills/index.js +8 -0
  896. package/dist/skills/index.js.map +1 -0
  897. package/dist/skills/skillScanner.d.ts +203 -0
  898. package/dist/skills/skillScanner.d.ts.map +1 -0
  899. package/dist/skills/skillScanner.js +559 -0
  900. package/dist/skills/skillScanner.js.map +1 -0
  901. package/dist/skills/skillsResource.d.ts +69 -0
  902. package/dist/skills/skillsResource.d.ts.map +1 -0
  903. package/dist/skills/skillsResource.js +257 -0
  904. package/dist/skills/skillsResource.js.map +1 -0
  905. package/dist/startup/index.d.ts +9 -0
  906. package/dist/startup/index.d.ts.map +1 -0
  907. package/dist/startup/index.js +12 -0
  908. package/dist/startup/index.js.map +1 -0
  909. package/dist/startup/startupIndexing.d.ts +80 -0
  910. package/dist/startup/startupIndexing.d.ts.map +1 -0
  911. package/dist/startup/startupIndexing.js +463 -0
  912. package/dist/startup/startupIndexing.js.map +1 -0
  913. package/dist/startup/validation.d.ts +89 -0
  914. package/dist/startup/validation.d.ts.map +1 -0
  915. package/dist/startup/validation.js +590 -0
  916. package/dist/startup/validation.js.map +1 -0
  917. package/dist/storage/index.d.ts +4 -0
  918. package/dist/storage/index.d.ts.map +1 -0
  919. package/dist/storage/index.js +4 -0
  920. package/dist/storage/index.js.map +1 -0
  921. package/dist/storage/overflowManager.d.ts +80 -0
  922. package/dist/storage/overflowManager.d.ts.map +1 -0
  923. package/dist/storage/overflowManager.js +317 -0
  924. package/dist/storage/overflowManager.js.map +1 -0
  925. package/dist/storage/overflowStorage.d.ts +69 -0
  926. package/dist/storage/overflowStorage.d.ts.map +1 -0
  927. package/dist/storage/overflowStorage.js +379 -0
  928. package/dist/storage/overflowStorage.js.map +1 -0
  929. package/dist/storage/toonFormat.d.ts +50 -0
  930. package/dist/storage/toonFormat.d.ts.map +1 -0
  931. package/dist/storage/toonFormat.js +224 -0
  932. package/dist/storage/toonFormat.js.map +1 -0
  933. package/dist/team-members/communication.d.ts +237 -0
  934. package/dist/team-members/communication.d.ts.map +1 -0
  935. package/dist/team-members/communication.js +650 -0
  936. package/dist/team-members/communication.js.map +1 -0
  937. package/dist/team-members/index.d.ts +14 -0
  938. package/dist/team-members/index.d.ts.map +1 -0
  939. package/dist/team-members/index.js +22 -0
  940. package/dist/team-members/index.js.map +1 -0
  941. package/dist/team-members/taskOrchestrator.d.ts +224 -0
  942. package/dist/team-members/taskOrchestrator.d.ts.map +1 -0
  943. package/dist/team-members/taskOrchestrator.js +574 -0
  944. package/dist/team-members/taskOrchestrator.js.map +1 -0
  945. package/dist/team-members/taskTeamMemberLogger.d.ts +157 -0
  946. package/dist/team-members/taskTeamMemberLogger.d.ts.map +1 -0
  947. package/dist/team-members/taskTeamMemberLogger.js +478 -0
  948. package/dist/team-members/taskTeamMemberLogger.js.map +1 -0
  949. package/dist/team-members/teamCommsService.d.ts +221 -0
  950. package/dist/team-members/teamCommsService.d.ts.map +1 -0
  951. package/dist/team-members/teamCommsService.js +628 -0
  952. package/dist/team-members/teamCommsService.js.map +1 -0
  953. package/dist/team-members/teamMemberChannels.d.ts +217 -0
  954. package/dist/team-members/teamMemberChannels.d.ts.map +1 -0
  955. package/dist/team-members/teamMemberChannels.js +687 -0
  956. package/dist/team-members/teamMemberChannels.js.map +1 -0
  957. package/dist/team-members/teamMemberDashboard.d.ts +222 -0
  958. package/dist/team-members/teamMemberDashboard.d.ts.map +1 -0
  959. package/dist/team-members/teamMemberDashboard.js +610 -0
  960. package/dist/team-members/teamMemberDashboard.js.map +1 -0
  961. package/dist/team-members/teamMemberDeployment.d.ts +60 -0
  962. package/dist/team-members/teamMemberDeployment.d.ts.map +1 -0
  963. package/dist/team-members/teamMemberDeployment.js +429 -0
  964. package/dist/team-members/teamMemberDeployment.js.map +1 -0
  965. package/dist/team-members/teamMemberDiscovery.d.ts +178 -0
  966. package/dist/team-members/teamMemberDiscovery.d.ts.map +1 -0
  967. package/dist/team-members/teamMemberDiscovery.js +446 -0
  968. package/dist/team-members/teamMemberDiscovery.js.map +1 -0
  969. package/dist/team-members/teamMemberHistory.d.ts +80 -0
  970. package/dist/team-members/teamMemberHistory.d.ts.map +1 -0
  971. package/dist/team-members/teamMemberHistory.js +426 -0
  972. package/dist/team-members/teamMemberHistory.js.map +1 -0
  973. package/dist/team-members/teamMemberLimits.d.ts +66 -0
  974. package/dist/team-members/teamMemberLimits.d.ts.map +1 -0
  975. package/dist/team-members/teamMemberLimits.js +259 -0
  976. package/dist/team-members/teamMemberLimits.js.map +1 -0
  977. package/dist/team-members/teamMemberRegistry.d.ts +199 -0
  978. package/dist/team-members/teamMemberRegistry.d.ts.map +1 -0
  979. package/dist/team-members/teamMemberRegistry.js +572 -0
  980. package/dist/team-members/teamMemberRegistry.js.map +1 -0
  981. package/dist/team-members/teamMemberTracker.d.ts +148 -0
  982. package/dist/team-members/teamMemberTracker.d.ts.map +1 -0
  983. package/dist/team-members/teamMemberTracker.js +828 -0
  984. package/dist/team-members/teamMemberTracker.js.map +1 -0
  985. package/dist/team-members/workers/aiWorker.d.ts +53 -0
  986. package/dist/team-members/workers/aiWorker.d.ts.map +1 -0
  987. package/dist/team-members/workers/aiWorker.js +322 -0
  988. package/dist/team-members/workers/aiWorker.js.map +1 -0
  989. package/dist/team-members/workers/baseWorker.d.ts +101 -0
  990. package/dist/team-members/workers/baseWorker.d.ts.map +1 -0
  991. package/dist/team-members/workers/baseWorker.js +179 -0
  992. package/dist/team-members/workers/baseWorker.js.map +1 -0
  993. package/dist/team-members/workers/codeReviewWorker.d.ts +3 -0
  994. package/dist/team-members/workers/codeReviewWorker.d.ts.map +1 -0
  995. package/dist/team-members/workers/codeReviewWorker.js +144 -0
  996. package/dist/team-members/workers/codeReviewWorker.js.map +1 -0
  997. package/dist/team-members/workers/index.d.ts +7 -0
  998. package/dist/team-members/workers/index.d.ts.map +1 -0
  999. package/dist/team-members/workers/index.js +7 -0
  1000. package/dist/team-members/workers/index.js.map +1 -0
  1001. package/dist/team-members/workers/repairWorker.d.ts +9 -0
  1002. package/dist/team-members/workers/repairWorker.d.ts.map +1 -0
  1003. package/dist/team-members/workers/repairWorker.js +102 -0
  1004. package/dist/team-members/workers/repairWorker.js.map +1 -0
  1005. package/dist/team-members/workers/sendToTeamMemberB.d.ts +9 -0
  1006. package/dist/team-members/workers/sendToTeamMemberB.d.ts.map +1 -0
  1007. package/dist/team-members/workers/sendToTeamMemberB.js +105 -0
  1008. package/dist/team-members/workers/sendToTeamMemberB.js.map +1 -0
  1009. package/dist/team-members/workers/specmemClient.d.ts +179 -0
  1010. package/dist/team-members/workers/specmemClient.d.ts.map +1 -0
  1011. package/dist/team-members/workers/specmemClient.js +421 -0
  1012. package/dist/team-members/workers/specmemClient.js.map +1 -0
  1013. package/dist/team-members/workers/testCommunication.d.ts +8 -0
  1014. package/dist/team-members/workers/testCommunication.d.ts.map +1 -0
  1015. package/dist/team-members/workers/testCommunication.js +136 -0
  1016. package/dist/team-members/workers/testCommunication.js.map +1 -0
  1017. package/dist/team-members/workers/testCommunicationSuite.d.ts +26 -0
  1018. package/dist/team-members/workers/testCommunicationSuite.d.ts.map +1 -0
  1019. package/dist/team-members/workers/testCommunicationSuite.js +415 -0
  1020. package/dist/team-members/workers/testCommunicationSuite.js.map +1 -0
  1021. package/dist/team-members/workers/testWorker.d.ts +9 -0
  1022. package/dist/team-members/workers/testWorker.d.ts.map +1 -0
  1023. package/dist/team-members/workers/testWorker.js +107 -0
  1024. package/dist/team-members/workers/testWorker.js.map +1 -0
  1025. package/dist/tools/agentDefinitions.d.ts +30 -0
  1026. package/dist/tools/agentDefinitions.d.ts.map +1 -0
  1027. package/dist/tools/agentDefinitions.js +166 -0
  1028. package/dist/tools/agentDefinitions.js.map +1 -0
  1029. package/dist/tools/goofy/checkSyncStatus.d.ts +68 -0
  1030. package/dist/tools/goofy/checkSyncStatus.d.ts.map +1 -0
  1031. package/dist/tools/goofy/checkSyncStatus.js +112 -0
  1032. package/dist/tools/goofy/checkSyncStatus.js.map +1 -0
  1033. package/dist/tools/goofy/codeMemoryLink.d.ts +82 -0
  1034. package/dist/tools/goofy/codeMemoryLink.d.ts.map +1 -0
  1035. package/dist/tools/goofy/codeMemoryLink.js +212 -0
  1036. package/dist/tools/goofy/codeMemoryLink.js.map +1 -0
  1037. package/dist/tools/goofy/compareInstanceMemory.d.ts +97 -0
  1038. package/dist/tools/goofy/compareInstanceMemory.d.ts.map +1 -0
  1039. package/dist/tools/goofy/compareInstanceMemory.js +218 -0
  1040. package/dist/tools/goofy/compareInstanceMemory.js.map +1 -0
  1041. package/dist/tools/goofy/createReasoningChain.d.ts +135 -0
  1042. package/dist/tools/goofy/createReasoningChain.d.ts.map +1 -0
  1043. package/dist/tools/goofy/createReasoningChain.js +257 -0
  1044. package/dist/tools/goofy/createReasoningChain.js.map +1 -0
  1045. package/dist/tools/goofy/deployTeamMember.d.ts +63 -0
  1046. package/dist/tools/goofy/deployTeamMember.d.ts.map +1 -0
  1047. package/dist/tools/goofy/deployTeamMember.js +103 -0
  1048. package/dist/tools/goofy/deployTeamMember.js.map +1 -0
  1049. package/dist/tools/goofy/drillDown.d.ts +143 -0
  1050. package/dist/tools/goofy/drillDown.d.ts.map +1 -0
  1051. package/dist/tools/goofy/drillDown.js +288 -0
  1052. package/dist/tools/goofy/drillDown.js.map +1 -0
  1053. package/dist/tools/goofy/extractClaudeSessions.d.ts +90 -0
  1054. package/dist/tools/goofy/extractClaudeSessions.d.ts.map +1 -0
  1055. package/dist/tools/goofy/extractClaudeSessions.js +277 -0
  1056. package/dist/tools/goofy/extractClaudeSessions.js.map +1 -0
  1057. package/dist/tools/goofy/extractContextRestorations.d.ts +70 -0
  1058. package/dist/tools/goofy/extractContextRestorations.d.ts.map +1 -0
  1059. package/dist/tools/goofy/extractContextRestorations.js +100 -0
  1060. package/dist/tools/goofy/extractContextRestorations.js.map +1 -0
  1061. package/dist/tools/goofy/findCodePointers.d.ts +364 -0
  1062. package/dist/tools/goofy/findCodePointers.d.ts.map +1 -0
  1063. package/dist/tools/goofy/findCodePointers.js +1764 -0
  1064. package/dist/tools/goofy/findCodePointers.js.map +1 -0
  1065. package/dist/tools/goofy/findMemoryGallery.d.ts +40 -0
  1066. package/dist/tools/goofy/findMemoryGallery.d.ts.map +1 -0
  1067. package/dist/tools/goofy/findMemoryGallery.js +66 -0
  1068. package/dist/tools/goofy/findMemoryGallery.js.map +1 -0
  1069. package/dist/tools/goofy/findWhatISaid.d.ts +300 -0
  1070. package/dist/tools/goofy/findWhatISaid.d.ts.map +1 -0
  1071. package/dist/tools/goofy/findWhatISaid.js +2547 -0
  1072. package/dist/tools/goofy/findWhatISaid.js.map +1 -0
  1073. package/dist/tools/goofy/forceResync.d.ts +57 -0
  1074. package/dist/tools/goofy/forceResync.d.ts.map +1 -0
  1075. package/dist/tools/goofy/forceResync.js +100 -0
  1076. package/dist/tools/goofy/forceResync.js.map +1 -0
  1077. package/dist/tools/goofy/getActiveTeamMembers.d.ts +48 -0
  1078. package/dist/tools/goofy/getActiveTeamMembers.d.ts.map +1 -0
  1079. package/dist/tools/goofy/getActiveTeamMembers.js +136 -0
  1080. package/dist/tools/goofy/getActiveTeamMembers.js.map +1 -0
  1081. package/dist/tools/goofy/getMemoryFull.d.ts +34 -0
  1082. package/dist/tools/goofy/getMemoryFull.d.ts.map +1 -0
  1083. package/dist/tools/goofy/getMemoryFull.js +58 -0
  1084. package/dist/tools/goofy/getMemoryFull.js.map +1 -0
  1085. package/dist/tools/goofy/getSessionWatcherStatus.d.ts +43 -0
  1086. package/dist/tools/goofy/getSessionWatcherStatus.d.ts.map +1 -0
  1087. package/dist/tools/goofy/getSessionWatcherStatus.js +92 -0
  1088. package/dist/tools/goofy/getSessionWatcherStatus.js.map +1 -0
  1089. package/dist/tools/goofy/getTeamMemberOutput.d.ts +35 -0
  1090. package/dist/tools/goofy/getTeamMemberOutput.d.ts.map +1 -0
  1091. package/dist/tools/goofy/getTeamMemberOutput.js +62 -0
  1092. package/dist/tools/goofy/getTeamMemberOutput.js.map +1 -0
  1093. package/dist/tools/goofy/getTeamMemberScreen.d.ts +28 -0
  1094. package/dist/tools/goofy/getTeamMemberScreen.d.ts.map +1 -0
  1095. package/dist/tools/goofy/getTeamMemberScreen.js +59 -0
  1096. package/dist/tools/goofy/getTeamMemberScreen.js.map +1 -0
  1097. package/dist/tools/goofy/getTeamMemberStatus.d.ts +33 -0
  1098. package/dist/tools/goofy/getTeamMemberStatus.d.ts.map +1 -0
  1099. package/dist/tools/goofy/getTeamMemberStatus.js +56 -0
  1100. package/dist/tools/goofy/getTeamMemberStatus.js.map +1 -0
  1101. package/dist/tools/goofy/index.d.ts +39 -0
  1102. package/dist/tools/goofy/index.d.ts.map +1 -0
  1103. package/dist/tools/goofy/index.js +51 -0
  1104. package/dist/tools/goofy/index.js.map +1 -0
  1105. package/dist/tools/goofy/interveneTeamMember.d.ts +33 -0
  1106. package/dist/tools/goofy/interveneTeamMember.d.ts.map +1 -0
  1107. package/dist/tools/goofy/interveneTeamMember.js +69 -0
  1108. package/dist/tools/goofy/interveneTeamMember.js.map +1 -0
  1109. package/dist/tools/goofy/killDeployedTeamMember.d.ts +29 -0
  1110. package/dist/tools/goofy/killDeployedTeamMember.d.ts.map +1 -0
  1111. package/dist/tools/goofy/killDeployedTeamMember.js +56 -0
  1112. package/dist/tools/goofy/killDeployedTeamMember.js.map +1 -0
  1113. package/dist/tools/goofy/linkTheVibes.d.ts +125 -0
  1114. package/dist/tools/goofy/linkTheVibes.d.ts.map +1 -0
  1115. package/dist/tools/goofy/linkTheVibes.js +354 -0
  1116. package/dist/tools/goofy/linkTheVibes.js.map +1 -0
  1117. package/dist/tools/goofy/listDeployedTeamMembers.d.ts +26 -0
  1118. package/dist/tools/goofy/listDeployedTeamMembers.d.ts.map +1 -0
  1119. package/dist/tools/goofy/listDeployedTeamMembers.js +52 -0
  1120. package/dist/tools/goofy/listDeployedTeamMembers.js.map +1 -0
  1121. package/dist/tools/goofy/listenForMessages.d.ts +56 -0
  1122. package/dist/tools/goofy/listenForMessages.d.ts.map +1 -0
  1123. package/dist/tools/goofy/listenForMessages.js +122 -0
  1124. package/dist/tools/goofy/listenForMessages.js.map +1 -0
  1125. package/dist/tools/goofy/memoryHealthCheck.d.ts +159 -0
  1126. package/dist/tools/goofy/memoryHealthCheck.d.ts.map +1 -0
  1127. package/dist/tools/goofy/memoryHealthCheck.js +443 -0
  1128. package/dist/tools/goofy/memoryHealthCheck.js.map +1 -0
  1129. package/dist/tools/goofy/rememberThisShit.d.ts +103 -0
  1130. package/dist/tools/goofy/rememberThisShit.d.ts.map +1 -0
  1131. package/dist/tools/goofy/rememberThisShit.js +291 -0
  1132. package/dist/tools/goofy/rememberThisShit.js.map +1 -0
  1133. package/dist/tools/goofy/sayToTeamMember.d.ts +55 -0
  1134. package/dist/tools/goofy/sayToTeamMember.d.ts.map +1 -0
  1135. package/dist/tools/goofy/sayToTeamMember.js +116 -0
  1136. package/dist/tools/goofy/sayToTeamMember.js.map +1 -0
  1137. package/dist/tools/goofy/selfMessage.d.ts +54 -0
  1138. package/dist/tools/goofy/selfMessage.d.ts.map +1 -0
  1139. package/dist/tools/goofy/selfMessage.js +111 -0
  1140. package/dist/tools/goofy/selfMessage.js.map +1 -0
  1141. package/dist/tools/goofy/sendHeartbeat.d.ts +53 -0
  1142. package/dist/tools/goofy/sendHeartbeat.d.ts.map +1 -0
  1143. package/dist/tools/goofy/sendHeartbeat.js +119 -0
  1144. package/dist/tools/goofy/sendHeartbeat.js.map +1 -0
  1145. package/dist/tools/goofy/showMeTheStats.d.ts +216 -0
  1146. package/dist/tools/goofy/showMeTheStats.d.ts.map +1 -0
  1147. package/dist/tools/goofy/showMeTheStats.js +535 -0
  1148. package/dist/tools/goofy/showMeTheStats.js.map +1 -0
  1149. package/dist/tools/goofy/smartRecall.d.ts +136 -0
  1150. package/dist/tools/goofy/smartRecall.d.ts.map +1 -0
  1151. package/dist/tools/goofy/smartRecall.js +286 -0
  1152. package/dist/tools/goofy/smartRecall.js.map +1 -0
  1153. package/dist/tools/goofy/smartSearch.d.ts +64 -0
  1154. package/dist/tools/goofy/smartSearch.d.ts.map +1 -0
  1155. package/dist/tools/goofy/smartSearch.js +89 -0
  1156. package/dist/tools/goofy/smartSearch.js.map +1 -0
  1157. package/dist/tools/goofy/smushMemoriesTogether.d.ts +128 -0
  1158. package/dist/tools/goofy/smushMemoriesTogether.d.ts.map +1 -0
  1159. package/dist/tools/goofy/smushMemoriesTogether.js +536 -0
  1160. package/dist/tools/goofy/smushMemoriesTogether.js.map +1 -0
  1161. package/dist/tools/goofy/spatialSearch.d.ts +198 -0
  1162. package/dist/tools/goofy/spatialSearch.d.ts.map +1 -0
  1163. package/dist/tools/goofy/spatialSearch.js +551 -0
  1164. package/dist/tools/goofy/spatialSearch.js.map +1 -0
  1165. package/dist/tools/goofy/spawnResearchTeamMember.d.ts +104 -0
  1166. package/dist/tools/goofy/spawnResearchTeamMember.d.ts.map +1 -0
  1167. package/dist/tools/goofy/spawnResearchTeamMember.js +290 -0
  1168. package/dist/tools/goofy/spawnResearchTeamMember.js.map +1 -0
  1169. package/dist/tools/goofy/spawnResearchTeamMemberTool.d.ts +121 -0
  1170. package/dist/tools/goofy/spawnResearchTeamMemberTool.d.ts.map +1 -0
  1171. package/dist/tools/goofy/spawnResearchTeamMemberTool.js +215 -0
  1172. package/dist/tools/goofy/spawnResearchTeamMemberTool.js.map +1 -0
  1173. package/dist/tools/goofy/startWatchingTheFiles.d.ts +81 -0
  1174. package/dist/tools/goofy/startWatchingTheFiles.d.ts.map +1 -0
  1175. package/dist/tools/goofy/startWatchingTheFiles.js +161 -0
  1176. package/dist/tools/goofy/startWatchingTheFiles.js.map +1 -0
  1177. package/dist/tools/goofy/stopWatchingTheFiles.d.ts +50 -0
  1178. package/dist/tools/goofy/stopWatchingTheFiles.d.ts.map +1 -0
  1179. package/dist/tools/goofy/stopWatchingTheFiles.js +81 -0
  1180. package/dist/tools/goofy/stopWatchingTheFiles.js.map +1 -0
  1181. package/dist/tools/goofy/whatDidIMean.d.ts +113 -0
  1182. package/dist/tools/goofy/whatDidIMean.d.ts.map +1 -0
  1183. package/dist/tools/goofy/whatDidIMean.js +401 -0
  1184. package/dist/tools/goofy/whatDidIMean.js.map +1 -0
  1185. package/dist/tools/goofy/yeahNahDeleteThat.d.ts +109 -0
  1186. package/dist/tools/goofy/yeahNahDeleteThat.d.ts.map +1 -0
  1187. package/dist/tools/goofy/yeahNahDeleteThat.js +319 -0
  1188. package/dist/tools/goofy/yeahNahDeleteThat.js.map +1 -0
  1189. package/dist/tools/index.d.ts +9 -0
  1190. package/dist/tools/index.d.ts.map +1 -0
  1191. package/dist/tools/index.js +9 -0
  1192. package/dist/tools/index.js.map +1 -0
  1193. package/dist/tools/teamMemberDeployer.d.ts +117 -0
  1194. package/dist/tools/teamMemberDeployer.d.ts.map +1 -0
  1195. package/dist/tools/teamMemberDeployer.js +613 -0
  1196. package/dist/tools/teamMemberDeployer.js.map +1 -0
  1197. package/dist/trace/index.d.ts +14 -0
  1198. package/dist/trace/index.d.ts.map +1 -0
  1199. package/dist/trace/index.js +16 -0
  1200. package/dist/trace/index.js.map +1 -0
  1201. package/dist/trace/tools/analyzeImpact.d.ts +90 -0
  1202. package/dist/trace/tools/analyzeImpact.d.ts.map +1 -0
  1203. package/dist/trace/tools/analyzeImpact.js +240 -0
  1204. package/dist/trace/tools/analyzeImpact.js.map +1 -0
  1205. package/dist/trace/tools/exploreDependencies.d.ts +81 -0
  1206. package/dist/trace/tools/exploreDependencies.d.ts.map +1 -0
  1207. package/dist/trace/tools/exploreDependencies.js +161 -0
  1208. package/dist/trace/tools/exploreDependencies.js.map +1 -0
  1209. package/dist/trace/tools/findSimilarBugs.d.ts +112 -0
  1210. package/dist/trace/tools/findSimilarBugs.d.ts.map +1 -0
  1211. package/dist/trace/tools/findSimilarBugs.js +216 -0
  1212. package/dist/trace/tools/findSimilarBugs.js.map +1 -0
  1213. package/dist/trace/tools/index.d.ts +22 -0
  1214. package/dist/trace/tools/index.d.ts.map +1 -0
  1215. package/dist/trace/tools/index.js +39 -0
  1216. package/dist/trace/tools/index.js.map +1 -0
  1217. package/dist/trace/tools/smartExplore.d.ts +126 -0
  1218. package/dist/trace/tools/smartExplore.d.ts.map +1 -0
  1219. package/dist/trace/tools/smartExplore.js +303 -0
  1220. package/dist/trace/tools/smartExplore.js.map +1 -0
  1221. package/dist/trace/tools/traceError.d.ts +101 -0
  1222. package/dist/trace/tools/traceError.d.ts.map +1 -0
  1223. package/dist/trace/tools/traceError.js +175 -0
  1224. package/dist/trace/tools/traceError.js.map +1 -0
  1225. package/dist/trace/traceExploreSystem.d.ts +271 -0
  1226. package/dist/trace/traceExploreSystem.d.ts.map +1 -0
  1227. package/dist/trace/traceExploreSystem.js +789 -0
  1228. package/dist/trace/traceExploreSystem.js.map +1 -0
  1229. package/dist/types/index.d.ts +421 -0
  1230. package/dist/types/index.d.ts.map +1 -0
  1231. package/dist/types/index.js +118 -0
  1232. package/dist/types/index.js.map +1 -0
  1233. package/dist/utils/circuitBreaker.d.ts +195 -0
  1234. package/dist/utils/circuitBreaker.d.ts.map +1 -0
  1235. package/dist/utils/circuitBreaker.js +374 -0
  1236. package/dist/utils/circuitBreaker.js.map +1 -0
  1237. package/dist/utils/cleanupHandler.d.ts +108 -0
  1238. package/dist/utils/cleanupHandler.d.ts.map +1 -0
  1239. package/dist/utils/cleanupHandler.js +203 -0
  1240. package/dist/utils/cleanupHandler.js.map +1 -0
  1241. package/dist/utils/compactXmlResponse.d.ts +60 -0
  1242. package/dist/utils/compactXmlResponse.d.ts.map +1 -0
  1243. package/dist/utils/compactXmlResponse.js +209 -0
  1244. package/dist/utils/compactXmlResponse.js.map +1 -0
  1245. package/dist/utils/cotBroadcast.d.ts +56 -0
  1246. package/dist/utils/cotBroadcast.d.ts.map +1 -0
  1247. package/dist/utils/cotBroadcast.js +157 -0
  1248. package/dist/utils/cotBroadcast.js.map +1 -0
  1249. package/dist/utils/debugLogger.d.ts +95 -0
  1250. package/dist/utils/debugLogger.d.ts.map +1 -0
  1251. package/dist/utils/debugLogger.js +610 -0
  1252. package/dist/utils/debugLogger.js.map +1 -0
  1253. package/dist/utils/fileProcessingQueue.d.ts +259 -0
  1254. package/dist/utils/fileProcessingQueue.d.ts.map +1 -0
  1255. package/dist/utils/fileProcessingQueue.js +714 -0
  1256. package/dist/utils/fileProcessingQueue.js.map +1 -0
  1257. package/dist/utils/humanReadableOutput.d.ts +124 -0
  1258. package/dist/utils/humanReadableOutput.d.ts.map +1 -0
  1259. package/dist/utils/humanReadableOutput.js +340 -0
  1260. package/dist/utils/humanReadableOutput.js.map +1 -0
  1261. package/dist/utils/index.d.ts +32 -0
  1262. package/dist/utils/index.d.ts.map +1 -0
  1263. package/dist/utils/index.js +71 -0
  1264. package/dist/utils/index.js.map +1 -0
  1265. package/dist/utils/instanceManager.d.ts +530 -0
  1266. package/dist/utils/instanceManager.d.ts.map +1 -0
  1267. package/dist/utils/instanceManager.js +1784 -0
  1268. package/dist/utils/instanceManager.js.map +1 -0
  1269. package/dist/utils/logger.d.ts +6 -0
  1270. package/dist/utils/logger.d.ts.map +1 -0
  1271. package/dist/utils/logger.js +49 -0
  1272. package/dist/utils/logger.js.map +1 -0
  1273. package/dist/utils/mapCleanup.d.ts +58 -0
  1274. package/dist/utils/mapCleanup.d.ts.map +1 -0
  1275. package/dist/utils/mapCleanup.js +150 -0
  1276. package/dist/utils/mapCleanup.js.map +1 -0
  1277. package/dist/utils/memoryManager.d.ts +349 -0
  1278. package/dist/utils/memoryManager.d.ts.map +1 -0
  1279. package/dist/utils/memoryManager.js +799 -0
  1280. package/dist/utils/memoryManager.js.map +1 -0
  1281. package/dist/utils/metrics.d.ts +160 -0
  1282. package/dist/utils/metrics.d.ts.map +1 -0
  1283. package/dist/utils/metrics.js +558 -0
  1284. package/dist/utils/metrics.js.map +1 -0
  1285. package/dist/utils/pathValidator.d.ts +96 -0
  1286. package/dist/utils/pathValidator.d.ts.map +1 -0
  1287. package/dist/utils/pathValidator.js +320 -0
  1288. package/dist/utils/pathValidator.js.map +1 -0
  1289. package/dist/utils/portAllocator.d.ts +296 -0
  1290. package/dist/utils/portAllocator.d.ts.map +1 -0
  1291. package/dist/utils/portAllocator.js +768 -0
  1292. package/dist/utils/portAllocator.js.map +1 -0
  1293. package/dist/utils/portUtils.d.ts +97 -0
  1294. package/dist/utils/portUtils.d.ts.map +1 -0
  1295. package/dist/utils/portUtils.js +285 -0
  1296. package/dist/utils/portUtils.js.map +1 -0
  1297. package/dist/utils/postgresAutoSetup.d.ts +55 -0
  1298. package/dist/utils/postgresAutoSetup.d.ts.map +1 -0
  1299. package/dist/utils/postgresAutoSetup.js +406 -0
  1300. package/dist/utils/postgresAutoSetup.js.map +1 -0
  1301. package/dist/utils/processHealthCheck.d.ts +61 -0
  1302. package/dist/utils/processHealthCheck.d.ts.map +1 -0
  1303. package/dist/utils/processHealthCheck.js +313 -0
  1304. package/dist/utils/processHealthCheck.js.map +1 -0
  1305. package/dist/utils/progressReporter.d.ts +151 -0
  1306. package/dist/utils/progressReporter.d.ts.map +1 -0
  1307. package/dist/utils/progressReporter.js +345 -0
  1308. package/dist/utils/progressReporter.js.map +1 -0
  1309. package/dist/utils/projectEnv.d.ts +73 -0
  1310. package/dist/utils/projectEnv.d.ts.map +1 -0
  1311. package/dist/utils/projectEnv.js +137 -0
  1312. package/dist/utils/projectEnv.js.map +1 -0
  1313. package/dist/utils/qoms.d.ts +122 -0
  1314. package/dist/utils/qoms.d.ts.map +1 -0
  1315. package/dist/utils/qoms.js +650 -0
  1316. package/dist/utils/qoms.js.map +1 -0
  1317. package/dist/utils/retryHelper.d.ts +122 -0
  1318. package/dist/utils/retryHelper.d.ts.map +1 -0
  1319. package/dist/utils/retryHelper.js +272 -0
  1320. package/dist/utils/retryHelper.js.map +1 -0
  1321. package/dist/utils/safeProcessTermination.d.ts +206 -0
  1322. package/dist/utils/safeProcessTermination.d.ts.map +1 -0
  1323. package/dist/utils/safeProcessTermination.js +552 -0
  1324. package/dist/utils/safeProcessTermination.js.map +1 -0
  1325. package/dist/utils/sessionInjector.d.ts +68 -0
  1326. package/dist/utils/sessionInjector.d.ts.map +1 -0
  1327. package/dist/utils/sessionInjector.js +189 -0
  1328. package/dist/utils/sessionInjector.js.map +1 -0
  1329. package/dist/utils/statsCache.d.ts +134 -0
  1330. package/dist/utils/statsCache.d.ts.map +1 -0
  1331. package/dist/utils/statsCache.js +285 -0
  1332. package/dist/utils/statsCache.js.map +1 -0
  1333. package/dist/utils/timeoutMiddleware.d.ts +81 -0
  1334. package/dist/utils/timeoutMiddleware.d.ts.map +1 -0
  1335. package/dist/utils/timeoutMiddleware.js +155 -0
  1336. package/dist/utils/timeoutMiddleware.js.map +1 -0
  1337. package/dist/utils/timerRegistry.d.ts +91 -0
  1338. package/dist/utils/timerRegistry.d.ts.map +1 -0
  1339. package/dist/utils/timerRegistry.js +187 -0
  1340. package/dist/utils/timerRegistry.js.map +1 -0
  1341. package/dist/utils/tokenCompressor.d.ts +332 -0
  1342. package/dist/utils/tokenCompressor.d.ts.map +1 -0
  1343. package/dist/utils/tokenCompressor.js +1306 -0
  1344. package/dist/utils/tokenCompressor.js.map +1 -0
  1345. package/dist/utils/tracing.d.ts +236 -0
  1346. package/dist/utils/tracing.d.ts.map +1 -0
  1347. package/dist/utils/tracing.js +378 -0
  1348. package/dist/utils/tracing.js.map +1 -0
  1349. package/dist/watcher/changeHandler.d.ts +123 -0
  1350. package/dist/watcher/changeHandler.d.ts.map +1 -0
  1351. package/dist/watcher/changeHandler.js +623 -0
  1352. package/dist/watcher/changeHandler.js.map +1 -0
  1353. package/dist/watcher/changeQueue.d.ts +133 -0
  1354. package/dist/watcher/changeQueue.d.ts.map +1 -0
  1355. package/dist/watcher/changeQueue.js +355 -0
  1356. package/dist/watcher/changeQueue.js.map +1 -0
  1357. package/dist/watcher/fileWatcher.d.ts +121 -0
  1358. package/dist/watcher/fileWatcher.d.ts.map +1 -0
  1359. package/dist/watcher/fileWatcher.js +531 -0
  1360. package/dist/watcher/fileWatcher.js.map +1 -0
  1361. package/dist/watcher/index.d.ts +94 -0
  1362. package/dist/watcher/index.d.ts.map +1 -0
  1363. package/dist/watcher/index.js +235 -0
  1364. package/dist/watcher/index.js.map +1 -0
  1365. package/dist/watcher/syncChecker.d.ts +93 -0
  1366. package/dist/watcher/syncChecker.d.ts.map +1 -0
  1367. package/dist/watcher/syncChecker.js +401 -0
  1368. package/dist/watcher/syncChecker.js.map +1 -0
  1369. package/dist/watcher/tsCompiler.d.ts +88 -0
  1370. package/dist/watcher/tsCompiler.d.ts.map +1 -0
  1371. package/dist/watcher/tsCompiler.js +212 -0
  1372. package/dist/watcher/tsCompiler.js.map +1 -0
  1373. package/embedding-sandbox/Dockerfile +77 -0
  1374. package/embedding-sandbox/Dockerfile.frankenstein +91 -0
  1375. package/embedding-sandbox/README.md +193 -0
  1376. package/embedding-sandbox/__pycache__/frankenstein-embeddings.cpython-312.pyc +0 -0
  1377. package/embedding-sandbox/__pycache__/frankenstein-embeddings.cpython-313.pyc +0 -0
  1378. package/embedding-sandbox/__pycache__/qqms_v2.cpython-312.pyc +0 -0
  1379. package/embedding-sandbox/__pycache__/qqms_v2.cpython-313.pyc +0 -0
  1380. package/embedding-sandbox/add_js_docs.py +684 -0
  1381. package/embedding-sandbox/build_docs_db.py +239 -0
  1382. package/embedding-sandbox/client.cjs +376 -0
  1383. package/embedding-sandbox/client.ts +913 -0
  1384. package/embedding-sandbox/deploy-frankenstein.sh +240 -0
  1385. package/embedding-sandbox/docker-compose.yml +60 -0
  1386. package/embedding-sandbox/docker-manager.py +325 -0
  1387. package/embedding-sandbox/docs/python_docs.db +0 -0
  1388. package/embedding-sandbox/download-model.mjs +79 -0
  1389. package/embedding-sandbox/download-model.py +28 -0
  1390. package/embedding-sandbox/embedding-supervisor.sh +164 -0
  1391. package/embedding-sandbox/frankenstein-embeddings.py +3940 -0
  1392. package/embedding-sandbox/manage-services.sh +354 -0
  1393. package/embedding-sandbox/overflow_queue.py +345 -0
  1394. package/embedding-sandbox/package.json +17 -0
  1395. package/embedding-sandbox/project_isolation.py +292 -0
  1396. package/embedding-sandbox/qqms_v2.py +967 -0
  1397. package/embedding-sandbox/ram-manager.sh +311 -0
  1398. package/embedding-sandbox/requirements-frankenstein.txt +7 -0
  1399. package/embedding-sandbox/run_js_docs.py +59 -0
  1400. package/embedding-sandbox/seed_docs.py +885 -0
  1401. package/embedding-sandbox/server-batch.mjs +228 -0
  1402. package/embedding-sandbox/server.mjs +389 -0
  1403. package/embedding-sandbox/specmem/sockets/claude-input-state.json +1 -0
  1404. package/embedding-sandbox/specmem/sockets/embedding-death-reason.txt +3 -0
  1405. package/embedding-sandbox/specmem/sockets/seen-sessions.json +1 -0
  1406. package/embedding-sandbox/specmem/sockets/session-start.lock +1 -0
  1407. package/embedding-sandbox/specmem/sockets/session-stops.log +7 -0
  1408. package/embedding-sandbox/start-frankenstein-throttled.sh +98 -0
  1409. package/embedding-sandbox/start-on-demand.sh +116 -0
  1410. package/embedding-sandbox/start-sandbox.sh +237 -0
  1411. package/embedding-sandbox/start-supervised.sh +11 -0
  1412. package/embedding-sandbox/stop-sandbox.sh +51 -0
  1413. package/embedding-sandbox/test-socket.mjs +61 -0
  1414. package/embedding-sandbox/warm-start.sh +353 -0
  1415. package/embedding-sandbox/warm_start_feeder.py +660 -0
  1416. package/legal/README.md +31 -0
  1417. package/legal/anthropic-privacy-center-screenshot-2026-01-30.png +0 -0
  1418. package/legal/anthropic-tos-screenshot-2026-01-30.png +0 -0
  1419. package/lib/codebase-bridge.cjs +308 -0
  1420. package/package.json +136 -0
  1421. package/plugins/specmem-agents/agents/bug-hunter.md +79 -0
  1422. package/plugins/specmem-agents/agents/memory-explorer.md +57 -0
  1423. package/plugins/specmem-agents/agents/team-coordinator.md +82 -0
  1424. package/scripts/auto-updater.cjs +399 -0
  1425. package/scripts/backfill-code-definition-embeddings.ts +440 -0
  1426. package/scripts/backfill-code-embeddings.ts +206 -0
  1427. package/scripts/capture-tos-screenshots.cjs +94 -0
  1428. package/scripts/check-global-install.cjs +67 -0
  1429. package/scripts/cleanup-embedding-servers.sh +25 -0
  1430. package/scripts/dashboard-standalone.sh +369 -0
  1431. package/scripts/deploy-hooks.cjs +1451 -0
  1432. package/scripts/deploy.sh +106 -0
  1433. package/scripts/docker-project-down.sh +83 -0
  1434. package/scripts/docker-project-list.sh +40 -0
  1435. package/scripts/docker-project-up.sh +79 -0
  1436. package/scripts/fast-backfill-embeddings.ts +173 -0
  1437. package/scripts/fast-batch-embedder.cjs +334 -0
  1438. package/scripts/first-run-model-setup.cjs +849 -0
  1439. package/scripts/global-postinstall.cjs +1957 -0
  1440. package/scripts/index-codebase.js +72 -0
  1441. package/scripts/migrate-fix-embeddings.py +110 -0
  1442. package/scripts/migrate-to-project-schemas.ts +525 -0
  1443. package/scripts/optimize-embedding-model.py +324 -0
  1444. package/scripts/optimize-instructions.cjs +530 -0
  1445. package/scripts/pack-docker-images.sh +68 -0
  1446. package/scripts/pack-for-testing.sh +130 -0
  1447. package/scripts/postinstall.cjs +54 -0
  1448. package/scripts/project-env.sh +51 -0
  1449. package/scripts/reset-db.sh +30 -0
  1450. package/scripts/run-indexer.ts +69 -0
  1451. package/scripts/run-migrations.js +47 -0
  1452. package/scripts/setup-db.sh +34 -0
  1453. package/scripts/setup-minimal-schema.sql +143 -0
  1454. package/scripts/skills/code-review.md +44 -0
  1455. package/scripts/skills/debugging.md +56 -0
  1456. package/scripts/skills/specmem-deployteam.md +239 -0
  1457. package/scripts/skills/teammemberskills/EFFICIENT_GREP.md +171 -0
  1458. package/scripts/skills/teammemberskills/task-planning.md +67 -0
  1459. package/scripts/specmem/sockets/session-start.lock +1 -0
  1460. package/scripts/specmem/sockets/session-stops.log +1 -0
  1461. package/scripts/specmem-health.sh +382 -0
  1462. package/scripts/specmem-init.cjs +6935 -0
  1463. package/scripts/strip-debug-logs.cjs +43 -0
  1464. package/scripts/test-mcp-standalone.sh +365 -0
  1465. package/scripts/test-optimized-models.py +166 -0
  1466. package/scripts/verify-embedding-fix.sh +148 -0
  1467. package/skills/code-review.md +44 -0
  1468. package/skills/debugging.md +56 -0
  1469. package/skills/specmem-deployteam.md +239 -0
  1470. package/skills/teammemberskills/EFFICIENT_GREP.md +171 -0
  1471. package/skills/teammemberskills/task-planning.md +67 -0
  1472. package/specmem-health.cjs +522 -0
  1473. package/specmem.env +216 -0
@@ -0,0 +1,2547 @@
1
+ /**
2
+ * findWhatISaid - semantic search hitting different
3
+ *
4
+ * uses vector similarity to find relevant memories
5
+ * supports natural language time queries like "yesterday" or "last week"
6
+ * also does hybrid search combining semantic + full-text for best results
7
+ *
8
+ * Now integrated with LWJEB event bus for memory:retrieved events
9
+ */
10
+ import { parseTimeExpression } from '../../mcp/mcpProtocolHandler.js';
11
+ import { logger } from '../../utils/logger.js';
12
+ import { getDebugLogger } from '../../utils/debugLogger.js';
13
+ import { getCoordinator } from '../../coordination/integration.js';
14
+ import { getEmbeddingSocketPath } from '../../config.js';
15
+ import { getEmbeddingTimeout, formatTimeout } from '../../config/embeddingTimeouts.js';
16
+ import { getHotPathManager } from '../../db/hotPathManager.js';
17
+ import { smartCompress } from '../../utils/tokenCompressor.js';
18
+ import { MiniCOTProvider } from '../../providers/MiniCOTProvider.js';
19
+ import { getDimensionService } from '../../services/DimensionService.js';
20
+ import { buildProjectWhereClause, getProjectContext, getProjectPathForInsert } from '../../services/ProjectContext.js';
21
+ import { formatAsCameraRollItem, thresholdToZoomLevel, ZOOM_CONFIGS } from '../../services/CameraZoomSearch.js';
22
+ import { formatHumanReadable } from '../../utils/humanReadableOutput.js';
23
+ import { cotStart, cotResult, cotError } from '../../utils/cotBroadcast.js';
24
+ // DEBUG LOGGING - only enabled when SPECMEM_DEBUG=1
25
+ const __debugLog = process.env['SPECMEM_DEBUG'] === '1'
26
+ ? (...args) => console.error('[DEBUG]', ...args) // stderr, not stdout!
27
+ : () => { };
28
+ /**
29
+ * Extract discoverable paths from memory content
30
+ * This is the KEY to getting lots of info from few memories
31
+ */
32
+ function extractDiscoverablePaths(content) {
33
+ const paths = {
34
+ filePaths: [],
35
+ codeBlocks: [],
36
+ urls: [],
37
+ memoryRefs: [],
38
+ technicalTerms: [],
39
+ researchQuestions: []
40
+ };
41
+ // Extract file paths (Unix and Windows style)
42
+ const filePathRegex = /(?:\/[\w.-]+)+\.(?:ts|js|tsx|jsx|py|go|rs|java|json|yaml|yml|md|css|html|sql|sh)/gi;
43
+ const fileMatches = content.match(filePathRegex);
44
+ if (fileMatches) {
45
+ paths.filePaths = [...new Set(fileMatches)].slice(0, 10);
46
+ }
47
+ // Extract code blocks with language detection
48
+ const codeBlockRegex = /```(\w+)?\n?([\s\S]*?)```/g;
49
+ let match;
50
+ while ((match = codeBlockRegex.exec(content)) !== null) {
51
+ const lang = match[1] || 'unknown';
52
+ const code = match[2].trim();
53
+ if (code.length > 10) {
54
+ // Try to infer file path from code content
55
+ let possiblePath;
56
+ const importMatch = code.match(/from ['"]([^'"]+)['"]/);
57
+ const requireMatch = code.match(/require\(['"]([^'"]+)['"]\)/);
58
+ if (importMatch)
59
+ possiblePath = importMatch[1];
60
+ else if (requireMatch)
61
+ possiblePath = requireMatch[1];
62
+ paths.codeBlocks.push({
63
+ language: lang,
64
+ preview: code.substring(0, 100) + (code.length > 100 ? '...' : ''),
65
+ fullContent: code.length > 200 ? undefined : code, // Only keep short code
66
+ possiblePath
67
+ });
68
+ }
69
+ }
70
+ paths.codeBlocks = paths.codeBlocks.slice(0, 5);
71
+ // Extract URLs
72
+ const urlRegex = /https?:\/\/[^\s\])"'<>]+/g;
73
+ const urlMatches = content.match(urlRegex);
74
+ if (urlMatches) {
75
+ paths.urls = [...new Set(urlMatches)].slice(0, 5);
76
+ }
77
+ // Extract technical terms (PascalCase classes, UPPER_CONSTANTS, function names)
78
+ const techTermRegex = /\b(?:[A-Z][a-z]+){2,}\b|\b[A-Z][A-Z0-9_]{2,}\b|\b\w+(?:Service|Manager|Handler|Provider|Factory|Controller|Repository)\b/g;
79
+ const techMatches = content.match(techTermRegex);
80
+ if (techMatches) {
81
+ paths.technicalTerms = [...new Set(techMatches)].slice(0, 10);
82
+ }
83
+ // Detect potential research questions (things that sound like external knowledge)
84
+ const researchIndicators = [
85
+ /how (?:does|do|to|can)/gi,
86
+ /what is (?:a |the )?[\w\s]+\?/gi,
87
+ /(?:documentation|docs|api|reference) for/gi,
88
+ /latest version of/gi,
89
+ /best practice for/gi
90
+ ];
91
+ for (const regex of researchIndicators) {
92
+ const matches = content.match(regex);
93
+ if (matches) {
94
+ paths.researchQuestions.push(...matches.slice(0, 2));
95
+ }
96
+ }
97
+ paths.researchQuestions = paths.researchQuestions.slice(0, 3);
98
+ return paths;
99
+ }
100
+ /**
101
+ * Format discoverable paths as compact Chinese-annotated hints
102
+ * These hints guide on what to explore next
103
+ */
104
+ function formatDiscoverableHints(paths) {
105
+ const hints = [];
106
+ if (paths.filePaths.length > 0) {
107
+ hints.push(`📁 文件路徑(${paths.filePaths.length}): ${paths.filePaths.slice(0, 3).join(', ')}${paths.filePaths.length > 3 ? '...' : ''}`);
108
+ }
109
+ if (paths.codeBlocks.length > 0) {
110
+ const langs = [...new Set(paths.codeBlocks.map(c => c.language))].join('/');
111
+ hints.push(`💻 代碼塊(${paths.codeBlocks.length}): ${langs}`);
112
+ }
113
+ if (paths.urls.length > 0) {
114
+ hints.push(`🔗 URL(${paths.urls.length}): 可研究`);
115
+ }
116
+ if (paths.technicalTerms.length > 0) {
117
+ hints.push(`🔧 技術詞: ${paths.technicalTerms.slice(0, 5).join(', ')}`);
118
+ }
119
+ if (paths.researchQuestions.length > 0) {
120
+ hints.push(`❓ 研究問題: ${paths.researchQuestions.length}個待確認`);
121
+ }
122
+ return hints.join(' | ');
123
+ }
124
+ /**
125
+ * Enrich a search result with discoverable paths
126
+ * This is what makes few memories yield lots of info
127
+ * NOW WITH CODE ORIGIN TRACKING - shows WHERE code came from!
128
+ */
129
+ function enrichSearchResult(result) {
130
+ const paths = extractDiscoverablePaths(result.memory.content);
131
+ // CRITICAL: Add source origin info to each code block
132
+ // This tells you WHERE the code came from (session, timestamp, who wrote it)
133
+ const memoryMeta = result.memory.metadata || {};
134
+ paths.codeBlocks = paths.codeBlocks.map(block => ({
135
+ ...block,
136
+ sourceMemoryId: result.memory.id,
137
+ sourceSessionId: memoryMeta.sessionId || memoryMeta.session_id,
138
+ sourceTimestamp: memoryMeta.timestamp || result.memory.createdAt?.toString(),
139
+ sourceRole: memoryMeta.role || (result.memory.tags?.includes('role:user') ? 'user' :
140
+ result.memory.tags?.includes('role:assistant') ? 'assistant' : undefined),
141
+ sourceProject: memoryMeta.project
142
+ }));
143
+ const hints = formatDiscoverableHints(paths);
144
+ return {
145
+ ...result,
146
+ _discoverable: paths,
147
+ _hints: hints.length > 0 ? hints : undefined
148
+ };
149
+ }
150
+ // Drilldown configuration - triggers intelligent prompts for user
151
+ const DRILLDOWN_THRESHOLDS = {
152
+ lowRelevance: 0.25, // Below this, suggest deeper search
153
+ highRelevance: 0.5, // Above this, results are good
154
+ fewResults: 3, // Fewer than this, suggest broader search
155
+ manyResults: 15 // More than this, suggest filtering
156
+ };
157
+ /**
158
+ * Generate user interaction prompt based on search results
159
+ * Returns structured data for AskUserQuestion tool
160
+ */
161
+ function generateUserInteractionPrompt(results, query, drilldown, aggregatedPaths) {
162
+ const resultCount = results.length;
163
+ const topSimilarity = results[0]?.similarity ?? 0;
164
+ // Case 1: No results - offer research options
165
+ if (resultCount === 0) {
166
+ return {
167
+ shouldPromptUser: true,
168
+ questionType: 'research',
169
+ question: `沒有找到關於 "${query}" 的記憶。要進行網絡研究嗎?`,
170
+ header: '研究選項',
171
+ options: [
172
+ { label: '快速WebSearch', description: '1-2個來源快速查找' },
173
+ { label: '深度研究', description: '3-5個來源詳細研究' },
174
+ { label: '跳過', description: '不需要額外資訊' }
175
+ ],
176
+ multiSelect: false,
177
+ contextHint: `查詢: "${query}" | 無本地記憶 | 建議網絡研究`
178
+ };
179
+ }
180
+ // Case 2: Very low relevance - offer drilldown
181
+ if (topSimilarity < DRILLDOWN_THRESHOLDS.lowRelevance) {
182
+ return {
183
+ shouldPromptUser: true,
184
+ questionType: 'drilldown',
185
+ question: `找到 ${resultCount} 條記憶,但相關性較低 (${Math.round(topSimilarity * 100)}%)。要深入搜索嗎?`,
186
+ header: '搜索深度',
187
+ options: [
188
+ { label: '深入搜索(50條)', description: '150MB RAM - 徹底搜索' },
189
+ { label: '擴大搜索(100條)', description: '150MB RAM - 搜索所有相關' },
190
+ { label: '網絡研究', description: '使用WebSearch獲取外部資訊' },
191
+ { label: '使用現有結果', description: '繼續使用當前結果' }
192
+ ],
193
+ multiSelect: false,
194
+ contextHint: `找到: ${resultCount}條 | 最高相似度: ${Math.round(topSimilarity * 100)}% | ${drilldown.prompt}`
195
+ };
196
+ }
197
+ // Case 3: Need research - offer research options
198
+ if (drilldown.needsResearch || aggregatedPaths.researchQuestions.length > 0) {
199
+ const researchTopics = aggregatedPaths.researchQuestions.slice(0, 2);
200
+ return {
201
+ shouldPromptUser: true,
202
+ questionType: 'research',
203
+ question: `記憶中發現需要研究的問題。要啟動研究代理嗎?`,
204
+ header: '研究建議',
205
+ options: [
206
+ { label: '啟動研究代理', description: `研究: ${researchTopics[0] || query}` },
207
+ { label: '快速WebSearch', description: '直接搜索不啟動代理' },
208
+ { label: '跳過研究', description: '本地記憶已足夠' }
209
+ ],
210
+ multiSelect: false,
211
+ contextHint: `研究問題: ${researchTopics.join(', ') || '無'} | ${drilldown.prompt}`
212
+ };
213
+ }
214
+ // Case 4: Has URLs to explore - offer to fetch
215
+ if (aggregatedPaths.urls.length > 0) {
216
+ return {
217
+ shouldPromptUser: true,
218
+ questionType: 'research',
219
+ question: `記憶中包含 ${aggregatedPaths.urls.length} 個URL。要獲取內容嗎?`,
220
+ header: 'URL探索',
221
+ options: [
222
+ { label: '獲取所有URL', description: `使用WebFetch獲取 ${aggregatedPaths.urls.length} 個URL` },
223
+ { label: '僅查看列表', description: '不獲取,只顯示URL列表' },
224
+ { label: '跳過', description: '不需要URL內容' }
225
+ ],
226
+ multiSelect: false,
227
+ contextHint: `URL數量: ${aggregatedPaths.urls.length} | 技術詞: ${aggregatedPaths.technicalTerms.slice(0, 3).join(', ')}`
228
+ };
229
+ }
230
+ // Case 5: Many results - offer filtering
231
+ if (resultCount > DRILLDOWN_THRESHOLDS.manyResults) {
232
+ return {
233
+ shouldPromptUser: true,
234
+ questionType: 'filter',
235
+ question: `找到 ${resultCount} 條結果,較多。要過濾嗎?`,
236
+ header: '結果過濾',
237
+ options: [
238
+ { label: '按相關性排序', description: '只保留最相關的10條' },
239
+ { label: '按時間過濾', description: '只看最近的記憶' },
240
+ { label: '查看全部', description: '不過濾,顯示所有結果' }
241
+ ],
242
+ multiSelect: false,
243
+ contextHint: `找到: ${resultCount}條 | 最高: ${Math.round(topSimilarity * 100)}% | 建議過濾`
244
+ };
245
+ }
246
+ // Case 6: Good results - no prompt needed, but still return confirmation structure
247
+ if (topSimilarity >= DRILLDOWN_THRESHOLDS.highRelevance) {
248
+ // Results are good, no user interaction needed
249
+ return null;
250
+ }
251
+ // Default: Medium relevance - let decide
252
+ return null;
253
+ }
254
+ // Chinese compacted drilldown prompts (saves ~40% tokens)
255
+ const DRILLDOWN_PROMPTS = {
256
+ // When top result has low similarity
257
+ lowRelevance: {
258
+ zh: '🔍 搜索結果相關性低 (相似度<25%) | 建議: 深度搜索或調整查詢',
259
+ en: 'Low relevance results - suggest deeper search or query refinement',
260
+ action: 'drilldown:deeper'
261
+ },
262
+ // When few results found
263
+ fewResults: {
264
+ zh: '📊 找到結果少於3條 | 建議: 擴大搜索範圍或嘗試同義詞',
265
+ en: 'Few results found - suggest broader search or synonyms',
266
+ action: 'drilldown:broader'
267
+ },
268
+ // When too many results
269
+ manyResults: {
270
+ zh: '📈 結果過多(>15條) | 建議: 添加過濾條件或更具體查詢',
271
+ en: 'Too many results - suggest filtering or more specific query',
272
+ action: 'drilldown:filter'
273
+ },
274
+ // When research might help
275
+ needsResearch: {
276
+ zh: '🌐 本地記憶不足 | 建議: WebSearch獲取最新資訊',
277
+ en: 'Local memory insufficient - suggest web research',
278
+ action: 'research:web'
279
+ },
280
+ // Good results
281
+ goodResults: {
282
+ zh: '✅ 找到相關記憶 | 上下文已壓縮保留',
283
+ en: 'Relevant memories found - context compressed and preserved',
284
+ action: 'none'
285
+ }
286
+ };
287
+ /**
288
+ * Analyze search results and generate drilldown suggestion
289
+ * Returns Traditional Chinese compacted prompt for token efficiency
290
+ */
291
+ function generateDrilldownSuggestion(results, query) {
292
+ const resultCount = results.length;
293
+ const topSimilarity = results[0]?.similarity ?? 0;
294
+ // Priority 1: No results at all
295
+ if (resultCount === 0) {
296
+ return {
297
+ prompt: `${DRILLDOWN_PROMPTS.needsResearch.zh}\n查詢: "${query}" → 無本地記憶匹配`,
298
+ action: 'research:web',
299
+ needsResearch: true
300
+ };
301
+ }
302
+ // Priority 2: Very low relevance (might be asking about something new)
303
+ if (topSimilarity < DRILLDOWN_THRESHOLDS.lowRelevance) {
304
+ const avgSim = results.reduce((a, r) => a + r.similarity, 0) / resultCount;
305
+ if (avgSim < 0.15) {
306
+ // Very poor match - likely needs web research
307
+ return {
308
+ prompt: `${DRILLDOWN_PROMPTS.needsResearch.zh}\n最高相似度: ${Math.round(topSimilarity * 100)}% | 平均: ${Math.round(avgSim * 100)}%`,
309
+ action: 'research:web',
310
+ needsResearch: true
311
+ };
312
+ }
313
+ return {
314
+ prompt: `${DRILLDOWN_PROMPTS.lowRelevance.zh}\n最高相似度: ${Math.round(topSimilarity * 100)}%`,
315
+ action: 'drilldown:deeper',
316
+ needsResearch: false
317
+ };
318
+ }
319
+ // Priority 3: Few results
320
+ if (resultCount < DRILLDOWN_THRESHOLDS.fewResults) {
321
+ return {
322
+ prompt: `${DRILLDOWN_PROMPTS.fewResults.zh}\n找到: ${resultCount}條 | 最高相似度: ${Math.round(topSimilarity * 100)}%`,
323
+ action: 'drilldown:broader',
324
+ needsResearch: false
325
+ };
326
+ }
327
+ // Priority 4: Too many results
328
+ if (resultCount > DRILLDOWN_THRESHOLDS.manyResults) {
329
+ return {
330
+ prompt: `${DRILLDOWN_PROMPTS.manyResults.zh}\n找到: ${resultCount}條 | 建議過濾標籤或類型`,
331
+ action: 'drilldown:filter',
332
+ needsResearch: false
333
+ };
334
+ }
335
+ // Good results!
336
+ return {
337
+ prompt: `${DRILLDOWN_PROMPTS.goodResults.zh}\n找到: ${resultCount}條 | 最高: ${Math.round(topSimilarity * 100)}%`,
338
+ action: 'none',
339
+ needsResearch: false
340
+ };
341
+ }
342
+ // fr fr we track search performance
343
+ let _searchCount = 0;
344
+ let _totalSearchTime = 0;
345
+ // ============================================================================
346
+ // DRILLDOWN REMINDERS - Force to actually USE the memory!
347
+ // ============================================================================
348
+ // Compact reminder - at TOP of response so sees it first
349
+ const DRILLDOWN_REMINDER = `⚠️ MEMORY POINTERS - DRILL DOWN BEFORE PROCEEDING:
350
+ 1. get_memory({ id }) - get FULL content of relevant memories
351
+ 2. find_memory({ query: "related term" }) - check related topics
352
+ 3. find_code_pointers({ query }) - explore any code paths mentioned
353
+ 💡 User has discussed this before - check their context!`;
354
+ // Compact empty results reminder
355
+ const EMPTY_RESULTS_REMINDER = `⚠️ NO MEMORIES FOUND - Try these:
356
+ 1. Rephrase: try synonyms, different wording
357
+ 2. find_code_pointers({ query }) - search code instead
358
+ 3. Remove filters (memoryTypes, tags, dateRange)`;
359
+ // ============================================================================
360
+ // HELP OUTPUT - shown when query is empty or "help"
361
+ // ============================================================================
362
+ const HELP_OUTPUT = `
363
+ # find_memory - Semantic Memory Search
364
+
365
+ Search across memories using meaning-based semantic search.
366
+ Finds content based on concepts and context, not just keywords.
367
+
368
+ ## Usage
369
+
370
+ \`\`\`
371
+ find_memory({ query: "your search" })
372
+ find_memory({ query: "authentication", galleryMode: true })
373
+ find_memory({ query: "last week", role: "user" })
374
+ \`\`\`
375
+
376
+ ## Parameters
377
+
378
+ | Parameter | Type | Default | Description |
379
+ |-----------|------|---------|-------------|
380
+ | query | string | required | Natural language search query |
381
+ | limit | number | 10 | Max results to return (max: 1000) |
382
+ | threshold | number | 0.25 | Min similarity score (0-1) |
383
+ | role | string | - | Filter by "user" or "assistant" |
384
+ | memoryTypes | array | - | Filter: episodic, semantic, procedural, working |
385
+ | tags | array | - | Filter by tags (OR logic) |
386
+ | importance | array | - | Filter: critical, high, medium, low, trivial |
387
+ | dateRange | object | - | { start, end } ISO timestamps |
388
+ | galleryMode | boolean | false | Enable Mini COT analysis (falls back to basic on error) |
389
+ | cameraRollMode | boolean | true | DEFAULT TRUE - Returns drilldownIDs for drill_down() |
390
+ | zoomLevel | string | - | ultra-wide/wide/normal/close/macro |
391
+ | summarize | boolean | true | Truncate content to save tokens |
392
+ | includeRecent | number | 0 | Force include last N recent memories |
393
+ | recencyBoost | boolean | true | Boost recent memories in ranking |
394
+ | keywordFallback | boolean | true | Fallback to keyword if semantic fails |
395
+
396
+ ## Examples
397
+
398
+ ### Find what the user said about a topic
399
+ \`\`\`json
400
+ {
401
+ "query": "database migration strategy",
402
+ "role": "user"
403
+ }
404
+ \`\`\`
405
+
406
+ ### Search with date filter
407
+ \`\`\`json
408
+ {
409
+ "query": "API authentication",
410
+ "dateRange": { "start": "2024-01-01", "end": "2024-12-31" }
411
+ }
412
+ \`\`\`
413
+
414
+ ### Camera roll mode is DEFAULT (drilldownIDs included)
415
+ \`\`\`json
416
+ {
417
+ "query": "websocket implementation",
418
+ "zoomLevel": "wide"
419
+ }
420
+ \`\`\`
421
+
422
+ ## Drill-Down
423
+
424
+ Results always include drilldownIDs (cameraRollMode is true by default):
425
+ - Use \`drill_down({ drilldownID: 123 })\` for full content + context
426
+ - Use \`get_memory({ id: "uuid..." })\` for raw memory
427
+
428
+ ## Tips
429
+
430
+ 1. **Time queries**: "yesterday", "last week", "3 days ago" are parsed automatically
431
+ 2. **Role filter**: Use \`role: "user"\` to find what YOU said (not )
432
+ 3. **Low results?**: Try \`keywordFallback: true\` and lower threshold
433
+ 4. **Recent activity?**: Set \`includeRecent: 10\` to see latest memories
434
+ `;
435
+ /**
436
+ * FindWhatISaid - semantic search tool
437
+ *
438
+ * fr fr this semantic search hitting different
439
+ * combines vector similarity with optional filters for precision
440
+ *
441
+ * Emits LWJEB events: memory:retrieved
442
+ */
443
+ export class FindWhatISaid {
444
+ db;
445
+ embeddingProvider;
446
+ name = 'find_memory';
447
+ description = 'Search across memories using semantic search - finds content based on meaning, not just keywords. Supports time queries like "yesterday" or "last week"';
448
+ coordinator = getCoordinator();
449
+ hotPathManager = null;
450
+ debugLogger = getDebugLogger();
451
+ inputSchema = {
452
+ type: 'object',
453
+ properties: {
454
+ query: {
455
+ type: 'string',
456
+ description: 'what you looking for - natural language works best. Leave empty for help.'
457
+ },
458
+ limit: {
459
+ type: 'number',
460
+ default: 10,
461
+ minimum: 1,
462
+ maximum: 1000,
463
+ description: 'how many results you want'
464
+ },
465
+ threshold: {
466
+ type: 'number',
467
+ default: 0.25,
468
+ minimum: 0,
469
+ maximum: 1,
470
+ description: 'minimum similarity score (0-1) - higher = more relevant. Default 0.25 filters garbage. Local embeddings: 0.2-0.5 typical for real matches.'
471
+ },
472
+ includeRecent: {
473
+ type: 'number',
474
+ default: 0,
475
+ minimum: 0,
476
+ maximum: 50,
477
+ description: 'Force include the last N most recent memories regardless of similarity. Use this to check recent prompts/discussions. Set to 5-10 to see recent activity.'
478
+ },
479
+ recencyBoost: {
480
+ type: 'boolean',
481
+ default: true,
482
+ description: 'Boost relevance of recent memories. Memories from last hour get 20% boost, last day 10% boost.'
483
+ },
484
+ keywordFallback: {
485
+ type: 'boolean',
486
+ default: true,
487
+ description: 'If embedding search returns no results, fallback to keyword (ILIKE) search.'
488
+ },
489
+ memoryTypes: {
490
+ type: 'array',
491
+ items: {
492
+ type: 'string',
493
+ enum: ['episodic', 'semantic', 'procedural', 'working', 'consolidated']
494
+ },
495
+ description: 'filter by memory type'
496
+ },
497
+ tags: {
498
+ type: 'array',
499
+ items: { type: 'string' },
500
+ description: 'filter by tags (OR logic)'
501
+ },
502
+ importance: {
503
+ type: 'array',
504
+ items: {
505
+ type: 'string',
506
+ enum: ['critical', 'high', 'medium', 'low', 'trivial']
507
+ },
508
+ description: 'filter by importance level'
509
+ },
510
+ dateRange: {
511
+ type: 'object',
512
+ properties: {
513
+ start: { type: 'string', format: 'date-time' },
514
+ end: { type: 'string', format: 'date-time' }
515
+ },
516
+ description: 'filter by creation date range'
517
+ },
518
+ includeExpired: {
519
+ type: 'boolean',
520
+ default: false,
521
+ description: 'include expired memories in results'
522
+ },
523
+ role: {
524
+ type: 'string',
525
+ enum: ['user', 'assistant'],
526
+ description: 'filter by message role - use "user" to find only things YOU said, "assistant" for responses'
527
+ },
528
+ summarize: {
529
+ type: 'boolean',
530
+ default: true,
531
+ description: 'DEFAULT TRUE - returns summarized content (first 500 chars) to save context. Set to false for full content. Use get_memory with the ID for drill-down'
532
+ },
533
+ galleryMode: {
534
+ oneOf: [
535
+ { type: 'boolean' },
536
+ { type: 'string', enum: ['ask'] }
537
+ ],
538
+ default: false,
539
+ description: 'Enable Mini COT analysis. Falls back to basic semantic search on error. "ask"=show mode options'
540
+ },
541
+ maxContentLength: {
542
+ type: 'number',
543
+ default: 500,
544
+ description: 'DEFAULT 500 - truncate content to this many characters. Set to 0 for no truncation. Reduces context consumption'
545
+ },
546
+ zoomLevel: {
547
+ type: 'string',
548
+ enum: ['ultra-wide', 'wide', 'normal', 'close', 'macro'],
549
+ description: 'Camera roll zoom level: ultra-wide (50 results, 15% threshold), wide (25, 25%), normal (15, 40%), close (10, 60%), macro (5, 80%)'
550
+ },
551
+ cameraRollMode: {
552
+ type: 'boolean',
553
+ default: true,
554
+ description: 'DEFAULT TRUE - Returns drilldownIDs for drill_down() exploration. Set to false for raw results.'
555
+ },
556
+ projectPath: {
557
+ type: 'string',
558
+ description: 'Search memories from a specific project path instead of current project. Use absolute path like "/home/user/my-other-project"'
559
+ },
560
+ allProjects: {
561
+ type: 'boolean',
562
+ default: false,
563
+ description: 'Search ALL projects instead of just current project. Useful for cross-referencing code/patterns across repos.'
564
+ },
565
+ // humanReadable is always true - removed as configurable option per user request
566
+ },
567
+ required: [] // query is not required - empty shows help
568
+ };
569
+ dimensionService = null;
570
+ constructor(db, embeddingProvider) {
571
+ this.db = db;
572
+ this.embeddingProvider = embeddingProvider;
573
+ try {
574
+ this.dimensionService = getDimensionService(db, embeddingProvider);
575
+ }
576
+ catch {
577
+ // Will initialize when needed
578
+ }
579
+ }
580
+ /**
581
+ * Build project filter condition for SQL queries
582
+ * Supports: current project (default), specific project (projectPath), or all projects (allProjects)
583
+ * Returns: { condition: string, params: unknown[], nextIndex: number }
584
+ */
585
+ buildProjectCondition(params, startIndex = 1) {
586
+ const conditions = [];
587
+ const queryParams = [];
588
+ let nextIndex = startIndex;
589
+ // allProjects = true: skip project filtering entirely
590
+ if (params.allProjects) {
591
+ // No project condition - search ALL projects
592
+ return { conditions, queryParams, nextIndex };
593
+ }
594
+ // Use specified projectPath or fall back to current project
595
+ const targetProject = params.projectPath || getProjectContext().getProjectPath();
596
+ conditions.push(`project_path = $${nextIndex}`);
597
+ queryParams.push(targetProject);
598
+ nextIndex++;
599
+ return { conditions, queryParams, nextIndex };
600
+ }
601
+ /**
602
+ * Get DimensionService (lazy initialization)
603
+ */
604
+ getDimService() {
605
+ if (!this.dimensionService) {
606
+ this.dimensionService = getDimensionService(this.db, this.embeddingProvider);
607
+ }
608
+ return this.dimensionService;
609
+ }
610
+ /**
611
+ * Validate and prepare embedding for memories table search
612
+ */
613
+ async prepareEmbedding(embedding, originalQuery) {
614
+ const dimService = this.getDimService();
615
+ const prepared = await dimService.validateAndPrepare('memories', embedding, originalQuery);
616
+ if (prepared.wasModified) {
617
+ logger.debug({ action: prepared.action }, 'Adjusted embedding dimension for memory search');
618
+ }
619
+ return prepared.embedding;
620
+ }
621
+ async execute(params) {
622
+ _searchCount++;
623
+ const startTime = Date.now();
624
+ // ============================================================================
625
+ // DEEP DEBUG: Method Entry
626
+ // ============================================================================
627
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'METHOD_ENTRY', {
628
+ query: params.query?.slice(0, 100),
629
+ limit: params.limit,
630
+ threshold: params.threshold,
631
+ memoryTypes: params.memoryTypes,
632
+ tags: params.tags,
633
+ galleryMode: params.galleryMode,
634
+ cameraRollMode: params.cameraRollMode,
635
+ zoomLevel: params.zoomLevel,
636
+ includeRecent: params.includeRecent,
637
+ recencyBoost: params.recencyBoost,
638
+ keywordFallback: params.keywordFallback,
639
+ startTime,
640
+ searchCount: _searchCount
641
+ });
642
+ // HELP MODE: No query = show help
643
+ if (!params.query || params.query.trim() === '' || params.query.toLowerCase() === 'help') {
644
+ logger.info({}, '[find_memory] Showing help - no query provided');
645
+ const now = new Date();
646
+ return [{
647
+ memory: {
648
+ id: 'help-output',
649
+ content: HELP_OUTPUT,
650
+ createdAt: now,
651
+ updatedAt: now,
652
+ tags: ['help', 'system'],
653
+ importance: 'medium',
654
+ memoryType: 'semantic',
655
+ metadata: { _isHelp: true }
656
+ },
657
+ similarity: 1.0,
658
+ highlights: []
659
+ }];
660
+ }
661
+ logger.debug({ query: params.query, limit: params.limit }, 'searching memories fr');
662
+ // Broadcast COT to dashboard
663
+ cotStart('find_memory', params.query || 'browsing');
664
+ try {
665
+ // Apply max result limit to prevent memory issues
666
+ const MAX_RESULTS = 1000;
667
+ const safeLimit = Math.min(params.limit ?? 10, MAX_RESULTS);
668
+ // humanReadable is always true - no longer configurable
669
+ const safeParams = {
670
+ ...params,
671
+ limit: safeLimit
672
+ };
673
+ // ============================================================================
674
+ // DEEP DEBUG: After Parameter Validation
675
+ // ============================================================================
676
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'PARAMS_VALIDATED', {
677
+ originalLimit: params.limit,
678
+ safeLimit,
679
+ MAX_RESULTS,
680
+ elapsedMs: Date.now() - startTime
681
+ });
682
+ // ============================================================================
683
+ // MODE SELECTION - Return options if user wants to choose
684
+ // ============================================================================
685
+ if (safeParams.galleryMode === 'ask') {
686
+ logger.info({ query: safeParams.query }, 'Returning search mode options for user selection');
687
+ const now = new Date();
688
+ return [{
689
+ memory: {
690
+ id: 'mode-selector',
691
+ content: `# Search Mode Selection\n\nQuery: "${safeParams.query}"\n\nChoose your search mode:\n\n## ⚡ Basic Search (Recommended for quick lookups)\n- **Speed**: Instant (~100-500ms)\n- **Features**: Semantic similarity, keyword matching, tag filtering, drill-down hints\n- **Best for**: Quick lookups, finding specific info, browsing history\n\n## 🎨 Gallery Mode (Deep analysis)\n- **Speed**: Slower (~5-15s depending on results)\n- **Features**: Mini COT brain analyzes with Chain-of-Thought reasoning, relevance explanations, research notes for unknown terms, Traditional Chinese compression\n- **Best for**: Deep analysis, understanding complex topics, research synthesis\n- **Note**: EXPERIMENTAL - requires Mini COT service running (TinyLlama)\n\n**Recommendation**: Use BASIC for most searches. Use GALLERY when you need the AI to deeply analyze and explain the results.\n\nTo proceed, call find_memory again with:\n- \`galleryMode: false\` for Basic Search\n- \`galleryMode: true\` for Gallery Mode`,
692
+ createdAt: now,
693
+ updatedAt: now,
694
+ tags: ['mode-selector', 'system'],
695
+ importance: 'medium',
696
+ memoryType: 'semantic',
697
+ metadata: {
698
+ _modeOptions: {
699
+ query: safeParams.query,
700
+ basic: { galleryMode: false, description: 'Fast semantic + keyword search' },
701
+ gallery: { galleryMode: true, description: 'Mini COT analysis with COT reasoning' }
702
+ }
703
+ }
704
+ },
705
+ similarity: 1.0,
706
+ highlights: []
707
+ }];
708
+ }
709
+ // check for natural language time expressions
710
+ let dateRange = safeParams.dateRange;
711
+ if (!dateRange) {
712
+ const parsedTime = parseTimeExpression(safeParams.query);
713
+ if (parsedTime) {
714
+ dateRange = {
715
+ start: parsedTime.start.toISOString(),
716
+ end: parsedTime.end.toISOString()
717
+ };
718
+ logger.debug({ dateRange }, 'parsed time expression from query');
719
+ }
720
+ }
721
+ // generate query embedding with timeout protection
722
+ // UNIFIED TIMEOUT CONFIG: Set SPECMEM_EMBEDDING_TIMEOUT (seconds) to control ALL timeouts
723
+ // Or use SPECMEM_FIND_EMBEDDING_TIMEOUT_MS for specific override
724
+ // See src/config/embeddingTimeouts.ts for full documentation
725
+ const EMBEDDING_TIMEOUT_MS = getEmbeddingTimeout('search');
726
+ // Get socket path for error reporting
727
+ const socketPath = getEmbeddingSocketPath();
728
+ // ============================================================================
729
+ // DEEP DEBUG: Before Embedding Generation
730
+ // ============================================================================
731
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'BEFORE_EMBEDDING', {
732
+ query: safeParams.query?.slice(0, 100),
733
+ socketPath,
734
+ timeoutMs: EMBEDDING_TIMEOUT_MS,
735
+ elapsedMs: Date.now() - startTime,
736
+ embeddingProviderType: this.embeddingProvider?.constructor?.name || 'unknown'
737
+ });
738
+ // Debug log: Search operation starting
739
+ this.debugLogger.searchOperation(safeParams.query, 'start', { socketPath });
740
+ const embeddingStartTime = Date.now();
741
+ this.debugLogger.embeddingGeneration(safeParams.query, socketPath, 'start');
742
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'EMBEDDING_STARTED', {
743
+ embeddingStartTime,
744
+ socketPath,
745
+ query: safeParams.query?.slice(0, 50)
746
+ });
747
+ const embeddingPromise = this.embeddingProvider.generateEmbedding(safeParams.query);
748
+ const timeoutPromise = new Promise((_, reject) => {
749
+ setTimeout(() => {
750
+ const timeoutError = new Error(`Embedding generation timeout after ${formatTimeout(EMBEDDING_TIMEOUT_MS)}. ` +
751
+ `Socket: ${socketPath}. ` +
752
+ `Set SPECMEM_EMBEDDING_TIMEOUT env var to increase timeout.`);
753
+ timeoutError.socketPath = socketPath;
754
+ timeoutError.code = 'EMBEDDING_TIMEOUT';
755
+ reject(timeoutError);
756
+ }, EMBEDDING_TIMEOUT_MS);
757
+ });
758
+ let rawEmbedding;
759
+ try {
760
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'AWAITING_EMBEDDING_PROMISE', {
761
+ elapsedMs: Date.now() - startTime
762
+ });
763
+ rawEmbedding = await Promise.race([embeddingPromise, timeoutPromise]);
764
+ const embeddingDuration = Date.now() - embeddingStartTime;
765
+ // ============================================================================
766
+ // DEEP DEBUG: After Embedding Generation (Success)
767
+ // ============================================================================
768
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'AFTER_EMBEDDING_SUCCESS', {
769
+ embeddingDuration,
770
+ rawEmbeddingDimension: rawEmbedding?.length,
771
+ rawEmbeddingFirstValues: rawEmbedding?.slice(0, 3),
772
+ elapsedMs: Date.now() - startTime
773
+ });
774
+ this.debugLogger.embeddingGeneration(safeParams.query, socketPath, 'complete', {
775
+ durationMs: embeddingDuration,
776
+ dimension: rawEmbedding.length
777
+ });
778
+ }
779
+ catch (embeddingError) {
780
+ const embeddingDuration = Date.now() - embeddingStartTime;
781
+ const err = embeddingError;
782
+ // ============================================================================
783
+ // DEEP DEBUG: After Embedding Generation (Error)
784
+ // ============================================================================
785
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'AFTER_EMBEDDING_ERROR', {
786
+ embeddingDuration,
787
+ errorMessage: err?.message?.slice(0, 200),
788
+ errorCode: err?.code,
789
+ errorName: err?.name,
790
+ socketPath,
791
+ elapsedMs: Date.now() - startTime
792
+ });
793
+ // Enhanced error with socket path info
794
+ this.debugLogger.embeddingGeneration(safeParams.query, socketPath, err.message.includes('timeout') ? 'timeout' : 'error', {
795
+ durationMs: embeddingDuration,
796
+ error: err
797
+ });
798
+ // Re-throw with enhanced message including socket path
799
+ const enhancedError = new Error(`Embedding generation failed: ${err.message}. ` +
800
+ `Socket path: ${socketPath}. ` +
801
+ `Duration: ${embeddingDuration}ms. ` +
802
+ `Troubleshooting: Check if embedding service is running (ps aux | grep frankenstein), ` +
803
+ `verify socket exists (ls -la ${socketPath}), check SPECMEM_DEBUG=true for more logs.`);
804
+ enhancedError.originalError = err;
805
+ enhancedError.socketPath = socketPath;
806
+ enhancedError.durationMs = embeddingDuration;
807
+ enhancedError.code = err.code || 'EMBEDDING_ERROR';
808
+ throw enhancedError;
809
+ }
810
+ // Validate and prepare embedding dimension using DimensionService
811
+ const queryEmbedding = await this.prepareEmbedding(rawEmbedding, safeParams.query);
812
+ // Debug log: Embedding phase complete
813
+ this.debugLogger.searchOperation(safeParams.query, 'embedding', {
814
+ durationMs: Date.now() - embeddingStartTime,
815
+ socketPath
816
+ });
817
+ // DEBUG: Log query embedding dimension and first few values
818
+ logger.info({
819
+ queryEmbeddingDim: queryEmbedding.length,
820
+ query: safeParams.query,
821
+ firstValues: queryEmbedding.slice(0, 3),
822
+ socketPath
823
+ }, 'Generated query embedding');
824
+ // do the search with timeout protection
825
+ // UNIFIED TIMEOUT CONFIG: See src/config/embeddingTimeouts.ts
826
+ // Uses 'dbSearch' timeout (6x master, or SPECMEM_FIND_SEARCH_TIMEOUT_MS)
827
+ const SEARCH_TIMEOUT_MS = getEmbeddingTimeout('dbSearch');
828
+ // ============================================================================
829
+ // DEEP DEBUG: Before Database Query
830
+ // ============================================================================
831
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'BEFORE_DB_QUERY', {
832
+ queryEmbeddingDimension: queryEmbedding?.length,
833
+ searchTimeoutMs: SEARCH_TIMEOUT_MS,
834
+ dateRange: dateRange ? { start: dateRange.start, end: dateRange.end } : null,
835
+ memoryTypes: safeParams.memoryTypes,
836
+ tags: safeParams.tags,
837
+ limit: safeParams.limit,
838
+ threshold: safeParams.threshold,
839
+ elapsedMs: Date.now() - startTime
840
+ });
841
+ // Debug log: Search phase starting
842
+ this.debugLogger.searchOperation(safeParams.query, 'search');
843
+ const searchStartTime = Date.now();
844
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'DB_QUERY_STARTED', {
845
+ searchStartTime,
846
+ query: safeParams.query?.slice(0, 50)
847
+ });
848
+ const searchPromise = this.semanticSearch({
849
+ ...safeParams,
850
+ dateRange
851
+ }, queryEmbedding);
852
+ const searchTimeoutPromise = new Promise((_, reject) => {
853
+ setTimeout(() => {
854
+ const timeoutError = new Error(`Search timeout after ${formatTimeout(SEARCH_TIMEOUT_MS)}. ` +
855
+ `Query: "${safeParams.query.slice(0, 50)}...". ` +
856
+ `Set SPECMEM_EMBEDDING_TIMEOUT env var to increase timeout.`);
857
+ timeoutError.code = 'SEARCH_TIMEOUT';
858
+ reject(timeoutError);
859
+ }, SEARCH_TIMEOUT_MS);
860
+ });
861
+ let results;
862
+ try {
863
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'AWAITING_DB_QUERY_PROMISE', {
864
+ elapsedMs: Date.now() - startTime
865
+ });
866
+ results = await Promise.race([searchPromise, searchTimeoutPromise]);
867
+ const searchDuration = Date.now() - searchStartTime;
868
+ // ============================================================================
869
+ // DEEP DEBUG: After Database Query (Success)
870
+ // ============================================================================
871
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'AFTER_DB_QUERY_SUCCESS', {
872
+ searchDuration,
873
+ resultCount: results?.length,
874
+ topSimilarity: results?.[0]?.similarity,
875
+ topMemoryId: results?.[0]?.memory?.id?.slice(0, 20),
876
+ elapsedMs: Date.now() - startTime
877
+ });
878
+ this.debugLogger.searchOperation(safeParams.query, 'complete', {
879
+ durationMs: searchDuration,
880
+ resultCount: results.length
881
+ });
882
+ }
883
+ catch (searchError) {
884
+ const searchDuration = Date.now() - searchStartTime;
885
+ const err = searchError;
886
+ // ============================================================================
887
+ // DEEP DEBUG: After Database Query (Error)
888
+ // ============================================================================
889
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'AFTER_DB_QUERY_ERROR', {
890
+ searchDuration,
891
+ errorMessage: err?.message?.slice(0, 200),
892
+ errorCode: err?.code,
893
+ errorName: err?.name,
894
+ elapsedMs: Date.now() - startTime
895
+ });
896
+ // Enhanced debug logging for search errors
897
+ this.debugLogger.searchOperation(safeParams.query, 'error', {
898
+ durationMs: searchDuration,
899
+ error: err,
900
+ socketPath
901
+ });
902
+ // Re-throw with enhanced context
903
+ const enhancedError = new Error(`Search failed: ${err.message}. ` +
904
+ `Duration: ${searchDuration}ms. ` +
905
+ `Query: "${safeParams.query.slice(0, 50)}...". ` +
906
+ `Socket: ${socketPath}. ` +
907
+ `Enable SPECMEM_DEBUG=true for detailed logs.`);
908
+ enhancedError.originalError = err;
909
+ enhancedError.code = err.code || 'SEARCH_ERROR';
910
+ enhancedError.durationMs = searchDuration;
911
+ throw enhancedError;
912
+ }
913
+ // ============================================================================
914
+ // I5 FIX: APPLY NEW SEARCH FEATURES
915
+ // ============================================================================
916
+ // ============================================================================
917
+ // DEEP DEBUG: Before Result Processing
918
+ // ============================================================================
919
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'BEFORE_RESULT_PROCESSING', {
920
+ rawResultCount: results?.length,
921
+ topRawSimilarity: results?.[0]?.similarity,
922
+ elapsedMs: Date.now() - startTime
923
+ });
924
+ // I5 FIX: Get includeRecent, recencyBoost, keywordFallback from params
925
+ const includeRecentCount = safeParams.includeRecent ?? 0;
926
+ const applyRecencyBoost = safeParams.recencyBoost !== false; // Default true
927
+ const useKeywordFallback = safeParams.keywordFallback !== false; // Default true
928
+ logger.info({
929
+ query: safeParams.query,
930
+ semanticResultCount: results.length,
931
+ includeRecent: includeRecentCount,
932
+ recencyBoost: applyRecencyBoost,
933
+ keywordFallback: useKeywordFallback
934
+ }, '[I5 FIX] Search phase 1 complete, applying fixes');
935
+ // I5 FIX: Apply recency boost to semantic results
936
+ if (applyRecencyBoost && results.length > 0) {
937
+ results = this.applyRecencyBoost(results);
938
+ logger.debug({ boostedCount: results.length }, '[I5 FIX] Recency boost applied');
939
+ }
940
+ // I5 FIX: Keyword fallback if semantic search returned nothing useful
941
+ let keywordResults = [];
942
+ const hasGoodSemanticResults = results.length > 0 && results[0]?.similarity >= 0.15;
943
+ if (useKeywordFallback && !hasGoodSemanticResults) {
944
+ logger.info({
945
+ query: safeParams.query,
946
+ semanticResults: results.length,
947
+ topSimilarity: results[0]?.similarity
948
+ }, '[I5 FIX] Low/no semantic results, triggering keyword fallback');
949
+ keywordResults = await this.keywordSearch(safeParams.query, safeParams);
950
+ }
951
+ // I5 FIX: Get recent memories if requested
952
+ let recentResults = [];
953
+ if (includeRecentCount > 0) {
954
+ recentResults = await this.getRecentMemories(includeRecentCount, safeParams);
955
+ logger.info({
956
+ recentRequested: includeRecentCount,
957
+ recentFound: recentResults.length
958
+ }, '[I5 FIX] Recent memories retrieved');
959
+ }
960
+ // I5 FIX: Merge all results if we have additional sources
961
+ if (recentResults.length > 0 || keywordResults.length > 0) {
962
+ const originalCount = results.length;
963
+ results = this.mergeAndDedupeResults(results, recentResults, keywordResults, safeParams.limit ?? 10);
964
+ logger.info({
965
+ originalSemanticCount: originalCount,
966
+ recentCount: recentResults.length,
967
+ keywordCount: keywordResults.length,
968
+ mergedCount: results.length
969
+ }, '[I5 FIX] Results merged from multiple sources');
970
+ }
971
+ const duration = Date.now() - startTime;
972
+ _totalSearchTime += duration;
973
+ // ============================================================================
974
+ // DEEP DEBUG: After Result Processing
975
+ // ============================================================================
976
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'AFTER_RESULT_PROCESSING', {
977
+ finalResultCount: results?.length,
978
+ topFinalSimilarity: results?.[0]?.similarity,
979
+ usedKeywordFallback: keywordResults?.length > 0,
980
+ keywordResultCount: keywordResults?.length,
981
+ usedRecentMemories: recentResults?.length > 0,
982
+ recentResultCount: recentResults?.length,
983
+ totalDurationMs: duration,
984
+ avgSearchTimeMs: _totalSearchTime / _searchCount,
985
+ elapsedMs: Date.now() - startTime
986
+ });
987
+ logger.info({
988
+ resultCount: results.length,
989
+ duration,
990
+ avgSearchTime: _totalSearchTime / _searchCount,
991
+ usedKeywordFallback: keywordResults.length > 0,
992
+ usedRecentMemories: recentResults.length > 0
993
+ }, 'search complete with I5 fixes');
994
+ // Log warning if search was slow
995
+ if (duration > 1000) {
996
+ logger.warn({ duration, query: safeParams.query }, 'slow search detected');
997
+ }
998
+ // Generate drilldown suggestion based on results
999
+ const drilldown = generateDrilldownSuggestion(results, safeParams.query);
1000
+ // Log drilldown analysis
1001
+ logger.info({
1002
+ query: safeParams.query,
1003
+ resultCount: results.length,
1004
+ topSimilarity: results[0]?.similarity,
1005
+ drilldownAction: drilldown.action,
1006
+ needsResearch: drilldown.needsResearch
1007
+ }, '[Drilldown] 分析完成');
1008
+ // Handle empty results with informative message
1009
+ if (results.length === 0) {
1010
+ logger.info({ query: safeParams.query, filters: { memoryTypes: safeParams.memoryTypes, tags: safeParams.tags } }, 'no results found for query');
1011
+ // Always use humanReadable format
1012
+ return formatHumanReadable('find_memory', [], {
1013
+ grey: true,
1014
+ showSimilarity: true,
1015
+ query: safeParams.query,
1016
+ emptyMessage: `No memories found for "${safeParams.query}". Try: broader terms, check_sync, or save_memory to add context.`
1017
+ });
1018
+ }
1019
+ // ============================================================================
1020
+ // GALLERY MODE - Mini COT Decision Model creates semantic gallery
1021
+ // ============================================================================
1022
+ if (safeParams.galleryMode === true) {
1023
+ logger.info({ query: safeParams.query, resultCount: results.length }, 'Gallery mode enabled - sending to Mini COT');
1024
+ try {
1025
+ const miniCOT = new MiniCOTProvider();
1026
+ // Prepare memories for gallery creation (send ENGLISH to CoT!)
1027
+ const memoriesForGallery = results.map(result => ({
1028
+ id: result.memory.id,
1029
+ keywords: result.memory.metadata?._semanticHints || result.memory.tags.join(', '),
1030
+ snippet: result.memory.content.slice(0, 300), // First 300 chars
1031
+ timestamp: result.memory.metadata?.timestamp, // When it was said
1032
+ role: result.memory.metadata?.role // Who said it (user/assistant)
1033
+ }));
1034
+ // Call Mini COT to create gallery (CoT analyzes in ENGLISH)
1035
+ const gallery = await miniCOT.createGallery(safeParams.query, memoriesForGallery);
1036
+ // ROUND-TRIP VERIFIED compression - compress CoT OUTPUT for token efficiency
1037
+ // Uses smartCompress: EN→Chinese→EN comparison, keeps English where context lost
1038
+ // MED-40 FIX: Add null check before compression to avoid undefined errors
1039
+ gallery.gallery = gallery.gallery.map(item => ({
1040
+ ...item,
1041
+ thumbnail: item.thumbnail ? smartCompress(item.thumbnail, { threshold: 0.75 }).result : '',
1042
+ cot: item.cot ? smartCompress(item.cot, { threshold: 0.75 }).result : ''
1043
+ }));
1044
+ logger.info({
1045
+ query: safeParams.query,
1046
+ galleryItems: gallery.gallery.length,
1047
+ researchedTerms: gallery.total_researched_terms
1048
+ }, 'Gallery created by Mini COT and compressed');
1049
+ // Always use humanReadable format
1050
+ const humanReadableData = gallery.gallery.map((item, idx) => ({
1051
+ id: item.id || `gallery-${idx}`,
1052
+ similarity: item.relevance ? item.relevance / 100 : 0.5,
1053
+ content: `[GALLERY] ${item.thumbnail || item.cot || 'No preview'}`,
1054
+ }));
1055
+ return formatHumanReadable('find_memory', humanReadableData, {
1056
+ grey: true,
1057
+ showSimilarity: true,
1058
+ query: safeParams.query,
1059
+ mode: 'gallery'
1060
+ });
1061
+ }
1062
+ catch (error) {
1063
+ logger.error({ error, query: safeParams.query }, 'Mini COT gallery creation failed - falling back to normal results');
1064
+ // Fall through to normal results on error
1065
+ }
1066
+ }
1067
+ // ============================================================================
1068
+ // CAMERA ROLL MODE - Default TRUE - zoom-based response format with drilldownIDs
1069
+ // ============================================================================
1070
+ // DEFAULT TRUE: Only disable if explicitly set to false
1071
+ const cameraRollModeRaw = safeParams.cameraRollMode;
1072
+ const cameraRollMode = cameraRollModeRaw !== false && cameraRollModeRaw !== 'false' && cameraRollModeRaw !== 0;
1073
+ const zoomLevelParam = safeParams.zoomLevel;
1074
+ logger.debug({
1075
+ cameraRollMode,
1076
+ cameraRollModeRaw,
1077
+ zoomLevelParam
1078
+ }, '[find_memory] Camera roll mode check (default: true)');
1079
+ if (cameraRollMode) {
1080
+ // Determine zoom level from parameter or threshold
1081
+ const zoomLevel = zoomLevelParam || thresholdToZoomLevel(safeParams.threshold ?? 0.1);
1082
+ const zoomConfig = ZOOM_CONFIGS[zoomLevel];
1083
+ logger.info({
1084
+ query: safeParams.query,
1085
+ zoomLevel,
1086
+ resultCount: results.length,
1087
+ threshold: zoomConfig.threshold
1088
+ }, 'Camera roll mode enabled');
1089
+ // Convert results to camera roll format
1090
+ const cameraRollItems = results.map(result => {
1091
+ // Try to find Response if this is a user message
1092
+ const metadata = result.memory.metadata || {};
1093
+ const claudeResponse = metadata.claudeResponse || metadata.response;
1094
+ return formatAsCameraRollItem({
1095
+ id: result.memory.id,
1096
+ content: result.memory.content,
1097
+ similarity: result.similarity,
1098
+ metadata,
1099
+ tags: result.memory.tags,
1100
+ createdAt: result.memory.createdAt
1101
+ }, zoomConfig, {
1102
+ claudeResponse,
1103
+ relatedCount: metadata.relatedCount,
1104
+ codePointers: metadata.codePointers
1105
+ });
1106
+ });
1107
+ // Always use humanReadable format
1108
+ const humanReadableData = cameraRollItems.map((item) => ({
1109
+ id: item.drilldownID || item.id,
1110
+ similarity: item.similarity || 0.5,
1111
+ content: item.preview || item.content || 'No preview',
1112
+ }));
1113
+ return formatHumanReadable('find_memory', humanReadableData, {
1114
+ grey: true,
1115
+ showSimilarity: true,
1116
+ query: safeParams.query,
1117
+ mode: 'camera_roll',
1118
+ zoomLevel
1119
+ });
1120
+ }
1121
+ // ============================================================================
1122
+ // CONTEXT ENRICHMENT PIPELINE
1123
+ // Like human memory: fragment -> connections -> deeper recall
1124
+ // ONLY when NOT in summarize mode - drill-down should be MINIMAL
1125
+ // ============================================================================
1126
+ // CLEAN OUTPUT - Show conversation pairs:
1127
+ // : <response>
1128
+ // UP: <user prompt that triggered it>
1129
+ // Default mode (summarize=true)
1130
+ // User feedback: "content wayyy too trimmed" - increased default
1131
+ if (safeParams.summarize !== false) {
1132
+ const maxContentLen = safeParams.maxContentLength || 1000; // Was 500
1133
+ const halfLen = Math.floor(maxContentLen / 2); // 500 each for user/claude
1134
+ // Helper to strip [CLAUDE] and [USER] prefixes
1135
+ const stripPrefix = (text) => {
1136
+ return text.replace(/^\[CLAUDE\]\s*/i, '').replace(/^\[USER\]\s*/i, '').trim();
1137
+ };
1138
+ // Helper to check if content is tool usage noise
1139
+ // IMPROVED: Check for tool calls anywhere in content, not just start
1140
+ const isToolNoise = (text) => {
1141
+ if (!text)
1142
+ return false;
1143
+ // Tool call patterns to filter
1144
+ const toolPatterns = [
1145
+ /\[Tools?:\s*\w+\]/i,
1146
+ /\[(?:Bash|Read|Write|Edit|Grep|Glob|Task|WebFetch|WebSearch|NotebookEdit):/i,
1147
+ /^(?:Bash|Read|Write|Edit|Grep|Glob)\s*$/i, // Tool name only
1148
+ /^\s*\{[\s\S]*"tool":\s*"\w+"/ // JSON tool call format
1149
+ ];
1150
+ return toolPatterns.some(p => p.test(text.slice(0, 200)));
1151
+ };
1152
+ // Helper to parse content that already contains both [USER] and [CLAUDE]
1153
+ const parseInlineConversation = (text) => {
1154
+ if (!text)
1155
+ return null;
1156
+ const userMatch = text.match(/\[USER\]\s*([^\[]*)/i);
1157
+ const claudeMatch = text.match(/\[CLAUDE\]\s*([\s\S]*?)(?:\[USER\]|$)/i);
1158
+ if (userMatch && claudeMatch && userMatch[1].trim() && claudeMatch[1].trim()) {
1159
+ return {
1160
+ user: userMatch[1].trim(),
1161
+ claude: claudeMatch[1].trim()
1162
+ };
1163
+ }
1164
+ return null;
1165
+ };
1166
+ // Build conversation-style output
1167
+ const formattedResults = await Promise.all(results.map(async (r) => {
1168
+ // CRITICAL FIX: Ensure metadata is never null/undefined before accessing properties
1169
+ const metadata = r.memory.metadata ?? {};
1170
+ // SKIP tool noise memories entirely
1171
+ if (isToolNoise(r.memory.content)) {
1172
+ return null; // Will be filtered out
1173
+ }
1174
+ // FIRST: Check if content already has both [USER] and [CLAUDE] parts
1175
+ // If so, parse directly without paired lookup
1176
+ const inlineParsed = parseInlineConversation(r.memory.content || '');
1177
+ if (inlineParsed) {
1178
+ const userPart = inlineParsed.user.length > halfLen
1179
+ ? inlineParsed.user.slice(0, halfLen) + '...'
1180
+ : inlineParsed.user;
1181
+ const claudePart = inlineParsed.claude.length > halfLen
1182
+ ? inlineParsed.claude.slice(0, halfLen) + '...'
1183
+ : inlineParsed.claude;
1184
+ return {
1185
+ id: r.memory.id,
1186
+ user: userPart,
1187
+ claude: claudePart,
1188
+ relevance: Math.round(r.similarity * 100) + '%'
1189
+ };
1190
+ }
1191
+ // Extract role with multiple fallback strategies
1192
+ const role = metadata.role
1193
+ || (r.memory.tags?.includes('role:user') ? 'user' : null)
1194
+ || (r.memory.tags?.includes('role:assistant') ? 'assistant' : null)
1195
+ // Content-based role detection as fallback
1196
+ || (r.memory.content?.startsWith('[CLAUDE]') ? 'assistant' : null)
1197
+ || (r.memory.content?.startsWith('[USER]') ? 'user' : null)
1198
+ || undefined;
1199
+ // CRITICAL FIX: Check both camelCase and snake_case for sessionId
1200
+ // Also check tags for session info as ultimate fallback
1201
+ let sessionId = metadata.sessionId || metadata.session_id;
1202
+ // Fallback: Check tags for session info (format: "session:xxx")
1203
+ if (!sessionId && r.memory.tags) {
1204
+ const sessionTag = r.memory.tags.find((tag) => tag.startsWith('session:'));
1205
+ if (sessionTag) {
1206
+ sessionId = sessionTag.replace('session:', '');
1207
+ }
1208
+ }
1209
+ // DEBUG: Log session extraction with all checked sources
1210
+ logger.debug({
1211
+ memoryId: r.memory.id,
1212
+ sessionId,
1213
+ sessionIdSource: metadata.sessionId ? 'metadata.sessionId'
1214
+ : metadata.session_id ? 'metadata.session_id'
1215
+ : sessionId ? 'tags' : 'none',
1216
+ role,
1217
+ timestamp: metadata.timestamp,
1218
+ hasMetadata: !!r.memory.metadata
1219
+ }, '[PAIRING] Session extraction for memory');
1220
+ let content = stripPrefix(r.memory.content || '');
1221
+ // Trim content to half length
1222
+ if (content.length > halfLen) {
1223
+ content = content.slice(0, halfLen) + '...';
1224
+ }
1225
+ // DYNAMIC PAIRED MESSAGE LOOKUP
1226
+ // Try multiple strategies to find the paired user/claude message
1227
+ let pairedContent;
1228
+ const memoryTimestamp = metadata.timestamp || r.memory.createdAt?.toISOString();
1229
+ const pairedRole = role === 'assistant' ? 'user' : 'assistant';
1230
+ // CROSS-PROJECT FIX: Use memory's own project_path for paired lookup
1231
+ // This ensures paired messages are found from the same project as the result
1232
+ const projectPath = metadata.project_path || getProjectContext().getProjectPath();
1233
+ try {
1234
+ let pairedQuery;
1235
+ // Track if we found a session-scoped result (prevents cross-session fallback)
1236
+ let foundInSession = false;
1237
+ // Strategy 1: Same session (if sessionId exists)
1238
+ // IMPORTANT: Use metadata->>'timestamp' (original time) NOT created_at (bulk import time)
1239
+ // EXCLUDE tool calls - they're not useful context
1240
+ // CRITICAL FIX: If sessionId exists, we MUST only return pairs from the SAME session
1241
+ // Do NOT fall through to cross-session strategies when sessionId is present
1242
+ // FIX: Check both camelCase 'sessionId' and snake_case 'session_id' in SQL
1243
+ if (sessionId && memoryTimestamp) {
1244
+ if (role === 'assistant') {
1245
+ // response -> find user prompt BEFORE it
1246
+ pairedQuery = await this.db.query(`
1247
+ SELECT content FROM memories
1248
+ WHERE COALESCE(metadata->>'sessionId', metadata->>'session_id') = $1
1249
+ AND (metadata->>'role' = 'user' OR 'role:user' = ANY(tags))
1250
+ AND COALESCE(metadata->>'timestamp', created_at::text)::timestamptz < $2::timestamptz
1251
+ AND content NOT LIKE '%[Tools:%'
1252
+ ORDER BY COALESCE(metadata->>'timestamp', created_at::text)::timestamptz DESC
1253
+ LIMIT 1
1254
+ `, [sessionId, memoryTimestamp]);
1255
+ }
1256
+ else {
1257
+ // User prompt -> find response AFTER it (skip tool calls!)
1258
+ pairedQuery = await this.db.query(`
1259
+ SELECT content FROM memories
1260
+ WHERE COALESCE(metadata->>'sessionId', metadata->>'session_id') = $1
1261
+ AND (metadata->>'role' = 'assistant' OR 'role:assistant' = ANY(tags))
1262
+ AND COALESCE(metadata->>'timestamp', created_at::text)::timestamptz > $2::timestamptz
1263
+ AND content NOT LIKE '%[Tools:%'
1264
+ ORDER BY COALESCE(metadata->>'timestamp', created_at::text)::timestamptz ASC
1265
+ LIMIT 1
1266
+ `, [sessionId, memoryTimestamp]);
1267
+ }
1268
+ // SIMPLIFIED PAIRING LOGIC (3 strategies max)
1269
+ // Pattern: user types → prompt saved → claude responds → response saved AFTER
1270
+ // So for user prompts: look for NEXT assistant message
1271
+ // For assistant responses: look for PREVIOUS user message
1272
+ if (pairedQuery && pairedQuery.rows.length > 0) {
1273
+ foundInSession = true;
1274
+ }
1275
+ else {
1276
+ // Strategy 1: Same session - find adjacent message with opposite role
1277
+ // User prompt → next assistant response in session
1278
+ // Assistant response → previous user prompt in session
1279
+ if (role === 'user') {
1280
+ // Find NEXT assistant message in this session ('s response to this prompt)
1281
+ pairedQuery = await this.db.query(`
1282
+ SELECT content FROM memories
1283
+ WHERE COALESCE(metadata->>'sessionId', metadata->>'session_id') = $1
1284
+ AND (metadata->>'role' = 'assistant' OR 'role:assistant' = ANY(tags))
1285
+ AND COALESCE(metadata->>'timestamp', created_at::text)::timestamptz > $2::timestamptz
1286
+ AND content NOT LIKE '%[Tools:%'
1287
+ ORDER BY COALESCE(metadata->>'timestamp', created_at::text)::timestamptz ASC
1288
+ LIMIT 1
1289
+ `, [sessionId, memoryTimestamp]);
1290
+ }
1291
+ else {
1292
+ // Find PREVIOUS user message in this session (the prompt responded to)
1293
+ pairedQuery = await this.db.query(`
1294
+ SELECT content FROM memories
1295
+ WHERE COALESCE(metadata->>'sessionId', metadata->>'session_id') = $1
1296
+ AND (metadata->>'role' = 'user' OR 'role:user' = ANY(tags))
1297
+ AND COALESCE(metadata->>'timestamp', created_at::text)::timestamptz < $2::timestamptz
1298
+ AND content NOT LIKE '%[Tools:%'
1299
+ ORDER BY COALESCE(metadata->>'timestamp', created_at::text)::timestamptz DESC
1300
+ LIMIT 1
1301
+ `, [sessionId, memoryTimestamp]);
1302
+ }
1303
+ if (pairedQuery && pairedQuery.rows.length > 0) {
1304
+ foundInSession = true;
1305
+ }
1306
+ }
1307
+ }
1308
+ // ============================================================================
1309
+ // NO-SESSION FALLBACK (Strategies 2-3) - ONLY when NO sessionId exists
1310
+ // ============================================================================
1311
+ else if (memoryTimestamp) {
1312
+ // Strategy 2: Same project - find adjacent message by timestamp
1313
+ // Simple: user → next assistant, assistant → previous user
1314
+ if (!pairedQuery || pairedQuery.rows.length === 0) {
1315
+ if (role === 'user') {
1316
+ // Find NEXT assistant message in project
1317
+ pairedQuery = await this.db.query(`
1318
+ SELECT content FROM memories
1319
+ WHERE (metadata->>'role' = 'assistant' OR 'role:assistant' = ANY(tags))
1320
+ AND metadata->>'project_path' = $1
1321
+ AND COALESCE(metadata->>'timestamp', created_at::text)::timestamptz > $2::timestamptz
1322
+ AND content NOT LIKE '%[Tools:%'
1323
+ ORDER BY COALESCE(metadata->>'timestamp', created_at::text)::timestamptz ASC
1324
+ LIMIT 1
1325
+ `, [projectPath, memoryTimestamp]);
1326
+ }
1327
+ else {
1328
+ // Find PREVIOUS user message in project
1329
+ pairedQuery = await this.db.query(`
1330
+ SELECT content FROM memories
1331
+ WHERE (metadata->>'role' = 'user' OR 'role:user' = ANY(tags))
1332
+ AND metadata->>'project_path' = $1
1333
+ AND COALESCE(metadata->>'timestamp', created_at::text)::timestamptz < $2::timestamptz
1334
+ AND content NOT LIKE '%[Tools:%'
1335
+ ORDER BY COALESCE(metadata->>'timestamp', created_at::text)::timestamptz DESC
1336
+ LIMIT 1
1337
+ `, [projectPath, memoryTimestamp]);
1338
+ }
1339
+ }
1340
+ // Strategy 3: ULTIMATE FALLBACK - closest opposite role in project by timestamp
1341
+ // Only if strategy 2 found nothing
1342
+ if (!pairedQuery || pairedQuery.rows.length === 0) {
1343
+ pairedQuery = await this.db.query(`
1344
+ SELECT content FROM memories
1345
+ WHERE (metadata->>'role' = $1 OR $2 = ANY(tags))
1346
+ AND metadata->>'project_path' = $3
1347
+ AND id != $5
1348
+ AND content NOT LIKE '%[Tools:%'
1349
+ ORDER BY ABS(EXTRACT(EPOCH FROM (
1350
+ COALESCE(metadata->>'timestamp', created_at::text)::timestamptz - $4::timestamptz
1351
+ )))
1352
+ LIMIT 1
1353
+ `, [pairedRole, `role:${pairedRole}`, projectPath, memoryTimestamp, r.memory.id]);
1354
+ }
1355
+ } // end no-session fallback block
1356
+ if (pairedQuery && pairedQuery.rows.length > 0) {
1357
+ pairedContent = stripPrefix(pairedQuery.rows[0].content);
1358
+ logger.debug({
1359
+ memoryId: r.memory.id,
1360
+ sessionId,
1361
+ pairedContentPreview: pairedContent.slice(0, 50),
1362
+ pairedRole: role === 'assistant' ? 'user' : 'assistant'
1363
+ }, '[PAIRING] Found paired message');
1364
+ if (pairedContent.length > halfLen) {
1365
+ pairedContent = pairedContent.slice(0, halfLen) + '...';
1366
+ }
1367
+ }
1368
+ else {
1369
+ logger.debug({
1370
+ memoryId: r.memory.id,
1371
+ sessionId,
1372
+ role,
1373
+ timestamp: metadata.timestamp
1374
+ }, '[PAIRING] No paired message found');
1375
+ }
1376
+ }
1377
+ catch (e) {
1378
+ // Ignore - paired lookup is optional
1379
+ logger.debug({ error: e, sessionId }, 'Paired message lookup failed');
1380
+ }
1381
+ // ALWAYS show both user: and claude: fields
1382
+ // Format: { user: "what user said", claude: "what claude said", relevance: "X%" }
1383
+ if (role === 'assistant') {
1384
+ return {
1385
+ id: r.memory.id,
1386
+ user: pairedContent || '(no user prompt found)',
1387
+ claude: content,
1388
+ relevance: Math.round(r.similarity * 100) + '%'
1389
+ };
1390
+ }
1391
+ else {
1392
+ // role === 'user' or undefined
1393
+ return {
1394
+ id: r.memory.id,
1395
+ user: content,
1396
+ claude: pairedContent || '', // Empty if no paired response found
1397
+ relevance: Math.round(r.similarity * 100) + '%'
1398
+ };
1399
+ }
1400
+ })).then(results => results.filter((r) => r !== null));
1401
+ // Always use humanReadable format
1402
+ const humanReadableData = formattedResults.map(r => ({
1403
+ id: r.id,
1404
+ similarity: parseFloat(r.relevance) / 100,
1405
+ // Only include [CLAUDE] if there's actual content (length > 0)
1406
+ content: r.claude && r.claude.length > 0 ? `[USER] ${r.user}\n[CLAUDE] ${r.claude}` : `[USER] ${r.user}`,
1407
+ }));
1408
+ return formatHumanReadable('find_memory', humanReadableData, {
1409
+ grey: true,
1410
+ showSimilarity: true,
1411
+ maxContentLength: safeParams.maxContentLength || 500,
1412
+ query: safeParams.query
1413
+ });
1414
+ }
1415
+ // FULL MODE: Enrich results with discoverable paths
1416
+ // Step 1: Enrich each result with discoverable paths
1417
+ const enrichedResults = results.map(enrichSearchResult);
1418
+ // Step 2: Aggregate all discoverable paths across results
1419
+ const aggregatedPaths = this.aggregateDiscoverablePaths(enrichedResults);
1420
+ // Step 3: Generate context enrichment summary (Chinese compacted)
1421
+ const contextEnrichment = this.generateContextEnrichment(safeParams.query, enrichedResults, aggregatedPaths, drilldown);
1422
+ // Step 4: Log enrichment for debugging
1423
+ logger.info({
1424
+ query: safeParams.query,
1425
+ filesFound: aggregatedPaths.filePaths.length,
1426
+ codeBlocksFound: aggregatedPaths.codeBlocks.length,
1427
+ urlsFound: aggregatedPaths.urls.length,
1428
+ techTermsFound: aggregatedPaths.technicalTerms.length,
1429
+ researchQuestionsFound: aggregatedPaths.researchQuestions.length
1430
+ }, '[ContextEnricher] 發現可探索路徑');
1431
+ // update access counts for returned memories (non-blocking)
1432
+ if (results.length > 0) {
1433
+ // Fire and forget - don't block on access count updates
1434
+ this.updateAccessCounts(results.map(r => r.memory.id)).catch(err => {
1435
+ logger.warn({ error: err }, 'failed to update access counts');
1436
+ });
1437
+ // Emit memory:retrieved event via LWJEB
1438
+ this.coordinator.emitMemoryRetrieved(results.map(r => r.memory.id), safeParams.query);
1439
+ // Record access for hot path tracking (non-blocking)
1440
+ // This helps build memory access patterns for prediction
1441
+ this.recordAccessPatterns(results.map(r => r.memory.id)).catch(err => {
1442
+ logger.debug({ error: err }, 'failed to record access patterns (non-critical)');
1443
+ });
1444
+ }
1445
+ // Step 5: Generate user interaction prompt for CLI control
1446
+ const userInteractionPrompt = generateUserInteractionPrompt(results, safeParams.query, drilldown, aggregatedPaths);
1447
+ // Step 6: Format research spawn instructions if needed
1448
+ const researchSpawnInstructions = drilldown.needsResearch
1449
+ ? this.generateResearchSpawnInstructions(safeParams.query, aggregatedPaths)
1450
+ : null;
1451
+ // ============================================================================
1452
+ // DEEP DEBUG: Method Exit (Success)
1453
+ // ============================================================================
1454
+ const finalDuration = Date.now() - startTime;
1455
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'METHOD_EXIT_SUCCESS', {
1456
+ finalDuration,
1457
+ enrichedResultCount: enrichedResults?.length,
1458
+ query: safeParams.query?.slice(0, 50)
1459
+ });
1460
+ // Broadcast COT result to dashboard
1461
+ cotResult('find_memory', `Found ${enrichedResults?.length || 0} memories`, enrichedResults?.length || 0);
1462
+ // Always use humanReadable format
1463
+ const humanReadableData = enrichedResults.map(r => ({
1464
+ id: r.memory.id,
1465
+ drilldownID: r.drilldownID,
1466
+ similarity: r.similarity,
1467
+ content: r.memory.content,
1468
+ tags: r.memory.tags,
1469
+ type: r.memory.memoryType,
1470
+ importance: r.memory.importance,
1471
+ createdAt: r.memory.createdAt
1472
+ }));
1473
+ return formatHumanReadable('find_memory', humanReadableData, {
1474
+ grey: true,
1475
+ showSimilarity: true,
1476
+ showTags: true,
1477
+ maxContentLength: safeParams.maxContentLength || 300,
1478
+ query: safeParams.query // Pass query for header display
1479
+ });
1480
+ }
1481
+ catch (error) {
1482
+ const duration = Date.now() - startTime;
1483
+ // Broadcast COT error to dashboard
1484
+ cotError('find_memory', error?.message?.slice(0, 100) || 'Unknown error');
1485
+ // ============================================================================
1486
+ // DEEP DEBUG: Method Exit (Error)
1487
+ // ============================================================================
1488
+ __debugLog('[FIND_MEMORY DEBUG]', Date.now(), 'METHOD_EXIT_ERROR', {
1489
+ duration,
1490
+ errorMessage: error?.message?.slice(0, 200),
1491
+ errorCode: error?.code,
1492
+ errorName: error?.name,
1493
+ query: params.query?.slice(0, 50)
1494
+ });
1495
+ // Get socket path for error context (may fail if error occurred before socketPath was set)
1496
+ let errorSocketPath = 'unknown';
1497
+ try {
1498
+ errorSocketPath = getEmbeddingSocketPath();
1499
+ }
1500
+ catch {
1501
+ // Ignore - socket path detection may have failed
1502
+ }
1503
+ // Extract error details for comprehensive logging
1504
+ const err = error;
1505
+ // Enhanced error logging with all context
1506
+ logger.error({
1507
+ error: {
1508
+ message: err.message,
1509
+ code: err.code,
1510
+ stack: err.stack?.slice(0, 1000),
1511
+ socketPath: err.socketPath || errorSocketPath,
1512
+ durationMs: err.durationMs
1513
+ },
1514
+ query: params.query?.slice(0, 100),
1515
+ duration,
1516
+ socketPath: errorSocketPath,
1517
+ debug: process.env['SPECMEM_DEBUG'] === 'true'
1518
+ }, 'search failed - see error details for troubleshooting');
1519
+ // Debug log the error with full context
1520
+ this.debugLogger.searchOperation(params.query || '', 'error', {
1521
+ durationMs: duration,
1522
+ error: err,
1523
+ socketPath: errorSocketPath
1524
+ });
1525
+ // Build comprehensive error message for MCP response
1526
+ const errorCode = err.code || 'UNKNOWN_ERROR';
1527
+ let userMessage;
1528
+ switch (errorCode) {
1529
+ case 'EMBEDDING_TIMEOUT':
1530
+ userMessage = `Embedding service timeout (${duration}ms). ` +
1531
+ `Socket: ${err.socketPath || errorSocketPath}. ` +
1532
+ `Check: 1) Is embedding service running? (ps aux | grep frankenstein) ` +
1533
+ `2) Socket exists? (ls -la ${err.socketPath || errorSocketPath}) ` +
1534
+ `3) Service healthy? (check logs in /tmp/specmem-*/embedding.log)`;
1535
+ break;
1536
+ case 'SEARCH_TIMEOUT':
1537
+ userMessage = `Database search timeout (${duration}ms). ` +
1538
+ `Check: 1) Database connection (pg_isready) ` +
1539
+ `2) Query complexity - try simpler terms ` +
1540
+ `3) Database load (check pg_stat_activity)`;
1541
+ break;
1542
+ case 'EMBEDDING_ERROR':
1543
+ userMessage = `Embedding generation failed: ${err.message}. ` +
1544
+ `Socket: ${err.socketPath || errorSocketPath}. ` +
1545
+ `This could be: socket not found, service not running, or input too long.`;
1546
+ break;
1547
+ case 'SEARCH_ERROR':
1548
+ userMessage = `Search query failed: ${err.message}. ` +
1549
+ `Check database connection and query syntax.`;
1550
+ break;
1551
+ default:
1552
+ userMessage = `find_memory error: ${err.message}. ` +
1553
+ `Socket: ${errorSocketPath}. ` +
1554
+ `Duration: ${duration}ms. ` +
1555
+ `Enable SPECMEM_DEBUG=true for detailed logs.`;
1556
+ }
1557
+ // Create error that will be properly serialized in MCP response
1558
+ const mcpError = new Error(userMessage);
1559
+ mcpError.code = errorCode;
1560
+ mcpError.socketPath = err.socketPath || errorSocketPath;
1561
+ mcpError.durationMs = duration;
1562
+ mcpError.query = params.query?.slice(0, 50);
1563
+ mcpError.troubleshooting = {
1564
+ enableDebug: 'Set SPECMEM_DEBUG=true for detailed logs',
1565
+ checkSocket: `ls -la ${err.socketPath || errorSocketPath}`,
1566
+ checkService: 'ps aux | grep frankenstein',
1567
+ checkLogs: 'tail -f /tmp/specmem-*/mcp-startup.log'
1568
+ };
1569
+ throw mcpError;
1570
+ }
1571
+ }
1572
+ /**
1573
+ * semanticSearch - the main search logic
1574
+ *
1575
+ * uses pgvector for cosine similarity search
1576
+ * applies filters for type, tags, importance, dates
1577
+ */
1578
+ async semanticSearch(params, queryEmbedding) {
1579
+ // build the query dynamically based on filters
1580
+ const conditions = ['embedding IS NOT NULL'];
1581
+ const queryParams = [];
1582
+ let paramIndex = 1;
1583
+ // IMPORTANT: Embedding MUST be $1 for the vector similarity query
1584
+ // Add embedding first as $1
1585
+ queryParams.push(`[${queryEmbedding.join(',')}]`);
1586
+ paramIndex++;
1587
+ // PROJECT NAMESPACING: Filter by current project (now $2)
1588
+ const projectFilter = buildProjectWhereClause(paramIndex);
1589
+ conditions.push(projectFilter.sql);
1590
+ queryParams.push(projectFilter.param);
1591
+ paramIndex = projectFilter.nextIndex;
1592
+ // expired filter
1593
+ if (!params.includeExpired) {
1594
+ conditions.push('(expires_at IS NULL OR expires_at > NOW())');
1595
+ }
1596
+ // memory type filter
1597
+ if (params.memoryTypes?.length) {
1598
+ conditions.push(`memory_type = ANY($${paramIndex}::memory_type[])`);
1599
+ queryParams.push(params.memoryTypes);
1600
+ paramIndex++;
1601
+ }
1602
+ // tags filter (OR logic)
1603
+ if (params.tags?.length) {
1604
+ conditions.push(`tags && $${paramIndex}::text[]`);
1605
+ queryParams.push(params.tags);
1606
+ paramIndex++;
1607
+ }
1608
+ // importance filter
1609
+ if (params.importance?.length) {
1610
+ conditions.push(`importance = ANY($${paramIndex}::importance_level[])`);
1611
+ queryParams.push(params.importance);
1612
+ paramIndex++;
1613
+ }
1614
+ // date range filter
1615
+ if (params.dateRange?.start) {
1616
+ conditions.push(`created_at >= $${paramIndex}::timestamptz`);
1617
+ queryParams.push(params.dateRange.start);
1618
+ paramIndex++;
1619
+ }
1620
+ if (params.dateRange?.end) {
1621
+ conditions.push(`created_at <= $${paramIndex}::timestamptz`);
1622
+ queryParams.push(params.dateRange.end);
1623
+ paramIndex++;
1624
+ }
1625
+ // NEW: Role filter - uses metadata->>'role' or tags
1626
+ if (params.role) {
1627
+ // Filter by role:user or role:assistant tag (more efficient with index)
1628
+ conditions.push(`$${paramIndex}::text = ANY(tags)`);
1629
+ queryParams.push(`role:${params.role}`);
1630
+ paramIndex++;
1631
+ }
1632
+ // ============================================================================
1633
+ // NOISE FILTERS: Exclude system-generated content dynamically via tags
1634
+ // ============================================================================
1635
+ // These tags are set at ingestion time by sessionParser/sessionWatcher:
1636
+ // - 'context-restoration' = raw context restoration summaries (not real user prompts)
1637
+ // - 'agent-deployment' = agent/team member deployment prompts
1638
+ // - 'consolidation-task' = code consolidation task prompts
1639
+ // Exclude these by default to avoid polluting find_memory results
1640
+ const noiseTags = ['context-restoration', 'agent-deployment', 'consolidation-task'];
1641
+ conditions.push(`NOT (tags && $${paramIndex}::text[])`);
1642
+ queryParams.push(noiseTags);
1643
+ paramIndex++;
1644
+ // threshold and limit - now parameterized for query plan caching
1645
+ // NOTE: Default 0.35 filters out noise while catching real matches
1646
+ // Local embeddings typically produce 0.2-0.5 similarity for relevant content
1647
+ const threshold = params.threshold ?? 0.35;
1648
+ const limit = params.limit ?? 10;
1649
+ // Add threshold and limit as parameters
1650
+ queryParams.push(threshold);
1651
+ const thresholdParam = paramIndex++;
1652
+ queryParams.push(limit);
1653
+ const limitParam = paramIndex;
1654
+ // the query - cosine similarity with pgvector
1655
+ // 1 - cosine_distance gives us similarity score
1656
+ // NOW FULLY PARAMETERIZED for better query plan caching
1657
+ const query = `
1658
+ SELECT
1659
+ id, content, memory_type, importance, tags, metadata,
1660
+ embedding, created_at, updated_at, access_count, last_accessed_at,
1661
+ 1 - (embedding <=> $1::vector) AS similarity
1662
+ FROM memories
1663
+ WHERE ${conditions.join(' AND ')}
1664
+ AND 1 - (embedding <=> $1::vector) >= $${thresholdParam}
1665
+ ORDER BY similarity DESC
1666
+ LIMIT $${limitParam}
1667
+ `;
1668
+ // DEBUG: Log the first param (embedding) length before query
1669
+ const embeddingParamStr = queryParams[0];
1670
+ const embeddingParamLen = embeddingParamStr?.match(/,/g)?.length || 0;
1671
+ logger.info({
1672
+ embeddingParamLength: embeddingParamLen + 1,
1673
+ embeddingPreview: embeddingParamStr?.substring(0, 50),
1674
+ paramCount: queryParams.length
1675
+ }, 'About to execute semantic search query');
1676
+ const queryStart = Date.now();
1677
+ const result = await this.db.query(query, queryParams);
1678
+ const queryDuration = Date.now() - queryStart;
1679
+ // Enhanced logging with similarity score distribution for debugging relevance issues
1680
+ const similarityScores = result.rows.map((r) => r.similarity);
1681
+ const sortedScores = [...similarityScores].sort((a, b) => b - a);
1682
+ logger.info({
1683
+ queryDuration,
1684
+ resultCount: result.rows.length,
1685
+ threshold,
1686
+ limit,
1687
+ // Similarity distribution - CRITICAL for debugging relevance issues
1688
+ topSimilarity: sortedScores[0] || 0,
1689
+ minSimilarity: sortedScores[sortedScores.length - 1] || 0,
1690
+ avgSimilarity: similarityScores.length > 0
1691
+ ? Math.round(similarityScores.reduce((a, b) => a + b, 0) / similarityScores.length * 1000) / 1000
1692
+ : 0,
1693
+ // Show distribution buckets
1694
+ above50pct: similarityScores.filter((s) => s >= 0.5).length,
1695
+ above30pct: similarityScores.filter((s) => s >= 0.3).length,
1696
+ above25pct: similarityScores.filter((s) => s >= 0.25).length,
1697
+ // Show top 3 scores for debugging
1698
+ top3Scores: sortedScores.slice(0, 3).map(s => Math.round(s * 1000) / 1000)
1699
+ }, '[RELEVANCE] Semantic search similarity distribution');
1700
+ // Apply Chinese Compactor approach: pass summarize/maxContentLength options
1701
+ const compactionOpts = {
1702
+ summarize: params.summarize,
1703
+ maxContentLength: params.maxContentLength
1704
+ };
1705
+ return result.rows.map((row) => this.rowToSearchResult(row, compactionOpts));
1706
+ }
1707
+ // ============================================================================
1708
+ // I5 FIX: NEW METHODS FOR RECENT MEMORIES, RECENCY BOOST, KEYWORD FALLBACK
1709
+ // ============================================================================
1710
+ /**
1711
+ * I5 FIX: Get recent memories regardless of similarity
1712
+ * This ensures we can always find recent prompts even if embeddings aren't ready
1713
+ */
1714
+ async getRecentMemories(count, params) {
1715
+ if (count <= 0)
1716
+ return [];
1717
+ logger.info({ count, allProjects: params.allProjects, projectPath: params.projectPath }, '[I5 FIX] Fetching recent memories for includeRecent');
1718
+ // Use helper for project filtering (supports cross-project search)
1719
+ const projectFilter = this.buildProjectCondition(params, 1);
1720
+ const conditions = [...projectFilter.conditions];
1721
+ const queryParams = [...projectFilter.queryParams];
1722
+ let paramIndex = projectFilter.nextIndex;
1723
+ // Apply same filters as main search (except threshold/embedding)
1724
+ if (!params.includeExpired) {
1725
+ conditions.push('(expires_at IS NULL OR expires_at > NOW())');
1726
+ }
1727
+ if (params.memoryTypes?.length) {
1728
+ conditions.push(`memory_type = ANY($${paramIndex}::memory_type[])`);
1729
+ queryParams.push(params.memoryTypes);
1730
+ paramIndex++;
1731
+ }
1732
+ if (params.role) {
1733
+ conditions.push(`$${paramIndex}::text = ANY(tags)`);
1734
+ queryParams.push(`role:${params.role}`);
1735
+ paramIndex++;
1736
+ }
1737
+ // Exclude noise tags (same as main search)
1738
+ const noiseTags = ['context-restoration', 'agent-deployment', 'consolidation-task'];
1739
+ conditions.push(`NOT (tags && $${paramIndex}::text[])`);
1740
+ queryParams.push(noiseTags);
1741
+ paramIndex++;
1742
+ queryParams.push(count);
1743
+ const limitParam = paramIndex;
1744
+ // MED-38 FIX: Mark fallback results clearly - similarity is not from semantic search
1745
+ const query = `
1746
+ SELECT
1747
+ id, content, memory_type, importance, tags, metadata,
1748
+ embedding, created_at, updated_at, access_count, last_accessed_at,
1749
+ 0.5 AS similarity, -- Fixed similarity for recent memories (not semantic)
1750
+ true AS is_fallback -- MED-38: Flag to indicate this is a fallback result
1751
+ FROM memories
1752
+ WHERE ${conditions.join(' AND ')}
1753
+ ORDER BY created_at DESC
1754
+ LIMIT $${limitParam}
1755
+ `;
1756
+ try {
1757
+ const result = await this.db.query(query, queryParams);
1758
+ logger.info({
1759
+ recentFound: result.rows.length,
1760
+ newestTimestamp: result.rows[0]?.created_at
1761
+ }, '[I5 FIX] Recent memories retrieved');
1762
+ const compactionOpts = {
1763
+ summarize: params.summarize,
1764
+ maxContentLength: params.maxContentLength
1765
+ };
1766
+ return result.rows.map((row) => this.rowToSearchResult(row, compactionOpts));
1767
+ }
1768
+ catch (error) {
1769
+ logger.error({ error }, '[I5 FIX] Failed to get recent memories');
1770
+ return [];
1771
+ }
1772
+ }
1773
+ /**
1774
+ * I5 FIX: Apply recency boost to search results
1775
+ * Memories from last hour: +20% similarity
1776
+ * Memories from last day: +10% similarity
1777
+ * This ensures recent discussions rank higher
1778
+ */
1779
+ applyRecencyBoost(results) {
1780
+ const now = Date.now();
1781
+ const oneHour = 60 * 60 * 1000;
1782
+ const oneDay = 24 * oneHour;
1783
+ return results.map(result => {
1784
+ const createdAt = result.memory.createdAt?.getTime() || 0;
1785
+ const age = now - createdAt;
1786
+ let boostFactor = 1.0;
1787
+ if (age < oneHour) {
1788
+ boostFactor = 1.20; // 20% boost for last hour
1789
+ }
1790
+ else if (age < oneDay) {
1791
+ boostFactor = 1.10; // 10% boost for last day
1792
+ }
1793
+ if (boostFactor > 1.0) {
1794
+ logger.debug({
1795
+ memoryId: result.memory.id,
1796
+ originalSimilarity: result.similarity,
1797
+ boostFactor,
1798
+ newSimilarity: Math.min(1.0, result.similarity * boostFactor),
1799
+ ageMinutes: Math.round(age / 60000)
1800
+ }, '[I5 FIX] Applied recency boost');
1801
+ }
1802
+ return {
1803
+ ...result,
1804
+ similarity: Math.min(1.0, result.similarity * boostFactor)
1805
+ };
1806
+ });
1807
+ }
1808
+ /**
1809
+ * I5 FIX: Keyword fallback search using ILIKE
1810
+ * When embeddings return nothing, do text-based search
1811
+ */
1812
+ async keywordSearch(query, params) {
1813
+ logger.info({ query, allProjects: params.allProjects, projectPath: params.projectPath }, '[I5 FIX] Performing keyword fallback search');
1814
+ const limit = params.limit ?? 10;
1815
+ // Extract keywords from query (split on spaces, filter short words)
1816
+ const keywords = query.toLowerCase()
1817
+ .split(/\s+/)
1818
+ .filter(w => w.length >= 3)
1819
+ .slice(0, 5); // Max 5 keywords
1820
+ if (keywords.length === 0) {
1821
+ logger.warn({ query }, '[I5 FIX] No usable keywords for fallback search');
1822
+ return [];
1823
+ }
1824
+ // Use helper for project filtering (supports cross-project search)
1825
+ const projectFilter = this.buildProjectCondition(params, 1);
1826
+ const conditions = [...projectFilter.conditions];
1827
+ const queryParams = [...projectFilter.queryParams];
1828
+ let paramIndex = projectFilter.nextIndex;
1829
+ // Add keyword conditions (OR logic - any keyword matches)
1830
+ const keywordConditions = keywords.map((_, idx) => {
1831
+ queryParams.push(`%${keywords[idx]}%`);
1832
+ return `content ILIKE $${paramIndex + idx}`;
1833
+ });
1834
+ conditions.push(`(${keywordConditions.join(' OR ')})`);
1835
+ paramIndex += keywords.length;
1836
+ if (!params.includeExpired) {
1837
+ conditions.push('(expires_at IS NULL OR expires_at > NOW())');
1838
+ }
1839
+ if (params.role) {
1840
+ conditions.push(`$${paramIndex}::text = ANY(tags)`);
1841
+ queryParams.push(`role:${params.role}`);
1842
+ paramIndex++;
1843
+ }
1844
+ // Exclude noise tags (same as main search)
1845
+ const noiseTags = ['context-restoration', 'agent-deployment', 'consolidation-task'];
1846
+ conditions.push(`NOT (tags && $${paramIndex}::text[])`);
1847
+ queryParams.push(noiseTags);
1848
+ paramIndex++;
1849
+ queryParams.push(limit);
1850
+ const limitParam = paramIndex;
1851
+ // MED-38 FIX: Mark fallback results clearly - similarity is not from semantic search
1852
+ const searchQuery = `
1853
+ SELECT
1854
+ id, content, memory_type, importance, tags, metadata,
1855
+ embedding, created_at, updated_at, access_count, last_accessed_at,
1856
+ 0.3 AS similarity, -- Fixed similarity for keyword matches (not semantic)
1857
+ true AS is_fallback -- MED-38: Flag to indicate this is a fallback result
1858
+ FROM memories
1859
+ WHERE ${conditions.join(' AND ')}
1860
+ ORDER BY created_at DESC
1861
+ LIMIT $${limitParam}
1862
+ `;
1863
+ try {
1864
+ const result = await this.db.query(searchQuery, queryParams);
1865
+ logger.info({
1866
+ keywordCount: keywords.length,
1867
+ resultsFound: result.rows.length,
1868
+ keywords
1869
+ }, '[I5 FIX] Keyword fallback search complete');
1870
+ const compactionOpts = {
1871
+ summarize: params.summarize,
1872
+ maxContentLength: params.maxContentLength
1873
+ };
1874
+ return result.rows.map((row) => this.rowToSearchResult(row, compactionOpts));
1875
+ }
1876
+ catch (error) {
1877
+ logger.error({ error, keywords }, '[I5 FIX] Keyword fallback search failed');
1878
+ return [];
1879
+ }
1880
+ }
1881
+ /**
1882
+ * I5 FIX: Merge and dedupe results from multiple sources
1883
+ * Priority: semantic results > recent results > keyword results
1884
+ *
1885
+ * REACTIVE DEDUPE: Also checks for content duplicates and queues DB cleanup
1886
+ */
1887
+ mergeAndDedupeResults(semanticResults, recentResults, keywordResults, limit) {
1888
+ const seenIds = new Set();
1889
+ const seenContent = new Map(); // content hash -> kept memory id
1890
+ const duplicateIds = []; // IDs to delete from DB
1891
+ const merged = [];
1892
+ // Helper to normalize content for comparison
1893
+ const normalizeContent = (content) => {
1894
+ return content
1895
+ .toLowerCase()
1896
+ .trim()
1897
+ .replace(/^\[user\]\s*/i, '')
1898
+ .replace(/^\[claude\]\s*/i, '')
1899
+ .slice(0, 500); // Compare first 500 chars
1900
+ };
1901
+ // Helper to add result with content dedup check
1902
+ const addResult = (result, source) => {
1903
+ if (seenIds.has(result.memory.id))
1904
+ return;
1905
+ const contentKey = normalizeContent(result.memory.content);
1906
+ const existingId = seenContent.get(contentKey);
1907
+ if (existingId) {
1908
+ // Content duplicate found - queue for DB deletion
1909
+ duplicateIds.push(result.memory.id);
1910
+ logger.debug({
1911
+ duplicateId: result.memory.id,
1912
+ keptId: existingId,
1913
+ contentPreview: contentKey.slice(0, 50)
1914
+ }, '[REACTIVE DEDUPE] Content duplicate detected');
1915
+ return;
1916
+ }
1917
+ seenIds.add(result.memory.id);
1918
+ seenContent.set(contentKey, result.memory.id);
1919
+ if (source) {
1920
+ merged.push({
1921
+ ...result,
1922
+ memory: {
1923
+ ...result.memory,
1924
+ metadata: { ...result.memory.metadata, _source: source }
1925
+ }
1926
+ });
1927
+ }
1928
+ else {
1929
+ merged.push(result);
1930
+ }
1931
+ };
1932
+ // Add semantic results first (highest priority)
1933
+ for (const result of semanticResults) {
1934
+ addResult(result);
1935
+ }
1936
+ // Add recent results second
1937
+ for (const result of recentResults) {
1938
+ addResult(result, 'recent');
1939
+ }
1940
+ // Add keyword results last
1941
+ for (const result of keywordResults) {
1942
+ addResult(result, 'keyword');
1943
+ }
1944
+ // REACTIVE DEDUPE: Delete duplicates from DB asynchronously
1945
+ // MED-42 FIX: Delay deletion by 30 seconds to allow drilldown on results before deletion
1946
+ // This prevents race condition where user tries to drill_down on a memory that was just deleted
1947
+ if (duplicateIds.length > 0) {
1948
+ logger.info({ count: duplicateIds.length, delaySeconds: 30 }, '[REACTIVE DEDUPE] Queuing content duplicates for cleanup (30s delay)');
1949
+ setTimeout(() => {
1950
+ this.cleanupDuplicates(duplicateIds).catch(err => {
1951
+ logger.warn({ error: err }, '[REACTIVE DEDUPE] Failed to cleanup duplicates');
1952
+ });
1953
+ }, 30000); // 30 second delay before deletion
1954
+ }
1955
+ // Sort by similarity (descending) and take limit
1956
+ return merged
1957
+ .sort((a, b) => b.similarity - a.similarity)
1958
+ .slice(0, limit);
1959
+ }
1960
+ /**
1961
+ * REACTIVE DEDUPE: Delete duplicate memories from database
1962
+ * PROJECT ISOLATED: Only deletes from current project
1963
+ * Called asynchronously when content duplicates are detected in search results
1964
+ */
1965
+ async cleanupDuplicates(ids) {
1966
+ if (ids.length === 0)
1967
+ return;
1968
+ try {
1969
+ const projectPath = getProjectPathForInsert();
1970
+ const result = await this.db.query(`DELETE FROM memories WHERE id = ANY($1::uuid[]) AND project_path = $2 RETURNING id`, [ids, projectPath]);
1971
+ logger.info({
1972
+ requested: ids.length,
1973
+ deleted: result.rowCount,
1974
+ projectPath
1975
+ }, '[REACTIVE DEDUPE] Duplicates cleaned from DB');
1976
+ }
1977
+ catch (error) {
1978
+ logger.error({ error, ids }, '[REACTIVE DEDUPE] Failed to delete duplicates');
1979
+ }
1980
+ }
1981
+ /**
1982
+ * hybridSearch - combines semantic + full-text search
1983
+ *
1984
+ * best of both worlds - vector similarity for meaning
1985
+ * plus full-text search for exact matches
1986
+ */
1987
+ async hybridSearch(params, queryEmbedding) {
1988
+ const limit = params.limit ?? 10;
1989
+ // NOTE: Default 0.35 filters out noise while catching real matches
1990
+ const threshold = params.threshold ?? 0.35;
1991
+ // CROSS-PROJECT SUPPORT: Build project condition
1992
+ const allProjects = params.allProjects === true;
1993
+ const targetProject = params.projectPath || getProjectContext().getProjectPath();
1994
+ // Build project filter clause (empty if allProjects)
1995
+ const projectClause = allProjects ? '' : 'AND project_path = $3';
1996
+ // semantic search component - with optional project filter
1997
+ const semanticQuery = `
1998
+ SELECT
1999
+ id, content, memory_type, importance, tags, metadata,
2000
+ embedding, created_at, updated_at, access_count, last_accessed_at,
2001
+ 1 - (embedding <=> $1::vector) AS similarity,
2002
+ 0.7 AS weight
2003
+ FROM memories
2004
+ WHERE embedding IS NOT NULL
2005
+ AND (expires_at IS NULL OR expires_at > NOW())
2006
+ ${projectClause}
2007
+ AND 1 - (embedding <=> $1::vector) >= ${threshold}
2008
+ `;
2009
+ // full-text search component - with optional project filter
2010
+ const ftsQuery = `
2011
+ SELECT
2012
+ id, content, memory_type, importance, tags, metadata,
2013
+ embedding, created_at, updated_at, access_count, last_accessed_at,
2014
+ ts_rank(content_tsv, plainto_tsquery('english', $2)) AS similarity,
2015
+ 0.3 AS weight
2016
+ FROM memories
2017
+ WHERE content_tsv @@ plainto_tsquery('english', $2)
2018
+ AND (expires_at IS NULL OR expires_at > NOW())
2019
+ ${projectClause}
2020
+ `;
2021
+ // combine and dedupe - semantic results get priority
2022
+ // NOTE: Using ON instead of USING to avoid vector type comparison issues
2023
+ const combinedQuery = `
2024
+ WITH semantic AS (${semanticQuery}),
2025
+ fts AS (${ftsQuery})
2026
+ SELECT DISTINCT ON (COALESCE(s.id, f.id))
2027
+ COALESCE(s.id, f.id) AS id,
2028
+ COALESCE(s.content, f.content) AS content,
2029
+ COALESCE(s.memory_type, f.memory_type) AS memory_type,
2030
+ COALESCE(s.importance, f.importance) AS importance,
2031
+ COALESCE(s.tags, f.tags) AS tags,
2032
+ COALESCE(s.metadata, f.metadata) AS metadata,
2033
+ COALESCE(s.embedding, f.embedding) AS embedding,
2034
+ COALESCE(s.created_at, f.created_at) AS created_at,
2035
+ COALESCE(s.updated_at, f.updated_at) AS updated_at,
2036
+ COALESCE(s.access_count, f.access_count) AS access_count,
2037
+ COALESCE(s.last_accessed_at, f.last_accessed_at) AS last_accessed_at,
2038
+ COALESCE(s.similarity * s.weight, 0) + COALESCE(f.similarity * f.weight, 0) AS similarity
2039
+ FROM semantic s
2040
+ FULL OUTER JOIN fts f ON s.id = f.id
2041
+ ORDER BY COALESCE(s.id, f.id), similarity DESC
2042
+ LIMIT ${limit}
2043
+ `;
2044
+ // Build query params - include projectPath only if not searching all projects
2045
+ const queryParams = allProjects
2046
+ ? [`[${queryEmbedding.join(',')}]`, params.query]
2047
+ : [`[${queryEmbedding.join(',')}]`, params.query, targetProject];
2048
+ const result = await this.db.query(combinedQuery, queryParams);
2049
+ // Apply Chinese Compactor approach
2050
+ const compactionOpts = {
2051
+ summarize: params.summarize,
2052
+ maxContentLength: params.maxContentLength
2053
+ };
2054
+ return result.rows.map((row) => this.rowToSearchResult(row, compactionOpts));
2055
+ }
2056
+ /**
2057
+ * update access counts for returned memories
2058
+ *
2059
+ * helps with relevance scoring over time
2060
+ */
2061
+ async updateAccessCounts(memoryIds) {
2062
+ try {
2063
+ await this.db.query(`UPDATE memories
2064
+ SET access_count = access_count + 1,
2065
+ last_accessed_at = NOW()
2066
+ WHERE id = ANY($1::uuid[])`, [memoryIds]);
2067
+ }
2068
+ catch (error) {
2069
+ // non-critical, just log it
2070
+ logger.warn({ error }, 'failed to update access counts');
2071
+ }
2072
+ }
2073
+ /**
2074
+ * Record access patterns for hot path tracking
2075
+ *
2076
+ * When memories are accessed together, we track the transition
2077
+ * to build up hot paths that can be predicted/prefetched
2078
+ */
2079
+ async recordAccessPatterns(memoryIds) {
2080
+ if (memoryIds.length < 2)
2081
+ return;
2082
+ try {
2083
+ // Lazy initialize hot path manager
2084
+ if (!this.hotPathManager) {
2085
+ try {
2086
+ this.hotPathManager = getHotPathManager(this.db.pool);
2087
+ }
2088
+ catch {
2089
+ // If hot path manager isn't initialized yet, skip
2090
+ return;
2091
+ }
2092
+ }
2093
+ // Record each memory access in sequence
2094
+ for (const memoryId of memoryIds) {
2095
+ await this.hotPathManager.recordAccess(memoryId);
2096
+ }
2097
+ }
2098
+ catch (error) {
2099
+ // Non-critical - just log
2100
+ logger.debug({ error }, 'hot path recording failed (tables may not exist yet)');
2101
+ }
2102
+ }
2103
+ /**
2104
+ * highlight matching content
2105
+ *
2106
+ * shows context around matches for better UX
2107
+ */
2108
+ getHighlights(content, query) {
2109
+ const highlights = [];
2110
+ const words = query.toLowerCase().split(/\s+/).filter(w => w.length > 2);
2111
+ const contentLower = content.toLowerCase();
2112
+ for (const word of words) {
2113
+ const index = contentLower.indexOf(word);
2114
+ if (index !== -1) {
2115
+ const start = Math.max(0, index - 50);
2116
+ const end = Math.min(content.length, index + word.length + 50);
2117
+ let highlight = content.substring(start, end);
2118
+ if (start > 0)
2119
+ highlight = '...' + highlight;
2120
+ if (end < content.length)
2121
+ highlight = highlight + '...';
2122
+ highlights.push(highlight);
2123
+ }
2124
+ }
2125
+ return highlights.slice(0, 3); // max 3 highlights
2126
+ }
2127
+ /**
2128
+ * Create search result with AGGRESSIVE content compaction
2129
+ * Uses Chinese Compactor for token savings + truncation for drill-down
2130
+ *
2131
+ * When summarize=true (DEFAULT): Returns MINIMAL structure for drill-down decision
2132
+ * When summarize=false: Returns full Memory object
2133
+ */
2134
+ rowToSearchResult(row, opts = {}) {
2135
+ let content = row.content;
2136
+ let contentTruncated = false;
2137
+ const originalLength = row.content.length;
2138
+ // STEP 1: Truncate first - User feedback: "content wayyy too trimmed"
2139
+ const summarize = opts.summarize !== false; // Default TRUE
2140
+ const maxLen = opts.maxContentLength ?? 1000; // Was 500 - doubled for more context
2141
+ if (maxLen > 0 && content.length > maxLen) {
2142
+ content = content.substring(0, maxLen) + '...';
2143
+ contentTruncated = true;
2144
+ }
2145
+ // STEP 2: Apply Chinese compression for additional token savings
2146
+ // Only compress if content is long enough to benefit
2147
+ let compressionRatio = 1.0;
2148
+ if (content.length > 50) {
2149
+ const compressed = smartCompress(content, {
2150
+ threshold: 0.80, // Allow slightly lossy for big savings
2151
+ minLength: 30
2152
+ });
2153
+ content = compressed.result;
2154
+ compressionRatio = compressed.compressionRatio;
2155
+ }
2156
+ // DRILL-DOWN MODE: Return minimal but MEANINGFUL structure when summarize=true
2157
+ // Key: Show ACTUAL CONTENT preview, not just IDs and metadata!
2158
+ if (summarize) {
2159
+ // Extract the most meaningful part of content (skip metadata-looking text)
2160
+ const meaningfulContent = this.extractMeaningfulContent(content, maxLen);
2161
+ // Create a semantic summary in Traditional Chinese for token efficiency
2162
+ const semanticHint = this.createSemanticHint(row, meaningfulContent);
2163
+ const memory = {
2164
+ id: row.id,
2165
+ // CRITICAL: Show actual meaningful content, not just truncated raw text
2166
+ content: meaningfulContent,
2167
+ // Include semantic hint for understanding
2168
+ memoryType: row.memory_type,
2169
+ // Tags help understand context
2170
+ tags: row.tags.slice(0, 5),
2171
+ // Metadata: PRESERVE original (sessionId, timestamp, role) + add drill hints
2172
+ metadata: {
2173
+ ...row.metadata, // CRITICAL: Keep sessionId, timestamp, role for pairing!
2174
+ _preview: semanticHint, // Chinese-compressed semantic summary
2175
+ _drill: `get_memory({id: "${row.id}"})`,
2176
+ _fullLen: originalLength,
2177
+ _created: row.created_at ? new Date(row.created_at).toLocaleDateString() : undefined
2178
+ }
2179
+ };
2180
+ // MED-38 FIX: Include isFallback flag to indicate similarity is synthetic, not from semantic search
2181
+ return {
2182
+ memory,
2183
+ similarity: row.similarity,
2184
+ highlights: [],
2185
+ ...(row.is_fallback ? { isFallback: true, fallbackNote: 'Similarity score is synthetic (recent/keyword), not from semantic search' } : {})
2186
+ };
2187
+ }
2188
+ // FULL MODE: Return complete Memory object when summarize=false
2189
+ const memory = {
2190
+ id: row.id,
2191
+ content: content,
2192
+ memoryType: row.memory_type,
2193
+ importance: row.importance,
2194
+ tags: row.tags,
2195
+ metadata: {
2196
+ ...row.metadata,
2197
+ ...(contentTruncated ? {
2198
+ _truncated: true,
2199
+ _len: originalLength,
2200
+ _drill: `get_memory({id: "${row.id}"})`
2201
+ } : {}),
2202
+ ...(compressionRatio < 0.9 ? { _compressed: true } : {})
2203
+ },
2204
+ embedding: undefined, // NEVER return embeddings - huge token waste
2205
+ createdAt: row.created_at,
2206
+ updatedAt: row.updated_at,
2207
+ accessCount: row.access_count,
2208
+ lastAccessedAt: row.last_accessed_at ?? undefined
2209
+ };
2210
+ // MED-38 FIX: Include isFallback flag to indicate similarity is synthetic, not from semantic search
2211
+ return {
2212
+ memory,
2213
+ similarity: row.similarity,
2214
+ highlights: [],
2215
+ ...(row.is_fallback ? { isFallback: true, fallbackNote: 'Similarity score is synthetic (recent/keyword), not from semantic search' } : {})
2216
+ };
2217
+ }
2218
+ parseEmbedding(embeddingStr) {
2219
+ const cleaned = embeddingStr.replace(/[\[\]]/g, '');
2220
+ return cleaned.split(',').map(Number);
2221
+ }
2222
+ // ============================================================================
2223
+ // CONTEXT ENRICHMENT METHODS
2224
+ // Like human memory recall - fragment leads to connections leads to deeper recall
2225
+ // ============================================================================
2226
+ /**
2227
+ * Aggregate discoverable paths from all enriched results
2228
+ * Combines and deduplicates paths for a unified exploration map
2229
+ */
2230
+ aggregateDiscoverablePaths(results) {
2231
+ const aggregated = {
2232
+ filePaths: [],
2233
+ codeBlocks: [],
2234
+ urls: [],
2235
+ memoryRefs: [],
2236
+ technicalTerms: [],
2237
+ researchQuestions: []
2238
+ };
2239
+ for (const result of results) {
2240
+ if (!result._discoverable)
2241
+ continue;
2242
+ const paths = result._discoverable;
2243
+ aggregated.filePaths.push(...paths.filePaths);
2244
+ aggregated.codeBlocks.push(...paths.codeBlocks);
2245
+ aggregated.urls.push(...paths.urls);
2246
+ aggregated.memoryRefs.push(...paths.memoryRefs);
2247
+ aggregated.technicalTerms.push(...paths.technicalTerms);
2248
+ aggregated.researchQuestions.push(...paths.researchQuestions);
2249
+ }
2250
+ // Deduplicate
2251
+ aggregated.filePaths = [...new Set(aggregated.filePaths)].slice(0, 15);
2252
+ aggregated.urls = [...new Set(aggregated.urls)].slice(0, 10);
2253
+ aggregated.technicalTerms = [...new Set(aggregated.technicalTerms)].slice(0, 15);
2254
+ aggregated.researchQuestions = [...new Set(aggregated.researchQuestions)].slice(0, 5);
2255
+ return aggregated;
2256
+ }
2257
+ /**
2258
+ * Generate context enrichment summary
2259
+ * This is the KEY output that tells what to explore next
2260
+ * Uses Traditional Chinese for token efficiency
2261
+ */
2262
+ generateContextEnrichment(query, results, aggregatedPaths, drilldown) {
2263
+ const lines = [];
2264
+ // Header with query context (Chinese compacted)
2265
+ lines.push(`<specmem-context query="${query}">`);
2266
+ lines.push(` 記憶召回: ${results.length}條 | ${drilldown.prompt}`);
2267
+ // Discoverable exploration paths
2268
+ if (aggregatedPaths.filePaths.length > 0) {
2269
+ lines.push(` 📁 可探索文件(${aggregatedPaths.filePaths.length}):`);
2270
+ for (const path of aggregatedPaths.filePaths.slice(0, 5)) {
2271
+ lines.push(` → ${path}`);
2272
+ }
2273
+ if (aggregatedPaths.filePaths.length > 5) {
2274
+ lines.push(` ... +${aggregatedPaths.filePaths.length - 5}個文件`);
2275
+ }
2276
+ }
2277
+ if (aggregatedPaths.codeBlocks.length > 0) {
2278
+ const langs = [...new Set(aggregatedPaths.codeBlocks.map(c => c.language))];
2279
+ lines.push(` 💻 代碼塊(${aggregatedPaths.codeBlocks.length}): ${langs.join(', ')}`);
2280
+ // Show first code block preview
2281
+ const first = aggregatedPaths.codeBlocks[0];
2282
+ if (first.possiblePath) {
2283
+ lines.push(` → 可能來源: ${first.possiblePath}`);
2284
+ }
2285
+ }
2286
+ if (aggregatedPaths.technicalTerms.length > 0) {
2287
+ lines.push(` 🔧 技術概念: ${aggregatedPaths.technicalTerms.slice(0, 8).join(', ')}`);
2288
+ }
2289
+ if (aggregatedPaths.urls.length > 0) {
2290
+ lines.push(` 🔗 相關URL(${aggregatedPaths.urls.length}): 可WebFetch研究`);
2291
+ }
2292
+ // Research suggestions
2293
+ if (drilldown.needsResearch || aggregatedPaths.researchQuestions.length > 0) {
2294
+ lines.push(` ❓ 研究建議:`);
2295
+ if (drilldown.needsResearch) {
2296
+ lines.push(` → 本地記憶不足,建議WebSearch: "${query}"`);
2297
+ }
2298
+ for (const q of aggregatedPaths.researchQuestions.slice(0, 2)) {
2299
+ lines.push(` → ${q}`);
2300
+ }
2301
+ }
2302
+ // Drilldown action hint
2303
+ if (drilldown.action !== 'none') {
2304
+ lines.push(` 🎯 建議操作: ${this.formatDrilldownAction(drilldown.action)}`);
2305
+ }
2306
+ lines.push(`</specmem-context>`);
2307
+ return lines.join('\n');
2308
+ }
2309
+ /**
2310
+ * Format drilldown action as Chinese instruction
2311
+ */
2312
+ formatDrilldownAction(action) {
2313
+ const actions = {
2314
+ 'drilldown:deeper': '深入搜索 - 使用get_memory獲取完整內容',
2315
+ 'drilldown:broader': '擴大搜索 - 嘗試相關詞或增加limit',
2316
+ 'drilldown:filter': '過濾結果 - 添加memoryTypes或tags參數',
2317
+ 'research:web': '網絡研究 - 使用WebSearch獲取最新資訊',
2318
+ 'none': '記憶足夠'
2319
+ };
2320
+ return actions[action] || action;
2321
+ }
2322
+ /**
2323
+ * Generate context for empty results
2324
+ * Guides on what to do when no memories match
2325
+ */
2326
+ generateEmptyResultContext(query, drilldown) {
2327
+ return `<specmem-context query="${query}">
2328
+ ⚠️ 無匹配記憶
2329
+ ${drilldown.prompt}
2330
+
2331
+ 建議操作:
2332
+ 1. WebSearch "${query}" - 獲取外部資訊
2333
+ 2. 調整查詢 - 嘗試不同關鍵詞
2334
+ 3. 檢查拼寫 - 確保查詢正確
2335
+ 4. 擴大範圍 - 移除過濾條件
2336
+ </specmem-context>`;
2337
+ }
2338
+ /**
2339
+ * Generate research spawn instructions
2340
+ * These instructions tell how to spawn a research team member
2341
+ * when local memory is insufficient
2342
+ */
2343
+ generateResearchSpawnInstructions(query, aggregatedPaths) {
2344
+ const hasCodePaths = aggregatedPaths.filePaths.length > 0 || aggregatedPaths.codeBlocks.length > 0;
2345
+ const hasResearchQuestions = aggregatedPaths.researchQuestions.length > 0;
2346
+ const hasUrls = aggregatedPaths.urls.length > 0;
2347
+ // Determine research type
2348
+ let researchType = 'web';
2349
+ if (hasCodePaths && (hasResearchQuestions || hasUrls)) {
2350
+ researchType = 'both';
2351
+ }
2352
+ else if (hasCodePaths) {
2353
+ researchType = 'code';
2354
+ }
2355
+ // Build task prompt for the research team member
2356
+ const taskParts = [];
2357
+ if (researchType === 'code' || researchType === 'both') {
2358
+ taskParts.push(`探索代碼路徑: ${aggregatedPaths.filePaths.slice(0, 3).join(', ')}`);
2359
+ if (aggregatedPaths.technicalTerms.length > 0) {
2360
+ taskParts.push(`技術概念: ${aggregatedPaths.technicalTerms.slice(0, 5).join(', ')}`);
2361
+ }
2362
+ }
2363
+ if (researchType === 'web' || researchType === 'both') {
2364
+ if (hasResearchQuestions) {
2365
+ taskParts.push(`研究問題: ${aggregatedPaths.researchQuestions.slice(0, 2).join('; ')}`);
2366
+ }
2367
+ else {
2368
+ taskParts.push(`WebSearch查詢: "${query}"`);
2369
+ }
2370
+ if (hasUrls) {
2371
+ taskParts.push(`可WebFetch的URL: ${aggregatedPaths.urls.length}個`);
2372
+ }
2373
+ }
2374
+ // Context for the research team member (Chinese compacted)
2375
+ const contextForTeamMember = `<specmem-research-context>
2376
+ 原始查詢: "${query}"
2377
+ 研究類型: ${researchType}
2378
+ ${taskParts.map(p => ` ${p}`).join('\n')}
2379
+
2380
+ 指示:
2381
+ - 收集相關資訊後,使用save_memory保存重要發現
2382
+ - 研究完成後返回簡潔摘要
2383
+ - 使用傳統中文壓縮輸出以節省tokens
2384
+ </specmem-research-context>`;
2385
+ // Subteam member type based on research needs
2386
+ const subteamMemberType = researchType === 'code' ? 'Explore' : 'general-purpose';
2387
+ // Task prompt for spawning
2388
+ const taskPrompt = researchType === 'code'
2389
+ ? `探索SpecMem代碼庫以理解: ${query}\n重點文件: ${aggregatedPaths.filePaths.slice(0, 3).join(', ')}`
2390
+ : `研究: ${query}\n${hasResearchQuestions ? `問題: ${aggregatedPaths.researchQuestions[0]}` : '使用WebSearch獲取最新資訊'}`;
2391
+ return {
2392
+ shouldSpawnResearch: true,
2393
+ researchType,
2394
+ taskPrompt,
2395
+ subteamMemberType,
2396
+ contextForTeamMember
2397
+ };
2398
+ }
2399
+ /**
2400
+ * Extract meaningful preview from content
2401
+ * Avoids showing just metadata like session IDs and timestamps
2402
+ */
2403
+ extractMeaningfulPreview(content) {
2404
+ // Skip metadata-looking lines (session IDs, timestamps, etc.)
2405
+ const lines = content.split('\n');
2406
+ let meaningfulLine = '';
2407
+ for (const line of lines) {
2408
+ const trimmed = line.trim();
2409
+ // Skip empty lines
2410
+ if (!trimmed)
2411
+ continue;
2412
+ // Skip lines that look like metadata
2413
+ if (/^(session|memory|created|id|timestamp|metadata)[:=]/i.test(trimmed))
2414
+ continue;
2415
+ if (/^[a-f0-9-]{36}$/i.test(trimmed))
2416
+ continue; // UUIDs
2417
+ if (/^\d{4}-\d{2}-\d{2}/.test(trimmed))
2418
+ continue; // Dates
2419
+ // Found a meaningful line
2420
+ meaningfulLine = trimmed;
2421
+ break;
2422
+ }
2423
+ // Truncate to 60 chars
2424
+ if (meaningfulLine.length > 60) {
2425
+ meaningfulLine = meaningfulLine.substring(0, 57) + '...';
2426
+ }
2427
+ return meaningfulLine || content.substring(0, 50) + '...';
2428
+ }
2429
+ /**
2430
+ * Extract meaningful content, skipping metadata-looking lines
2431
+ * Returns actual content can understand and drill down on
2432
+ */
2433
+ extractMeaningfulContent(content, maxLen) {
2434
+ const lines = content.split('\n');
2435
+ const meaningfulLines = [];
2436
+ let charCount = 0;
2437
+ // Patterns that indicate metadata (should skip)
2438
+ const metadataPatterns = [
2439
+ /^session[_\s-]?id[:=\s]/i,
2440
+ /^memory[_\s-]?id[:=\s]/i,
2441
+ /^created[_\s-]?at[:=\s]/i,
2442
+ /^updated[_\s-]?at[:=\s]/i,
2443
+ /^timestamp[:=\s]/i,
2444
+ /^id[:=\s]/i,
2445
+ /^uuid[:=\s]/i,
2446
+ /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i, // UUID only line
2447
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/, // ISO timestamp only line
2448
+ /^metadata[:=\s]*\{/i,
2449
+ /^tags[:=\s]*\[/i,
2450
+ ];
2451
+ for (const line of lines) {
2452
+ const trimmed = line.trim();
2453
+ if (!trimmed)
2454
+ continue;
2455
+ // Skip metadata lines
2456
+ let isMetadata = false;
2457
+ for (const pattern of metadataPatterns) {
2458
+ if (pattern.test(trimmed)) {
2459
+ isMetadata = true;
2460
+ break;
2461
+ }
2462
+ }
2463
+ if (isMetadata)
2464
+ continue;
2465
+ // Add meaningful line
2466
+ meaningfulLines.push(trimmed);
2467
+ charCount += trimmed.length;
2468
+ // Stop if we have enough
2469
+ if (charCount >= maxLen)
2470
+ break;
2471
+ }
2472
+ // If we found meaningful content, use it
2473
+ if (meaningfulLines.length > 0) {
2474
+ let result = meaningfulLines.join('\n');
2475
+ if (result.length > maxLen) {
2476
+ result = result.substring(0, maxLen - 3) + '...';
2477
+ }
2478
+ return result;
2479
+ }
2480
+ // Fallback: just use first maxLen chars
2481
+ return content.length > maxLen ? content.substring(0, maxLen - 3) + '...' : content;
2482
+ }
2483
+ /**
2484
+ * Create a semantic hint in Traditional Chinese for token efficiency
2485
+ * This gives a quick understanding of what the memory is about
2486
+ */
2487
+ createSemanticHint(row, content) {
2488
+ const parts = [];
2489
+ // Memory type in Chinese
2490
+ const typeMap = {
2491
+ 'episodic': '情節記憶', // Episode/event memory
2492
+ 'semantic': '語義記憶', // Factual/knowledge memory
2493
+ 'procedural': '程序記憶', // How-to memory
2494
+ 'working': '工作記憶', // Temporary/active memory
2495
+ 'consolidated': '長期記憶' // Consolidated/important memory
2496
+ };
2497
+ const memType = typeMap[row.memory_type] || row.memory_type;
2498
+ parts.push(`類型:${memType}`);
2499
+ // Importance in Chinese
2500
+ const importanceMap = {
2501
+ 'critical': '🔴關鍵',
2502
+ 'high': '🟠重要',
2503
+ 'medium': '🟡一般',
2504
+ 'low': '🟢低',
2505
+ 'trivial': '⚪微'
2506
+ };
2507
+ const imp = importanceMap[row.importance] || row.importance;
2508
+ parts.push(`重要:${imp}`);
2509
+ // Extract key topic from content (first sentence or 50 chars)
2510
+ const firstSentence = content.split(/[.!?。!?\n]/)[0]?.trim() || content;
2511
+ const topic = firstSentence.length > 50 ? firstSentence.substring(0, 47) + '...' : firstSentence;
2512
+ parts.push(`主題:${topic}`);
2513
+ // Tags if present (max 3)
2514
+ if (row.tags && row.tags.length > 0) {
2515
+ const tagStr = row.tags.slice(0, 3).join(',');
2516
+ parts.push(`標籤:${tagStr}`);
2517
+ }
2518
+ return parts.join(' | ');
2519
+ }
2520
+ /**
2521
+ * Extract keywords from query for related searches
2522
+ */
2523
+ extractKeywords(query) {
2524
+ // Remove stop words and get meaningful terms
2525
+ const stopWords = new Set(['the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
2526
+ 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should',
2527
+ 'may', 'might', 'must', 'shall', 'can', 'need', 'to', 'of', 'in', 'for', 'on',
2528
+ 'with', 'at', 'by', 'from', 'as', 'into', 'through', 'during', 'before', 'after',
2529
+ 'above', 'below', 'between', 'under', 'again', 'further', 'then', 'once', 'here',
2530
+ 'there', 'when', 'where', 'why', 'how', 'all', 'each', 'few', 'more', 'most',
2531
+ 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than',
2532
+ 'too', 'very', 'just', 'and', 'but', 'if', 'or', 'because', 'until', 'while',
2533
+ 'about', 'what', 'which', 'who', 'this', 'that', 'these', 'those', 'it', 'its']);
2534
+ const words = query.toLowerCase().split(/\s+/);
2535
+ const keywords = words.filter(w => w.length > 2 && !stopWords.has(w));
2536
+ // Return unique keywords
2537
+ return [...new Set(keywords)];
2538
+ }
2539
+ static getStats() {
2540
+ return {
2541
+ searchCount: _searchCount,
2542
+ totalSearchTime: _totalSearchTime,
2543
+ averageSearchTime: _searchCount > 0 ? _totalSearchTime / _searchCount : 0
2544
+ };
2545
+ }
2546
+ }
2547
+ //# sourceMappingURL=findWhatISaid.js.map