squish-memory 1.1.5 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (646) hide show
  1. package/.env.example +32 -16
  2. package/CHANGELOG.md +147 -0
  3. package/README.md +120 -78
  4. package/{scripts → bin}/dependency-manager.mjs +217 -217
  5. package/{scripts → bin}/detect-clients.mjs +78 -78
  6. package/bin/install-interactive.mjs +321 -0
  7. package/bin/squish-mcp.mjs +44 -0
  8. package/bin/squish.mjs +33 -0
  9. package/config/mcp-migration-map.json +1 -6
  10. package/config/mcp-mode-semantics.json +19 -23
  11. package/config/mcp-remote-auth.json +3 -26
  12. package/config/mcp-universal.schema.json +5 -35
  13. package/config/settings.json +107 -52
  14. package/config.js +5 -0
  15. package/config.ts +218 -0
  16. package/core/adapters/config/claude-code.ts +133 -0
  17. package/core/adapters/config/cursor.ts +90 -0
  18. package/core/adapters/config/opencode.ts +89 -0
  19. package/core/adapters/config/windsurf.ts +90 -0
  20. package/core/adapters/index.ts +102 -0
  21. package/core/adapters/timeline.ts +116 -0
  22. package/core/adapters/types.ts +166 -0
  23. package/core/agent-preferences.ts +140 -0
  24. package/core/algorithms/analytics/token-estimator.ts +216 -0
  25. package/core/algorithms/detection/hash-filters.ts +260 -0
  26. package/core/algorithms/detection/semantic-ranker.ts +194 -0
  27. package/core/algorithms/detection/two-stage-detector.ts +421 -0
  28. package/core/algorithms/handlers/approve-merge.ts +215 -0
  29. package/core/algorithms/handlers/detect-duplicates.ts +192 -0
  30. package/core/algorithms/handlers/get-stats.ts +132 -0
  31. package/core/algorithms/handlers/list-proposals.ts +130 -0
  32. package/core/algorithms/handlers/preview-merge.ts +139 -0
  33. package/core/algorithms/handlers/reject-merge.ts +93 -0
  34. package/core/algorithms/handlers/reverse-merge.ts +155 -0
  35. package/{dist/core/algorithms/index.js → core/algorithms/index.ts} +39 -26
  36. package/core/algorithms/operations/cache-maintenance.ts +182 -0
  37. package/core/algorithms/safety/safety-checks.ts +256 -0
  38. package/core/algorithms/strategies/merge-strategies.ts +381 -0
  39. package/core/algorithms/types.ts +140 -0
  40. package/core/algorithms/utils/response-builder.ts +61 -0
  41. package/core/associations.ts +363 -0
  42. package/core/beliefs/decay.ts +289 -0
  43. package/core/beliefs/extractor.ts +131 -0
  44. package/core/beliefs/store.ts +557 -0
  45. package/core/beliefs/types.ts +38 -0
  46. package/core/commands/mcp-server.ts +5 -0
  47. package/core/compression.ts +177 -0
  48. package/core/config.js +2 -0
  49. package/core/consolidation.ts +330 -0
  50. package/core/context/agent-context.ts +388 -0
  51. package/core/context/context-paging.ts +449 -0
  52. package/core/context/context-window.ts +234 -0
  53. package/core/context/context.ts +35 -0
  54. package/core/embeddings/embeddings.ts +616 -0
  55. package/core/embeddings/google-multimodal.ts +200 -0
  56. package/{dist/core/local-embeddings.js → core/embeddings/local-embeddings.ts} +12 -11
  57. package/core/embeddings/qmd-client.ts +495 -0
  58. package/core/embeddings/transformers-local.ts +261 -0
  59. package/core/embeddings.js +4 -0
  60. package/core/error-handling.ts +206 -0
  61. package/core/external +219 -0
  62. package/core/graph/entity-deduplicator.ts +232 -0
  63. package/core/graph/graph-builder.ts +257 -0
  64. package/core/graph/graph-traversal.ts +490 -0
  65. package/core/graph/index.ts +24 -0
  66. package/core/graph/llm-entity-extractor.ts +402 -0
  67. package/core/graph/multi-hop-retrieval.ts +317 -0
  68. package/core/graph/relationship-extractor.ts +465 -0
  69. package/core/hooks/agent-hooks.ts +653 -0
  70. package/core/hooks/auto-tagger.ts +149 -0
  71. package/core/hooks/capture-filter.ts +169 -0
  72. package/core/hot-cache.ts +388 -0
  73. package/core/index.ts +10 -0
  74. package/core/ingestion/agent-memory.ts +167 -0
  75. package/core/ingestion/core-memory.ts +326 -0
  76. package/core/ingestion/learnings.ts +260 -0
  77. package/core/ingestion/signal-engine.ts +266 -0
  78. package/core/integrations/obsidian-vault.ts +197 -0
  79. package/core/layers/generator.ts +115 -0
  80. package/{dist/core/lib/db-client.d.ts → core/lib/db-client.ts} +168 -114
  81. package/core/lib/parse-embedding.ts +59 -0
  82. package/{dist/core/lib/schemas.js → core/lib/schemas.ts} +102 -87
  83. package/core/lib/types.ts +49 -0
  84. package/core/lib/utils.ts +151 -0
  85. package/core/lib/validation.ts +180 -0
  86. package/core/lifecycle.ts +353 -0
  87. package/core/logger.ts +59 -0
  88. package/core/memory/bridge-discovery.ts +395 -0
  89. package/core/memory/categorizer.ts +390 -0
  90. package/core/memory/conflict-detector.ts +62 -0
  91. package/core/memory/consolidation.ts +372 -0
  92. package/core/memory/context-collector.ts +75 -0
  93. package/core/memory/contradiction-resolver.ts +494 -0
  94. package/core/memory/edit-workflow.ts +174 -0
  95. package/core/memory/entity-extractor.ts +426 -0
  96. package/core/memory/entity-resolver.ts +89 -0
  97. package/core/memory/explain.ts +112 -0
  98. package/core/memory/fact-deriver.ts +300 -0
  99. package/core/memory/fact-extractor.ts +120 -0
  100. package/core/memory/feedback-tracker.ts +200 -0
  101. package/core/memory/hooks.ts +230 -0
  102. package/core/memory/hybrid-retrieval.ts +65 -0
  103. package/core/memory/hybrid-scorer.ts +325 -0
  104. package/core/memory/hybrid-search.ts +748 -0
  105. package/core/memory/importance.ts +319 -0
  106. package/{dist/core/memory/index.js → core/memory/index.ts} +11 -10
  107. package/core/memory/loader.ts +178 -0
  108. package/core/memory/markdown/markdown-storage.ts +318 -0
  109. package/core/memory/memories.ts +565 -0
  110. package/core/memory/memory-lifecycle.ts +51 -0
  111. package/core/memory/memory-manager.ts +53 -0
  112. package/core/memory/migrate.ts +173 -0
  113. package/core/memory/normalization.ts +30 -0
  114. package/core/memory/path-strengthener.ts +211 -0
  115. package/core/memory/progressive-disclosure.ts +392 -0
  116. package/core/memory/query-processor.ts +130 -0
  117. package/core/memory/query-rewriter.ts +153 -0
  118. package/core/memory/response-analyzer.ts +81 -0
  119. package/core/memory/retrieval-feedback.ts +276 -0
  120. package/core/memory/serialization.ts +83 -0
  121. package/core/memory/stale-cleaner.ts +147 -0
  122. package/core/memory/stats.ts +181 -0
  123. package/core/memory/telemetry.ts +392 -0
  124. package/core/memory/temporal-facts.ts +356 -0
  125. package/core/memory/temporal-parser.ts +477 -0
  126. package/core/memory/trigger-detector.ts +104 -0
  127. package/core/memory/write-gate.ts +288 -0
  128. package/{dist/core/places/index.js → core/places/index.ts} +12 -12
  129. package/core/places/memory-places.ts +339 -0
  130. package/core/places/places.ts +406 -0
  131. package/core/places/rules.ts +308 -0
  132. package/core/places/walking.ts +192 -0
  133. package/core/projects +89 -0
  134. package/core/projects.ts +131 -0
  135. package/core/redis.ts +82 -0
  136. package/core/responses.ts +187 -0
  137. package/core/runtime/trust-report.ts +195 -0
  138. package/core/runtime/trust-state.ts +360 -0
  139. package/core/scheduler/cron-scheduler.ts +590 -0
  140. package/core/scheduler/heartbeat.ts +91 -0
  141. package/{dist/core/scheduler/index.js → core/scheduler/index.ts} +8 -8
  142. package/core/scheduler/job-runner.ts +197 -0
  143. package/core/search/conversations.ts +166 -0
  144. package/core/search/entities.ts +46 -0
  145. package/core/search/folder-context.ts +154 -0
  146. package/core/search/graph-boost.ts +22 -0
  147. package/{dist/core/search/index.js → core/search/index.ts} +4 -5
  148. package/core/search/qmd-wrapper.ts +84 -0
  149. package/core/security/encrypt.ts +51 -0
  150. package/core/security/governance.ts +102 -0
  151. package/core/security/privacy.ts +108 -0
  152. package/core/security/secret-detector.ts +122 -0
  153. package/core/session/auto-load.ts +160 -0
  154. package/core/session/entity-tracker.ts +363 -0
  155. package/{dist/core/session/index.js → core/session/index.ts} +7 -7
  156. package/core/session/reference-resolver.ts +158 -0
  157. package/core/session/self-iteration-job.ts +478 -0
  158. package/core/session/session-hooks.ts +69 -0
  159. package/core/session/types.ts +36 -0
  160. package/core/session/working-set.ts +275 -0
  161. package/{dist/core/snapshots/cleanup.js → core/snapshots/cleanup.ts} +13 -12
  162. package/core/snapshots/comparison.ts +59 -0
  163. package/core/snapshots/creation.ts +139 -0
  164. package/core/snapshots/retrieval.ts +44 -0
  165. package/core/snapshots/stats.ts +63 -0
  166. package/core/storage/cache.ts +241 -0
  167. package/core/storage/database.ts +23 -0
  168. package/{dist/core/summarization/cleanup.js → core/summarization/cleanup.ts} +13 -12
  169. package/core/summarization/queries.ts +32 -0
  170. package/core/summarization/stats.ts +64 -0
  171. package/core/summarization/strategies.ts +52 -0
  172. package/core/summarization.ts +248 -0
  173. package/core/temporal-facts.ts +244 -0
  174. package/core/tracing/collector.ts +470 -0
  175. package/core/tracing/visualizer.ts +195 -0
  176. package/core/utils/cleanup-operations.ts +50 -0
  177. package/core/utils/content-extraction.ts +95 -0
  178. package/core/utils/filter-builder.ts +56 -0
  179. package/core/utils/history-traversal.ts +63 -0
  180. package/core/utils/memory-operations.ts +56 -0
  181. package/core/utils/query-operations.ts +83 -0
  182. package/core/utils/summarization-helpers.ts +45 -0
  183. package/core/utils/temporal-queries.ts +39 -0
  184. package/{dist/core/utils/vector-operations.js → core/utils/vector-operations.ts} +135 -129
  185. package/core/utils/version-management.ts +74 -0
  186. package/core/worker.ts +333 -0
  187. package/db/adapter.ts +215 -0
  188. package/{dist/db/bootstrap.js → db/bootstrap.ts} +388 -418
  189. package/db/drizzle/migrations/0000_needy_cerebro.sql +402 -0
  190. package/db/drizzle/migrations/meta/0000_snapshot.json +3451 -0
  191. package/db/drizzle/migrations/meta/_journal.json +13 -0
  192. package/db/drizzle/schema-sqlite.ts +1032 -0
  193. package/db/drizzle/schema.ts +1128 -0
  194. package/db/drizzle.config.ts +12 -0
  195. package/db/index.ts +83 -0
  196. package/db/init.sql +5 -0
  197. package/db/migrations/associations.ts +35 -0
  198. package/db/migrations/beliefs.ts +89 -0
  199. package/db/migrations/core-memory.ts +35 -0
  200. package/db/migrations/fts.ts +59 -0
  201. package/db/migrations/index.ts +54 -0
  202. package/db/migrations/indexes.ts +36 -0
  203. package/db/migrations/learnings.ts +34 -0
  204. package/db/migrations/maintenance.ts +68 -0
  205. package/db/migrations/memories.ts +22 -0
  206. package/db/migrations/memory-places.ts +35 -0
  207. package/db/migrations/places.ts +49 -0
  208. package/db/migrations/projects.ts +21 -0
  209. package/db/migrations/tier-conversion.ts +24 -0
  210. package/db/neon.ts +22 -0
  211. package/db/schema/beliefs.ts +50 -0
  212. package/db/schema/generator.ts +159 -0
  213. package/db/schema/index.ts +58 -0
  214. package/db/schema/learnings.ts +32 -0
  215. package/db/schema/memories.ts +83 -0
  216. package/db/schema/projects.ts +33 -0
  217. package/db/schema.ts +13 -0
  218. package/db/supabase.ts +27 -0
  219. package/mcp.json.example +8 -11
  220. package/package.json +140 -159
  221. package/packages/cli/package.json +22 -0
  222. package/packages/cli/src/commands/clean.ts +68 -0
  223. package/packages/cli/src/commands/context.ts +79 -0
  224. package/packages/cli/src/commands/doctor.ts +357 -0
  225. package/packages/cli/src/commands/forget.ts +72 -0
  226. package/packages/cli/src/commands/health.ts +36 -0
  227. package/packages/cli/src/commands/inspect.ts +41 -0
  228. package/packages/cli/src/commands/link.ts +50 -0
  229. package/packages/cli/src/commands/migrate.ts +93 -0
  230. package/packages/cli/src/commands/recall.ts +99 -0
  231. package/packages/cli/src/commands/recent.ts +57 -0
  232. package/packages/cli/src/commands/remember.ts +139 -0
  233. package/packages/cli/src/commands/run.ts +58 -0
  234. package/packages/cli/src/commands/stale.ts +43 -0
  235. package/packages/cli/src/commands/stats.ts +42 -0
  236. package/packages/cli/src/index.ts +57 -0
  237. package/packages/cli/tsconfig.json +24 -0
  238. package/packages/mcp/package.json +26 -0
  239. package/packages/mcp/src/index.ts +940 -0
  240. package/packages/mcp/tsconfig.json +20 -0
  241. package/skills/squish-memory/SKILL.md +38 -35
  242. package/skills/squish-memory/{scripts/install.sh → install.sh} +1 -1
  243. package/skills/squish-memory/references/claude-desktop.json +12 -0
  244. package/skills/squish-memory/references/openclaw.json +13 -0
  245. package/skills/squish-memory/references/opencode.json +14 -0
  246. package/config/hooks/claude-code-hooks.json +0 -39
  247. package/config/hooks/cursor-hooks.json +0 -30
  248. package/config/hooks/opencode-hooks.json +0 -30
  249. package/config/hooks/windsurf-hooks.json +0 -30
  250. package/config/mcp-cli-fallback-policy.json +0 -22
  251. package/config/mcp.json +0 -38
  252. package/config/plugin-manifest.json +0 -101
  253. package/config/plugin-manifest.schema.json +0 -244
  254. package/config/plugin.json +0 -32
  255. package/config/remote-memory-policy.json +0 -32
  256. package/core/commands/context-paging.md +0 -51
  257. package/core/commands/context-status.md +0 -22
  258. package/core/commands/context.md +0 -5
  259. package/core/commands/core-memory.md +0 -56
  260. package/core/commands/health.md +0 -5
  261. package/core/commands/init.md +0 -39
  262. package/core/commands/merge.md +0 -113
  263. package/core/commands/recall.md +0 -5
  264. package/core/commands/remember.md +0 -11
  265. package/core/commands/search.md +0 -10
  266. package/dist/config.d.ts +0 -83
  267. package/dist/config.js +0 -242
  268. package/dist/core/adapters/config/claude-code.d.ts +0 -45
  269. package/dist/core/adapters/config/claude-code.js +0 -113
  270. package/dist/core/adapters/config/cursor.d.ts +0 -26
  271. package/dist/core/adapters/config/cursor.js +0 -74
  272. package/dist/core/adapters/config/opencode.d.ts +0 -23
  273. package/dist/core/adapters/config/opencode.js +0 -73
  274. package/dist/core/adapters/config/windsurf.d.ts +0 -26
  275. package/dist/core/adapters/config/windsurf.js +0 -74
  276. package/dist/core/adapters/index.d.ts +0 -45
  277. package/dist/core/adapters/index.js +0 -84
  278. package/dist/core/adapters/scripts/install-adapter.d.ts +0 -19
  279. package/dist/core/adapters/scripts/install-adapter.js +0 -149
  280. package/dist/core/adapters/timeline.d.ts +0 -23
  281. package/dist/core/adapters/timeline.js +0 -88
  282. package/dist/core/adapters/types.d.ts +0 -157
  283. package/dist/core/adapters/types.js +0 -50
  284. package/dist/core/algorithms/analytics/token-estimator.d.ts +0 -50
  285. package/dist/core/algorithms/analytics/token-estimator.js +0 -154
  286. package/dist/core/algorithms/detection/hash-filters.d.ts +0 -47
  287. package/dist/core/algorithms/detection/hash-filters.js +0 -190
  288. package/dist/core/algorithms/detection/semantic-ranker.d.ts +0 -32
  289. package/dist/core/algorithms/detection/semantic-ranker.js +0 -118
  290. package/dist/core/algorithms/detection/two-stage-detector.d.ts +0 -52
  291. package/dist/core/algorithms/detection/two-stage-detector.js +0 -299
  292. package/dist/core/algorithms/handlers/approve-merge.d.ts +0 -22
  293. package/dist/core/algorithms/handlers/approve-merge.js +0 -179
  294. package/dist/core/algorithms/handlers/detect-duplicates.d.ts +0 -47
  295. package/dist/core/algorithms/handlers/detect-duplicates.js +0 -145
  296. package/dist/core/algorithms/handlers/get-stats.d.ts +0 -39
  297. package/dist/core/algorithms/handlers/get-stats.js +0 -88
  298. package/dist/core/algorithms/handlers/list-proposals.d.ts +0 -45
  299. package/dist/core/algorithms/handlers/list-proposals.js +0 -83
  300. package/dist/core/algorithms/handlers/preview-merge.d.ts +0 -39
  301. package/dist/core/algorithms/handlers/preview-merge.js +0 -93
  302. package/dist/core/algorithms/handlers/reject-merge.d.ts +0 -28
  303. package/dist/core/algorithms/handlers/reject-merge.js +0 -69
  304. package/dist/core/algorithms/handlers/reverse-merge.d.ts +0 -21
  305. package/dist/core/algorithms/handlers/reverse-merge.js +0 -121
  306. package/dist/core/algorithms/index.d.ts +0 -21
  307. package/dist/core/algorithms/operations/cache-maintenance.d.ts +0 -12
  308. package/dist/core/algorithms/operations/cache-maintenance.js +0 -157
  309. package/dist/core/algorithms/safety/safety-checks.d.ts +0 -22
  310. package/dist/core/algorithms/safety/safety-checks.js +0 -179
  311. package/dist/core/algorithms/strategies/merge-strategies.d.ts +0 -50
  312. package/dist/core/algorithms/strategies/merge-strategies.js +0 -288
  313. package/dist/core/algorithms/types.d.ts +0 -133
  314. package/dist/core/algorithms/types.js +0 -5
  315. package/dist/core/algorithms/utils/response-builder.d.ts +0 -28
  316. package/dist/core/algorithms/utils/response-builder.js +0 -37
  317. package/dist/core/associations.d.ts +0 -31
  318. package/dist/core/associations.js +0 -248
  319. package/dist/core/autosave.d.ts +0 -19
  320. package/dist/core/autosave.js +0 -16
  321. package/dist/core/commands/managed-sync.d.ts +0 -10
  322. package/dist/core/commands/managed-sync.js +0 -64
  323. package/dist/core/commands/mcp-server.d.ts +0 -3
  324. package/dist/core/commands/mcp-server.js +0 -739
  325. package/dist/core/consolidation.d.ts +0 -37
  326. package/dist/core/consolidation.js +0 -248
  327. package/dist/core/context/agent-context.d.ts +0 -106
  328. package/dist/core/context/agent-context.js +0 -274
  329. package/dist/core/context/context-paging.d.ts +0 -80
  330. package/dist/core/context/context-paging.js +0 -328
  331. package/dist/core/context/context-window.d.ts +0 -40
  332. package/dist/core/context/context-window.js +0 -177
  333. package/dist/core/context/context.d.ts +0 -7
  334. package/dist/core/context/context.js +0 -22
  335. package/dist/core/embeddings/google-multimodal.d.ts +0 -14
  336. package/dist/core/embeddings/google-multimodal.js +0 -142
  337. package/dist/core/embeddings/qmd-client.d.ts +0 -136
  338. package/dist/core/embeddings/qmd-client.js +0 -403
  339. package/dist/core/embeddings.d.ts +0 -29
  340. package/dist/core/embeddings.js +0 -454
  341. package/dist/core/error-handling.d.ts +0 -63
  342. package/dist/core/error-handling.js +0 -173
  343. package/dist/core/external-folder/index.d.ts +0 -102
  344. package/dist/core/external-folder/index.js +0 -294
  345. package/dist/core/hooks/agent-hooks.d.ts +0 -74
  346. package/dist/core/hooks/agent-hooks.js +0 -244
  347. package/dist/core/hooks/auto-tagger.d.ts +0 -19
  348. package/dist/core/hooks/auto-tagger.js +0 -155
  349. package/dist/core/hooks/capture-filter.d.ts +0 -41
  350. package/dist/core/hooks/capture-filter.js +0 -128
  351. package/dist/core/index.d.ts +0 -10
  352. package/dist/core/index.js +0 -14
  353. package/dist/core/ingestion/agent-memory.d.ts +0 -22
  354. package/dist/core/ingestion/agent-memory.js +0 -109
  355. package/dist/core/ingestion/core-memory.d.ts +0 -78
  356. package/dist/core/ingestion/core-memory.js +0 -226
  357. package/dist/core/ingestion/learnings.d.ts +0 -57
  358. package/dist/core/ingestion/learnings.js +0 -202
  359. package/dist/core/layers/generator.d.ts +0 -25
  360. package/dist/core/layers/generator.js +0 -76
  361. package/dist/core/lib/db-client.js +0 -130
  362. package/dist/core/lib/schemas.d.ts +0 -129
  363. package/dist/core/lib/utils.d.ts +0 -14
  364. package/dist/core/lib/utils.js +0 -90
  365. package/dist/core/lib/validation.d.ts +0 -38
  366. package/dist/core/lib/validation.js +0 -151
  367. package/dist/core/lifecycle.d.ts +0 -26
  368. package/dist/core/lifecycle.js +0 -302
  369. package/dist/core/local-embeddings.d.ts +0 -11
  370. package/dist/core/logger.d.ts +0 -16
  371. package/dist/core/logger.js +0 -40
  372. package/dist/core/mcp/client.d.ts +0 -17
  373. package/dist/core/mcp/client.js +0 -101
  374. package/dist/core/mcp/index.d.ts +0 -6
  375. package/dist/core/mcp/index.js +0 -6
  376. package/dist/core/mcp/server.d.ts +0 -18
  377. package/dist/core/mcp/server.js +0 -157
  378. package/dist/core/mcp/standalone-server.d.ts +0 -13
  379. package/dist/core/mcp/standalone-server.js +0 -46
  380. package/dist/core/mcp/tools.d.ts +0 -9
  381. package/dist/core/mcp/tools.js +0 -365
  382. package/dist/core/mcp/types.d.ts +0 -315
  383. package/dist/core/mcp/types.js +0 -48
  384. package/dist/core/memory/bridge-discovery.d.ts +0 -50
  385. package/dist/core/memory/bridge-discovery.js +0 -291
  386. package/dist/core/memory/categorizer.d.ts +0 -27
  387. package/dist/core/memory/categorizer.js +0 -305
  388. package/dist/core/memory/conflict-detector.d.ts +0 -7
  389. package/dist/core/memory/conflict-detector.js +0 -43
  390. package/dist/core/memory/consolidation.d.ts +0 -42
  391. package/dist/core/memory/consolidation.js +0 -303
  392. package/dist/core/memory/context-collector.d.ts +0 -10
  393. package/dist/core/memory/context-collector.js +0 -56
  394. package/dist/core/memory/contradiction-resolver.d.ts +0 -40
  395. package/dist/core/memory/contradiction-resolver.js +0 -368
  396. package/dist/core/memory/edit-workflow.d.ts +0 -19
  397. package/dist/core/memory/edit-workflow.js +0 -120
  398. package/dist/core/memory/entity-extractor.d.ts +0 -33
  399. package/dist/core/memory/entity-extractor.js +0 -336
  400. package/dist/core/memory/entity-resolver.d.ts +0 -23
  401. package/dist/core/memory/entity-resolver.js +0 -64
  402. package/dist/core/memory/fact-extractor.d.ts +0 -24
  403. package/dist/core/memory/fact-extractor.js +0 -89
  404. package/dist/core/memory/feedback-tracker.d.ts +0 -12
  405. package/dist/core/memory/feedback-tracker.js +0 -155
  406. package/dist/core/memory/hooks.d.ts +0 -88
  407. package/dist/core/memory/hooks.js +0 -174
  408. package/dist/core/memory/hybrid-retrieval.d.ts +0 -29
  409. package/dist/core/memory/hybrid-retrieval.js +0 -139
  410. package/dist/core/memory/hybrid-scorer.d.ts +0 -40
  411. package/dist/core/memory/hybrid-scorer.js +0 -284
  412. package/dist/core/memory/hybrid-search.d.ts +0 -20
  413. package/dist/core/memory/hybrid-search.js +0 -359
  414. package/dist/core/memory/importance.d.ts +0 -63
  415. package/dist/core/memory/importance.js +0 -298
  416. package/dist/core/memory/index.d.ts +0 -8
  417. package/dist/core/memory/loader.d.ts +0 -31
  418. package/dist/core/memory/loader.js +0 -141
  419. package/dist/core/memory/markdown/markdown-storage.d.ts +0 -72
  420. package/dist/core/memory/markdown/markdown-storage.js +0 -243
  421. package/dist/core/memory/memories.d.ts +0 -47
  422. package/dist/core/memory/memories.js +0 -449
  423. package/dist/core/memory/memory-lifecycle.d.ts +0 -8
  424. package/dist/core/memory/memory-lifecycle.js +0 -55
  425. package/dist/core/memory/memory-manager.d.ts +0 -15
  426. package/dist/core/memory/memory-manager.js +0 -46
  427. package/dist/core/memory/migrate.d.ts +0 -21
  428. package/dist/core/memory/migrate.js +0 -134
  429. package/dist/core/memory/normalization.d.ts +0 -22
  430. package/dist/core/memory/normalization.js +0 -26
  431. package/dist/core/memory/progressive-disclosure.d.ts +0 -43
  432. package/dist/core/memory/progressive-disclosure.js +0 -280
  433. package/dist/core/memory/query-processor.d.ts +0 -21
  434. package/dist/core/memory/query-processor.js +0 -72
  435. package/dist/core/memory/query-rewriter.d.ts +0 -13
  436. package/dist/core/memory/query-rewriter.js +0 -118
  437. package/dist/core/memory/response-analyzer.d.ts +0 -9
  438. package/dist/core/memory/response-analyzer.js +0 -61
  439. package/dist/core/memory/serialization.d.ts +0 -10
  440. package/dist/core/memory/serialization.js +0 -84
  441. package/dist/core/memory/stats.d.ts +0 -22
  442. package/dist/core/memory/stats.js +0 -138
  443. package/dist/core/memory/telemetry.d.ts +0 -69
  444. package/dist/core/memory/telemetry.js +0 -313
  445. package/dist/core/memory/temporal-facts.d.ts +0 -41
  446. package/dist/core/memory/temporal-facts.js +0 -283
  447. package/dist/core/memory/temporal-parser.d.ts +0 -32
  448. package/dist/core/memory/temporal-parser.js +0 -385
  449. package/dist/core/memory/trigger-detector.d.ts +0 -14
  450. package/dist/core/memory/trigger-detector.js +0 -42
  451. package/dist/core/memory/write-gate.d.ts +0 -54
  452. package/dist/core/memory/write-gate.js +0 -210
  453. package/dist/core/namespaces/index.d.ts +0 -71
  454. package/dist/core/namespaces/index.js +0 -305
  455. package/dist/core/namespaces/uri-parser.d.ts +0 -31
  456. package/dist/core/namespaces/uri-parser.js +0 -74
  457. package/dist/core/obsidian-vault.d.ts +0 -30
  458. package/dist/core/obsidian-vault.js +0 -94
  459. package/dist/core/places/index.d.ts +0 -14
  460. package/dist/core/places/memory-places.d.ts +0 -68
  461. package/dist/core/places/memory-places.js +0 -261
  462. package/dist/core/places/places.d.ts +0 -88
  463. package/dist/core/places/places.js +0 -314
  464. package/dist/core/places/rules.d.ts +0 -74
  465. package/dist/core/places/rules.js +0 -240
  466. package/dist/core/places/walking.d.ts +0 -56
  467. package/dist/core/places/walking.js +0 -121
  468. package/dist/core/projects.d.ts +0 -17
  469. package/dist/core/projects.js +0 -108
  470. package/dist/core/redis.d.ts +0 -11
  471. package/dist/core/redis.js +0 -69
  472. package/dist/core/responses.d.ts +0 -96
  473. package/dist/core/responses.js +0 -122
  474. package/dist/core/scheduler/cron-scheduler.d.ts +0 -32
  475. package/dist/core/scheduler/cron-scheduler.js +0 -332
  476. package/dist/core/scheduler/heartbeat.d.ts +0 -11
  477. package/dist/core/scheduler/heartbeat.js +0 -73
  478. package/dist/core/scheduler/index.d.ts +0 -8
  479. package/dist/core/scheduler/job-runner.d.ts +0 -11
  480. package/dist/core/scheduler/job-runner.js +0 -164
  481. package/dist/core/search/conversations.d.ts +0 -25
  482. package/dist/core/search/conversations.js +0 -110
  483. package/dist/core/search/entities.d.ts +0 -12
  484. package/dist/core/search/entities.js +0 -31
  485. package/dist/core/search/folder-context.d.ts +0 -25
  486. package/dist/core/search/folder-context.js +0 -119
  487. package/dist/core/search/graph-boost.d.ts +0 -7
  488. package/dist/core/search/graph-boost.js +0 -23
  489. package/dist/core/search/index.d.ts +0 -4
  490. package/dist/core/search/qmd-search.d.ts +0 -61
  491. package/dist/core/search/qmd-search.js +0 -178
  492. package/dist/core/security/encrypt.d.ts +0 -6
  493. package/dist/core/security/encrypt.js +0 -47
  494. package/dist/core/security/governance.d.ts +0 -26
  495. package/dist/core/security/governance.js +0 -79
  496. package/dist/core/security/privacy.d.ts +0 -23
  497. package/dist/core/security/privacy.js +0 -82
  498. package/dist/core/security/secret-detector.d.ts +0 -32
  499. package/dist/core/security/secret-detector.js +0 -88
  500. package/dist/core/session/auto-load.d.ts +0 -6
  501. package/dist/core/session/auto-load.js +0 -119
  502. package/dist/core/session/index.d.ts +0 -7
  503. package/dist/core/session/self-iteration-job.d.ts +0 -20
  504. package/dist/core/session/self-iteration-job.js +0 -282
  505. package/dist/core/session/session-hooks.d.ts +0 -18
  506. package/dist/core/session/session-hooks.js +0 -58
  507. package/dist/core/session/types.d.ts +0 -26
  508. package/dist/core/session/types.js +0 -10
  509. package/dist/core/session-hooks/self-iteration-job.d.ts +0 -20
  510. package/dist/core/session-hooks/self-iteration-job.js +0 -282
  511. package/dist/core/session-hooks/session-hooks.d.ts +0 -18
  512. package/dist/core/session-hooks/session-hooks.js +0 -58
  513. package/dist/core/snapshots/cleanup.d.ts +0 -9
  514. package/dist/core/snapshots/comparison.d.ts +0 -19
  515. package/dist/core/snapshots/comparison.js +0 -43
  516. package/dist/core/snapshots/creation.d.ts +0 -19
  517. package/dist/core/snapshots/creation.js +0 -126
  518. package/dist/core/snapshots/retrieval.d.ts +0 -7
  519. package/dist/core/snapshots/retrieval.js +0 -41
  520. package/dist/core/snapshots/stats.d.ts +0 -11
  521. package/dist/core/snapshots/stats.js +0 -52
  522. package/dist/core/snapshots.d.ts +0 -29
  523. package/dist/core/snapshots.js +0 -220
  524. package/dist/core/storage/cache.d.ts +0 -13
  525. package/dist/core/storage/cache.js +0 -202
  526. package/dist/core/storage/database.d.ts +0 -12
  527. package/dist/core/storage/database.js +0 -12
  528. package/dist/core/summarization/cleanup.d.ts +0 -9
  529. package/dist/core/summarization/queries.d.ts +0 -9
  530. package/dist/core/summarization/queries.js +0 -28
  531. package/dist/core/summarization/stats.d.ts +0 -14
  532. package/dist/core/summarization/stats.js +0 -52
  533. package/dist/core/summarization/strategies.d.ts +0 -24
  534. package/dist/core/summarization/strategies.js +0 -28
  535. package/dist/core/summarization.d.ts +0 -37
  536. package/dist/core/summarization.js +0 -188
  537. package/dist/core/sync/qmd-sync.d.ts +0 -94
  538. package/dist/core/sync/qmd-sync.js +0 -201
  539. package/dist/core/temporal-facts.d.ts +0 -54
  540. package/dist/core/temporal-facts.js +0 -193
  541. package/dist/core/toon.d.ts +0 -43
  542. package/dist/core/toon.js +0 -160
  543. package/dist/core/tracing/collector.d.ts +0 -111
  544. package/dist/core/tracing/collector.js +0 -350
  545. package/dist/core/tracing/visualizer.d.ts +0 -32
  546. package/dist/core/tracing/visualizer.js +0 -165
  547. package/dist/core/utils/cleanup-operations.d.ts +0 -13
  548. package/dist/core/utils/cleanup-operations.js +0 -44
  549. package/dist/core/utils/content-extraction.d.ts +0 -19
  550. package/dist/core/utils/content-extraction.js +0 -75
  551. package/dist/core/utils/filter-builder.d.ts +0 -13
  552. package/dist/core/utils/filter-builder.js +0 -44
  553. package/dist/core/utils/history-traversal.d.ts +0 -13
  554. package/dist/core/utils/history-traversal.js +0 -50
  555. package/dist/core/utils/memory-operations.d.ts +0 -17
  556. package/dist/core/utils/memory-operations.js +0 -43
  557. package/dist/core/utils/query-operations.d.ts +0 -18
  558. package/dist/core/utils/query-operations.js +0 -65
  559. package/dist/core/utils/summarization-helpers.d.ts +0 -21
  560. package/dist/core/utils/summarization-helpers.js +0 -38
  561. package/dist/core/utils/temporal-queries.d.ts +0 -13
  562. package/dist/core/utils/temporal-queries.js +0 -27
  563. package/dist/core/utils/vector-operations.d.ts +0 -71
  564. package/dist/core/utils/version-management.d.ts +0 -9
  565. package/dist/core/utils/version-management.js +0 -61
  566. package/dist/core/worker.d.ts +0 -82
  567. package/dist/core/worker.js +0 -272
  568. package/dist/db/adapter.d.ts +0 -7
  569. package/dist/db/adapter.js +0 -175
  570. package/dist/db/bootstrap.d.ts +0 -9
  571. package/dist/db/drizzle/schema-sqlite.d.ts +0 -4837
  572. package/dist/db/drizzle/schema-sqlite.js +0 -684
  573. package/dist/db/drizzle/schema.d.ts +0 -4082
  574. package/dist/db/drizzle/schema.js +0 -770
  575. package/dist/db/drizzle.config.d.ts +0 -3
  576. package/dist/db/drizzle.config.js +0 -12
  577. package/dist/db/index.d.ts +0 -7
  578. package/dist/db/index.js +0 -89
  579. package/dist/db/neon.d.ts +0 -8
  580. package/dist/db/neon.js +0 -20
  581. package/dist/db/schema/index.d.ts +0 -40
  582. package/dist/db/schema/index.js +0 -105
  583. package/dist/db/schema/tables/context-sessions.d.ts +0 -9
  584. package/dist/db/schema/tables/context-sessions.js +0 -37
  585. package/dist/db/schema/tables/conversations.d.ts +0 -9
  586. package/dist/db/schema/tables/conversations.js +0 -47
  587. package/dist/db/schema/tables/core-memory.d.ts +0 -9
  588. package/dist/db/schema/tables/core-memory.js +0 -41
  589. package/dist/db/schema/tables/entities.d.ts +0 -9
  590. package/dist/db/schema/tables/entities.js +0 -39
  591. package/dist/db/schema/tables/entity-relations.d.ts +0 -9
  592. package/dist/db/schema/tables/entity-relations.js +0 -31
  593. package/dist/db/schema/tables/learnings.d.ts +0 -9
  594. package/dist/db/schema/tables/learnings.js +0 -66
  595. package/dist/db/schema/tables/memories.d.ts +0 -9
  596. package/dist/db/schema/tables/memories.js +0 -161
  597. package/dist/db/schema/tables/memory-associations.d.ts +0 -9
  598. package/dist/db/schema/tables/memory-associations.js +0 -39
  599. package/dist/db/schema/tables/memory-hash-cache.d.ts +0 -9
  600. package/dist/db/schema/tables/memory-hash-cache.js +0 -29
  601. package/dist/db/schema/tables/memory-merge-history.d.ts +0 -9
  602. package/dist/db/schema/tables/memory-merge-history.js +0 -33
  603. package/dist/db/schema/tables/memory-merge-proposals.d.ts +0 -9
  604. package/dist/db/schema/tables/memory-merge-proposals.js +0 -39
  605. package/dist/db/schema/tables/messages.d.ts +0 -9
  606. package/dist/db/schema/tables/messages.js +0 -41
  607. package/dist/db/schema/tables/namespaces.d.ts +0 -9
  608. package/dist/db/schema/tables/namespaces.js +0 -37
  609. package/dist/db/schema/tables/projects.d.ts +0 -9
  610. package/dist/db/schema/tables/projects.js +0 -31
  611. package/dist/db/schema/tables/users.d.ts +0 -9
  612. package/dist/db/schema/tables/users.js +0 -27
  613. package/dist/db/schema.d.ts +0 -3
  614. package/dist/db/schema.js +0 -11
  615. package/dist/db/supabase.d.ts +0 -9
  616. package/dist/db/supabase.js +0 -24
  617. package/dist/index.d.ts +0 -7
  618. package/dist/index.js +0 -1677
  619. package/dist/vendor/sql.js/sql-wasm.wasm +0 -0
  620. package/dist/webui/server.d.ts +0 -5
  621. package/dist/webui/server.js +0 -642
  622. package/generated/mcp/manifest.json +0 -23
  623. package/generated/mcp/mcp-servers.json +0 -25
  624. package/generated/mcp/mcporter.json +0 -34
  625. package/generated/mcp/openclaw-memory-qmd.json +0 -17
  626. package/generated/mcp/runtime.json +0 -12
  627. package/scripts/README.md +0 -60
  628. package/scripts/build-release.sh +0 -36
  629. package/scripts/check-secrets.js +0 -132
  630. package/scripts/copy-runtime-assets.mjs +0 -26
  631. package/scripts/generate-mcp.mjs +0 -264
  632. package/scripts/github-release.sh +0 -77
  633. package/scripts/init-dirs.mjs +0 -13
  634. package/scripts/install-claude-code.sh +0 -85
  635. package/scripts/install-cursor.sh +0 -56
  636. package/scripts/install-hooks.sh +0 -73
  637. package/scripts/install-interactive.mjs +0 -357
  638. package/scripts/install-opencode.sh +0 -75
  639. package/scripts/install-plugin.mjs +0 -415
  640. package/scripts/install-windsurf.sh +0 -67
  641. package/scripts/remote-preflight.mjs +0 -62
  642. package/scripts/squish-fallback.mjs +0 -132
  643. package/scripts/test-interactive.mjs +0 -131
  644. package/scripts/verify-mcp.mjs +0 -214
  645. package/skills/squish-memory/scripts/install.mjs +0 -335
  646. package/skills/squish-memory/write_skill.js +0 -2
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Token estimation for calculating context window savings from merges.
3
+ * Uses simple heuristic: 1 token ≈ 4 characters (can be upgraded to tiktoken for accuracy).
4
+ */
5
+
6
+ import type { Memory } from '../../../db/drizzle/schema.js';
7
+ import type { MergedMemory } from '../strategies/merge-strategies.js';
8
+ import { getDb } from '../../../db/index.js';
9
+ import { getSchema } from '../../../db/schema.js';
10
+ import { createDatabaseClient } from '../../../core/storage/database.js';
11
+ import { eq } from 'drizzle-orm';
12
+
13
+ function estimateTokensSimple(text: string): number {
14
+ if (!text) return 0;
15
+ return Math.ceil(text.length / 4);
16
+ }
17
+
18
+ function estimateMetadataOverhead(): number {
19
+ return 25;
20
+ }
21
+
22
+ function estimateMemoryTokens(memory: Memory): number {
23
+ let tokens = 0;
24
+
25
+ tokens += estimateTokensSimple(memory.content);
26
+
27
+ if (memory.summary) {
28
+ tokens += estimateTokensSimple(memory.summary);
29
+ }
30
+
31
+ if (memory.tags && memory.tags.length > 0) {
32
+ tokens += estimateTokensSimple(memory.tags.join(' '));
33
+ }
34
+
35
+ if (memory.metadata) {
36
+ tokens += estimateTokensSimple(JSON.stringify(memory.metadata));
37
+ }
38
+
39
+ tokens += estimateMetadataOverhead();
40
+
41
+ return tokens;
42
+ }
43
+
44
+ function estimateMergedMemoryTokens(merged: MergedMemory): number {
45
+ let tokens = 0;
46
+
47
+ tokens += estimateTokensSimple(merged.content);
48
+
49
+ if (merged.summary) {
50
+ tokens += estimateTokensSimple(merged.summary);
51
+ }
52
+
53
+ if (merged.tags && merged.tags.length > 0) {
54
+ tokens += estimateTokensSimple(merged.tags.join(' '));
55
+ }
56
+
57
+ tokens += estimateTokensSimple(JSON.stringify(merged.metadata));
58
+ tokens += estimateMetadataOverhead();
59
+
60
+ return tokens;
61
+ }
62
+
63
+ export function estimateTokensSaved(sources: Memory[], merged: MergedMemory): number {
64
+ const sourceTokens = sources.reduce((sum, memory) => sum + estimateMemoryTokens(memory), 0);
65
+ const mergedTokens = estimateMergedMemoryTokens(merged);
66
+ const savings = sourceTokens - mergedTokens;
67
+
68
+ return Math.max(0, savings);
69
+ }
70
+
71
+ export async function calculateProjectTokenSavings(
72
+ projectId: string
73
+ ): Promise<{
74
+ totalSaved: number;
75
+ mergeCount: number;
76
+ avgSavingsPerMerge: number;
77
+ tokenSavingPercentage: number;
78
+ totalMemoryTokens: number;
79
+ }> {
80
+ const db = createDatabaseClient(await getDb());
81
+ const schema = await getSchema();
82
+
83
+ const memories: Memory[] = await db
84
+ .select()
85
+ .from(schema.memories)
86
+ .where(eq(schema.memories.projectId, projectId));
87
+
88
+ const totalMemoryTokens = memories.reduce((sum, m) => sum + estimateMemoryTokens(m), 0);
89
+ if (!schema.memoryMergeHistory) {
90
+ return {
91
+ totalSaved: 0,
92
+ mergeCount: 0,
93
+ avgSavingsPerMerge: 0,
94
+ tokenSavingPercentage: 0,
95
+ totalMemoryTokens,
96
+ };
97
+ }
98
+
99
+ const mergeHistory: any[] = await db
100
+ .select()
101
+ .from(schema.memoryMergeHistory)
102
+ .where(eq(schema.memoryMergeHistory.projectId, projectId));
103
+
104
+ // Sum up token savings
105
+ const totalSaved = mergeHistory.reduce((sum, record) => sum + (record.tokensSaved || 0), 0);
106
+
107
+ const mergeCount = mergeHistory.length;
108
+ const avgSavingsPerMerge = mergeCount > 0 ? Math.round(totalSaved / mergeCount) : 0;
109
+ const tokenSavingPercentage = totalMemoryTokens > 0 ? (totalSaved / totalMemoryTokens) * 100 : 0;
110
+
111
+ return {
112
+ totalSaved,
113
+ mergeCount,
114
+ avgSavingsPerMerge,
115
+ tokenSavingPercentage,
116
+ totalMemoryTokens,
117
+ };
118
+ }
119
+
120
+ /**
121
+ * Format token counts for display
122
+ *
123
+ * Converts token count to human-readable format with context usage
124
+ */
125
+ export function formatTokenCount(tokens: number): string {
126
+ // Show percentage of typical context window
127
+ // Claude 3 / GPT-4: 128k tokens (~32k practical for context)
128
+ const contextWindow = 128000;
129
+ const typicalUseful = 32000;
130
+
131
+ const percentage = (tokens / contextWindow) * 100;
132
+ const usefulPercent = (tokens / typicalUseful) * 100;
133
+
134
+ if (tokens < 1000) {
135
+ return `${tokens} tokens (${percentage.toFixed(3)}% of context)`;
136
+ }
137
+
138
+ const kiloTokens = (tokens / 1000).toFixed(1);
139
+ return `${kiloTokens}k tokens (${usefulPercent.toFixed(1)}% of typical recall window)`;
140
+ }
141
+
142
+ /**
143
+ * Format savings report
144
+ */
145
+ export function formatSavingsReport(savings: {
146
+ totalSaved: number;
147
+ mergeCount: number;
148
+ avgSavingsPerMerge: number;
149
+ tokenSavingPercentage: number;
150
+ totalMemoryTokens: number;
151
+ }): string {
152
+ const lines: string[] = [];
153
+
154
+ lines.push('Memory Merge Savings Report');
155
+ lines.push('='.repeat(40));
156
+
157
+ if (savings.mergeCount === 0) {
158
+ lines.push('No merges completed yet');
159
+ return lines.join('\n');
160
+ }
161
+
162
+ lines.push(`Total Merges: ${savings.mergeCount}`);
163
+ lines.push(`Total Tokens Saved: ${formatTokenCount(savings.totalSaved)}`);
164
+ lines.push(`Avg Savings per Merge: ${formatTokenCount(savings.avgSavingsPerMerge)}`);
165
+ lines.push(`Reduction: ${savings.tokenSavingPercentage.toFixed(2)}%`);
166
+ lines.push(`Total Memory Tokens: ${formatTokenCount(savings.totalMemoryTokens)}`);
167
+
168
+ return lines.join('\n');
169
+ }
170
+
171
+ /**
172
+ * Estimate savings for a proposed merge (preview)
173
+ *
174
+ * Used in merge preview to show user estimated savings
175
+ */
176
+ export function estimateMergeSavingsPreview(
177
+ sources: Memory[],
178
+ merged: MergedMemory
179
+ ): { savedTokens: number; savedPercentage: number } {
180
+ const sourceTokens = sources.reduce((sum, m) => sum + estimateMemoryTokens(m), 0);
181
+ const mergedTokens = estimateMergedMemoryTokens(merged);
182
+ const savedTokens = Math.max(0, sourceTokens - mergedTokens);
183
+ const savedPercentage = sourceTokens > 0 ? (savedTokens / sourceTokens) * 100 : 0;
184
+
185
+ return { savedTokens, savedPercentage };
186
+ }
187
+
188
+ /**
189
+ * Get token statistics for a set of memories
190
+ */
191
+ export function getTokenStatistics(memories: Memory[]): {
192
+ total: number;
193
+ min: number;
194
+ max: number;
195
+ average: number;
196
+ median: number;
197
+ } {
198
+ const counts = memories.map((m) => estimateMemoryTokens(m));
199
+ const total = counts.reduce((a, b) => a + b, 0);
200
+ const min = Math.min(...counts);
201
+ const max = Math.max(...counts);
202
+ const average = Math.round(total / counts.length);
203
+
204
+ // Calculate median
205
+ const sorted = [...counts].sort((a, b) => a - b);
206
+ const middle = Math.floor(sorted.length / 2);
207
+ const median = sorted.length % 2 !== 0 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2;
208
+
209
+ return {
210
+ total,
211
+ min,
212
+ max,
213
+ average,
214
+ median: Math.round(median),
215
+ };
216
+ }
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Hash-based duplicate detection filters (Stage 1).
3
+ * Uses SimHash and MinHash for fast approximate matching before semantic analysis.
4
+ */
5
+
6
+ /**
7
+ * SimHash: Fast fingerprinting for near-duplicate detection.
8
+ * Tokenizes content, weights by frequency, and produces comparable hash fingerprints.
9
+ * Similar documents produce similar hashes with Hamming distance indicating edit distance.
10
+ */
11
+ export class SimHashFilter {
12
+ private readonly dimensions = 32; // 32-bit hash
13
+
14
+ generateHash(content: string): string {
15
+ if (!content || content.trim().length === 0) {
16
+ return '0'.repeat(16);
17
+ }
18
+
19
+ const tokens = content
20
+ .toLowerCase()
21
+ .split(/\W+/)
22
+ .filter((token) => token.length > 0);
23
+
24
+ if (tokens.length === 0) {
25
+ return '0'.repeat(16);
26
+ }
27
+
28
+ const tokenFreq = new Map<string, number>();
29
+ for (const token of tokens) {
30
+ tokenFreq.set(token, (tokenFreq.get(token) || 0) + 1);
31
+ }
32
+
33
+ const hashBits = new Array(this.dimensions).fill(0);
34
+
35
+ for (const [token, freq] of tokenFreq.entries()) {
36
+ const tokenHash = this.hashToken(token);
37
+ for (let i = 0; i < this.dimensions; i++) {
38
+ const bitSet = (tokenHash >>> i) & 1;
39
+ hashBits[i] += bitSet === 1 ? freq : -freq;
40
+ }
41
+ }
42
+
43
+ let result = 0;
44
+ for (let i = 0; i < this.dimensions; i++) {
45
+ if (hashBits[i] > 0) {
46
+ result |= 1 << i;
47
+ }
48
+ }
49
+
50
+ return (result >>> 0).toString(16).padStart(16, '0');
51
+ }
52
+
53
+ hammingDistance(hash1: string, hash2: string): number {
54
+ const num1 = BigInt('0x' + hash1);
55
+ const num2 = BigInt('0x' + hash2);
56
+ const xor = num1 ^ num2;
57
+ return this.popcount(xor);
58
+ }
59
+
60
+ findCandidates(
61
+ targetHash: string,
62
+ allHashes: Map<string, string>,
63
+ threshold: number
64
+ ): string[] {
65
+ const candidates: string[] = [];
66
+
67
+ for (const [memoryId, hash] of allHashes.entries()) {
68
+ const distance = this.hammingDistance(targetHash, hash);
69
+ if (distance <= threshold) {
70
+ candidates.push(memoryId);
71
+ }
72
+ }
73
+
74
+ return candidates;
75
+ }
76
+
77
+ private hashToken(token: string): number {
78
+ let hash = 2166136261;
79
+
80
+ for (let i = 0; i < token.length; i++) {
81
+ hash ^= token.charCodeAt(i);
82
+ hash = (hash * 16777619) & 0xffffffff;
83
+ }
84
+
85
+ const high = hash >>> 16;
86
+ const low = hash & 0xffff;
87
+ return (high * 65599 + low) >>> 0;
88
+ }
89
+
90
+ private popcount(n: bigint): number {
91
+ let count = 0;
92
+ while (n > 0n) {
93
+ count += Number(n & 1n);
94
+ n = n >> 1n;
95
+ }
96
+ return count;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * MinHash: Estimates Jaccard similarity using character n-grams and multiple hash functions.
102
+ * Keeps minimum hash for each function, resulting in comparable signatures.
103
+ * More effective than SimHash for paraphrases. 128 functions give ~1% error margin.
104
+ */
105
+ export class MinHashFilter {
106
+ private readonly numPermutations = 128; // Number of independent hash functions
107
+ private readonly ngramSize = 3; // Character n-gram size
108
+
109
+ generateSignature(content: string): number[] {
110
+ if (!content || content.trim().length === 0) {
111
+ return new Array(this.numPermutations).fill(0);
112
+ }
113
+
114
+ const ngrams = this.generateNgrams(content.toLowerCase(), this.ngramSize);
115
+
116
+ if (ngrams.length === 0) {
117
+ return new Array(this.numPermutations).fill(0);
118
+ }
119
+
120
+ const signature = new Array(this.numPermutations).fill(Number.MAX_SAFE_INTEGER);
121
+
122
+ for (const ngram of ngrams) {
123
+ for (let i = 0; i < this.numPermutations; i++) {
124
+ const hashValue = this.hashNgramWithSeed(ngram, i);
125
+ signature[i] = Math.min(signature[i], hashValue);
126
+ }
127
+ }
128
+
129
+ return signature;
130
+ }
131
+
132
+ jaccardSimilarity(sig1: number[], sig2: number[]): number {
133
+ if (sig1.length !== sig2.length) {
134
+ return 0;
135
+ }
136
+
137
+ if (sig1.length === 0) {
138
+ return 1;
139
+ }
140
+
141
+ let matches = 0;
142
+ for (let i = 0; i < sig1.length; i++) {
143
+ if (sig1[i] === sig2[i]) {
144
+ matches++;
145
+ }
146
+ }
147
+
148
+ return matches / sig1.length;
149
+ }
150
+
151
+ findCandidates(
152
+ targetSig: number[],
153
+ allSigs: Map<string, number[]>,
154
+ threshold: number
155
+ ): string[] {
156
+ const candidates: string[] = [];
157
+
158
+ for (const [memoryId, sig] of allSigs.entries()) {
159
+ const similarity = this.jaccardSimilarity(targetSig, sig);
160
+ if (similarity >= threshold) {
161
+ candidates.push(memoryId);
162
+ }
163
+ }
164
+
165
+ return candidates;
166
+ }
167
+
168
+ private generateNgrams(content: string, size: number): string[] {
169
+ const ngrams: string[] = [];
170
+ const padded = ' '.repeat(size - 1) + content + ' '.repeat(size - 1);
171
+
172
+ for (let i = 0; i <= padded.length - size; i++) {
173
+ ngrams.push(padded.substring(i, i + size));
174
+ }
175
+
176
+ return ngrams;
177
+ }
178
+
179
+ private hashNgramWithSeed(ngram: string, seed: number): number {
180
+ let hash = seed;
181
+
182
+ for (let i = 0; i < ngram.length; i++) {
183
+ hash = (hash << 5) - hash + ngram.charCodeAt(i);
184
+ hash = hash & hash;
185
+ }
186
+
187
+ return Math.abs(hash);
188
+ }
189
+ }
190
+
191
+ export interface Stage1CandidatePair {
192
+ memoryId1: string;
193
+ memoryId2: string;
194
+ simhashDistance: number;
195
+ minhashSimilarity: number;
196
+ matched: 'simhash' | 'minhash' | 'both';
197
+ }
198
+
199
+ /**
200
+ * Combine SimHash and MinHash filters using union approach.
201
+ * Candidates pass if they match EITHER filter, casting wider net for stage 2 ranking.
202
+ */
203
+ export function findCandidatePairs(
204
+ memories: Map<string, string>,
205
+ allSimhashes: Map<string, string>,
206
+ allMinhashes: Map<string, number[]>,
207
+ options: {
208
+ simhashThreshold?: number;
209
+ minhashThreshold?: number;
210
+ }
211
+ ): Stage1CandidatePair[] {
212
+ const simhashThreshold = options.simhashThreshold ?? 4;
213
+ const minhashThreshold = options.minhashThreshold ?? 0.7;
214
+
215
+ const simhashFilter = new SimHashFilter();
216
+ const minhashFilter = new MinHashFilter();
217
+
218
+ const candidatePairs: Stage1CandidatePair[] = [];
219
+ const seen = new Set<string>();
220
+
221
+ const memoryIds = Array.from(memories.keys());
222
+
223
+ for (let i = 0; i < memoryIds.length; i++) {
224
+ const id1 = memoryIds[i];
225
+ const simhash1 = allSimhashes.get(id1);
226
+ const minhash1 = allMinhashes.get(id1);
227
+
228
+ if (!simhash1 || !minhash1) continue;
229
+
230
+ for (let j = i + 1; j < memoryIds.length; j++) {
231
+ const id2 = memoryIds[j];
232
+ const simhash2 = allSimhashes.get(id2);
233
+ const minhash2 = allMinhashes.get(id2);
234
+
235
+ if (!simhash2 || !minhash2) continue;
236
+
237
+ const pairKey = id1 < id2 ? `${id1}:${id2}` : `${id2}:${id1}`;
238
+ if (seen.has(pairKey)) continue;
239
+
240
+ const simhashDist = simhashFilter.hammingDistance(simhash1, simhash2);
241
+ const simhashMatch = simhashDist <= simhashThreshold;
242
+
243
+ const minhashSim = minhashFilter.jaccardSimilarity(minhash1, minhash2);
244
+ const minhashMatch = minhashSim >= minhashThreshold;
245
+
246
+ if (simhashMatch || minhashMatch) {
247
+ seen.add(pairKey);
248
+ candidatePairs.push({
249
+ memoryId1: id1,
250
+ memoryId2: id2,
251
+ simhashDistance: simhashDist,
252
+ minhashSimilarity: minhashSim,
253
+ matched: simhashMatch && minhashMatch ? 'both' : simhashMatch ? 'simhash' : 'minhash',
254
+ });
255
+ }
256
+ }
257
+ }
258
+
259
+ return candidatePairs;
260
+ }
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Semantic ranking using embeddings (Stage 2 of two-stage detection).
3
+ * Ranks candidates from Stage 1 by semantic similarity using cosine distance.
4
+ */
5
+
6
+ import type { Memory } from '../../../db/drizzle/schema.js';
7
+ import { cosineSimilarity } from '../../../core/utils/vector-operations.js';
8
+
9
+ export interface RankedCandidate {
10
+ memoryId1: string;
11
+ memoryId2: string;
12
+ memory1: Memory;
13
+ memory2: Memory;
14
+ cosineSimilarity: number;
15
+ confidenceLevel: 'high' | 'medium' | 'low';
16
+ mergeReason: string;
17
+ }
18
+
19
+ function calculateConfidence(
20
+ memory1: Memory,
21
+ memory2: Memory,
22
+ cosineSim: number
23
+ ): 'high' | 'medium' | 'low' {
24
+ if (cosineSim >= 0.90) {
25
+ const factors = calculateConfidenceFactors(memory1, memory2);
26
+ if (factors.sameType && factors.tagOverlap > 0.5) {
27
+ return 'high';
28
+ }
29
+ if (factors.sameType || factors.tagOverlap > 0.3) {
30
+ return 'high';
31
+ }
32
+ return 'medium';
33
+ }
34
+
35
+ if (cosineSim >= 0.80) {
36
+ const factors = calculateConfidenceFactors(memory1, memory2);
37
+ if (factors.sameType && factors.contentLengthSimilarity > 0.7) {
38
+ return 'medium';
39
+ }
40
+ return 'medium';
41
+ }
42
+
43
+ return 'low';
44
+ }
45
+
46
+ interface ConfidenceFactors {
47
+ sameType: boolean;
48
+ tagOverlap: number;
49
+ contentLengthSimilarity: number;
50
+ }
51
+
52
+ function calculateConfidenceFactors(memory1: Memory, memory2: Memory): ConfidenceFactors {
53
+ const sameType = memory1.type === memory2.type;
54
+
55
+ const tags1 = new Set(memory1.tags || []);
56
+ const tags2 = new Set(memory2.tags || []);
57
+ const overlap = Array.from(tags1).filter((tag) => tags2.has(tag)).length;
58
+ const union = new Set([...tags1, ...tags2]).size;
59
+ const tagOverlap = union === 0 ? 0 : overlap / union;
60
+
61
+ const len1 = memory1.content.length;
62
+ const len2 = memory2.content.length;
63
+ const maxLen = Math.max(len1, len2);
64
+ const minLen = Math.min(len1, len2);
65
+ const contentLengthSimilarity = maxLen === 0 ? 1 : minLen / maxLen;
66
+
67
+ return {
68
+ sameType,
69
+ tagOverlap,
70
+ contentLengthSimilarity,
71
+ };
72
+ }
73
+
74
+ function generateMergeReason(
75
+ memory1: Memory,
76
+ memory2: Memory,
77
+ cosineSim: number,
78
+ confidenceLevel: 'high' | 'medium' | 'low'
79
+ ): string {
80
+ const factors = calculateConfidenceFactors(memory1, memory2);
81
+ const parts: string[] = [];
82
+
83
+ parts.push(`Semantic similarity: ${(cosineSim * 100).toFixed(1)}%`);
84
+
85
+ if (factors.sameType) {
86
+ parts.push(`Same type (${memory1.type})`);
87
+ } else {
88
+ parts.push(`Different types (${memory1.type} vs ${memory2.type})`);
89
+ }
90
+
91
+ if (factors.tagOverlap > 0) {
92
+ parts.push(`${(factors.tagOverlap * 100).toFixed(0)}% tag overlap`);
93
+ }
94
+
95
+ const len1 = memory1.content.length;
96
+ const len2 = memory2.content.length;
97
+ const diffPercent = Math.abs(len1 - len2) / Math.max(len1, len2);
98
+ parts.push(`Content length difference: ${(diffPercent * 100).toFixed(0)}%`);
99
+
100
+ parts.push(`Confidence: ${confidenceLevel}`);
101
+
102
+ return parts.join(' • ');
103
+ }
104
+
105
+ export async function rankCandidates(
106
+ candidates: Array<{ memoryId1: string; memoryId2: string }>,
107
+ memories: Map<string, Memory>,
108
+ embeddings: Map<string, number[]>,
109
+ options: {
110
+ semanticThreshold?: number;
111
+ topK?: number;
112
+ }
113
+ ): Promise<RankedCandidate[]> {
114
+ const semanticThreshold = options.semanticThreshold ?? 0.85;
115
+ const topK = options.topK ?? 10;
116
+
117
+ const rankedCandidates: RankedCandidate[] = [];
118
+
119
+ for (const { memoryId1, memoryId2 } of candidates) {
120
+ const memory1 = memories.get(memoryId1);
121
+ const memory2 = memories.get(memoryId2);
122
+ const embedding1 = embeddings.get(memoryId1);
123
+ const embedding2 = embeddings.get(memoryId2);
124
+
125
+ if (!memory1 || !memory2 || !embedding1 || !embedding2) {
126
+ continue;
127
+ }
128
+
129
+ const similarity = cosineSimilarity(embedding1, embedding2);
130
+
131
+ if (similarity < semanticThreshold) {
132
+ continue;
133
+ }
134
+
135
+ const confidence = calculateConfidence(memory1, memory2, similarity);
136
+ const mergeReason = generateMergeReason(memory1, memory2, similarity, confidence);
137
+
138
+ rankedCandidates.push({
139
+ memoryId1,
140
+ memoryId2,
141
+ memory1,
142
+ memory2,
143
+ cosineSimilarity: similarity,
144
+ confidenceLevel: confidence,
145
+ mergeReason,
146
+ });
147
+ }
148
+
149
+ rankedCandidates.sort((a, b) => b.cosineSimilarity - a.cosineSimilarity);
150
+
151
+ const selectedByMemory = new Map<string, number>();
152
+ const filtered: RankedCandidate[] = [];
153
+
154
+ for (const candidate of rankedCandidates) {
155
+ const count1 = (selectedByMemory.get(candidate.memoryId1) || 0) + 1;
156
+ const count2 = (selectedByMemory.get(candidate.memoryId2) || 0) + 1;
157
+
158
+ if (count1 <= topK && count2 <= topK) {
159
+ filtered.push(candidate);
160
+ selectedByMemory.set(candidate.memoryId1, count1);
161
+ selectedByMemory.set(candidate.memoryId2, count2);
162
+ }
163
+ }
164
+
165
+ return filtered;
166
+ }
167
+
168
+ export function analyzePair(
169
+ memory1: Memory,
170
+ memory2: Memory,
171
+ embedding1: number[],
172
+ embedding2: number[]
173
+ ): {
174
+ cosineSimilarity: number;
175
+ confidenceLevel: 'high' | 'medium' | 'low';
176
+ mergeReason: string;
177
+ factors: {
178
+ sameType: boolean;
179
+ tagOverlap: number;
180
+ contentLengthSimilarity: number;
181
+ };
182
+ } {
183
+ const similarity = cosineSimilarity(embedding1, embedding2);
184
+ const confidence = calculateConfidence(memory1, memory2, similarity);
185
+ const mergeReason = generateMergeReason(memory1, memory2, similarity, confidence);
186
+ const factors = calculateConfidenceFactors(memory1, memory2);
187
+
188
+ return {
189
+ cosineSimilarity: similarity,
190
+ confidenceLevel: confidence,
191
+ mergeReason,
192
+ factors,
193
+ };
194
+ }