squish-memory 1.0.2 → 1.1.5

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 (341) hide show
  1. package/.env.example +130 -0
  2. package/CHANGELOG.md +55 -0
  3. package/README.md +150 -287
  4. package/config/hooks/claude-code-hooks.json +39 -0
  5. package/config/hooks/cursor-hooks.json +30 -0
  6. package/config/hooks/opencode-hooks.json +30 -0
  7. package/config/hooks/windsurf-hooks.json +30 -0
  8. package/config/mcp-mode-semantics.json +23 -21
  9. package/config/plugin-manifest.json +101 -152
  10. package/{plugin.json → config/plugin.json} +2 -2
  11. package/config/settings.json +52 -51
  12. package/{commands → core/commands}/init.md +39 -39
  13. package/dist/config.d.ts +28 -4
  14. package/dist/config.js +97 -29
  15. package/dist/core/adapters/config/claude-code.d.ts +45 -0
  16. package/dist/core/adapters/config/claude-code.js +113 -0
  17. package/dist/core/adapters/config/cursor.d.ts +26 -0
  18. package/dist/core/adapters/config/cursor.js +74 -0
  19. package/dist/core/adapters/config/opencode.d.ts +23 -0
  20. package/dist/core/adapters/config/opencode.js +73 -0
  21. package/dist/core/adapters/config/windsurf.d.ts +26 -0
  22. package/dist/core/adapters/config/windsurf.js +74 -0
  23. package/dist/core/adapters/index.d.ts +45 -0
  24. package/dist/core/adapters/index.js +84 -0
  25. package/dist/core/adapters/scripts/install-adapter.d.ts +19 -0
  26. package/dist/core/adapters/scripts/install-adapter.js +149 -0
  27. package/dist/core/adapters/timeline.d.ts +23 -0
  28. package/dist/core/adapters/timeline.js +88 -0
  29. package/dist/core/adapters/types.d.ts +157 -0
  30. package/dist/core/adapters/types.js +50 -0
  31. package/dist/{algorithms → core/algorithms}/analytics/token-estimator.d.ts +1 -1
  32. package/dist/{algorithms → core/algorithms}/analytics/token-estimator.js +3 -3
  33. package/dist/{algorithms → core/algorithms}/detection/semantic-ranker.d.ts +1 -1
  34. package/dist/{algorithms → core/algorithms}/detection/semantic-ranker.js +1 -1
  35. package/dist/{algorithms → core/algorithms}/detection/two-stage-detector.d.ts +1 -1
  36. package/dist/{algorithms → core/algorithms}/detection/two-stage-detector.js +7 -10
  37. package/dist/{algorithms → core/algorithms}/handlers/approve-merge.js +4 -4
  38. package/dist/{algorithms → core/algorithms}/handlers/detect-duplicates.js +3 -3
  39. package/dist/{algorithms → core/algorithms}/handlers/get-stats.js +3 -3
  40. package/dist/{algorithms → core/algorithms}/handlers/list-proposals.js +3 -3
  41. package/dist/{algorithms → core/algorithms}/handlers/preview-merge.js +3 -3
  42. package/dist/{algorithms → core/algorithms}/handlers/reject-merge.js +3 -3
  43. package/dist/{algorithms → core/algorithms}/handlers/reverse-merge.js +3 -3
  44. package/dist/core/algorithms/index.d.ts +21 -0
  45. package/dist/core/algorithms/index.js +26 -0
  46. package/dist/core/algorithms/operations/cache-maintenance.d.ts +12 -0
  47. package/dist/core/algorithms/operations/cache-maintenance.js +157 -0
  48. package/dist/{algorithms → core/algorithms}/safety/safety-checks.d.ts +1 -1
  49. package/dist/{algorithms → core/algorithms}/strategies/merge-strategies.d.ts +19 -1
  50. package/dist/{algorithms → core/algorithms}/strategies/merge-strategies.js +74 -123
  51. package/dist/core/algorithms/types.d.ts +133 -0
  52. package/dist/core/algorithms/types.js +5 -0
  53. package/dist/core/associations.d.ts +1 -2
  54. package/dist/core/associations.js +1 -2
  55. package/dist/core/autosave.d.ts +19 -0
  56. package/dist/core/autosave.js +16 -0
  57. package/dist/{commands → core/commands}/managed-sync.js +5 -5
  58. package/dist/core/commands/mcp-server.js +739 -0
  59. package/dist/core/context/agent-context.d.ts +106 -0
  60. package/dist/core/context/agent-context.js +274 -0
  61. package/dist/core/{context-paging.d.ts → context/context-paging.d.ts} +2 -12
  62. package/dist/core/{context-paging.js → context/context-paging.js} +19 -39
  63. package/dist/core/context/context-window.d.ts +40 -0
  64. package/dist/core/context/context-window.js +177 -0
  65. package/dist/core/context/context.js +22 -0
  66. package/dist/core/embeddings.d.ts +1 -1
  67. package/dist/core/embeddings.js +54 -2
  68. package/dist/core/error-handling.d.ts +63 -0
  69. package/dist/core/error-handling.js +173 -0
  70. package/dist/core/external-folder/index.d.ts +102 -0
  71. package/dist/core/external-folder/index.js +294 -0
  72. package/dist/core/hooks/agent-hooks.d.ts +74 -0
  73. package/dist/core/hooks/agent-hooks.js +244 -0
  74. package/dist/core/hooks/auto-tagger.d.ts +19 -0
  75. package/dist/core/hooks/auto-tagger.js +155 -0
  76. package/dist/core/hooks/capture-filter.d.ts +41 -0
  77. package/dist/core/hooks/capture-filter.js +128 -0
  78. package/dist/core/index.d.ts +6 -6
  79. package/dist/core/index.js +6 -6
  80. package/dist/core/{agent-memory.js → ingestion/agent-memory.js} +5 -7
  81. package/dist/core/{core-memory.js → ingestion/core-memory.js} +4 -4
  82. package/dist/core/ingestion/learnings.d.ts +57 -0
  83. package/dist/core/ingestion/learnings.js +202 -0
  84. package/dist/core/lib/db-client.d.ts +114 -0
  85. package/dist/core/lib/db-client.js +130 -0
  86. package/dist/core/lib/schemas.d.ts +129 -0
  87. package/dist/core/lib/schemas.js +87 -0
  88. package/dist/core/{utils.d.ts → lib/utils.d.ts} +1 -0
  89. package/dist/core/{utils.js → lib/utils.js} +31 -15
  90. package/dist/core/lib/validation.d.ts +38 -0
  91. package/dist/core/lib/validation.js +151 -0
  92. package/dist/core/lifecycle.d.ts +7 -0
  93. package/dist/core/lifecycle.js +140 -20
  94. package/dist/core/local-embeddings.d.ts +6 -1
  95. package/dist/core/local-embeddings.js +6 -15
  96. package/dist/core/logger.js +7 -1
  97. package/dist/core/mcp/tools.js +35 -3
  98. package/dist/core/memory/categorizer.js +1 -0
  99. package/dist/core/memory/conflict-detector.js +1 -1
  100. package/dist/core/memory/consolidation.d.ts +1 -10
  101. package/dist/core/memory/consolidation.js +2 -11
  102. package/dist/core/memory/context-collector.js +1 -1
  103. package/dist/core/memory/edit-workflow.js +1 -1
  104. package/dist/core/memory/entity-resolver.js +7 -7
  105. package/dist/core/memory/fact-extractor.js +12 -12
  106. package/dist/core/memory/feedback-tracker.js +1 -1
  107. package/dist/core/memory/hooks.d.ts +88 -0
  108. package/dist/core/memory/hooks.js +174 -0
  109. package/dist/core/memory/hybrid-retrieval.js +2 -2
  110. package/dist/core/memory/hybrid-search.d.ts +1 -6
  111. package/dist/core/memory/hybrid-search.js +70 -84
  112. package/dist/core/memory/importance.d.ts +8 -13
  113. package/dist/core/memory/importance.js +47 -74
  114. package/dist/core/memory/loader.d.ts +31 -0
  115. package/dist/core/memory/loader.js +141 -0
  116. package/dist/core/memory/markdown/markdown-storage.d.ts +72 -0
  117. package/dist/core/memory/markdown/markdown-storage.js +243 -0
  118. package/dist/core/memory/memories.d.ts +12 -4
  119. package/dist/core/memory/memories.js +192 -180
  120. package/dist/core/memory/memory-lifecycle.d.ts +8 -0
  121. package/dist/core/memory/memory-lifecycle.js +55 -0
  122. package/dist/core/memory/migrate.d.ts +21 -0
  123. package/dist/core/memory/migrate.js +134 -0
  124. package/dist/core/memory/normalization.d.ts +22 -0
  125. package/dist/core/memory/normalization.js +26 -0
  126. package/dist/core/memory/progressive-disclosure.js +1 -1
  127. package/dist/core/memory/query-rewriter.js +9 -9
  128. package/dist/core/memory/serialization.d.ts +4 -0
  129. package/dist/core/memory/serialization.js +49 -0
  130. package/dist/core/memory/stats.d.ts +5 -0
  131. package/dist/core/memory/stats.js +63 -12
  132. package/dist/core/memory/temporal-facts.js +21 -0
  133. package/dist/core/memory/write-gate.js +1 -1
  134. package/dist/core/obsidian-vault.d.ts +30 -0
  135. package/dist/core/obsidian-vault.js +94 -0
  136. package/dist/core/places/index.d.ts +14 -0
  137. package/dist/core/places/index.js +14 -0
  138. package/dist/core/places/memory-places.d.ts +68 -0
  139. package/dist/core/places/memory-places.js +261 -0
  140. package/dist/core/places/places.d.ts +88 -0
  141. package/dist/core/places/places.js +314 -0
  142. package/dist/core/places/rules.d.ts +74 -0
  143. package/dist/core/places/rules.js +240 -0
  144. package/dist/core/places/walking.d.ts +56 -0
  145. package/dist/core/places/walking.js +121 -0
  146. package/dist/core/projects.d.ts +5 -0
  147. package/dist/core/projects.js +39 -18
  148. package/dist/core/responses.d.ts +96 -0
  149. package/dist/core/responses.js +122 -0
  150. package/dist/core/scheduler/cron-scheduler.js +29 -7
  151. package/dist/core/scheduler/index.d.ts +1 -1
  152. package/dist/core/scheduler/index.js +1 -1
  153. package/dist/core/scheduler/job-runner.js +1 -1
  154. package/dist/core/search/conversations.js +40 -42
  155. package/dist/core/search/entities.js +6 -9
  156. package/dist/core/search/graph-boost.d.ts +7 -0
  157. package/dist/core/search/graph-boost.js +23 -0
  158. package/dist/core/search/qmd-search.js +4 -4
  159. package/dist/core/security/encrypt.d.ts +6 -0
  160. package/dist/core/security/encrypt.js +47 -0
  161. package/dist/core/{governance.d.ts → security/governance.d.ts} +6 -1
  162. package/dist/core/security/governance.js +79 -0
  163. package/dist/core/session/auto-load.js +6 -6
  164. package/dist/core/session/index.d.ts +1 -1
  165. package/dist/core/session/index.js +1 -1
  166. package/dist/core/session/self-iteration-job.d.ts +20 -0
  167. package/dist/core/session/self-iteration-job.js +282 -0
  168. package/dist/core/session/session-hooks.d.ts +18 -0
  169. package/dist/core/session/session-hooks.js +58 -0
  170. package/dist/core/session-hooks/self-iteration-job.js +35 -35
  171. package/dist/core/{cache.js → storage/cache.js} +2 -2
  172. package/dist/core/sync/qmd-sync.d.ts +1 -13
  173. package/dist/core/sync/qmd-sync.js +1 -13
  174. package/dist/core/toon.d.ts +43 -0
  175. package/dist/core/toon.js +160 -0
  176. package/dist/core/utils/memory-operations.js +1 -1
  177. package/dist/core/utils/vector-operations.d.ts +71 -0
  178. package/dist/core/utils/vector-operations.js +129 -0
  179. package/dist/db/adapter.d.ts +3 -3
  180. package/dist/db/adapter.js +99 -88
  181. package/dist/db/bootstrap.js +820 -522
  182. package/dist/{drizzle → db/drizzle}/schema-sqlite.d.ts +74 -25
  183. package/dist/{drizzle → db/drizzle}/schema-sqlite.js +91 -24
  184. package/dist/{drizzle → db/drizzle}/schema.d.ts +79 -32
  185. package/dist/{drizzle → db/drizzle}/schema.js +106 -35
  186. package/dist/db/drizzle.config.d.ts +3 -0
  187. package/dist/db/drizzle.config.js +12 -0
  188. package/dist/db/index.d.ts +1 -5
  189. package/dist/db/index.js +51 -8
  190. package/dist/db/neon.d.ts +8 -0
  191. package/dist/db/neon.js +20 -0
  192. package/dist/db/schema/index.d.ts +40 -0
  193. package/dist/db/schema/index.js +105 -0
  194. package/dist/db/schema/tables/context-sessions.d.ts +9 -0
  195. package/dist/db/schema/tables/context-sessions.js +37 -0
  196. package/dist/db/schema/tables/conversations.d.ts +9 -0
  197. package/dist/db/schema/tables/conversations.js +47 -0
  198. package/dist/db/schema/tables/core-memory.d.ts +9 -0
  199. package/dist/db/schema/tables/core-memory.js +41 -0
  200. package/dist/db/schema/tables/entities.d.ts +9 -0
  201. package/dist/db/schema/tables/entities.js +39 -0
  202. package/dist/db/schema/tables/entity-relations.d.ts +9 -0
  203. package/dist/db/schema/tables/entity-relations.js +31 -0
  204. package/dist/db/schema/tables/learnings.d.ts +9 -0
  205. package/dist/db/schema/tables/learnings.js +66 -0
  206. package/dist/db/schema/tables/memories.d.ts +9 -0
  207. package/dist/db/schema/tables/memories.js +161 -0
  208. package/dist/db/schema/tables/memory-associations.d.ts +9 -0
  209. package/dist/db/schema/tables/memory-associations.js +39 -0
  210. package/dist/db/schema/tables/memory-hash-cache.d.ts +9 -0
  211. package/dist/db/schema/tables/memory-hash-cache.js +29 -0
  212. package/dist/db/schema/tables/memory-merge-history.d.ts +9 -0
  213. package/dist/db/schema/tables/memory-merge-history.js +33 -0
  214. package/dist/db/schema/tables/memory-merge-proposals.d.ts +9 -0
  215. package/dist/db/schema/tables/memory-merge-proposals.js +39 -0
  216. package/dist/db/schema/tables/messages.d.ts +9 -0
  217. package/dist/db/schema/tables/messages.js +41 -0
  218. package/dist/db/schema/tables/namespaces.d.ts +9 -0
  219. package/dist/db/schema/tables/namespaces.js +37 -0
  220. package/dist/db/schema/tables/projects.d.ts +9 -0
  221. package/dist/db/schema/tables/projects.js +31 -0
  222. package/dist/db/schema/tables/users.d.ts +9 -0
  223. package/dist/db/schema/tables/users.js +27 -0
  224. package/dist/db/schema.d.ts +1 -1
  225. package/dist/db/schema.js +2 -2
  226. package/dist/db/supabase.d.ts +9 -0
  227. package/dist/db/supabase.js +24 -0
  228. package/dist/index.d.ts +2 -14
  229. package/dist/index.js +1320 -640
  230. package/dist/vendor/sql.js/sql-wasm.wasm +0 -0
  231. package/dist/webui/server.d.ts +5 -0
  232. package/dist/{api/web/web.js → webui/server.js} +511 -508
  233. package/generated/mcp/manifest.json +1 -1
  234. package/{.mcp.json → mcp.json.example} +1 -1
  235. package/package.json +159 -181
  236. package/scripts/README.md +60 -0
  237. package/scripts/copy-runtime-assets.mjs +26 -0
  238. package/scripts/generate-mcp.mjs +264 -264
  239. package/scripts/github-release.sh +4 -4
  240. package/scripts/install-claude-code.sh +85 -0
  241. package/scripts/install-cursor.sh +56 -0
  242. package/scripts/install-hooks.sh +73 -0
  243. package/scripts/install-interactive.mjs +357 -677
  244. package/scripts/install-opencode.sh +75 -0
  245. package/scripts/install-windsurf.sh +67 -0
  246. package/skills/squish-memory/SKILL.md +104 -114
  247. package/skills/squish-memory/{install.mjs → scripts/install.mjs} +2 -2
  248. package/skills/squish-memory/{install.sh → scripts/install.sh} +2 -2
  249. package/skills/squish-memory/write_skill.js +2 -0
  250. package/.claude-plugin/marketplace.json +0 -20
  251. package/.claude-plugin/plugin.json +0 -32
  252. package/.env.mcp.example +0 -60
  253. package/QUICK-START.md +0 -71
  254. package/bin/squish-add.mjs +0 -32
  255. package/bin/squish-rm.mjs +0 -21
  256. package/commands/observe.md +0 -5
  257. package/dist/api/web/index.d.ts +0 -3
  258. package/dist/api/web/index.js +0 -4
  259. package/dist/api/web/web-server.d.ts +0 -3
  260. package/dist/api/web/web-server.js +0 -6
  261. package/dist/api/web/web.d.ts +0 -4
  262. package/dist/commands/mcp-server.js +0 -393
  263. package/dist/core/context.js +0 -24
  264. package/dist/core/governance.js +0 -64
  265. package/dist/core/observations.d.ts +0 -26
  266. package/dist/core/observations.js +0 -110
  267. package/dist/core/requirements.d.ts +0 -20
  268. package/dist/core/requirements.js +0 -35
  269. package/hooks/hooks.json +0 -52
  270. package/hooks/post-tool-use.js +0 -26
  271. package/hooks/session-end.js +0 -28
  272. package/hooks/session-start.js +0 -33
  273. package/hooks/user-prompt-submit.js +0 -26
  274. package/hooks/utils.js +0 -153
  275. package/npx-installer.js +0 -208
  276. package/packages/plugin-claude-code/README.md +0 -73
  277. package/packages/plugin-claude-code/dist/plugin-wrapper.d.ts +0 -35
  278. package/packages/plugin-claude-code/dist/plugin-wrapper.js +0 -191
  279. package/packages/plugin-claude-code/package.json +0 -31
  280. package/packages/plugin-openclaw/README.md +0 -70
  281. package/packages/plugin-openclaw/dist/index.d.ts +0 -49
  282. package/packages/plugin-openclaw/dist/index.js +0 -262
  283. package/packages/plugin-openclaw/openclaw.plugin.json +0 -94
  284. package/packages/plugin-openclaw/package.json +0 -31
  285. package/packages/plugin-opencode/install.mjs +0 -217
  286. package/packages/plugin-opencode/package.json +0 -21
  287. package/scripts/db/check-db.mjs +0 -88
  288. package/scripts/db/fix-all-columns.mjs +0 -52
  289. package/scripts/db/fix-schema-all.mjs +0 -55
  290. package/scripts/db/fix-schema-full.mjs +0 -46
  291. package/scripts/db/fix-schema.mjs +0 -38
  292. package/scripts/db/init-db.mjs +0 -13
  293. package/scripts/db/recreate-db.mjs +0 -14
  294. package/scripts/install-mcp.mjs +0 -116
  295. package/scripts/install-web.sh +0 -120
  296. package/scripts/install.mjs +0 -340
  297. package/scripts/openclaw-bootstrap.mjs +0 -127
  298. package/scripts/package-release.sh +0 -71
  299. package/scripts/test/test-all-systems.mjs +0 -139
  300. package/scripts/test/test-memory-system.mjs +0 -139
  301. package/scripts/test/test-v0.5.0.mjs +0 -210
  302. package/skills/memory-guide/SKILL.md +0 -332
  303. package/skills/squish-cli/SKILL.md +0 -240
  304. package/skills/squish-mcp/SKILL.md +0 -355
  305. package/skills/squish-memory/claude-desktop.json +0 -12
  306. package/skills/squish-memory/openclaw.json +0 -13
  307. package/skills/squish-memory/opencode.json +0 -14
  308. package/skills/squish-memory/skill.json +0 -32
  309. /package/{commands → core/commands}/context-paging.md +0 -0
  310. /package/{commands → core/commands}/context-status.md +0 -0
  311. /package/{commands → core/commands}/context.md +0 -0
  312. /package/{commands → core/commands}/core-memory.md +0 -0
  313. /package/{commands → core/commands}/health.md +0 -0
  314. /package/{commands → core/commands}/merge.md +0 -0
  315. /package/{commands → core/commands}/recall.md +0 -0
  316. /package/{commands → core/commands}/remember.md +0 -0
  317. /package/{commands → core/commands}/search.md +0 -0
  318. /package/dist/{algorithms → core/algorithms}/detection/hash-filters.d.ts +0 -0
  319. /package/dist/{algorithms → core/algorithms}/detection/hash-filters.js +0 -0
  320. /package/dist/{algorithms → core/algorithms}/handlers/approve-merge.d.ts +0 -0
  321. /package/dist/{algorithms → core/algorithms}/handlers/detect-duplicates.d.ts +0 -0
  322. /package/dist/{algorithms → core/algorithms}/handlers/get-stats.d.ts +0 -0
  323. /package/dist/{algorithms → core/algorithms}/handlers/list-proposals.d.ts +0 -0
  324. /package/dist/{algorithms → core/algorithms}/handlers/preview-merge.d.ts +0 -0
  325. /package/dist/{algorithms → core/algorithms}/handlers/reject-merge.d.ts +0 -0
  326. /package/dist/{algorithms → core/algorithms}/handlers/reverse-merge.d.ts +0 -0
  327. /package/dist/{algorithms → core/algorithms}/safety/safety-checks.js +0 -0
  328. /package/dist/{algorithms → core/algorithms}/utils/response-builder.d.ts +0 -0
  329. /package/dist/{algorithms → core/algorithms}/utils/response-builder.js +0 -0
  330. /package/dist/{commands → core/commands}/managed-sync.d.ts +0 -0
  331. /package/dist/{commands → core/commands}/mcp-server.d.ts +0 -0
  332. /package/dist/core/{context.d.ts → context/context.d.ts} +0 -0
  333. /package/dist/core/{agent-memory.d.ts → ingestion/agent-memory.d.ts} +0 -0
  334. /package/dist/core/{core-memory.d.ts → ingestion/core-memory.d.ts} +0 -0
  335. /package/dist/core/{privacy.d.ts → security/privacy.d.ts} +0 -0
  336. /package/dist/core/{privacy.js → security/privacy.js} +0 -0
  337. /package/dist/core/{secret-detector.d.ts → security/secret-detector.d.ts} +0 -0
  338. /package/dist/core/{secret-detector.js → security/secret-detector.js} +0 -0
  339. /package/dist/core/{cache.d.ts → storage/cache.d.ts} +0 -0
  340. /package/dist/core/{database.d.ts → storage/database.d.ts} +0 -0
  341. /package/dist/core/{database.js → storage/database.js} +0 -0
