claude-memory-layer 1.0.27 → 1.0.29

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 (331) hide show
  1. package/.env.example +7 -0
  2. package/AGENTS.md +11 -0
  3. package/README.md +374 -49
  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 +12 -5
  56. package/scripts/build.ts +25 -8
  57. package/scripts/generate-session-qrels.ts +126 -0
  58. package/scripts/postinstall-embedding-backend.cjs +142 -0
  59. package/scripts/replay-retrieval-benchmark.ts +69 -0
  60. package/specs/thin-core-refactor/context.md +275 -0
  61. package/specs/thin-core-refactor/plan.md +536 -0
  62. package/specs/thin-core-refactor/spec.md +465 -0
  63. package/src/adapters/claude/capture/index.ts +3 -0
  64. package/src/adapters/claude/context/index.ts +3 -0
  65. package/src/adapters/claude/hooks/index.ts +21 -0
  66. package/src/adapters/claude/hooks/post-tool-use.ts +239 -0
  67. package/src/adapters/claude/hooks/prompt-injection-policy.ts +104 -0
  68. package/src/adapters/claude/hooks/semantic-daemon-client.ts +209 -0
  69. package/src/adapters/claude/hooks/semantic-daemon.ts +283 -0
  70. package/src/adapters/claude/hooks/session-end.ts +59 -0
  71. package/src/adapters/claude/hooks/session-start.ts +73 -0
  72. package/src/adapters/claude/hooks/stop.ts +128 -0
  73. package/src/adapters/claude/hooks/user-prompt-submit.ts +361 -0
  74. package/src/adapters/claude/index.ts +4 -0
  75. package/src/adapters/claude/transcript/index.ts +4 -0
  76. package/src/adapters/claude/transcript/transcript-reader.ts +57 -0
  77. package/src/adapters/claude/transcript/turn-reconstructor.ts +65 -0
  78. package/src/apps/cli/claude-settings-hooks.ts +138 -0
  79. package/src/apps/cli/codex-import-runner.ts +125 -0
  80. package/src/apps/cli/codex-validation-output.ts +95 -0
  81. package/src/apps/cli/hermes-import-runner.ts +130 -0
  82. package/src/apps/cli/hermes-validation-output.ts +91 -0
  83. package/src/apps/cli/index.ts +1731 -0
  84. package/src/apps/cli/mcp-install.ts +106 -0
  85. package/src/apps/cli/retrieval-disclosure-output.ts +196 -0
  86. package/src/apps/dashboard/assets/js/bootstrap.js +244 -0
  87. package/src/apps/dashboard/assets/js/chat.js +373 -0
  88. package/src/apps/dashboard/assets/js/disclosure.js +232 -0
  89. package/src/apps/dashboard/assets/js/modals.js +298 -0
  90. package/src/apps/dashboard/assets/js/overview.js +655 -0
  91. package/src/apps/dashboard/assets/js/state.js +72 -0
  92. package/src/apps/dashboard/assets/js/views.js +468 -0
  93. package/src/{ui → apps/dashboard}/index.html +43 -1
  94. package/src/apps/dashboard/index.ts +3 -0
  95. package/src/{ui → apps/dashboard}/style.css +222 -0
  96. package/src/apps/index.ts +5 -0
  97. package/src/apps/server/api/chat.ts +244 -0
  98. package/src/apps/server/api/citations.ts +105 -0
  99. package/src/apps/server/api/events.ts +137 -0
  100. package/src/apps/server/api/health.ts +53 -0
  101. package/src/apps/server/api/index.ts +26 -0
  102. package/src/apps/server/api/projects.ts +74 -0
  103. package/src/apps/server/api/search.ts +184 -0
  104. package/src/apps/server/api/sessions.ts +115 -0
  105. package/src/apps/server/api/stats.ts +723 -0
  106. package/src/apps/server/api/turns.ts +143 -0
  107. package/src/apps/server/api/utils.ts +65 -0
  108. package/src/apps/server/index.ts +111 -0
  109. package/src/cli/index.ts +2 -1311
  110. package/src/cli/retrieval-disclosure-output.ts +2 -0
  111. package/src/compat/index.ts +5 -0
  112. package/src/core/derive/fact-deriver.ts +170 -0
  113. package/src/core/derive/index.ts +2 -0
  114. package/src/core/derive/summary-deriver.ts +76 -0
  115. package/src/core/embedder.ts +4 -152
  116. package/src/core/engine/embedding-maintenance-service.ts +187 -0
  117. package/src/core/engine/endless-memory-services.ts +4 -0
  118. package/src/core/engine/index.ts +19 -0
  119. package/src/core/engine/memory-engine-services.ts +170 -0
  120. package/src/core/engine/memory-ingest-service.ts +317 -0
  121. package/src/core/engine/memory-query-service.ts +173 -0
  122. package/src/core/engine/memory-runtime-service.ts +162 -0
  123. package/src/core/engine/memory-service-composition.ts +231 -0
  124. package/src/core/engine/retrieval-analytics-service.ts +181 -0
  125. package/src/core/engine/retrieval-disclosure-service.ts +420 -0
  126. package/src/core/engine/retrieval-orchestrator.ts +377 -0
  127. package/src/core/engine/retrieval-services.ts +176 -0
  128. package/src/core/engine/shared-memory-services.ts +4 -0
  129. package/src/core/entity-repo.ts +1 -3
  130. package/src/core/event-store.ts +3 -3
  131. package/src/core/evidence-aligner.ts +2 -2
  132. package/src/core/external-market-context.ts +582 -0
  133. package/src/core/graduation.ts +2 -3
  134. package/src/core/index.ts +21 -0
  135. package/src/core/matcher.ts +2 -4
  136. package/src/core/model/memory-fact.ts +30 -0
  137. package/src/core/model/memory-rule.ts +14 -0
  138. package/src/core/model/memory-summary.ts +21 -0
  139. package/src/core/model/raw-event.ts +28 -0
  140. package/src/core/model/retrieval-result.ts +35 -0
  141. package/src/core/privacy/filter.ts +21 -10
  142. package/src/core/product-validation-matrix.ts +314 -0
  143. package/src/core/progressive-retriever.ts +1 -2
  144. package/src/core/registry/project-path.ts +54 -0
  145. package/src/core/registry/session-registry.ts +69 -0
  146. package/src/core/replay-evaluator.ts +625 -0
  147. package/src/core/retrieval-benchmark.ts +117 -0
  148. package/src/core/retrieval-quality.ts +109 -0
  149. package/src/core/retriever.ts +53 -15
  150. package/src/core/session-qrels.ts +360 -0
  151. package/src/core/shared-event-store.ts +1 -1
  152. package/src/core/sqlite-event-store.ts +35 -11
  153. package/src/core/task/blocker-resolver.ts +2 -2
  154. package/src/core/task/task-resolver.ts +0 -1
  155. package/src/core/vector-outbox.ts +1 -10
  156. package/src/core/vector-worker.ts +1 -1
  157. package/src/extensions/endless-memory/endless-memory-services.ts +350 -0
  158. package/src/extensions/endless-memory/index.ts +1 -0
  159. package/src/extensions/index.ts +5 -0
  160. package/src/extensions/mcp/handlers.ts +960 -0
  161. package/src/extensions/mcp/index.ts +48 -0
  162. package/src/extensions/mcp/tools.ts +252 -0
  163. package/src/extensions/shared-memory/index.ts +1 -0
  164. package/src/extensions/shared-memory/shared-memory-services.ts +211 -0
  165. package/src/extensions/vector/embedder.ts +197 -0
  166. package/src/extensions/vector/index.ts +1 -0
  167. package/src/hooks/post-tool-use.ts +3 -236
  168. package/src/hooks/semantic-daemon-client.ts +1 -208
  169. package/src/hooks/semantic-daemon.ts +6 -271
  170. package/src/hooks/session-end.ts +4 -79
  171. package/src/hooks/session-start.ts +4 -73
  172. package/src/hooks/stop.ts +3 -173
  173. package/src/hooks/user-prompt-submit.ts +3 -338
  174. package/src/index.ts +13 -0
  175. package/src/mcp/handlers.ts +2 -212
  176. package/src/mcp/index.ts +3 -46
  177. package/src/mcp/tools.ts +2 -78
  178. package/src/server/api/chat.ts +2 -244
  179. package/src/server/api/citations.ts +2 -105
  180. package/src/server/api/events.ts +2 -137
  181. package/src/server/api/health.ts +2 -53
  182. package/src/server/api/index.ts +2 -26
  183. package/src/server/api/projects.ts +2 -74
  184. package/src/server/api/search.ts +2 -102
  185. package/src/server/api/sessions.ts +2 -115
  186. package/src/server/api/stats.ts +2 -724
  187. package/src/server/api/turns.ts +2 -143
  188. package/src/server/api/utils.ts +2 -46
  189. package/src/server/index.ts +2 -100
  190. package/src/services/bootstrap-organizer.ts +46 -26
  191. package/src/services/codex-session-history-importer.ts +521 -29
  192. package/src/services/hermes-session-history-importer.ts +733 -0
  193. package/src/services/memory-service-config.ts +36 -0
  194. package/src/services/memory-service-registry.ts +150 -0
  195. package/src/services/memory-service.ts +211 -1325
  196. package/src/services/session-history-importer.ts +58 -14
  197. package/tests/README.md +23 -0
  198. package/tests/adapters/claude/claude-semantic-daemon-adapter.test.ts +54 -0
  199. package/tests/adapters/claude/claude-transcript-reconstructor.test.ts +98 -0
  200. package/tests/adapters/claude-hook-prompt-injection-policy.test.ts +99 -0
  201. package/tests/apps/app-layer-boundary.test.ts +48 -0
  202. package/tests/apps/claude-settings-hooks.test.ts +107 -0
  203. package/tests/apps/cli-disclosure-output.test.ts +212 -0
  204. package/tests/apps/codex-import-runner.test.ts +99 -0
  205. package/tests/apps/codex-validation-output.test.ts +100 -0
  206. package/tests/apps/hermes-import-runner.test.ts +99 -0
  207. package/tests/apps/mcp-install-command.test.ts +59 -0
  208. package/tests/apps/package-build-entrypoints.test.ts +30 -0
  209. package/tests/apps/postinstall-embedding-backend.test.ts +167 -0
  210. package/tests/apps/search-api-disclosure.test.ts +162 -0
  211. package/tests/apps/stats-api-lightweight.test.ts +67 -0
  212. package/tests/apps/ui-disclosure-output.test.ts +140 -0
  213. package/tests/{bootstrap-organizer.test.ts → core/bootstrap-organizer.test.ts} +1 -1
  214. package/tests/{canonical-key.test.ts → core/canonical-key.test.ts} +1 -1
  215. package/tests/core/codex-session-history-importer-validation.test.ts +185 -0
  216. package/tests/{consolidation-worker.test.ts → core/consolidation-worker.test.ts} +2 -2
  217. package/tests/core/embedding-maintenance-service.test.ts +282 -0
  218. package/tests/{evidence-aligner.test.ts → core/evidence-aligner.test.ts} +1 -1
  219. package/tests/core/external-market-context.test.ts +209 -0
  220. package/tests/core/fact-deriver.test.ts +79 -0
  221. package/tests/core/hermes-session-history-importer-validation.test.ts +609 -0
  222. package/tests/{ingest-interceptor.test.ts → core/ingest-interceptor.test.ts} +1 -1
  223. package/tests/{markdown-mirror.test.ts → core/markdown-mirror.test.ts} +2 -2
  224. package/tests/{matcher.test.ts → core/matcher.test.ts} +1 -1
  225. package/tests/{md-mirror.test.ts → core/md-mirror.test.ts} +2 -2
  226. package/tests/core/memory-engine-services.test.ts +240 -0
  227. package/tests/core/memory-ingest-service.test.ts +296 -0
  228. package/tests/core/memory-query-service.test.ts +129 -0
  229. package/tests/core/memory-runtime-service.test.ts +201 -0
  230. package/tests/core/memory-service-composition.test.ts +192 -0
  231. package/tests/core/memory-service-config.test.ts +41 -0
  232. package/tests/core/memory-service-facade.test.ts +30 -0
  233. package/tests/core/memory-service-registry.test.ts +206 -0
  234. package/tests/core/product-validation-matrix.test.ts +61 -0
  235. package/tests/core/project-registry.test.ts +78 -0
  236. package/tests/core/replay-evaluator.test.ts +181 -0
  237. package/tests/core/retrieval-analytics-service.test.ts +210 -0
  238. package/tests/core/retrieval-benchmark.test.ts +93 -0
  239. package/tests/core/retrieval-disclosure-service.test.ts +264 -0
  240. package/tests/core/retrieval-orchestrator.test.ts +403 -0
  241. package/tests/core/retrieval-quality.test.ts +31 -0
  242. package/tests/core/retrieval-services.test.ts +185 -0
  243. package/tests/{retriever-fallback-chain.test.ts → core/retriever-fallback-chain.test.ts} +3 -3
  244. package/tests/{retriever-strategy-scope.test.ts → core/retriever-strategy-scope.test.ts} +70 -3
  245. package/tests/{retriever.memu-adoption.test.ts → core/retriever.memu-adoption.test.ts} +3 -3
  246. package/tests/core/session-history-importer-filter.test.ts +78 -0
  247. package/tests/core/session-qrels.test.ts +250 -0
  248. package/tests/{sqlite-event-store-replication.test.ts → core/sqlite-event-store-replication.test.ts} +36 -1
  249. package/tests/core/summary-deriver.test.ts +66 -0
  250. package/tests/extensions/embedder-warning-suppression.test.ts +53 -0
  251. package/tests/extensions/endless-memory-extension-boundary.test.ts +17 -0
  252. package/tests/extensions/endless-memory-services.test.ts +325 -0
  253. package/tests/extensions/mcp-context-tools.test.ts +905 -0
  254. package/tests/extensions/mcp-extension-boundary.test.ts +21 -0
  255. package/tests/extensions/mcp-package-build.test.ts +22 -0
  256. package/tests/extensions/mcp-project-aware-tools.test.ts +102 -0
  257. package/tests/extensions/shared-memory-extension-boundary.test.ts +24 -0
  258. package/tests/extensions/shared-memory-services.test.ts +309 -0
  259. package/tests/extensions/vector-extension-boundary.test.ts +21 -0
  260. package/.claude/settings.local.json +0 -25
  261. package/.npm-cache/_cacache/content-v2/sha512/04/76/c098f88dfe584a2b80870bff7421b05d17d3d9ee1027f77772332a22d3f93a9a57101a2855107f6ad82077a818bba912b2bc317f2361b5ddb09ad284d9ce +0 -0
  262. package/.npm-cache/_cacache/content-v2/sha512/60/25/d2ecd39cfc7cab58351162814be77f935c6d6491c10c3745d456da7ddb2117ffd90c10e53fe3c0f1ed16b403307841543634504398b16ee4e6b6dd8e0c45 +0 -0
  263. package/.npm-cache/_cacache/index-v5/2b/9a/7f8f40206ed8a2e0a84efaa953ccaed1f5d001e14b931083f2e7a0738007 +0 -2
  264. package/.npm-cache/_cacache/index-v5/2e/d9/fcfa5c6a6abdc2a3644ab84a95936047298c465a2f47ee03db8f7fe1e946 +0 -3
  265. package/.npm-cache/_cacache/index-v5/a9/42/e519633356d12d3d2f19da66a8301016d496c8f5c3e0554124aaa62dc043 +0 -2
  266. package/.npm-cache/_logs/2026-02-26T12_04_52_729Z-debug-0.log +0 -256
  267. package/.npm-cache/_logs/2026-02-26T12_05_36_835Z-debug-0.log +0 -18
  268. package/.npm-cache/_logs/2026-02-26T12_05_45_982Z-debug-0.log +0 -32
  269. package/.npm-cache/_logs/2026-02-26T12_05_48_515Z-debug-0.log +0 -260
  270. package/.npm-cache/_logs/2026-02-26T12_05_53_567Z-debug-0.log +0 -69
  271. package/.npm-cache/_update-notifier-last-checked +0 -0
  272. package/bootstrap-kb/decisions/decisions.md +0 -244
  273. package/bootstrap-kb/glossary/glossary.md +0 -46
  274. package/bootstrap-kb/modules/.claude-plugin.md +0 -22
  275. package/bootstrap-kb/modules/agents.md.md +0 -15
  276. package/bootstrap-kb/modules/claude.md.md +0 -15
  277. package/bootstrap-kb/modules/context.md.md +0 -15
  278. package/bootstrap-kb/modules/docs.md +0 -18
  279. package/bootstrap-kb/modules/handoff.md.md +0 -15
  280. package/bootstrap-kb/modules/package-lock.json.md +0 -15
  281. package/bootstrap-kb/modules/package.json.md +0 -15
  282. package/bootstrap-kb/modules/plan.md.md +0 -15
  283. package/bootstrap-kb/modules/readme.md.md +0 -15
  284. package/bootstrap-kb/modules/scripts.md +0 -26
  285. package/bootstrap-kb/modules/spec.md.md +0 -15
  286. package/bootstrap-kb/modules/specs.md +0 -20
  287. package/bootstrap-kb/modules/src.md +0 -51
  288. package/bootstrap-kb/modules/tests.md +0 -42
  289. package/bootstrap-kb/modules/tsconfig.json.md +0 -15
  290. package/bootstrap-kb/modules/vitest.config.ts.md +0 -15
  291. package/bootstrap-kb/overview/overview.md +0 -40
  292. package/bootstrap-kb/sources/manifest.json +0 -950
  293. package/bootstrap-kb/sources/manifest.md +0 -227
  294. package/bootstrap-kb/timeline/timeline.md +0 -57
  295. package/claude-memory-layer-1.0.14.tgz +0 -0
  296. package/d.sh +0 -3
  297. package/deploy.sh +0 -3
  298. package/dist/ui/app.js +0 -2101
  299. package/memory/.claude-plugin/commands/2026-02-25.md +0 -263
  300. package/memory/_index.md +0 -419
  301. package/memory/agent_response/uncategorized/2026-02-26.md +0 -176
  302. package/memory/agent_response/uncategorized/2026-03-03.md +0 -14
  303. package/memory/agent_response/uncategorized/2026-03-04.md +0 -1421
  304. package/memory/agent_response/uncategorized/2026-03-05.md +0 -157
  305. package/memory/default/uncategorized/2026-02-25.md +0 -4839
  306. package/memory/session_summary/uncategorized/2026-02-26.md +0 -13
  307. package/memory/session_summary/uncategorized/2026-03-03.md +0 -5
  308. package/memory/session_summary/uncategorized/2026-03-04.md +0 -50
  309. package/memory/specs/20260207-dashboard-upgrade/2026-02-25.md +0 -142
  310. package/memory/specs/citations-system/2026-02-25.md +0 -1121
  311. package/memory/specs/endless-mode/2026-02-25.md +0 -1392
  312. package/memory/specs/entity-edge-model/2026-02-25.md +0 -1263
  313. package/memory/specs/evidence-aligner-v2/2026-02-25.md +0 -1028
  314. package/memory/specs/mcp-desktop-integration/2026-02-25.md +0 -1334
  315. package/memory/specs/post-tool-use-hook/2026-02-25.md +0 -1164
  316. package/memory/specs/private-tags/2026-02-25.md +0 -1057
  317. package/memory/specs/progressive-disclosure/2026-02-25.md +0 -1436
  318. package/memory/specs/task-entity-system/2026-02-25.md +0 -924
  319. package/memory/specs/vector-outbox-v2/2026-02-25.md +0 -1510
  320. package/memory/specs/web-viewer-ui/2026-02-25.md +0 -1709
  321. package/memory/tool_observation/uncategorized/2026-02-26.md +0 -209
  322. package/memory/tool_observation/uncategorized/2026-03-03.md +0 -21
  323. package/memory/tool_observation/uncategorized/2026-03-04.md +0 -1033
  324. package/memory/tool_observation/uncategorized/2026-03-05.md +0 -33
  325. package/memory/user_prompt/uncategorized/2026-02-26.md +0 -25
  326. package/memory/user_prompt/uncategorized/2026-03-04.md +0 -634
  327. package/memory/user_prompt/uncategorized/2026-03-05.md +0 -6
  328. package/specs/optional-duckdb/context.md +0 -77
  329. package/specs/optional-duckdb/plan.md +0 -142
  330. package/specs/optional-duckdb/spec.md +0 -35
  331. 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