squish-memory 1.1.5 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) 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 +46 -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/core/algorithms/index.ts +39 -0
  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/core/lib/db-client.ts +168 -0
  81. package/core/lib/parse-embedding.ts +59 -0
  82. package/core/lib/schemas.ts +102 -0
  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/core/memory/index.ts +11 -0
  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/core/places/index.ts +14 -0
  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 +581 -0
  140. package/core/scheduler/heartbeat.ts +91 -0
  141. package/core/scheduler/index.ts +8 -0
  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/core/search/index.ts +4 -0
  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/core/session/index.ts +7 -0
  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/core/snapshots/cleanup.ts +13 -0
  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/core/summarization/cleanup.ts +13 -0
  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/core/utils/vector-operations.ts +135 -0
  185. package/core/utils/version-management.ts +74 -0
  186. package/core/worker.ts +324 -0
  187. package/db/adapter.ts +215 -0
  188. package/db/bootstrap.ts +1055 -0
  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/dist/config.d.ts +40 -17
  220. package/dist/config.js +150 -198
  221. package/dist/core/adapters/types.d.ts +13 -33
  222. package/dist/core/adapters/types.js +1 -1
  223. package/dist/core/agent-preferences.d.ts +16 -0
  224. package/dist/core/agent-preferences.js +124 -0
  225. package/dist/core/algorithms/safety/safety-checks.d.ts +1 -5
  226. package/dist/core/algorithms/types.d.ts +0 -8
  227. package/dist/core/associations.d.ts +3 -1
  228. package/dist/core/associations.js +37 -1
  229. package/dist/core/beliefs/decay.d.ts +27 -0
  230. package/dist/core/beliefs/decay.js +217 -0
  231. package/dist/core/beliefs/extractor.d.ts +9 -0
  232. package/dist/core/beliefs/extractor.js +113 -0
  233. package/dist/core/beliefs/store.d.ts +46 -0
  234. package/dist/core/beliefs/store.js +466 -0
  235. package/dist/core/beliefs/types.d.ts +28 -0
  236. package/dist/core/beliefs/types.js +2 -0
  237. package/dist/core/commands/mcp-server.d.ts +0 -1
  238. package/dist/core/commands/mcp-server.js +4 -737
  239. package/dist/core/commands/remember.d.ts +24 -0
  240. package/dist/core/commands/remember.js +144 -0
  241. package/dist/core/{toon.d.ts → compression.d.ts} +6 -4
  242. package/dist/core/{toon.js → compression.js} +8 -8
  243. package/dist/core/context/agent-context.js +1 -1
  244. package/dist/core/embeddings/embeddings.d.ts +29 -0
  245. package/dist/core/embeddings/embeddings.js +546 -0
  246. package/dist/core/embeddings/google-multimodal.js +6 -2
  247. package/dist/core/{local-embeddings.d.ts → embeddings/local-embeddings.d.ts} +1 -1
  248. package/dist/core/embeddings/local-embeddings.js +11 -0
  249. package/dist/core/embeddings/qmd-client.js +1 -1
  250. package/dist/core/embeddings/transformers-local.d.ts +64 -0
  251. package/dist/core/embeddings/transformers-local.js +213 -0
  252. package/dist/core/embeddings.d.ts +1 -28
  253. package/dist/core/embeddings.js +2 -453
  254. package/dist/core/graph/entity-deduplicator.d.ts +24 -0
  255. package/dist/core/graph/entity-deduplicator.js +183 -0
  256. package/dist/core/graph/graph-builder.d.ts +46 -0
  257. package/dist/core/graph/graph-builder.js +174 -0
  258. package/dist/core/graph/graph-traversal.d.ts +80 -0
  259. package/dist/core/graph/graph-traversal.js +315 -0
  260. package/dist/core/graph/index.d.ts +19 -0
  261. package/dist/core/graph/index.js +13 -0
  262. package/dist/core/graph/llm-entity-extractor.d.ts +49 -0
  263. package/dist/core/graph/llm-entity-extractor.js +313 -0
  264. package/dist/core/graph/multi-hop-retrieval.d.ts +48 -0
  265. package/dist/core/graph/multi-hop-retrieval.js +215 -0
  266. package/dist/core/graph/relationship-extractor.d.ts +48 -0
  267. package/dist/core/graph/relationship-extractor.js +351 -0
  268. package/dist/core/hooks/agent-hooks.d.ts +10 -1
  269. package/dist/core/hooks/agent-hooks.js +301 -24
  270. package/dist/core/hot-cache.d.ts +86 -0
  271. package/dist/core/hot-cache.js +285 -0
  272. package/dist/core/index.d.ts +9 -9
  273. package/dist/core/index.js +9 -12
  274. package/dist/core/ingestion/core-memory.d.ts +2 -2
  275. package/dist/core/ingestion/core-memory.js +3 -3
  276. package/dist/core/ingestion/learnings.js +3 -0
  277. package/dist/core/ingestion/signal-engine.d.ts +41 -0
  278. package/dist/core/ingestion/signal-engine.js +201 -0
  279. package/dist/core/{obsidian-vault.d.ts → integrations/obsidian-vault.d.ts} +2 -1
  280. package/dist/core/{obsidian-vault.js → integrations/obsidian-vault.js} +69 -7
  281. package/dist/core/lib/parse-embedding.d.ts +9 -0
  282. package/dist/core/lib/parse-embedding.js +58 -0
  283. package/dist/core/lib/schemas.d.ts +57 -54
  284. package/dist/core/lib/types.d.ts +45 -0
  285. package/dist/core/lib/types.js +6 -0
  286. package/dist/core/lib/utils.d.ts +4 -0
  287. package/dist/core/lib/utils.js +55 -0
  288. package/dist/core/lifecycle.d.ts +0 -1
  289. package/dist/core/lifecycle.js +13 -23
  290. package/dist/core/logger.d.ts +1 -0
  291. package/dist/core/logger.js +14 -8
  292. package/dist/core/mcp/tools.d.ts +0 -2
  293. package/dist/core/mcp/tools.js +0 -87
  294. package/dist/core/mcp/types.d.ts +25 -253
  295. package/dist/core/mcp/types.js +2 -2
  296. package/dist/core/memory/categorizer.js +1 -0
  297. package/dist/core/memory/consolidation.js +2 -28
  298. package/dist/core/memory/entity-extractor.d.ts +4 -0
  299. package/dist/core/memory/entity-extractor.js +30 -16
  300. package/dist/core/memory/explain.d.ts +18 -0
  301. package/dist/core/memory/explain.js +92 -0
  302. package/dist/core/memory/fact-deriver.d.ts +31 -0
  303. package/dist/core/memory/fact-deriver.js +236 -0
  304. package/dist/core/memory/hybrid-retrieval.d.ts +14 -16
  305. package/dist/core/memory/hybrid-retrieval.js +25 -127
  306. package/dist/core/memory/hybrid-scorer.js +6 -23
  307. package/dist/core/memory/hybrid-search.d.ts +10 -7
  308. package/dist/core/memory/hybrid-search.js +458 -221
  309. package/dist/core/memory/importance.d.ts +0 -17
  310. package/dist/core/memory/importance.js +1 -58
  311. package/dist/core/memory/index.d.ts +1 -0
  312. package/dist/core/memory/index.js +1 -0
  313. package/dist/core/memory/memories.d.ts +13 -17
  314. package/dist/core/memory/memories.js +78 -75
  315. package/dist/core/memory/memory-lifecycle.d.ts +2 -2
  316. package/dist/core/memory/memory-lifecycle.js +10 -18
  317. package/dist/core/memory/normalization.d.ts +1 -16
  318. package/dist/core/memory/path-strengthener.d.ts +39 -0
  319. package/dist/core/memory/path-strengthener.js +150 -0
  320. package/dist/core/memory/query-processor.js +37 -3
  321. package/dist/core/memory/retrieval-feedback.d.ts +70 -0
  322. package/dist/core/memory/retrieval-feedback.js +213 -0
  323. package/dist/core/memory/stale-cleaner.d.ts +26 -0
  324. package/dist/core/memory/stale-cleaner.js +97 -0
  325. package/dist/core/memory/stats.d.ts +10 -0
  326. package/dist/core/memory/stats.js +8 -3
  327. package/dist/core/memory/trigger-detector.d.ts +8 -1
  328. package/dist/core/memory/trigger-detector.js +42 -5
  329. package/dist/core/places/index.d.ts +1 -1
  330. package/dist/core/places/index.js +1 -1
  331. package/dist/core/places/places.d.ts +13 -13
  332. package/dist/core/places/places.js +27 -27
  333. package/dist/core/places/rules.js +23 -23
  334. package/dist/core/places/walking.d.ts +3 -3
  335. package/dist/core/places/walking.js +7 -7
  336. package/dist/core/projects.js +8 -0
  337. package/dist/core/runtime/trust-report.d.ts +102 -0
  338. package/dist/core/runtime/trust-report.js +107 -0
  339. package/dist/core/runtime/trust-state.d.ts +12 -0
  340. package/dist/core/runtime/trust-state.js +309 -0
  341. package/dist/core/scheduler/cron-scheduler.d.ts +1 -1
  342. package/dist/core/scheduler/cron-scheduler.js +164 -3
  343. package/dist/core/scheduler/job-runner.js +1 -1
  344. package/dist/core/search/qmd-wrapper.d.ts +36 -0
  345. package/dist/core/search/qmd-wrapper.js +58 -0
  346. package/dist/core/session/auto-load.js +28 -3
  347. package/dist/core/session/entity-tracker.d.ts +62 -0
  348. package/dist/core/session/entity-tracker.js +287 -0
  349. package/dist/core/session/reference-resolver.d.ts +26 -0
  350. package/dist/core/session/reference-resolver.js +121 -0
  351. package/dist/core/session/self-iteration-job.d.ts +15 -0
  352. package/dist/core/session/self-iteration-job.js +163 -58
  353. package/dist/core/session/working-set.d.ts +50 -0
  354. package/dist/core/session/working-set.js +212 -0
  355. package/dist/core/snapshots/creation.d.ts +2 -8
  356. package/dist/core/snapshots/creation.js +3 -12
  357. package/dist/core/utils/summarization-helpers.d.ts +0 -4
  358. package/dist/core/utils/summarization-helpers.js +1 -6
  359. package/dist/db/bootstrap.d.ts +2 -0
  360. package/dist/db/bootstrap.js +229 -280
  361. package/dist/db/drizzle/schema-sqlite.d.ts +702 -1
  362. package/dist/db/drizzle/schema-sqlite.js +83 -4
  363. package/dist/db/drizzle/schema.d.ts +653 -1
  364. package/dist/db/drizzle/schema.js +93 -4
  365. package/dist/db/migrations/associations.d.ts +6 -0
  366. package/dist/db/migrations/associations.js +29 -0
  367. package/dist/db/migrations/beliefs.d.ts +10 -0
  368. package/dist/db/migrations/beliefs.js +76 -0
  369. package/dist/db/migrations/core-memory.d.ts +6 -0
  370. package/dist/db/migrations/core-memory.js +29 -0
  371. package/dist/db/migrations/fts.d.ts +6 -0
  372. package/dist/db/migrations/fts.js +52 -0
  373. package/dist/db/migrations/index.d.ts +25 -0
  374. package/dist/db/migrations/index.js +51 -0
  375. package/dist/db/migrations/indexes.d.ts +6 -0
  376. package/dist/db/migrations/indexes.js +30 -0
  377. package/dist/db/migrations/learnings.d.ts +7 -0
  378. package/dist/db/migrations/learnings.js +26 -0
  379. package/dist/db/migrations/maintenance.d.ts +6 -0
  380. package/dist/db/migrations/maintenance.js +61 -0
  381. package/dist/db/migrations/memories.d.ts +7 -0
  382. package/dist/db/migrations/memories.js +16 -0
  383. package/dist/db/migrations/memory-places.d.ts +6 -0
  384. package/dist/db/migrations/memory-places.js +29 -0
  385. package/dist/db/migrations/places.d.ts +6 -0
  386. package/dist/db/migrations/places.js +43 -0
  387. package/dist/db/migrations/projects.d.ts +3 -0
  388. package/dist/db/migrations/projects.js +13 -0
  389. package/dist/db/migrations/tier-conversion.d.ts +7 -0
  390. package/dist/db/migrations/tier-conversion.js +20 -0
  391. package/dist/db/schema/beliefs.d.ts +9 -0
  392. package/dist/db/schema/beliefs.js +46 -0
  393. package/dist/db/schema/generator.d.ts +38 -0
  394. package/dist/db/schema/generator.js +108 -0
  395. package/dist/db/schema/index.d.ts +19 -20
  396. package/dist/db/schema/index.js +25 -79
  397. package/dist/db/schema/learnings.d.ts +7 -0
  398. package/dist/db/schema/learnings.js +30 -0
  399. package/dist/db/schema/memories.d.ts +7 -0
  400. package/dist/db/schema/memories.js +81 -0
  401. package/dist/db/schema/projects.d.ts +4 -0
  402. package/dist/db/schema/projects.js +31 -0
  403. package/dist/packages/mcp/src/index.d.ts +3 -0
  404. package/dist/packages/mcp/src/index.js +733 -0
  405. package/mcp.json.example +8 -11
  406. package/package.json +57 -76
  407. package/packages/cli/package.json +22 -0
  408. package/packages/cli/src/commands/clean.ts +68 -0
  409. package/packages/cli/src/commands/context.ts +79 -0
  410. package/packages/cli/src/commands/doctor.ts +357 -0
  411. package/packages/cli/src/commands/forget.ts +72 -0
  412. package/packages/cli/src/commands/health.ts +36 -0
  413. package/packages/cli/src/commands/inspect.ts +41 -0
  414. package/packages/cli/src/commands/link.ts +50 -0
  415. package/packages/cli/src/commands/migrate.ts +93 -0
  416. package/packages/cli/src/commands/recall.ts +99 -0
  417. package/packages/cli/src/commands/recent.ts +57 -0
  418. package/packages/cli/src/commands/remember.ts +139 -0
  419. package/packages/cli/src/commands/run.ts +58 -0
  420. package/packages/cli/src/commands/stale.ts +43 -0
  421. package/packages/cli/src/commands/stats.ts +42 -0
  422. package/packages/cli/src/index.ts +57 -0
  423. package/packages/cli/tsconfig.json +24 -0
  424. package/packages/mcp/package.json +26 -0
  425. package/packages/mcp/src/index.ts +877 -0
  426. package/packages/mcp/tsconfig.json +20 -0
  427. package/skills/squish-memory/SKILL.md +38 -35
  428. package/skills/squish-memory/{scripts/install.sh → install.sh} +1 -1
  429. package/skills/squish-memory/references/claude-desktop.json +12 -0
  430. package/skills/squish-memory/references/openclaw.json +13 -0
  431. package/skills/squish-memory/references/opencode.json +14 -0
  432. package/config/hooks/claude-code-hooks.json +0 -39
  433. package/config/hooks/cursor-hooks.json +0 -30
  434. package/config/hooks/opencode-hooks.json +0 -30
  435. package/config/hooks/windsurf-hooks.json +0 -30
  436. package/config/mcp-cli-fallback-policy.json +0 -22
  437. package/config/mcp.json +0 -38
  438. package/config/plugin-manifest.json +0 -101
  439. package/config/plugin-manifest.schema.json +0 -244
  440. package/config/plugin.json +0 -32
  441. package/config/remote-memory-policy.json +0 -32
  442. package/core/commands/context-paging.md +0 -51
  443. package/core/commands/context-status.md +0 -22
  444. package/core/commands/context.md +0 -5
  445. package/core/commands/core-memory.md +0 -56
  446. package/core/commands/health.md +0 -5
  447. package/core/commands/init.md +0 -39
  448. package/core/commands/merge.md +0 -113
  449. package/core/commands/recall.md +0 -5
  450. package/core/commands/remember.md +0 -11
  451. package/core/commands/search.md +0 -10
  452. package/dist/core/commands/managed-sync.d.ts +0 -10
  453. package/dist/core/commands/managed-sync.js +0 -64
  454. package/dist/core/external-folder/index.d.ts +0 -102
  455. package/dist/core/external-folder/index.js +0 -294
  456. package/dist/core/namespaces/index.d.ts +0 -71
  457. package/dist/core/namespaces/index.js +0 -305
  458. package/dist/core/namespaces/uri-parser.d.ts +0 -31
  459. package/dist/core/namespaces/uri-parser.js +0 -74
  460. package/dist/core/search/qmd-search.d.ts +0 -61
  461. package/dist/core/search/qmd-search.js +0 -178
  462. package/dist/core/session-hooks/self-iteration-job.d.ts +0 -20
  463. package/dist/core/session-hooks/self-iteration-job.js +0 -282
  464. package/dist/core/session-hooks/session-hooks.d.ts +0 -18
  465. package/dist/core/session-hooks/session-hooks.js +0 -58
  466. package/dist/core/snapshots.d.ts +0 -29
  467. package/dist/core/snapshots.js +0 -220
  468. package/dist/core/sync/qmd-sync.d.ts +0 -94
  469. package/dist/core/sync/qmd-sync.js +0 -201
  470. package/dist/index.d.ts +0 -7
  471. package/dist/index.js +0 -1677
  472. package/dist/vendor/sql.js/sql-wasm.wasm +0 -0
  473. package/dist/webui/server.d.ts +0 -5
  474. package/dist/webui/server.js +0 -642
  475. package/generated/mcp/manifest.json +0 -23
  476. package/generated/mcp/mcp-servers.json +0 -25
  477. package/generated/mcp/mcporter.json +0 -34
  478. package/generated/mcp/openclaw-memory-qmd.json +0 -17
  479. package/generated/mcp/runtime.json +0 -12
  480. package/scripts/README.md +0 -60
  481. package/scripts/build-release.sh +0 -36
  482. package/scripts/check-secrets.js +0 -132
  483. package/scripts/copy-runtime-assets.mjs +0 -26
  484. package/scripts/generate-mcp.mjs +0 -264
  485. package/scripts/github-release.sh +0 -77
  486. package/scripts/init-dirs.mjs +0 -13
  487. package/scripts/install-claude-code.sh +0 -85
  488. package/scripts/install-cursor.sh +0 -56
  489. package/scripts/install-hooks.sh +0 -73
  490. package/scripts/install-interactive.mjs +0 -357
  491. package/scripts/install-opencode.sh +0 -75
  492. package/scripts/install-plugin.mjs +0 -415
  493. package/scripts/install-windsurf.sh +0 -67
  494. package/scripts/remote-preflight.mjs +0 -62
  495. package/scripts/squish-fallback.mjs +0 -132
  496. package/scripts/test-interactive.mjs +0 -131
  497. package/scripts/verify-mcp.mjs +0 -214
  498. package/skills/squish-memory/scripts/install.mjs +0 -335
  499. package/skills/squish-memory/write_skill.js +0 -2
