claude-memory-layer 1.0.26 → 1.0.28

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 (328) hide show
  1. package/.env.example +7 -0
  2. package/AGENTS.md +11 -0
  3. package/README.md +184 -41
  4. package/benchmarks/replay/anonymized-real-sessions.json +48 -0
  5. package/dist/cli/index.js +10097 -6003
  6. package/dist/cli/index.js.map +4 -4
  7. package/dist/core/index.js +9745 -5587
  8. package/dist/core/index.js.map +4 -4
  9. package/dist/hooks/post-tool-use.js +6545 -5270
  10. package/dist/hooks/post-tool-use.js.map +4 -4
  11. package/dist/hooks/semantic-daemon.js +6646 -5354
  12. package/dist/hooks/semantic-daemon.js.map +4 -4
  13. package/dist/hooks/session-end.js +6618 -5347
  14. package/dist/hooks/session-end.js.map +4 -4
  15. package/dist/hooks/session-start.js +6619 -5354
  16. package/dist/hooks/session-start.js.map +4 -4
  17. package/dist/hooks/stop.js +6614 -5325
  18. package/dist/hooks/stop.js.map +4 -4
  19. package/dist/hooks/user-prompt-submit.js +6702 -5356
  20. package/dist/hooks/user-prompt-submit.js.map +4 -4
  21. package/dist/index.js +13537 -0
  22. package/dist/index.js.map +7 -0
  23. package/dist/mcp/index.js +20770 -0
  24. package/dist/mcp/index.js.map +7 -0
  25. package/dist/server/api/index.js +6632 -5319
  26. package/dist/server/api/index.js.map +4 -4
  27. package/dist/server/index.js +6667 -5340
  28. package/dist/server/index.js.map +4 -4
  29. package/dist/services/memory-service.js +6568 -5350
  30. package/dist/services/memory-service.js.map +4 -4
  31. package/dist/ui/assets/js/bootstrap.js +244 -0
  32. package/dist/ui/assets/js/chat.js +373 -0
  33. package/dist/ui/assets/js/disclosure.js +232 -0
  34. package/dist/ui/assets/js/modals.js +298 -0
  35. package/dist/ui/assets/js/overview.js +655 -0
  36. package/dist/ui/assets/js/state.js +72 -0
  37. package/dist/ui/assets/js/views.js +468 -0
  38. package/dist/ui/index.html +43 -1
  39. package/dist/ui/index.ts +3 -0
  40. package/dist/ui/style.css +222 -0
  41. package/docs/ARCHITECTURE_COMPARISON_AND_RECOMMENDATIONS.md +627 -0
  42. package/docs/HERMES_MEMORY_INGESTION_ANALYSIS.md +440 -0
  43. package/docs/MEMORY_USEFULNESS_AUDIT.md +371 -0
  44. package/docs/MEMORY_USEFULNESS_AUDIT_RAW.json +80 -0
  45. package/docs/MEMSEARCH_PROJECT_STRUCTURE_ANALYSIS.md +333 -0
  46. package/docs/PRODUCT_VALIDATION_MATRIX.md +82 -0
  47. package/docs/PROJECT_STRUCTURE_ANALYSIS.md +421 -0
  48. package/docs/REFACTORING_MILESTONES_AND_ISSUES.md +501 -0
  49. package/docs/REFACTORING_PLAN_THIN_CORE.md +414 -0
  50. package/docs/REFERENCE_PROJECT_ANALYSES.md +25 -0
  51. package/docs/SUPERLOCALMEMORY_PROJECT_STRUCTURE_ANALYSIS.md +452 -0
  52. package/docs/TARGET_ARCHITECTURE_AND_FOLDER_STRUCTURE.md +446 -0
  53. package/docs/architecture/comparison-index.md +47 -0
  54. package/docs/reports/codex-real-data-validation-20260505T040447Z.md +46 -0
  55. package/package.json +9 -5
  56. package/scripts/build.ts +25 -8
  57. package/scripts/generate-session-qrels.ts +126 -0
  58. package/scripts/replay-retrieval-benchmark.ts +69 -0
  59. package/specs/thin-core-refactor/context.md +275 -0
  60. package/specs/thin-core-refactor/plan.md +536 -0
  61. package/specs/thin-core-refactor/spec.md +465 -0
  62. package/src/adapters/claude/capture/index.ts +3 -0
  63. package/src/adapters/claude/context/index.ts +3 -0
  64. package/src/adapters/claude/hooks/index.ts +21 -0
  65. package/src/adapters/claude/hooks/post-tool-use.ts +239 -0
  66. package/src/adapters/claude/hooks/prompt-injection-policy.ts +104 -0
  67. package/src/adapters/claude/hooks/semantic-daemon-client.ts +209 -0
  68. package/src/adapters/claude/hooks/semantic-daemon.ts +283 -0
  69. package/src/adapters/claude/hooks/session-end.ts +59 -0
  70. package/src/adapters/claude/hooks/session-start.ts +73 -0
  71. package/src/adapters/claude/hooks/stop.ts +128 -0
  72. package/src/adapters/claude/hooks/user-prompt-submit.ts +361 -0
  73. package/src/adapters/claude/index.ts +4 -0
  74. package/src/adapters/claude/transcript/index.ts +4 -0
  75. package/src/adapters/claude/transcript/transcript-reader.ts +57 -0
  76. package/src/adapters/claude/transcript/turn-reconstructor.ts +65 -0
  77. package/src/apps/cli/claude-settings-hooks.ts +138 -0
  78. package/src/apps/cli/codex-import-runner.ts +125 -0
  79. package/src/apps/cli/codex-validation-output.ts +95 -0
  80. package/src/apps/cli/hermes-import-runner.ts +130 -0
  81. package/src/apps/cli/hermes-validation-output.ts +91 -0
  82. package/src/apps/cli/index.ts +1731 -0
  83. package/src/apps/cli/mcp-install.ts +106 -0
  84. package/src/apps/cli/retrieval-disclosure-output.ts +196 -0
  85. package/src/apps/dashboard/assets/js/bootstrap.js +244 -0
  86. package/src/apps/dashboard/assets/js/chat.js +373 -0
  87. package/src/apps/dashboard/assets/js/disclosure.js +232 -0
  88. package/src/apps/dashboard/assets/js/modals.js +298 -0
  89. package/src/apps/dashboard/assets/js/overview.js +655 -0
  90. package/src/apps/dashboard/assets/js/state.js +72 -0
  91. package/src/apps/dashboard/assets/js/views.js +468 -0
  92. package/src/{ui → apps/dashboard}/index.html +43 -1
  93. package/src/apps/dashboard/index.ts +3 -0
  94. package/src/{ui → apps/dashboard}/style.css +222 -0
  95. package/src/apps/index.ts +5 -0
  96. package/src/apps/server/api/chat.ts +244 -0
  97. package/src/apps/server/api/citations.ts +105 -0
  98. package/src/apps/server/api/events.ts +137 -0
  99. package/src/apps/server/api/health.ts +53 -0
  100. package/src/apps/server/api/index.ts +26 -0
  101. package/src/apps/server/api/projects.ts +74 -0
  102. package/src/apps/server/api/search.ts +184 -0
  103. package/src/apps/server/api/sessions.ts +115 -0
  104. package/src/apps/server/api/stats.ts +723 -0
  105. package/src/apps/server/api/turns.ts +143 -0
  106. package/src/apps/server/api/utils.ts +65 -0
  107. package/src/apps/server/index.ts +111 -0
  108. package/src/cli/index.ts +2 -1311
  109. package/src/cli/retrieval-disclosure-output.ts +2 -0
  110. package/src/compat/index.ts +5 -0
  111. package/src/core/derive/fact-deriver.ts +170 -0
  112. package/src/core/derive/index.ts +2 -0
  113. package/src/core/derive/summary-deriver.ts +76 -0
  114. package/src/core/embedder.ts +4 -152
  115. package/src/core/engine/embedding-maintenance-service.ts +187 -0
  116. package/src/core/engine/endless-memory-services.ts +4 -0
  117. package/src/core/engine/index.ts +19 -0
  118. package/src/core/engine/memory-engine-services.ts +170 -0
  119. package/src/core/engine/memory-ingest-service.ts +317 -0
  120. package/src/core/engine/memory-query-service.ts +173 -0
  121. package/src/core/engine/memory-runtime-service.ts +162 -0
  122. package/src/core/engine/memory-service-composition.ts +231 -0
  123. package/src/core/engine/retrieval-analytics-service.ts +181 -0
  124. package/src/core/engine/retrieval-disclosure-service.ts +420 -0
  125. package/src/core/engine/retrieval-orchestrator.ts +377 -0
  126. package/src/core/engine/retrieval-services.ts +176 -0
  127. package/src/core/engine/shared-memory-services.ts +4 -0
  128. package/src/core/entity-repo.ts +1 -3
  129. package/src/core/event-store.ts +3 -3
  130. package/src/core/evidence-aligner.ts +2 -2
  131. package/src/core/external-market-context.ts +582 -0
  132. package/src/core/graduation.ts +2 -3
  133. package/src/core/index.ts +21 -0
  134. package/src/core/matcher.ts +2 -4
  135. package/src/core/model/memory-fact.ts +30 -0
  136. package/src/core/model/memory-rule.ts +14 -0
  137. package/src/core/model/memory-summary.ts +21 -0
  138. package/src/core/model/raw-event.ts +28 -0
  139. package/src/core/model/retrieval-result.ts +35 -0
  140. package/src/core/privacy/filter.ts +21 -10
  141. package/src/core/product-validation-matrix.ts +314 -0
  142. package/src/core/progressive-retriever.ts +1 -2
  143. package/src/core/registry/project-path.ts +54 -0
  144. package/src/core/registry/session-registry.ts +69 -0
  145. package/src/core/replay-evaluator.ts +625 -0
  146. package/src/core/retrieval-benchmark.ts +117 -0
  147. package/src/core/retrieval-quality.ts +109 -0
  148. package/src/core/retriever.ts +53 -15
  149. package/src/core/session-qrels.ts +360 -0
  150. package/src/core/shared-event-store.ts +1 -1
  151. package/src/core/sqlite-event-store.ts +35 -11
  152. package/src/core/task/blocker-resolver.ts +2 -2
  153. package/src/core/task/task-resolver.ts +0 -1
  154. package/src/core/vector-outbox.ts +1 -10
  155. package/src/core/vector-worker.ts +1 -1
  156. package/src/extensions/endless-memory/endless-memory-services.ts +350 -0
  157. package/src/extensions/endless-memory/index.ts +1 -0
  158. package/src/extensions/index.ts +5 -0
  159. package/src/extensions/mcp/handlers.ts +960 -0
  160. package/src/extensions/mcp/index.ts +48 -0
  161. package/src/extensions/mcp/tools.ts +252 -0
  162. package/src/extensions/shared-memory/index.ts +1 -0
  163. package/src/extensions/shared-memory/shared-memory-services.ts +211 -0
  164. package/src/extensions/vector/embedder.ts +197 -0
  165. package/src/extensions/vector/index.ts +1 -0
  166. package/src/hooks/post-tool-use.ts +3 -236
  167. package/src/hooks/semantic-daemon-client.ts +1 -208
  168. package/src/hooks/semantic-daemon.ts +6 -271
  169. package/src/hooks/session-end.ts +4 -79
  170. package/src/hooks/session-start.ts +4 -73
  171. package/src/hooks/stop.ts +3 -173
  172. package/src/hooks/user-prompt-submit.ts +3 -338
  173. package/src/index.ts +13 -0
  174. package/src/mcp/handlers.ts +2 -212
  175. package/src/mcp/index.ts +3 -46
  176. package/src/mcp/tools.ts +2 -78
  177. package/src/server/api/chat.ts +2 -244
  178. package/src/server/api/citations.ts +2 -105
  179. package/src/server/api/events.ts +2 -137
  180. package/src/server/api/health.ts +2 -53
  181. package/src/server/api/index.ts +2 -26
  182. package/src/server/api/projects.ts +2 -74
  183. package/src/server/api/search.ts +2 -102
  184. package/src/server/api/sessions.ts +2 -115
  185. package/src/server/api/stats.ts +2 -724
  186. package/src/server/api/turns.ts +2 -143
  187. package/src/server/api/utils.ts +2 -46
  188. package/src/server/index.ts +2 -100
  189. package/src/services/bootstrap-organizer.ts +46 -26
  190. package/src/services/codex-session-history-importer.ts +521 -29
  191. package/src/services/hermes-session-history-importer.ts +733 -0
  192. package/src/services/memory-service-config.ts +36 -0
  193. package/src/services/memory-service-registry.ts +150 -0
  194. package/src/services/memory-service.ts +211 -1325
  195. package/src/services/session-history-importer.ts +58 -14
  196. package/tests/README.md +23 -0
  197. package/tests/adapters/claude/claude-semantic-daemon-adapter.test.ts +54 -0
  198. package/tests/adapters/claude/claude-transcript-reconstructor.test.ts +98 -0
  199. package/tests/adapters/claude-hook-prompt-injection-policy.test.ts +99 -0
  200. package/tests/apps/app-layer-boundary.test.ts +48 -0
  201. package/tests/apps/claude-settings-hooks.test.ts +107 -0
  202. package/tests/apps/cli-disclosure-output.test.ts +212 -0
  203. package/tests/apps/codex-import-runner.test.ts +99 -0
  204. package/tests/apps/codex-validation-output.test.ts +100 -0
  205. package/tests/apps/hermes-import-runner.test.ts +99 -0
  206. package/tests/apps/mcp-install-command.test.ts +59 -0
  207. package/tests/apps/package-build-entrypoints.test.ts +30 -0
  208. package/tests/apps/search-api-disclosure.test.ts +162 -0
  209. package/tests/apps/stats-api-lightweight.test.ts +67 -0
  210. package/tests/apps/ui-disclosure-output.test.ts +140 -0
  211. package/tests/{bootstrap-organizer.test.ts → core/bootstrap-organizer.test.ts} +1 -1
  212. package/tests/{canonical-key.test.ts → core/canonical-key.test.ts} +1 -1
  213. package/tests/core/codex-session-history-importer-validation.test.ts +185 -0
  214. package/tests/{consolidation-worker.test.ts → core/consolidation-worker.test.ts} +2 -2
  215. package/tests/core/embedding-maintenance-service.test.ts +282 -0
  216. package/tests/{evidence-aligner.test.ts → core/evidence-aligner.test.ts} +1 -1
  217. package/tests/core/external-market-context.test.ts +209 -0
  218. package/tests/core/fact-deriver.test.ts +79 -0
  219. package/tests/core/hermes-session-history-importer-validation.test.ts +609 -0
  220. package/tests/{ingest-interceptor.test.ts → core/ingest-interceptor.test.ts} +1 -1
  221. package/tests/{markdown-mirror.test.ts → core/markdown-mirror.test.ts} +2 -2
  222. package/tests/{matcher.test.ts → core/matcher.test.ts} +1 -1
  223. package/tests/{md-mirror.test.ts → core/md-mirror.test.ts} +2 -2
  224. package/tests/core/memory-engine-services.test.ts +240 -0
  225. package/tests/core/memory-ingest-service.test.ts +296 -0
  226. package/tests/core/memory-query-service.test.ts +129 -0
  227. package/tests/core/memory-runtime-service.test.ts +201 -0
  228. package/tests/core/memory-service-composition.test.ts +192 -0
  229. package/tests/core/memory-service-config.test.ts +41 -0
  230. package/tests/core/memory-service-facade.test.ts +30 -0
  231. package/tests/core/memory-service-registry.test.ts +206 -0
  232. package/tests/core/product-validation-matrix.test.ts +61 -0
  233. package/tests/core/project-registry.test.ts +78 -0
  234. package/tests/core/replay-evaluator.test.ts +181 -0
  235. package/tests/core/retrieval-analytics-service.test.ts +210 -0
  236. package/tests/core/retrieval-benchmark.test.ts +93 -0
  237. package/tests/core/retrieval-disclosure-service.test.ts +264 -0
  238. package/tests/core/retrieval-orchestrator.test.ts +403 -0
  239. package/tests/core/retrieval-quality.test.ts +31 -0
  240. package/tests/core/retrieval-services.test.ts +185 -0
  241. package/tests/{retriever-fallback-chain.test.ts → core/retriever-fallback-chain.test.ts} +3 -3
  242. package/tests/{retriever-strategy-scope.test.ts → core/retriever-strategy-scope.test.ts} +70 -3
  243. package/tests/{retriever.memu-adoption.test.ts → core/retriever.memu-adoption.test.ts} +3 -3
  244. package/tests/core/session-history-importer-filter.test.ts +78 -0
  245. package/tests/core/session-qrels.test.ts +250 -0
  246. package/tests/{sqlite-event-store-replication.test.ts → core/sqlite-event-store-replication.test.ts} +36 -1
  247. package/tests/core/summary-deriver.test.ts +66 -0
  248. package/tests/extensions/embedder-warning-suppression.test.ts +53 -0
  249. package/tests/extensions/endless-memory-extension-boundary.test.ts +17 -0
  250. package/tests/extensions/endless-memory-services.test.ts +325 -0
  251. package/tests/extensions/mcp-context-tools.test.ts +905 -0
  252. package/tests/extensions/mcp-extension-boundary.test.ts +21 -0
  253. package/tests/extensions/mcp-package-build.test.ts +22 -0
  254. package/tests/extensions/mcp-project-aware-tools.test.ts +102 -0
  255. package/tests/extensions/shared-memory-extension-boundary.test.ts +24 -0
  256. package/tests/extensions/shared-memory-services.test.ts +309 -0
  257. package/tests/extensions/vector-extension-boundary.test.ts +21 -0
  258. package/.claude/settings.local.json +0 -25
  259. package/.npm-cache/_cacache/content-v2/sha512/04/76/c098f88dfe584a2b80870bff7421b05d17d3d9ee1027f77772332a22d3f93a9a57101a2855107f6ad82077a818bba912b2bc317f2361b5ddb09ad284d9ce +0 -0
  260. package/.npm-cache/_cacache/content-v2/sha512/60/25/d2ecd39cfc7cab58351162814be77f935c6d6491c10c3745d456da7ddb2117ffd90c10e53fe3c0f1ed16b403307841543634504398b16ee4e6b6dd8e0c45 +0 -0
  261. package/.npm-cache/_cacache/index-v5/2b/9a/7f8f40206ed8a2e0a84efaa953ccaed1f5d001e14b931083f2e7a0738007 +0 -2
  262. package/.npm-cache/_cacache/index-v5/2e/d9/fcfa5c6a6abdc2a3644ab84a95936047298c465a2f47ee03db8f7fe1e946 +0 -3
  263. package/.npm-cache/_cacache/index-v5/a9/42/e519633356d12d3d2f19da66a8301016d496c8f5c3e0554124aaa62dc043 +0 -2
  264. package/.npm-cache/_logs/2026-02-26T12_04_52_729Z-debug-0.log +0 -256
  265. package/.npm-cache/_logs/2026-02-26T12_05_36_835Z-debug-0.log +0 -18
  266. package/.npm-cache/_logs/2026-02-26T12_05_45_982Z-debug-0.log +0 -32
  267. package/.npm-cache/_logs/2026-02-26T12_05_48_515Z-debug-0.log +0 -260
  268. package/.npm-cache/_logs/2026-02-26T12_05_53_567Z-debug-0.log +0 -69
  269. package/.npm-cache/_update-notifier-last-checked +0 -0
  270. package/bootstrap-kb/decisions/decisions.md +0 -244
  271. package/bootstrap-kb/glossary/glossary.md +0 -46
  272. package/bootstrap-kb/modules/.claude-plugin.md +0 -22
  273. package/bootstrap-kb/modules/agents.md.md +0 -15
  274. package/bootstrap-kb/modules/claude.md.md +0 -15
  275. package/bootstrap-kb/modules/context.md.md +0 -15
  276. package/bootstrap-kb/modules/docs.md +0 -18
  277. package/bootstrap-kb/modules/handoff.md.md +0 -15
  278. package/bootstrap-kb/modules/package-lock.json.md +0 -15
  279. package/bootstrap-kb/modules/package.json.md +0 -15
  280. package/bootstrap-kb/modules/plan.md.md +0 -15
  281. package/bootstrap-kb/modules/readme.md.md +0 -15
  282. package/bootstrap-kb/modules/scripts.md +0 -26
  283. package/bootstrap-kb/modules/spec.md.md +0 -15
  284. package/bootstrap-kb/modules/specs.md +0 -20
  285. package/bootstrap-kb/modules/src.md +0 -51
  286. package/bootstrap-kb/modules/tests.md +0 -42
  287. package/bootstrap-kb/modules/tsconfig.json.md +0 -15
  288. package/bootstrap-kb/modules/vitest.config.ts.md +0 -15
  289. package/bootstrap-kb/overview/overview.md +0 -40
  290. package/bootstrap-kb/sources/manifest.json +0 -950
  291. package/bootstrap-kb/sources/manifest.md +0 -227
  292. package/bootstrap-kb/timeline/timeline.md +0 -57
  293. package/claude-memory-layer-1.0.14.tgz +0 -0
  294. package/d.sh +0 -3
  295. package/deploy.sh +0 -3
  296. package/dist/ui/app.js +0 -2101
  297. package/memory/.claude-plugin/commands/2026-02-25.md +0 -263
  298. package/memory/_index.md +0 -418
  299. package/memory/agent_response/uncategorized/2026-02-26.md +0 -176
  300. package/memory/agent_response/uncategorized/2026-03-03.md +0 -14
  301. package/memory/agent_response/uncategorized/2026-03-04.md +0 -1421
  302. package/memory/agent_response/uncategorized/2026-03-05.md +0 -48
  303. package/memory/default/uncategorized/2026-02-25.md +0 -4839
  304. package/memory/session_summary/uncategorized/2026-02-26.md +0 -13
  305. package/memory/session_summary/uncategorized/2026-03-03.md +0 -5
  306. package/memory/session_summary/uncategorized/2026-03-04.md +0 -50
  307. package/memory/specs/20260207-dashboard-upgrade/2026-02-25.md +0 -142
  308. package/memory/specs/citations-system/2026-02-25.md +0 -1121
  309. package/memory/specs/endless-mode/2026-02-25.md +0 -1392
  310. package/memory/specs/entity-edge-model/2026-02-25.md +0 -1263
  311. package/memory/specs/evidence-aligner-v2/2026-02-25.md +0 -1028
  312. package/memory/specs/mcp-desktop-integration/2026-02-25.md +0 -1334
  313. package/memory/specs/post-tool-use-hook/2026-02-25.md +0 -1164
  314. package/memory/specs/private-tags/2026-02-25.md +0 -1057
  315. package/memory/specs/progressive-disclosure/2026-02-25.md +0 -1436
  316. package/memory/specs/task-entity-system/2026-02-25.md +0 -924
  317. package/memory/specs/vector-outbox-v2/2026-02-25.md +0 -1510
  318. package/memory/specs/web-viewer-ui/2026-02-25.md +0 -1709
  319. package/memory/tool_observation/uncategorized/2026-02-26.md +0 -209
  320. package/memory/tool_observation/uncategorized/2026-03-03.md +0 -21
  321. package/memory/tool_observation/uncategorized/2026-03-04.md +0 -1033
  322. package/memory/tool_observation/uncategorized/2026-03-05.md +0 -29
  323. package/memory/user_prompt/uncategorized/2026-02-26.md +0 -25
  324. package/memory/user_prompt/uncategorized/2026-03-04.md +0 -634
  325. package/specs/optional-duckdb/context.md +0 -77
  326. package/specs/optional-duckdb/plan.md +0 -142
  327. package/specs/optional-duckdb/spec.md +0 -35
  328. package/src/ui/app.js +0 -2101