@@ -0,0 +1,23 @@
1
+ import { getDb } from '../../db/index.js';
2
+ import { memoryAssociations } from '../../db/drizzle/schema.js';
3
+ import { inArray } from 'drizzle-orm';
4
+ /**
5
+ * Compute a simple graph boost for a set of memory IDs.
6
+ * For each memory, sum (weight * coactivationCount) of outgoing associations.
7
+ * Returns a map from memoryId to boost value (default 0).
8
+ */
9
+ export async function computeGraphBoost(memoryIds) {
10
+ const boost = {};
11
+ if (memoryIds.length === 0)
12
+ return boost;
13
+ const db = await getDb();
14
+ // @ts-ignore - drizzle overload
15
+ const rows = await db.select().from(memoryAssociations).where(inArray(memoryAssociations.fromMemoryId, memoryIds));
16
+ for (const row of rows) {
17
+ const from = row.fromMemoryId;
18
+ const val = (row.weight ?? 0) * (row.coactivationCount ?? 0);
19
+ boost[from] = (boost[from] ?? 0) + val;
20
+ }
21
+ return boost;
22
+ }
23
+ //# sourceMappingURL=graph-boost.js.map
@@ -15,7 +15,7 @@
15
15
  * GitHub: https://github.com/tobi/qmd