@@ -0,0 +1,733 @@
1
+ #!/usr/bin/env node
2
+ // CRITICAL: Redirect console.log to stderr to prevent JSON-RPC stream corruption
3
+ // MCP stdio requires stdout to contain ONLY valid JSON-RPC messages
4
+ console.log = console.error;
5
+ console.info = console.error;
6
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
9
+ import express from "express";
10
+ import { z } from "zod";
11
+ import { config } from "../../../config.js";
12
+ import { getDb } from "../../../db/index.js";
13
+ import { getSchema } from "../../../db/schema.js";
14
+ import { eq } from "drizzle-orm";
15
+ import { startWorker, stopWorker } from "../../../core/worker.js";
16
+ import { initializeScheduler } from "../../../core/scheduler/cron-scheduler.js";
17
+ import { filterByDateRange } from "../../../core/lib/utils.js";
18
+ import { buildContextState, buildHealthState, buildInspectState, buildStatsState, resolveProjectScope, } from "../../../core/runtime/trust-state.js";
19
+ import { rememberMemory, search as searchMemories, getMemory, getRecent } from "../../../core/memory/memories.js";
20
+ import { getQMDClient } from "../../../core/embeddings/qmd-client.js";
21
+ import { createAssociation, getRelatedMemories } from "../../../core/associations.js";
22
+ import { createLearning } from "../../../core/ingestion/learnings.js";
23
+ import { getAllProjects } from "../../../core/projects.js";
24
+ const SERVER_NAME = "squish-memory";
25
+ const SERVER_VERSION = "1.2.0";
26
+ // Create server instance ONCE (not per-session)
27
+ const { server: SQUISH_SERVER, toolCount: SQUISH_TOOL_COUNT } = createSquishServer();
28
+ console.error(`[MCP] Server created with ${SQUISH_TOOL_COUNT} tools`);
29
+ function parseArgs() {
30
+ const args = process.argv.slice(2);
31
+ let mode = "stdio";
32
+ let port = config.mcpServerPort || 8767;
33
+ let health = false;
34
+ for (let i = 0; i < args.length; i++) {
35
+ if (args[i] === "--http" || args[i] === "-h") {
36
+ mode = "http";
37
+ }
38
+ else if (args[i] === "--stdio" || args[i] === "-s") {
39
+ mode = "stdio";
40
+ }
41
+ else if (args[i] === "--port" || args[i] === "-p") {
42
+ port = parseInt(args[i + 1], 10) || 8767;
43
+ i++;
44
+ }
45
+ else if (args[i] === "--health" || args[i] === "--check") {
46
+ health = true;
47
+ }
48
+ }
49
+ if (process.env.SQUISH_MCP_MODE === "http") {
50
+ mode = "http";
51
+ }
52
+ return { mode, port, health };
53
+ }
54
+ function safeRegisterTool(server, name, definition, handler) {
55
+ try {
56
+ server.registerTool(name, definition, handler);
57
+ console.error(`[MCP] Registered tool: ${name}`);
58
+ return true;
59
+ }
60
+ catch (error) {
61
+ console.error(`[MCP] Failed to register tool ${name}:`, error);
62
+ return false;
63
+ }
64
+ }
65
+ function createSquishServer() {
66
+ const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION }, { capabilities: { tools: {} } });
67
+ let toolCount = 0;
68
+ console.error(`[MCP] Starting tool registration...`);
69
+ // squish_timeline - 3-layer progressive disclosure
70
+ if (safeRegisterTool(server, "squish_timeline", {
71
+ description: "3-layer progressive disclosure - index (~50 tokens), timeline (~200 tokens), detail (~2000 tokens)",
72
+ inputSchema: {
73
+ query: z.string().describe("Search query"),
74
+ depth: z.enum(["index", "timeline", "detail"]).default("index").describe("Progressive disclosure depth"),
75
+ limit: z.number().min(1).max(100).default(10).describe("Max results"),
76
+ project: z.string().optional().describe("Project path")
77
+ }
78
+ }, async ({ query, depth = "index", limit = 10, project }) => {
79
+ const { getTimeline } = await import('../../../core/adapters/timeline.js');
80
+ const result = await getTimeline(query, depth, limit, project);
81
+ const formatted = result.results.map((r, i) => {
82
+ if (depth === "index") {
83
+ return `${i + 1}. ${r.title}`;
84
+ }
85
+ else if (depth === "timeline") {
86
+ return `${i + 1}. [${r.type}] ${r.content} (${r.tags?.join(', ') || 'no tags'})`;
87
+ }
88
+ else {
89
+ return `${i + 1}. [${r.type}] ${r.content?.substring(0, 200)}...`;
90
+ }
91
+ }).join("\n");
92
+ return { content: [{ type: "text", text: `Timeline (${depth}, ~${result.tokenEstimate} tokens):\n\n${formatted}` }] };
93
+ }))
94
+ toolCount++;
95
+ // squish_remember - UNIFIED MEMORY WRITE
96
+ // Single smart write path: auto-detects intent and routes to memory or learning
97
+ if (safeRegisterTool(server, "squish_remember", {
98
+ description: "Store any memory or learning. System auto-detects type and routes appropriately. This is THE memory write tool for agents - handles hot/cold tiers, confidence, and all memory types.",
99
+ inputSchema: {
100
+ content: z.string().describe("What to remember - can be a fact, decision, lesson, observation, or note"),
101
+ project: z.string().optional().describe("Project path (auto-detected if not provided)"),
102
+ tags: z.array(z.string()).optional().describe("Optional tags for organization"),
103
+ tier: z.enum(["hot", "cold"]).default("hot").describe("Memory tier: hot=active/frequently accessed, cold=archived (simplified, warm removed)"),
104
+ type: z.enum(["observation", "fact", "decision", "context", "preference", "note"]).optional().describe("Memory type - auto-detected if not provided"),
105
+ learningType: z.enum(["success", "failure", "fix", "insight"]).optional().describe("Learning type when routing to learning storage"),
106
+ confidence: z.number().min(0).max(100).optional().describe("Confidence level 0-100 (default: auto-calculated)"),
107
+ source: z.string().optional().describe("Source of memory: mcp, cli, voice, chat, document (default: mcp)"),
108
+ route: z.enum(["auto", "memory", "learning", "note"]).default("auto").describe("Force routing: auto=detect, memory=store as memory, learning=store as learning, note=store as note"),
109
+ pin: z.boolean().default(false).describe("Pin memory to prevent pruning/consolidation"),
110
+ unpin: z.boolean().default(false).describe("Unpin memory")
111
+ }
112
+ }, async ({ content, project, tags = [], tier = "hot", type, learningType, confidence, source, route = "auto", pin = false, unpin = false }) => {
113
+ // Import detection function
114
+ const { detectMemorySignals } = await import('../../../core/memory/trigger-detector.js');
115
+ const signals = detectMemorySignals(content);
116
+ let routing = "memory";
117
+ let inferredType = type || signals.suggestedType;
118
+ let routingReason = "";
119
+ // Check for learning patterns if auto mode
120
+ if (route === "auto") {
121
+ const hasLessonPattern = /(\bfailed\s+because\b|\blesson\s+learned\b|\bnext\s+time\b|\broot\s+cause\b|\bsuccess\b.*\bbecause\b|\bi\s+learned\b|\binsight\b)/i.test(content);
122
+ const hasLearningType = /(\bsuccess\b|\bfailure\b|\bfix\b|\binsight\b)/i.test(content);
123
+ // Enhanced learning detection from rationale patterns
124
+ const hasHackPattern = /(\bHACK\b|\bworkaround\b|\btemporary\s+fix\b)/i.test(content);
125
+ const hasFixmePattern = /(\bFIXME\b|\bXXX\b|\bbug\b.*\bfix\b)/i.test(content);
126
+ if (hasLessonPattern || hasLearningType || hasHackPattern || hasFixmePattern) {
127
+ routing = "learning";
128
+ if (hasHackPattern || hasFixmePattern) {
129
+ routingReason = "Detected code pattern (HACK/FIXME)";
130
+ }
131
+ else {
132
+ routingReason = "Detected learning pattern in content";
133
+ }
134
+ }
135
+ else if (signals.suggestedType === 'task') {
136
+ routing = "memory";
137
+ routingReason = "Detected TODO pattern";
138
+ }
139
+ else if (signals.suggestedType === 'observation' && /\b(note|note\s+that|log|remember)\b/i.test(content)) {
140
+ routing = "note";
141
+ routingReason = "Detected note pattern";
142
+ }
143
+ else {
144
+ routing = "memory";
145
+ routingReason = `Detected as ${inferredType}`;
146
+ }
147
+ }
148
+ else if (route === "learning") {
149
+ routing = "learning";
150
+ routingReason = "Override: forced to learning";
151
+ }
152
+ else if (route === "note") {
153
+ routing = "note";
154
+ routingReason = "Override: forced to note";
155
+ }
156
+ else {
157
+ routing = "memory";
158
+ routingReason = "Override: forced to memory";
159
+ }
160
+ let result;
161
+ if (routing === "learning") {
162
+ // Determine learning type from content or override
163
+ let finalLearningType = learningType || "insight";
164
+ if (!learningType) {
165
+ if (/(\bsuccess\b|\bworked\b|\bfinished\b)/i.test(content))
166
+ finalLearningType = "success";
167
+ else if (/(\bfailed\b|\berror\b|\bbroke\b)/i.test(content))
168
+ finalLearningType = "failure";
169
+ else if (/(\bfix\b|\b workaround\b|\bsolved\b)/i.test(content))
170
+ finalLearningType = "fix";
171
+ }
172
+ const learning = await createLearning({
173
+ type: finalLearningType,
174
+ content,
175
+ project,
176
+ autoLink: true
177
+ });
178
+ result = { id: learning.id, type: "learning", learningType: finalLearningType, content };
179
+ }
180
+ else {
181
+ // Store as memory with all options
182
+ const memory = await rememberMemory({
183
+ content,
184
+ type: inferredType,
185
+ tags,
186
+ project,
187
+ tier,
188
+ source: source || 'mcp'
189
+ });
190
+ // Handle pin/unpin after creation
191
+ if (pin) {
192
+ const { pinMemory } = await import('../../../core/security/governance.js');
193
+ await pinMemory(memory.id);
194
+ }
195
+ else if (unpin) {
196
+ const { unpinMemory } = await import('../../../core/security/governance.js');
197
+ await unpinMemory(memory.id);
198
+ }
199
+ result = { id: memory.id, type: "memory", memoryType: inferredType, tier, content, pined: pin };
200
+ // Auto-update knowledge graph (fire-and-forget)
201
+ const { addMemoryToGraph } = await import('../../../core/graph/graph-builder.js');
202
+ const graphResult = await addMemoryToGraph(memory.id).catch((e) => {
203
+ console.warn('[Graph] Auto-update failed:', e.message);
204
+ return null;
205
+ });
206
+ if (graphResult) {
207
+ result.graph = { entities: graphResult.entitiesCreated, relations: graphResult.relationsCreated };
208
+ }
209
+ }
210
+ return {
211
+ content: [{
212
+ type: "text",
213
+ text: `Remembered: ${result.id}\nRouting: ${routing}\nType: ${routing === "learning" ? result.learningType : result.memoryType}\nTier: ${routing === "memory" ? tier : 'N/A'}\nPriority: ${signals.priority}\nConfidence: ${signals.confidence}\nPined: ${result.pinned}\nReason: ${routingReason}\n\n${content.substring(0, 100)}${content.length > 100 ? '...' : ''}`
214
+ }]
215
+ };
216
+ }))
217
+ toolCount++;
218
+ // squish_recall - Retrieve a memory by ID or query
219
+ if (safeRegisterTool(server, "squish_recall", {
220
+ description: "Recall memories by query, or retrieve a specific memory by ID",
221
+ inputSchema: {
222
+ query: z.string().describe("Query text or memory ID to recall"),
223
+ limit: z.number().min(1).max(100).default(5).describe("Maximum results for query recall"),
224
+ project: z.string().optional().describe("Project path filter"),
225
+ type: z.enum(["observation", "fact", "decision", "context", "preference", "note", "task"]).optional().describe("Filter by memory type"),
226
+ place: z.string().optional().describe("Filter by place (inbox, ref, wip, sandbox, board, sparks, archive)")
227
+ }
228
+ }, async ({ query, limit = 5, project, type, place }) => {
229
+ const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(query);
230
+ if (isUuid) {
231
+ const memory = await getMemory(query);
232
+ if (!memory) {
233
+ return { content: [{ type: "text", text: `Memory not found: ${query}` }], isError: true };
234
+ }
235
+ return { content: [{ type: "text", text: JSON.stringify({ ok: true, count: 1, results: [memory] }, null, 2) }] };
236
+ }
237
+ const results = await searchMemories({
238
+ query,
239
+ limit,
240
+ project,
241
+ type,
242
+ placeType: place
243
+ });
244
+ return { content: [{ type: "text", text: JSON.stringify({ ok: true, count: results.length, results }, null, 2) }] };
245
+ }))
246
+ toolCount++;
247
+ // squish_forget - Delete a memory by ID, or bulk delete with filters
248
+ if (safeRegisterTool(server, "squish_forget", {
249
+ description: "Delete a memory by ID, or bulk delete with filters (older-than, search, type)",
250
+ inputSchema: {
251
+ memoryId: z.string().optional().describe("Memory ID to delete (single)"),
252
+ olderThan: z.string().optional().describe("Bulk delete memories older than (e.g., '30 days', '6 months')"),
253
+ search: z.string().optional().describe("Search query to match specific memories"),
254
+ type: z.string().optional().describe("Filter by memory type"),
255
+ confirm: z.boolean().optional().describe("Actually delete (default is dry-run)"),
256
+ limit: z.number().optional().describe("Max memories to delete"),
257
+ project: z.string().optional().describe("Project path (defaults to current)")
258
+ }
259
+ }, async ({ memoryId, olderThan, search, type, confirm = false, limit = 100, project }) => {
260
+ const db = await getDb();
261
+ const schema = await getSchema();
262
+ const sqliteDb = db;
263
+ const proj = project || process.cwd();
264
+ // Single memory deletion
265
+ if (memoryId) {
266
+ await sqliteDb.delete(schema.memories).where(eq(schema.memories.id, memoryId));
267
+ return { content: [{ type: "text", text: `Memory deleted: ${memoryId}` }] };
268
+ }
269
+ // Bulk deletion
270
+ if (!olderThan && !search) {
271
+ return { content: [{ type: "text", text: "Error: Provide memoryId or use --older-than / --search for bulk delete" }], isError: true };
272
+ }
273
+ const results = await searchMemories({ query: search || '', type: type, limit, project: proj });
274
+ let filtered = results;
275
+ if (olderThan) {
276
+ filtered = filterByDateRange(results, '', olderThan);
277
+ }
278
+ const deleted = [];
279
+ if (confirm) {
280
+ for (const mem of filtered) {
281
+ await sqliteDb.delete(schema.memories).where(eq(schema.memories.id, mem.id));
282
+ deleted.push(mem.id);
283
+ }
284
+ }
285
+ return { content: [{ type: "text", text: JSON.stringify({ ok: true, matched: filtered.length, deleted: deleted.length, dryRun: !confirm }, null, 2) }] };
286
+ }))
287
+ toolCount++;
288
+ // squish_link - Unified graph operations (find related, add links, list)
289
+ if (safeRegisterTool(server, "squish_link", {
290
+ description: "Manage memory associations: find related memories, add links, or list associations",
291
+ inputSchema: {
292
+ action: z.enum(["find", "add", "list"]).describe("Action: find, add, or list"),
293
+ memoryId: z.string().optional().describe("Memory ID (for find action)"),
294
+ fromMemoryId: z.string().optional().describe("Source memory ID (for add action)"),
295
+ toMemoryId: z.string().optional().describe("Target memory ID (for add action)"),
296
+ type: z.string().optional().describe("Association type (for add action): relates_to, supports, contradicts, supersedes, duplicate"),
297
+ weight: z.number().min(0).max(1).default(0.5).describe("Association strength (0-1)"),
298
+ depth: z.number().min(1).max(5).default(2).describe("Graph traversal depth (for find action)"),
299
+ minWeight: z.number().min(0).max(1).default(0.3).describe("Minimum weight (for find action)")
300
+ }
301
+ }, async ({ action, memoryId, fromMemoryId, toMemoryId, type = "relates_to", weight = 0.5, depth = 2, minWeight = 0.3 }) => {
302
+ if (action === "find") {
303
+ if (!memoryId) {
304
+ return { content: [{ type: "text", text: "Error: memoryId required for find action" }], isError: true };
305
+ }
306
+ const related = await getRelatedMemories(memoryId, depth * 5);
307
+ const filtered = related.filter((r) => r.weight >= minWeight);
308
+ const formatted = filtered.map((r, i) => `${i + 1}. [${r.type || "memory"}] ${r.content?.substring(0, 100)}... (weight: ${r.weight?.toFixed(2)})`).join("\n");
309
+ return { content: [{ type: "text", text: `Found ${filtered.length} related memories:\n\n${formatted}` }] };
310
+ }
311
+ if (action === "add") {
312
+ if (!fromMemoryId || !toMemoryId) {
313
+ return { content: [{ type: "text", text: "Error: fromMemoryId and toMemoryId required for add action" }], isError: true };
314
+ }
315
+ await createAssociation(fromMemoryId, toMemoryId, type, weight);
316
+ // Auto-update knowledge graph (fire-and-forget)
317
+ try {
318
+ const { addMemoryToGraph } = await import('../../../core/graph/graph-builder.js');
319
+ await Promise.all([
320
+ addMemoryToGraph(fromMemoryId).catch(() => null),
321
+ addMemoryToGraph(toMemoryId).catch(() => null)
322
+ ]);
323
+ }
324
+ catch (e) {
325
+ // Ignore graph errors
326
+ }
327
+ return { content: [{ type: "text", text: `Association created: ${fromMemoryId} -> ${toMemoryId} (${type})` }] };
328
+ }
329
+ if (action === "list") {
330
+ const db = await getDb();
331
+ const schema = await getSchema();
332
+ const sqliteDb = db;
333
+ const associations = await sqliteDb.select().from(schema.memoryAssociations).limit(100);
334
+ return { content: [{ type: "text", text: JSON.stringify({ ok: true, count: associations.length, associations }, null, 2) }] };
335
+ }
336
+ return { content: [{ type: "text", text: "Error: invalid action. Use find, add, or list" }], isError: true };
337
+ }))
338
+ toolCount++;
339
+ // squish_context - Get project context or list registered projects
340
+ if (safeRegisterTool(server, "squish_context", {
341
+ description: "Get project context or list registered projects",
342
+ inputSchema: {
343
+ project: z.string().optional().describe("Project path"),
344
+ limit: z.number().min(1).max(50).default(10).describe("Maximum memories to return"),
345
+ listProjects: z.boolean().optional().describe("List registered projects instead of loading context")
346
+ }
347
+ }, async ({ project, limit = 10, listProjects = false }) => {
348
+ if (listProjects) {
349
+ const projects = await getAllProjects();
350
+ const scope = await resolveProjectScope(project);
351
+ return {
352
+ content: [{
353
+ type: "text",
354
+ text: JSON.stringify({
355
+ ok: true,
356
+ count: projects.length,
357
+ currentProject: scope.currentProject,
358
+ otherProjects: scope.otherProjects,
359
+ projects: projects.map((entry) => ({
360
+ id: entry.id,
361
+ name: entry.name,
362
+ path: entry.path,
363
+ resolution: entry.path === '.' ? 'legacy-placeholder' : (entry.metadata?.source === 'mcp' ? 'auto-created' : 'inferred'),
364
+ })),
365
+ nextStep: scope.nextStep,
366
+ }, null, 2),
367
+ }],
368
+ };
369
+ }
370
+ const context = await buildContextState(project, limit);
371
+ return { content: [{ type: "text", text: JSON.stringify({ ok: true, ...context }, null, 2) }] };
372
+ }))
373
+ toolCount++;
374
+ // squish_health - Check Squish system health status
375
+ if (safeRegisterTool(server, "squish_health", {
376
+ description: "Check Squish system health status",
377
+ inputSchema: {
378
+ project: z.string().optional().describe("Project path")
379
+ }
380
+ }, async ({ project }) => {
381
+ const qmdClient = await getQMDClient();
382
+ const qmdAvailable = await qmdClient.isAvailable();
383
+ const health = await buildHealthState(project);
384
+ return { content: [{ type: "text", text: JSON.stringify({
385
+ ok: health.severity !== "broken",
386
+ version: SERVER_VERSION,
387
+ qmd: qmdAvailable ? "available" : "unavailable",
388
+ timestamp: new Date().toISOString(),
389
+ ...health,
390
+ }, null, 2) }] };
391
+ }))
392
+ toolCount++;
393
+ // squish_stats - Get memory statistics for a project
394
+ if (safeRegisterTool(server, "squish_stats", {
395
+ description: "Get memory statistics for a project",
396
+ inputSchema: {
397
+ project: z.string().optional().describe("Project path (defaults to current)")
398
+ }
399
+ }, async ({ project }) => {
400
+ const stats = await buildStatsState(project || process.cwd());
401
+ return { content: [{ type: "text", text: JSON.stringify({ ok: true, ...stats }, null, 2) }] };
402
+ }))
403
+ toolCount++;
404
+ // squish_inspect - Explain why a memory was retained
405
+ if (safeRegisterTool(server, "squish_inspect", {
406
+ description: "Explain why a memory was retained, where it was routed, and whether raw fallback exists",
407
+ inputSchema: {
408
+ memoryId: z.string().uuid().describe("Memory ID to inspect")
409
+ }
410
+ }, async ({ memoryId }) => {
411
+ const inspection = await buildInspectState(memoryId);
412
+ if (!inspection) {
413
+ return { content: [{ type: "text", text: `Memory not found: ${memoryId}` }], isError: true };
414
+ }
415
+ return { content: [{ type: "text", text: JSON.stringify({ ok: true, inspection }, null, 2) }] };
416
+ }))
417
+ toolCount++;
418
+ // squish_pin - Pin or unpin a memory to prevent consolidation
419
+ if (safeRegisterTool(server, "squish_pin", {
420
+ description: "Pin or unpin a memory to prevent consolidation",
421
+ inputSchema: {
422
+ memoryId: z.string().uuid().describe("Memory ID"),
423
+ pinned: z.boolean().default(true).describe("Pin (true) or unpin (false)")
424
+ }
425
+ }, async ({ memoryId, pinned }) => {
426
+ const db = await getDb();
427
+ const schema = await getSchema();
428
+ const sqliteDb = db;
429
+ await sqliteDb.update(schema.memories)
430
+ .set({ isPinned: pinned })
431
+ .where(eq(schema.memories.id, memoryId));
432
+ return { content: [{ type: "text", text: `Memory ${memoryId} ${pinned ? 'pinned' : 'unpinned'}` }] };
433
+ }))
434
+ toolCount++;
435
+ // squish_recent - Get recent memories by period
436
+ if (safeRegisterTool(server, "squish_recent", {
437
+ description: "Get recent memories by period (today, yesterday, thisweek, 7days, 30days, or custom)",
438
+ inputSchema: {
439
+ period: z.string().optional().describe("Period: today, yesterday, thisweek, 7days, 14days, 30days, 90days"),
440
+ since: z.string().optional().describe("Start date (alternative to period, e.g., '3 days', '2026-01-01')"),
441
+ until: z.string().optional().describe("End date (alternative to period, e.g., 'now', '2026-01-15')"),
442
+ limit: z.number().optional().describe("Max results to return"),
443
+ project: z.string().optional().describe("Project path (defaults to current)")
444
+ }
445
+ }, async ({ period = 'today', since, until, limit = 10, project }) => {
446
+ const proj = project || process.cwd();
447
+ let sinceDate, untilDate;
448
+ if (since && until) {
449
+ sinceDate = since;
450
+ untilDate = until;
451
+ }
452
+ else if (since) {
453
+ sinceDate = since;
454
+ untilDate = 'now';
455
+ }
456
+ else {
457
+ const periodMap = {
458
+ today: ['today', 'now'],
459
+ yesterday: ['yesterday', 'today'],
460
+ thisweek: ['thisweek', 'now'],
461
+ '7days': ['7 days', 'now'],
462
+ '14days': ['14 days', 'now'],
463
+ '30days': ['30 days', 'now'],
464
+ '90days': ['90 days', 'now'],
465
+ };
466
+ const mapped = periodMap[period];
467
+ if (mapped) {
468
+ [sinceDate, untilDate] = mapped;
469
+ }
470
+ else {
471
+ sinceDate = period;
472
+ untilDate = 'now';
473
+ }
474
+ }
475
+ const results = await getRecent(proj, 100);
476
+ const filtered = filterByDateRange(results, sinceDate, untilDate);
477
+ const limited = filtered.slice(0, limit);
478
+ return { content: [{ type: "text", text: JSON.stringify({ ok: true, period, since: sinceDate, until: untilDate, count: limited.length, results: limited }, null, 2) }] };
479
+ }))
480
+ toolCount++;
481
+ // squish_stale - Show stale memories
482
+ if (safeRegisterTool(server, "squish_stale", {
483
+ description: "Show stale memories (old, low-confidence, or rarely accessed)",
484
+ inputSchema: {
485
+ days: z.number().optional().describe("Show memories older than N days"),
486
+ limit: z.number().optional().describe("Max results to return"),
487
+ project: z.string().optional().describe("Project path (defaults to current)")
488
+ }
489
+ }, async ({ days = 30, limit = 20, project }) => {
490
+ const proj = project || process.cwd();
491
+ const cutoffDate = new Date(Date.now() - days * 86400000);
492
+ const results = await getRecent(proj, 500);
493
+ const stale = results.filter((m) => {
494
+ const created = m.createdAt ? new Date(m.createdAt) : null;
495
+ const isOld = created && created < cutoffDate;
496
+ const isLowConfidence = m.confidenceLevel === 'outdated' || m.confidenceLevel === 'speculative';
497
+ const hasLowImportance = (m.importance || 50) < 40;
498
+ return isOld || isLowConfidence || hasLowImportance;
499
+ });
500
+ const limited = stale.slice(0, limit);
501
+ const summary = {
502
+ totalStale: stale.length,
503
+ old: stale.filter((m) => m.createdAt && new Date(m.createdAt) < cutoffDate).length,
504
+ lowConfidence: stale.filter((m) => m.confidenceLevel === 'outdated' || m.confidenceLevel === 'speculative').length,
505
+ lowImportance: stale.filter((m) => (m.importance || 50) < 40).length,
506
+ };
507
+ return { content: [{ type: "text", text: JSON.stringify({ ok: true, summary, memories: limited }, null, 2) }] };
508
+ }))
509
+ toolCount++;
510
+ console.error(`[MCP] Tool registration complete. Registered ${toolCount} tools.`);
511
+ return { server, toolCount };
512
+ }
513
+ async function runStdio(server, toolCount) {
514
+ console.error(`[MCP] Starting in STDIO mode...`);
515
+ const transport = new StdioServerTransport();
516
+ transport.onclose = () => {
517
+ console.error(`[MCP] STDIO transport closed`);
518
+ };
519
+ await server.connect(transport);
520
+ console.error(`[MCP] Connected via stdio. ${toolCount} tools available.`);
521
+ // Keep process alive - wait for stdin to close or process signals
522
+ await new Promise((resolve) => {
523
+ process.stdin.on('close', () => {
524
+ console.error(`[MCP] STDIO stdin closed, shutting down`);
525
+ resolve();
526
+ });
527
+ process.on('SIGINT', () => {
528
+ console.error(`[MCP] Received SIGINT, shutting down`);
529
+ resolve();
530
+ });
531
+ process.on('SIGTERM', () => {
532
+ console.error(`[MCP] Received SIGTERM, shutting down`);
533
+ resolve();
534
+ });
535
+ });
536
+ }
537
+ async function runHttp(server, port) {
538
+ console.error(`[MCP] Starting in Streamable HTTP mode on port ${port}...`);
539
+ const app = express();
540
+ app.use(express.json({ strict: false }));
541
+ // Store transports by session ID
542
+ const transports = new Map();
543
+ // Helper to check if request is an initialization request
544
+ function isInitializeRequest(body) {
545
+ return body?.method === 'initialize';
546
+ }
547
+ // Health check endpoint
548
+ app.get("/health", (req, res) => {
549
+ res.json({ status: "ok", server: SERVER_NAME, version: SERVER_VERSION });
550
+ });
551
+ // Streamable HTTP POST endpoint
552
+ app.post("/mcp", async (req, res) => {
553
+ const sessionId = req.headers["mcp-session-id"];
554
+ const body = req.body;
555
+ let transport;
556
+ let serverToUse;
557
+ // Check if we have an existing transport for this session
558
+ if (sessionId && transports.has(sessionId)) {
559
+ transport = transports.get(sessionId);
560
+ serverToUse = server;
561
+ }
562
+ // If no existing transport, create new one (only for initialize requests)
563
+ if (!transport) {
564
+ if (!isInitializeRequest(body)) {
565
+ res.status(400).json({
566
+ jsonrpc: '2.0',
567
+ error: { code: -32000, message: 'Bad Request: No valid session ID and not an initialize request' },
568
+ id: body?.id || null
569
+ });
570
+ return;
571
+ }
572
+ // Create NEW server instance for this session (required - can't reuse)
573
+ const { server: newServer } = createSquishServer();
574
+ serverToUse = newServer;
575
+ // Create new transport with JSON response mode
576
+ transport = new StreamableHTTPServerTransport({
577
+ sessionIdGenerator: () => crypto.randomUUID(),
578
+ enableJsonResponse: true,
579
+ onsessioninitialized: (newSessionId) => {
580
+ console.error(`[MCP] Session initialized: ${newSessionId}`);
581
+ transports.set(newSessionId, transport);
582
+ }
583
+ });
584
+ // Connect the NEW session-specific server to this transport
585
+ try {
586
+ await serverToUse.connect(transport);
587
+ }
588
+ catch (connectError) {
589
+ // Ignore "Already connected" errors - can happen if server was used before
590
+ if (connectError.message?.includes('Already connected')) {
591
+ console.error(`[MCP] Server already connected, creating fresh server...`);
592
+ const { server: freshServer } = createSquishServer();
593
+ serverToUse = freshServer;
594
+ await serverToUse.connect(transport);
595
+ }
596
+ else {
597
+ console.error(`[MCP] Connect error:`, connectError.message);
598
+ }
599
+ }
600
+ // Set up onclose handler
601
+ transport.onclose = () => {
602
+ const sid = transport?.sessionId;
603
+ if (sid) {
604
+ console.error(`[MCP] Session closed: ${sid}`);
605
+ transports.delete(sid);
606
+ }
607
+ };
608
+ transport.onerror = (error) => {
609
+ console.error(`[MCP] Transport error:`, error);
610
+ };
611
+ }
612
+ try {
613
+ // Handle the request with the parsed body
614
+ await transport.handleRequest(req, res, body);
615
+ }
616
+ catch (error) {
617
+ console.error(`[MCP] Error handling request:`, error);
618
+ if (!res.headersSent) {
619
+ res.status(500).json({ error: "Internal server error" });
620
+ }
621
+ }
622
+ });
623
+ // Streamable HTTP GET endpoint (for SSE)
624
+ app.get("/mcp", async (req, res) => {
625
+ const sessionId = req.headers["mcp-session-id"];
626
+ if (!sessionId || !transports.has(sessionId)) {
627
+ res.status(400).send('Invalid or missing session ID');
628
+ return;
629
+ }
630
+ const transport = transports.get(sessionId);
631
+ try {
632
+ await transport.handleRequest(req, res);
633
+ }
634
+ catch (error) {
635
+ console.error(`[MCP] Error handling GET request:`, error);
636
+ if (!res.headersSent) {
637
+ res.status(500).json({ error: "Internal server error" });
638
+ }
639
+ }
640
+ });
641
+ // DELETE endpoint to close session
642
+ app.delete("/mcp", async (req, res) => {
643
+ const sessionId = req.headers["mcp-session-id"];
644
+ if (!sessionId || !transports.has(sessionId)) {
645
+ res.status(400).send('Invalid or missing session ID');
646
+ return;
647
+ }
648
+ const transport = transports.get(sessionId);
649
+ try {
650
+ await transport.handleRequest(req, res);
651
+ }
652
+ catch (error) {
653
+ console.error(`[MCP] Error handling DELETE request:`, error);
654
+ if (!res.headersSent) {
655
+ res.status(500).json({ error: "Internal server error" });
656
+ }
657
+ }
658
+ });
659
+ await new Promise((resolve) => app.listen(port, () => {
660
+ console.error(`[MCP] HTTP server listening on port ${port}`);
661
+ console.error(`[MCP] Streamable HTTP endpoint: http://localhost:${port}/mcp`);
662
+ console.error(`[MCP] Health: http://localhost:${port}/health`);
663
+ resolve();
664
+ }));
665
+ }
666
+ async function runHealthCheck() {
667
+ console.error(`[MCP] Running health check...`);
668
+ try {
669
+ const { server, toolCount } = createSquishServer();
670
+ console.error(`[MCP] Health check passed. Server initialized with ${toolCount} tools.`);
671
+ process.exit(0);
672
+ }
673
+ catch (error) {
674
+ console.error(`[MCP] Health check failed:`, error);
675
+ process.exit(1);
676
+ }
677
+ }
678
+ async function main() {
679
+ try {
680
+ console.error(`[${SERVER_NAME}] v${SERVER_VERSION} initializing...`);
681
+ console.error(`[${SERVER_NAME}] Mode: ${config.isManagedMode ? "managed" : "local"}`);
682
+ console.error(`[${SERVER_NAME}] Embeddings: ${config.embeddingsProvider}`);
683
+ const { mode, port, health } = parseArgs();
684
+ if (health) {
685
+ await runHealthCheck();
686
+ return;
687
+ }
688
+ // Start background worker for lifecycle maintenance, decay, etc.
689
+ try {
690
+ await startWorker();
691
+ console.error(`[${SERVER_NAME}] Background worker started`);
692
+ }
693
+ catch (error) {
694
+ console.error(`[${SERVER_NAME}] Warning: Failed to start background worker:`, error);
695
+ }
696
+ // Initialize cron scheduler for scheduled jobs
697
+ try {
698
+ await initializeScheduler();
699
+ console.error(`[${SERVER_NAME}] Cron scheduler initialized`);
700
+ }
701
+ catch (error) {
702
+ console.error(`[${SERVER_NAME}] Warning: Failed to initialize scheduler:`, error);
703
+ }
704
+ const shutdown = async () => {
705
+ console.error(`[${SERVER_NAME}] Shutting down...`);
706
+ try {
707
+ await stopWorker();
708
+ console.error(`[${SERVER_NAME}] Background worker stopped`);
709
+ }
710
+ catch (error) {
711
+ console.error(`[${SERVER_NAME}] Error stopping worker:`, error);
712
+ }
713
+ process.exit(0);
714
+ };
715
+ process.on("SIGINT", shutdown);
716
+ process.on("SIGTERM", shutdown);
717
+ if (mode === "stdio") {
718
+ await runStdio(SQUISH_SERVER, SQUISH_TOOL_COUNT);
719
+ }
720
+ else {
721
+ await runHttp(SQUISH_SERVER, port);
722
+ }
723
+ }
724
+ catch (error) {
725
+ console.error(`[${SERVER_NAME}] Fatal error:`, error);
726
+ process.exit(1);
727
+ }
728
+ }
729
+ main().catch((error) => {
730
+ console.error(`[${SERVER_NAME}] Fatal error:`, error);
731
+ process.exit(1);
732
+ });
733
+ //# sourceMappingURL=index.js.map