@@ -1,143 +1,2 @@
1
- /**
2
- * Turns API
3
- * Endpoints for viewing events grouped by conversation turn
4
- *
5
- * A "turn" groups a user_prompt with its associated tool_observations
6
- * and the final agent_response into a single logical unit.
7
- */
8
-
9
- import { Hono } from 'hono';
10
- import { getServiceFromQuery } from './utils.js';
11
-
12
- export const turnsRouter = new Hono();
13
-
14
- // GET /api/turns?sessionId=xxx - List turns for a session
15
- turnsRouter.get('/', async (c) => {
16
- const sessionId = c.req.query('sessionId');
17
- const limit = parseInt(c.req.query('limit') || '20', 10);
18
- const offset = parseInt(c.req.query('offset') || '0', 10);
19
-
20
- if (!sessionId) {
21
- return c.json({ error: 'sessionId is required' }, 400);
22
- }
23
-
24
- const memoryService = getServiceFromQuery(c);
25
-
26
- try {
27
- await memoryService.initialize();
28
-
29
- const turns = await memoryService.getSessionTurns(sessionId, { limit, offset });
30
- const totalTurns = await memoryService.countSessionTurns(sessionId);
31
-
32
- return c.json({
33
- turns: turns.map(t => ({
34
- turnId: t.turnId,
35
- startedAt: t.startedAt.toISOString(),
36
- promptPreview: t.promptPreview,
37
- eventCount: t.eventCount,
38
- toolCount: t.toolCount,
39
- hasResponse: t.hasResponse,
40
- events: t.events.map(e => ({
41
- id: e.id,
42
- eventType: e.eventType,
43
- timestamp: e.timestamp instanceof Date ? e.timestamp.toISOString() : e.timestamp,
44
- preview: e.content.slice(0, 300) + (e.content.length > 300 ? '...' : ''),
45
- contentLength: e.content.length
46
- }))
47
- })),
48
- total: totalTurns,
49
- limit,
50
- offset,
51
- hasMore: offset + limit < totalTurns
52
- });
53
- } catch (error) {
54
- return c.json({ error: (error as Error).message }, 500);
55
- } finally {
56
- await memoryService.shutdown();
57
- }
58
- });
59
-
60
- // GET /api/turns/:turnId - Get full turn details
61
- turnsRouter.get('/:turnId', async (c) => {
62
- const { turnId } = c.req.param();
63
- const memoryService = getServiceFromQuery(c);
64
-
65
- try {
66
- await memoryService.initialize();
67
-
68
- const events = await memoryService.getEventsByTurn(turnId);
69
-
70
- if (events.length === 0) {
71
- return c.json({ error: 'Turn not found' }, 404);
72
- }
73
-
74
- const promptEvent = events.find(e => e.eventType === 'user_prompt');
75
- const toolEvents = events.filter(e => e.eventType === 'tool_observation');
76
- const responseEvents = events.filter(e => e.eventType === 'agent_response');
77
-
78
- return c.json({
79
- turnId,
80
- sessionId: events[0].sessionId,
81
- startedAt: events[0].timestamp instanceof Date
82
- ? events[0].timestamp.toISOString()
83
- : events[0].timestamp,
84
- prompt: promptEvent ? {
85
- id: promptEvent.id,
86
- content: promptEvent.content,
87
- timestamp: promptEvent.timestamp instanceof Date
88
- ? promptEvent.timestamp.toISOString()
89
- : promptEvent.timestamp
90
- } : null,
91
- tools: toolEvents.map(e => {
92
- let toolName = '';
93
- let success = true;
94
- try {
95
- const parsed = JSON.parse(e.content);
96
- toolName = parsed.toolName || '';
97
- success = parsed.success !== false;
98
- } catch { /* ignore */ }
99
-
100
- return {
101
- id: e.id,
102
- toolName,
103
- success,
104
- timestamp: e.timestamp instanceof Date ? e.timestamp.toISOString() : e.timestamp,
105
- preview: e.content.slice(0, 500) + (e.content.length > 500 ? '...' : '')
106
- };
107
- }),
108
- responses: responseEvents.map(e => ({
109
- id: e.id,
110
- content: e.content,
111
- timestamp: e.timestamp instanceof Date ? e.timestamp.toISOString() : e.timestamp
112
- })),
113
- totalEvents: events.length
114
- });
115
- } catch (error) {
116
- return c.json({ error: (error as Error).message }, 500);
117
- } finally {
118
- await memoryService.shutdown();
119
- }
120
- });
121
-
122
- // POST /api/turns/backfill - Backfill turn_ids from metadata
123
- turnsRouter.post('/backfill', async (c) => {
124
- const memoryService = getServiceFromQuery(c);
125
-
126
- try {
127
- await memoryService.initialize();
128
- const updated = await memoryService.backfillTurnIds();
129
-
130
- return c.json({
131
- success: true,
132
- updated,
133
- message: `Backfilled turn_id for ${updated} events`
134
- });
135
- } catch (error) {
136
- return c.json({
137
- success: false,
138
- error: (error as Error).message
139
- }, 500);
140
- } finally {
141
- await memoryService.shutdown();
142
- }
143
- });
1
+ /** Compatibility API module. Real app lives in src/apps/server/api. */
2
+ export * from '../../apps/server/api/turns.js';
@@ -1,46 +1,2 @@
1
- /**
2
- * API Utilities
3
- * Shared helpers for API endpoints
4
- */
5
-
6
- import type { Context } from 'hono';
7
- import * as path from 'path';
8
- import * as os from 'os';
9
- import { getReadOnlyMemoryService } from '../../services/memory-service.js';
10
- import { MemoryService } from '../../services/memory-service.js';
11
-
12
- /**
13
- * Get the appropriate MemoryService based on the ?project= query parameter.
14
- * - If ?project=<hash> is set (8 hex chars), resolves directly to project storage
15
- * - If ?project=<path> is set, computes hash from path
16
- * - Otherwise, returns the global read-only service
17
- *
18
- * Always creates read-only services for the dashboard API to avoid
19
- * VectorWorker lifecycle issues with per-request services.
20
- */
21
- export function getServiceFromQuery(c: Context): MemoryService {
22
- const project = c.req.query('project') || c.req.query('projectId');
23
- if (project) {
24
- // Check if it's a hash (8 hex chars) or a path
25
- const isHash = /^[a-f0-9]{8}$/.test(project);
26
- let storagePath: string;
27
-
28
- if (isHash) {
29
- storagePath = path.join(os.homedir(), '.claude-code', 'memory', 'projects', project);
30
- } else {
31
- // Import hashProjectPath dynamically to compute the hash from path
32
- const crypto = require('crypto');
33
- const normalized = project.replace(/\/+$/, '') || '/';
34
- const hash = crypto.createHash('sha256').update(normalized).digest('hex').slice(0, 8);
35
- storagePath = path.join(os.homedir(), '.claude-code', 'memory', 'projects', hash);
36
- }
37
-
38
- return new MemoryService({
39
- storagePath,
40
- readOnly: true,
41
- analyticsEnabled: false,
42
- sharedStoreConfig: { enabled: false }
43
- });
44
- }
45
- return getReadOnlyMemoryService();
46
- }
1
+ /** Compatibility API module. Real app lives in src/apps/server/api. */
2
+ export * from '../../apps/server/api/utils.js';
@@ -1,100 +1,2 @@
1
- /**
2
- * Web Viewer HTTP Server
3
- * Provides REST API and serves static UI files
4
- */
5
-
6
- // These are injected by the esbuild banner
7
- declare const __dirname: string;
8
- declare const __filename: string;
9
-
10
- import { Hono } from 'hono';
11
- import { cors } from 'hono/cors';
12
- import { logger } from 'hono/logger';
13
- import { serve } from '@hono/node-server';
14
- import { serveStatic } from '@hono/node-server/serve-static';
15
- import * as path from 'path';
16
- import * as fs from 'fs';
17
- import type { Server } from 'http';
18
-
19
- import { apiRouter } from './api/index.js';
20
-
21
- const app = new Hono();
22
-
23
- // Middleware
24
- app.use('/*', cors());
25
- app.use('/*', logger());
26
-
27
- // API routes
28
- app.route('/api', apiRouter);
29
-
30
- // Health check
31
- app.get('/health', (c) => c.json({ status: 'ok', timestamp: new Date().toISOString() }));
32
-
33
- // Static files (UI)
34
- const uiPath = path.join(__dirname, '../../dist/ui');
35
- if (fs.existsSync(uiPath)) {
36
- app.use('/*', serveStatic({ root: uiPath }));
37
- }
38
-
39
- // Fallback for SPA routing
40
- app.get('*', (c) => {
41
- const indexPath = path.join(uiPath, 'index.html');
42
- if (fs.existsSync(indexPath)) {
43
- return c.html(fs.readFileSync(indexPath, 'utf-8'));
44
- }
45
- return c.text('UI not built. Run "npm run build:ui" first.', 404);
46
- });
47
-
48
- export { app };
49
-
50
- let serverInstance: Server | null = null;
51
-
52
- /**
53
- * Start the HTTP server
54
- */
55
- export function startServer(port: number = 37777): Server {
56
- if (serverInstance) {
57
- return serverInstance;
58
- }
59
-
60
- serverInstance = serve({
61
- fetch: app.fetch,
62
- port,
63
- hostname: '127.0.0.1'
64
- });
65
-
66
- console.log(`🧠 Code Memory viewer started at http://localhost:${port}`);
67
-
68
- return serverInstance;
69
- }
70
-
71
- /**
72
- * Stop the HTTP server
73
- */
74
- export function stopServer(): void {
75
- if (serverInstance) {
76
- serverInstance.close();
77
- serverInstance = null;
78
- }
79
- }
80
-
81
- /**
82
- * Check if server is running on given port
83
- */
84
- export async function isServerRunning(port: number = 37777): Promise<boolean> {
85
- try {
86
- const response = await fetch(`http://127.0.0.1:${port}/health`);
87
- return response.ok;
88
- } catch {
89
- return false;
90
- }
91
- }
92
-
93
- // Start server if run directly
94
- // Check if this file is being run directly (not imported)
95
- const isMainModule = process.argv[1]?.includes('server/index') ||
96
- process.argv[1]?.endsWith('server.js');
97
- if (isMainModule) {
98
- const port = parseInt(process.env.PORT || '37777', 10);
99
- startServer(port);
100
- }
1
+ /** Compatibility server entrypoint. Real app lives in src/apps/server. */
2
+ export * from '../apps/server/index.js';
@@ -103,37 +103,52 @@ function runGit(repoPath: string, command: string): string {
103
103
  return execSync(`git -C ${JSON.stringify(repoPath)} ${command}`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
104
104
  }
105
105
 
106
+ function parseGitLog(raw: string): CommitInfo[] {
107
+ const lines = raw.split(/\r?\n/);
108
+ const commits: CommitInfo[] = [];
109
+ let current: CommitInfo | null = null;
110
+
111
+ for (const line of lines) {
112
+ if (!line.trim()) {
113
+ if (current) {
114
+ commits.push(current);
115
+ current = null;
116
+ }
117
+ continue;
118
+ }
119
+
120
+ if (line.includes('\t') && line.split('\t').length >= 4) {
121
+ if (current) commits.push(current);
122
+ const [hash, date, author, ...subjectRest] = line.split('\t');
123
+ current = { hash, date, author, subject: subjectRest.join('\t').trim(), files: [] };
124
+ } else if (current) {
125
+ current.files.push(line.trim());
126
+ }
127
+ }
128
+
129
+ if (current) commits.push(current);
130
+ return commits;
131
+ }
132
+
106
133
  function getGitCommits(repoPath: string, since = '180 days ago', maxCommits = 1000): CommitInfo[] {
107
134
  try {
108
135
  const raw = runGit(
109
136
  repoPath,
110
137
  `log --since=${JSON.stringify(since)} -n ${Math.max(1, maxCommits)} --date=short --pretty=format:%H%x09%ad%x09%an%x09%s --name-only --reverse`
111
138
  );
139
+ return parseGitLog(raw);
140
+ } catch {
141
+ return [];
142
+ }
143
+ }
112
144
 
113
- const lines = raw.split(/\r?\n/);
114
- const commits: CommitInfo[] = [];
115
- let current: CommitInfo | null = null;
116
-
117
- for (const line of lines) {
118
- if (!line.trim()) {
119
- if (current) {
120
- commits.push(current);
121
- current = null;
122
- }
123
- continue;
124
- }
125
-
126
- if (line.includes('\t') && line.split('\t').length >= 4) {
127
- if (current) commits.push(current);
128
- const [hash, date, author, ...subjectRest] = line.split('\t');
129
- current = { hash, date, author, subject: subjectRest.join('\t').trim(), files: [] };
130
- } else if (current) {
131
- current.files.push(line.trim());
132
- }
133
- }
134
-
135
- if (current) commits.push(current);
136
- return commits;
145
+ function getGitCommitsAfterHash(repoPath: string, hash: string, maxCommits = 1000): CommitInfo[] {
146
+ try {
147
+ const raw = runGit(
148
+ repoPath,
149
+ `log ${JSON.stringify(`${hash}..HEAD`)} -n ${Math.max(1, maxCommits)} --date=short --pretty=format:%H%x09%ad%x09%an%x09%s --name-only --reverse`
150
+ );
151
+ return parseGitLog(raw);
137
152
  } catch {
138
153
  return [];
139
154
  }
@@ -194,6 +209,7 @@ function sourceLine(source: string): string {
194
209
  interface ExistingManifest {
195
210
  generatedAt?: string;
196
211
  lastCommitDate?: string;
212
+ lastCommitHash?: string;
197
213
  }
198
214
 
199
215
  function loadExistingManifest(outDir: string): ExistingManifest | null {
@@ -238,7 +254,9 @@ export async function bootstrapKnowledgeBase(options: BootstrapKnowledgeOptions)
238
254
 
239
255
  const codeFiles = walkCodeFiles(repoPath);
240
256
  const modules = summarizeModules(repoPath, codeFiles);
241
- const commits = getGitCommits(repoPath, since, maxCommits);
257
+ const commits = options.incremental && existingManifest?.lastCommitHash
258
+ ? getGitCommitsAfterHash(repoPath, existingManifest.lastCommitHash, maxCommits)
259
+ : getGitCommits(repoPath, since, maxCommits);
242
260
  const decisions = extractDecisions(commits);
243
261
  const timeline = buildTimeline(commits);
244
262
  const glossary = buildGlossary(codeFiles);
@@ -390,7 +408,8 @@ export async function bootstrapKnowledgeBase(options: BootstrapKnowledgeOptions)
390
408
  ...commits.slice(0, 400).map((c) => ({ type: 'commit', ref: c.hash, date: c.date, subject: c.subject }))
391
409
  ];
392
410
 
393
- const latestCommitDate = commits.length > 0 ? commits[commits.length - 1].date : undefined;
411
+ const latestCommitDate = commits.length > 0 ? commits[commits.length - 1].date : existingManifest?.lastCommitDate;
412
+ const latestCommitHash = commits.length > 0 ? commits[commits.length - 1].hash : existingManifest?.lastCommitHash;
394
413
  const manifest = {
395
414
  generatedAt: new Date().toISOString(),
396
415
  deterministicPipeline: true,
@@ -406,6 +425,7 @@ export async function bootstrapKnowledgeBase(options: BootstrapKnowledgeOptions)
406
425
  glossaryTerms: glossary.length
407
426
  },
408
427
  lastCommitDate: latestCommitDate,
428
+ lastCommitHash: latestCommitHash,
409
429
  outputs,
410
430
  allOutputs,
411
431
  sources: sourceItems