16
16
  */
17
17
  import { getQMDClient } from '../embeddings/qmd-client.js';
18
- import { searchMemories } from '../memory/memories.js';
18
+ import { search } from '../memory/memories.js';
19
19
  import { logger } from '../logger.js';
20
20
  import { config } from '../../config.js';
21
21
  /**
@@ -29,7 +29,7 @@ export async function searchWithQMD(options) {
29
29
  if (!(await client.isAvailable())) {
30
30
  logger.warn('QMD unavailable, falling back to Squish search');
31
31
  // Fallback to Squish search
32
- const squishResults = await searchMemories(options);
32
+ const squishResults = await search(options);
33
33
  return squishResults.map((r) => ({
34
34
  ...r,
35
35
  source: 'squish'
@@ -73,7 +73,7 @@ export async function searchWithQMD(options) {
73
73
  catch (error) {
74
74
  logger.error(`QMD search failed: ${error}`);
75
75
  // Fallback to Squish search
76
- const squishResults = await searchMemories(options);
76
+ const squishResults = await search(options);
77
77
  return squishResults.map((r) => ({
78
78
  ...r,
79
79
  source: 'squish'
@@ -93,7 +93,7 @@ export async function fusedSearch(options) {
93
93
  const qmdAvailable = await client.isAvailable();
94
94
  // Run searches in parallel
95
95
  const results = await Promise.allSettled([
96
- searchMemories(options),
96
+ search(options),
97
97
  qmdAvailable ? searchWithQMD({ ...options, includeSquishResults: false }) : []
98
98
  ]);
99
99
  const squishResults = results[0].status === 'fulfilled'
@@ -0,0 +1,6 @@
1
+ export declare function encrypt(plain: string, passphrase?: string): {
2
+ ciphertext: string;
3
+ nonce: string;
4
+ };
5
+ export declare function decrypt(ciphertext: string, nonceB64: string, passphrase?: string): string;
6
+ //# sourceMappingURL=encrypt.d.ts.map
@@ -0,0 +1,47 @@
1
+ import { randomBytes, pbkdf2Sync, createCipheriv, createDecipheriv } from 'crypto';
2
+ import { config } from '../../config.js';
3
+ const ITERATIONS = 100_000;
4
+ const KEY_LEN = 32; // 256-bit
5
+ const DIGEST = 'sha256';
6
+ const ALGO = 'aes-256-gcm';
7
+ const NONCE_LEN = 12;
8
+ /**
9
+ * Derive a symmetric key from the passphrase and a salt.
10
+ * The salt is stored in `.squish/salt` (plain text) and is generated once.
11
+ */
12
+ function getSalt() {
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const saltPath = path.join(config.dataDir, 'salt');
16
+ if (!fs.existsSync(saltPath)) {
17
+ const salt = randomBytes(16).toString('hex');
18
+ fs.writeFileSync(saltPath, salt);
19
+ return Buffer.from(salt, 'hex');
20
+ }
21
+ return Buffer.from(fs.readFileSync(saltPath, 'utf-8'), 'hex');
22
+ }
23
+ function deriveKey(passphrase) {
24
+ const salt = getSalt();
25
+ return pbkdf2Sync(passphrase, salt, ITERATIONS, KEY_LEN, DIGEST);
26
+ }
27
+ export function encrypt(plain, passphrase) {
28
+ const key = deriveKey(passphrase || config.encryptionPassphrase);
29
+ const nonce = randomBytes(NONCE_LEN);
30
+ const cipher = createCipheriv(ALGO, key, nonce);
31
+ const encrypted = Buffer.concat([cipher.update(plain, 'utf8'), cipher.final()]);
32
+ const tag = cipher.getAuthTag();
33
+ const ciphertext = Buffer.concat([encrypted, tag]).toString('base64');
34
+ return { ciphertext, nonce: nonce.toString('base64') };
35
+ }
36
+ export function decrypt(ciphertext, nonceB64, passphrase) {
37
+ const key = deriveKey(passphrase || config.encryptionPassphrase);
38
+ const nonce = Buffer.from(nonceB64, 'base64');
39
+ const data = Buffer.from(ciphertext, 'base64');
40
+ const tag = data.slice(data.length - 16);
41
+ const encrypted = data.slice(0, data.length - 16);
42
+ const decipher = createDecipheriv(ALGO, key, nonce);
43
+ decipher.setAuthTag(tag);
44
+ const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
45
+ return decrypted.toString('utf8');
46
+ }
47
+ //# sourceMappingURL=encrypt.js.map
@@ -16,6 +16,11 @@ export declare function pinMemory(memoryId: string): Promise<void>;
16
16
  export declare function unpinMemory(memoryId: string): Promise<void>;
