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