17
17
  /**
18
18
  * Get all pinned memories for auto-injection into context
19
+ * Works regardless of governance settings - pinned memories should always be accessible
19
20
  */
20
- export declare function getPinnedMemories(): Promise<any[]>;
21
+ export declare function getPinnedMemories(projectId?: string): Promise<any[]>;
22
+ /**
23
+ * Get pinned memories formatted for context injection
24
+ */
25
+ export declare function getPinnedMemoriesForContext(projectId?: string): Promise<string[]>;
21
26
  //# sourceMappingURL=governance.d.ts.map
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Memory Governance
3
+ * Implements protection, pinning, and immutability rules
4
+ */
5
+ import { eq } from 'drizzle-orm';
6
+ import { getDb } from '../../db/index.js';
7
+ import { getSchema } from '../../db/schema.js';
8
+ import { performMemoryOperation } from '../utils/memory-operations.js';
9
+ import { logger } from '../logger.js';
10
+ import { createDatabaseClient } from '../storage/database.js';
11
+ /**
12
+ * Mark a memory as protected (cannot be evicted)
13
+ */
14
+ export async function protectMemory(memoryId, reason) {
15
+ await performMemoryOperation(memoryId, {
16
+ name: 'protecting memory',
17
+ updates: {
18
+ isProtected: true,
19
+ metadata: { protectionReason: reason, protectedAt: new Date().toISOString() },
20
+ },
21
+ });
22
+ }
23
+ /**
24
+ * Pin a memory for automatic injection into context
25
+ */
26
+ export async function pinMemory(memoryId) {
27
+ const db = createDatabaseClient(await getDb());
28
+ const schema = await getSchema();
29
+ await db
30
+ .update(schema.memories)
31
+ .set({
32
+ isPinned: true,
33
+ importanceScore: 100,
34
+ lastImportanceRecalc: new Date(),
35
+ })
36
+ .where(eq(schema.memories.id, memoryId));
37
+ }
38
+ /**
39
+ * Unpin a memory
40
+ */
41
+ export async function unpinMemory(memoryId) {
42
+ const db = createDatabaseClient(await getDb());
43
+ const schema = await getSchema();
44
+ await db
45
+ .update(schema.memories)
46
+ .set({
47
+ isPinned: false,
48
+ lastImportanceRecalc: new Date(),
49
+ })
50
+ .where(eq(schema.memories.id, memoryId));
51
+ }
52
+ /**
53
+ * Get all pinned memories for auto-injection into context
54
+ * Works regardless of governance settings - pinned memories should always be accessible
55
+ */
56
+ export async function getPinnedMemories(projectId) {
57
+ try {
58
+ const db = await getDb();
59
+ const schema = await getSchema();
60
+ let query = db
61
+ .select()
62
+ .from(schema.memories)
63
+ .where(eq(schema.memories.isPinned, true))
64
+ .limit(50);
65
+ return await query;
66
+ }
67
+ catch (error) {
68
+ logger.error('Error retrieving pinned memories', error);
69
+ return [];
70
+ }
71
+ }
72
+ /**
73
+ * Get pinned memories formatted for context injection
74
+ */
75
+ export async function getPinnedMemoriesForContext(projectId) {
76
+ const pinned = await getPinnedMemories(projectId);
77
+ return pinned.map(m => `[Pinned] ${m.content?.substring(0, 500) || '(no content)'}`);
78
+ }
79
+ //# sourceMappingURL=governance.js.map
@@ -1,10 +1,10 @@
1
1
  /** Session Auto-Load - Automatically load context when MCP session initializes */
2
2
  import { logger } from '../logger.js';
3
3
  import { config } from '../../config.js';
4
- import { initializeCoreMemory, getCoreMemory } from '../core-memory.js';
5
- import { searchMemories } from '../memory/memories.js';
6
- import { getProjectContext } from '../context.js';
7
- import { ensureProject } from '../projects.js';
4
+ import { initializeCoreMemory, getCoreMemory } from '../ingestion/core-memory.js';
5
+ import { search } from '../memory/memories.js';
6
+ import { getProjectContext } from '../context/context.js';
7
+ import { getOrCreateProject } from '../projects.js';
8
8
  import { DEFAULT_AUTO_LOAD_CONFIG } from './types.js';
9
9
  function estimateTokens(text) {
10
10
  return Math.ceil(text.length / 4);
@@ -26,7 +26,7 @@ export async function performAutoLoad(projectPath, customConfig) {
26
26
  return result;
27
27
  }
28
28
  try {
29
- const project = await ensureProject(projectPath);
29
+ const project = await getOrCreateProject(projectPath);
30
30
  if (!project) {
31
31
  result.warnings.push(`Failed to create/find project: ${projectPath}`);
32
32
  result.duration = Date.now() - startTime;
@@ -52,7 +52,7 @@ export async function performAutoLoad(projectPath, customConfig) {
52
52
  }
53
53
  if (cfg.includeRecentMemories && cfg.recentMemoryCount > 0) {
54
54
  try {
55
- const recentMemories = await searchMemories({
55
+ const recentMemories = await search({
56
56
  query: '',
57
57
  project: projectPath,
58
58
  limit: cfg.recentMemoryCount,
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Session Module
3
- * v0.10.0 - Session management and auto-load
3
+ * Session management and auto-load
4
4
  */
5
5
  export * from './types.js';
6
6
  export * from './auto-load.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Session Module
3
- * v0.10.0 - Session management and auto-load
3
+ * Session management and auto-load
4
4
  */
5
5
  export * from './types.js';
6
6
  export * from './auto-load.js';
@@ -0,0 +1,20 @@
1
+ /** Self-Iteration Job - Auto-extract key facts from ended conversations
2
+ *
3
+ * Processes conversations to extract memories and generate summaries
4
+ */
5
+ import { type JobHandler } from '../scheduler/cron-scheduler.js';
6
+ export interface SelfIterationConfig {
7
+ enabled: boolean;
8
+ extractFacts: boolean;
9
+ generateSummaries: boolean;
10
+ consolidateMemories: boolean;
11
+ minMessageCount: number;
12
+ maxMessagesToProcess: number;
13
+ }
14
+ declare const DEFAULT_CONFIG: SelfIterationConfig;
15
+ /**
16
+ * Register self-iteration job handler
17
+ */
18
+ declare const selfIterationHandler: JobHandler;
19
+ export { selfIterationHandler, DEFAULT_CONFIG };
20
+ //# sourceMappingURL=self-iteration-job.d.ts.map
@@ -0,0 +1,282 @@
1
+ /** Self-Iteration Job - Auto-extract key facts from ended conversations
2
+ *
3
+ * Processes conversations to extract memories and generate summaries
4
+ */
5
+ import { sql, eq } from 'drizzle-orm';
6
+ import { getDb } from '../../db/index.js';
7
+ import { getSchema } from '../../db/schema.js';
8
+ import { rememberMemory } from '../memory/memories.js';
9
+ import { logger } from '../logger.js';
10
+ const DEFAULT_CONFIG = {
11
+ enabled: true,
12
+ extractFacts: true,
13
+ generateSummaries: true,
14
+ consolidateMemories: true,
15
+ minMessageCount: 5,
16
+ maxMessagesToProcess: 50,
17
+ };
18
+ /**
19
+ * Build fact extraction prompt
20
+ */
21
+ function buildFactExtractionPrompt(messages) {
22
+ const messagesText = messages.map(m => `[${m.role}]: ${m.content}`).join('\n\n');
23
+ return `Extract key facts, decisions, and user preferences from this conversation.
24
+
25
+ Format your response as JSON:
26
+ {
27
+ "extractedFacts": [
28
+ {
29
+ "content": "specific fact text",
30
+ "type": "fact|decision|preference|observation",
31
+ "confidence": 0-100
32
+ }
33
+ ]
34
+ }
35
+
36
+ Only extract truly meaningful information that should be remembered:
37
+ - Facts that are useful for future work or decisions
38
+ - User preferences and choices
39
+ - Important decisions made
40
+ - Patterns or behaviors observed
41
+
42
+ Do NOT extract:
43
+ - Temporary conversational details
44
+ - Greetings or pleasantries
45
+ - Unless they indicate something significant
46
+
47
+ Conversation messages:
48
+ ${messagesText}`;
49
+ }
50
+ /**
51
+ * Build summary generation prompt
52
+ */
53
+ function buildSummaryPrompt(messages) {
54
+ const messagesText = messages.map(m => `[${m.role}]: ${m.content}`).join('\n\n');
55
+ return `Generate a concise summary of this conversation (2-3 sentences, under 300 characters).
56
+
57
+ Focus on:
58
+ - What was accomplished
59
+ - Key decisions made
60
+ - Important context established
61
+
62
+ Conversation messages:
63
+ ${messagesText}`;
64
+ }
65
+ /**
66
+ * Parse LLM fact extraction response
67
+ */
68
+ function parseExtractedFacts(llmResponse) {
69
+ try {
70
+ const jsonMatch = llmResponse.match(/\{[\s\S]*\}/);
71
+ if (!jsonMatch)
72
+ return [];
73
+ const json = JSON.parse(jsonMatch[0]);
74
+ return json.extractedFacts || [];
75
+ }
76
+ catch {
77
+ logger.warn('[SelfIteration] Failed to parse fact extraction response');
78
+ return [];
79
+ }
80
+ }
81
+ /**
82
+ * Get conversations ready for self-iteration
83
+ */
84
+ async function getConversationsForIteration(maxMessages) {
85
+ const db = await getDb();
86
+ if (!db)
87
+ return [];
88
+ const schema = await getSchema();
89
+ const sqliteDb = db;
90
+ // Get conversations that:
91
+ // 1. Have ended (endedAt is not null)
92
+ // 2. Haven't been processed yet (metadata.selfIterationProcessed is not set)
93
+ // 3. Have enough messages (messageCount >= minMessageCount)
94
+ const conversations = await sqliteDb.select()
95
+ .from(schema.conversations)
96
+ .where(sql `${schema.conversations.endedAt} IS NOT NULL
97
+ AND (${schema.conversations.metadata}->>'selfIterationProcessed') IS NULL
98
+ AND ${schema.conversations.messageCount} >= ?`)
99
+ .limit(10);
100
+ return conversations;
101
+ }
102
+ /**
103
+ * Get messages for a conversation
104
+ */
105
+ async function getConversationMessages(conversationId) {
106
+ const db = await getDb();
107
+ if (!db)
108
+ return [];
109
+ const schema = await getSchema();
110
+ const sqliteDb = db;
111
+ const messages = await sqliteDb.select()
112
+ .from(schema.messages)
113
+ .where(eq(schema.messages.conversationId, conversationId))
114
+ .orderBy(schema.messages.createdAt);
115
+ return messages.map((m) => ({
116
+ id: m.id,
117
+ conversationId: m.conversation_id,
118
+ role: m.role,
119
+ content: m.content,
120
+ createdAt: new Date(m.createdAt),
121
+ }));
122
+ }
123
+ /**
124
+ * Mark conversation as processed
125
+ */
126
+ async function markConversationProcessed(conversationId) {
127
+ const db = await getDb();
128
+ if (!db)
129
+ return;
130
+ const schema = await getSchema();
131
+ const sqliteDb = db;
132
+ await sqliteDb.update(schema.conversations)
133
+ .set({
134
+ metadata: sql `json_set(${schema.conversations.metadata}, 'selfIterationProcessed', true)`,
135
+ })
136
+ .where(eq(schema.conversations.id, conversationId));
137
+ }
138
+ /**
139
+ * Process a single conversation
140
+ */
141
+ async function processConversation(conversation, config) {
142
+ const messages = await getConversationMessages(conversation.id);
143
+ let memoriesCreated = 0;
144
+ let summariesCreated = 0;
145
+ // Limit messages if configured
146
+ const messagesToProcess = config.maxMessagesToProcess > 0
147
+ ? messages.slice(-config.maxMessagesToProcess)
148
+ : messages;
149
+ if (messagesToProcess.length === 0) {
150
+ return { memoriesCreated, summariesCreated };
151
+ }
152
+ // Extract facts
153
+ if (config.extractFacts) {
154
+ const prompt = buildFactExtractionPrompt(messagesToProcess);
155
+ // Here we would call an LLM client to extract facts
156
+ // For now, we'll use a simple heuristic extraction
157
+ const extractedFacts = [];
158
+ for (const msg of messagesToProcess) {
159
+ if (msg.role === 'user') {
160
+ const content = msg.content.toLowerCase();
161
+ // Look for user preferences
162
+ if (content.includes('i want') || content.includes('i prefer') || content.includes('i like')) {
163
+ extractedFacts.push({
164
+ content: `User preference: ${msg.content}`,
165
+ type: 'preference',
166
+ confidence: 70,
167
+ });
168
+ }
169
+ // Look for decisions
170
+ if (content.includes('i will') || content.includes('i decide') || content.includes('let\'s')) {
171
+ extractedFacts.push({
172
+ content: `Decision: ${msg.content}`,
173
+ type: 'decision',
174
+ confidence: 80,
175
+ });
176
+ }
177
+ }
178
+ }
179
+ // Store extracted facts as memories
180
+ for (const fact of extractedFacts) {
181
+ if (fact.confidence >= 60) {
182
+ try {
183
+ await rememberMemory({
184
+ content: fact.content,
185
+ type: fact.type,
186
+ project: conversation.projectId,
187
+ metadata: {
188
+ extractionMethod: 'self-iteration',
189
+ confidence: fact.confidence,
190
+ conversationId: conversation.id,
191
+ sessionId: conversation.sessionId,
192
+ },
193
+ });
194
+ memoriesCreated++;
195
+ logger.info(`[SelfIteration] Extracted memory: ${fact.type} - ${fact.content.substring(0, 50)}...`);
196
+ }
197
+ catch (error) {
198
+ logger.error(`[SelfIteration] Failed to store memory:`, error);
199
+ }
200
+ }
201
+ }
202
+ }
203
+ // Generate summary
204
+ if (config.generateSummaries && messagesToProcess.length > 0) {
205
+ const prompt = buildSummaryPrompt(messagesToProcess);
206
+ // Here we would call an LLM client to generate summary
207
+ // For now, use simple heuristic
208
+ const userMessages = messagesToProcess.filter(m => m.role === 'user');
209
+ const lastMessage = userMessages[userMessages.length - 1]?.content || '';
210
+ const summary = lastMessage.substring(0, Math.min(250, lastMessage.length));
211
+ // Update conversation with summary
212
+ const db = await getDb();
213
+ const schema = await getSchema();
214
+ const sqliteDb = db;
215
+ await sqliteDb.update(schema.conversations)
216
+ .set({ summary })
217
+ .where(eq(schema.conversations.id, conversation.id));
218
+ summariesCreated++;
219
+ logger.info(`[SelfIteration] Generated summary for conversation ${conversation.sessionId}`);
220
+ }
221
+ return { memoriesCreated, summariesCreated };
222
+ }
223
+ /**
224
+ * Register self-iteration job handler
225
+ */
226
+ const selfIterationHandler = async (context) => {
227
+ logger.info('[SelfIteration] Starting job');
228
+ const config = {
229
+ ...DEFAULT_CONFIG,
230
+ ...context.config,
231
+ };
232
+ if (!config.enabled) {
233
+ logger.info('[SelfIteration] Job disabled, skipping');
234
+ return { recordsProcessed: 0, summary: { status: 'disabled' } };
235
+ }
236
+ try {
237
+ const conversations = await getConversationsForIteration(config.maxMessagesToProcess || DEFAULT_CONFIG.maxMessagesToProcess);
238
+ if (conversations.length === 0) {
239
+ logger.info('[SelfIteration] No conversations to process');
240
+ return { recordsProcessed: 0, summary: { status: 'no_conversations' } };
241
+ }
242
+ let totalMemoriesCreated = 0;
243
+ let totalSummariesGenerated = 0;
244
+ let processedCount = 0;
245
+ for (const conversation of conversations) {
246
+ // Skip if already processed
247
+ if (conversation.metadata?.selfIterationProcessed) {
248
+ continue;
249
+ }
250
+ try {
251
+ const result = await processConversation(conversation, config);
252
+ totalMemoriesCreated += result.memoriesCreated;
253
+ totalSummariesGenerated += result.summariesCreated;
254
+ await markConversationProcessed(conversation.id);
255
+ processedCount++;
256
+ }
257
+ catch (error) {
258
+ logger.error(`[SelfIteration] Failed to process conversation ${conversation.id}:`, error);
259
+ }
260
+ }
261
+ logger.info(`[SelfIteration] Processed ${processedCount}/${conversations.length} conversations`);
262
+ logger.info(`[SelfIteration] Created ${totalMemoriesCreated} memories`);
263
+ logger.info(`[SelfIteration] Generated ${totalSummariesGenerated} summaries`);
264
+ return {
265
+ recordsProcessed: processedCount,
266
+ summary: {
267
+ memoriesCreated: totalMemoriesCreated,
268
+ summariesGenerated: totalSummariesGenerated,
269
+ totalConversations: conversations.length,
270
+ },
271
+ };
272
+ }
273
+ catch (error) {
274
+ logger.error('[SelfIteration] Job failed:', error);
275
+ return {
276
+ recordsProcessed: 0,
277
+ summary: { error: error instanceof Error ? error.message : String(error) },
278
+ };
279
+ }
280
+ };
281
+ export { selfIterationHandler, DEFAULT_CONFIG };
282
+ //# sourceMappingURL=self-iteration-job.js.map
@@ -0,0 +1,18 @@
1
+ /** Session Hooks - Lifecycle hooks for conversation management
2
+ *
3
+ * Provides functions to be called when sessions start/end
4
+ */
5
+ /**
6
+ * Called when a session ends
7
+ * Marks the conversation as ended so self-iteration can process it
8
+ */
9
+ export declare function onSessionEnd(sessionId: string): Promise<void>;
10
+ /**
11
+ * Get active sessions for a project
12
+ */
13
+ export declare function getActiveSessions(projectId: string): Promise<string[]>;
14
+ /**
15
+ * End all sessions for a project
16
+ */
17
+ export declare function endAllProjectSessions(projectId: string): Promise<number>;
18
+ //# sourceMappingURL=session-hooks.d.ts.map
@@ -0,0 +1,58 @@
1
+ /** Session Hooks - Lifecycle hooks for conversation management
2
+ *
3
+ * Provides functions to be called when sessions start/end
4
+ */
5
+ import { sql, eq } from 'drizzle-orm';
6
+ import { getDb } from '../../db/index.js';
7
+ import { getSchema } from '../../db/schema.js';
8
+ import { logger } from '../logger.js';
9
+ /**
10
+ * Called when a session ends
11
+ * Marks the conversation as ended so self-iteration can process it
12
+ */
13
+ export async function onSessionEnd(sessionId) {
14
+ logger.info(`[SessionHooks] Session ended: ${sessionId}`);
15
+ const db = await getDb();
16
+ if (!db) {
17
+ logger.warn('[SessionHooks] Database unavailable, cannot end session');
18
+ return;
19
+ }
20
+ const schema = await getSchema();
21
+ const sqliteDb = db;
22
+ // Mark conversation as ended
23
+ await sqliteDb.update(schema.conversations)
24
+ .set({ endedAt: new Date() })
25
+ .where(eq(schema.conversations.sessionId, sessionId));
26
+ logger.info(`[SessionHooks] Session ${sessionId} marked as ended`);
27
+ }
28
+ /**
29
+ * Get active sessions for a project
30
+ */
31
+ export async function getActiveSessions(projectId) {
32
+ const db = await getDb();
33
+ if (!db)
34
+ return [];
35
+ const schema = await getSchema();
36
+ const sqliteDb = db;
37
+ const sessions = await sqliteDb.select()
38
+ .from(schema.conversations)
39
+ .where(eq(schema.conversations.projectId, projectId))
40
+ .where(sql `${schema.conversations.endedAt} IS NULL`);
41
+ return sessions.map((s) => s.session_id);
42
+ }
43
+ /**
44
+ * End all sessions for a project
45
+ */
46
+ export async function endAllProjectSessions(projectId) {
47
+ const db = await getDb();
48
+ if (!db)
49
+ return 0;
50
+ const schema = await getSchema();
51
+ const sqliteDb = db;
52
+ const result = await sqliteDb.update(schema.conversations)
53
+ .set({ endedAt: new Date() })
54
+ .where(eq(schema.conversations.projectId, projectId));
55
+ logger.info(`[SessionHooks] Ended ${result.rowCount} sessions for project ${projectId}`);
56
+ return result.rowCount || 0;
57
+ }
58
+ //# sourceMappingURL=session-hooks.js.map