@memorax/memorax-code 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +53 -0
  3. package/bin/memorax-cli.mjs +28 -0
  4. package/bin/memorax-code-backend.mjs +4 -0
  5. package/bin/memorax-code-claude.mjs +4 -0
  6. package/bin/memorax-code-codex.mjs +4 -0
  7. package/bin/memorax-code-npm-preinstall.mjs +55 -0
  8. package/bin/memorax-code-plugin-postinstall.mjs +1236 -0
  9. package/bin/memorax-code.mjs +204 -0
  10. package/docs/configuration.md +232 -0
  11. package/docs/troubleshooting.md +179 -0
  12. package/lib/client-hook-runtime.mjs +32 -0
  13. package/lib/memorax-code-adapter-common/src/backend-connection.d.mts +111 -0
  14. package/lib/memorax-code-adapter-common/src/backend-connection.mjs +304 -0
  15. package/lib/memorax-code-adapter-common/src/clients/claude-command.mjs +38 -0
  16. package/lib/memorax-code-adapter-common/src/clients/codex-command.mjs +41 -0
  17. package/lib/memorax-code-adapter-common/src/clients/codex-plugin-artifact.d.mts +3 -0
  18. package/lib/memorax-code-adapter-common/src/clients/codex-plugin-artifact.mjs +38 -0
  19. package/lib/memorax-code-adapter-common/src/config-utils.d.mts +27 -0
  20. package/lib/memorax-code-adapter-common/src/config-utils.mjs +391 -0
  21. package/lib/memorax-code-adapter-common/src/hooks/capture-cwd-hook.mjs +137 -0
  22. package/lib/memorax-code-adapter-common/src/hooks/client-hook-launcher.mjs +324 -0
  23. package/lib/memorax-code-adapter-common/src/hooks/ensure-backend-runner.mjs +142 -0
  24. package/lib/memorax-code-adapter-common/src/hooks/hook-runtime-generation.d.mts +38 -0
  25. package/lib/memorax-code-adapter-common/src/hooks/hook-runtime-generation.mjs +501 -0
  26. package/lib/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +277 -0
  27. package/lib/memorax-code-adapter-common/src/memorax-code-config-file.d.mts +28 -0
  28. package/lib/memorax-code-adapter-common/src/memorax-code-config-file.mjs +296 -0
  29. package/lib/memorax-code-adapter-common/src/memorax-defaults.d.mts +10 -0
  30. package/lib/memorax-code-adapter-common/src/memorax-defaults.mjs +12 -0
  31. package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-job-context.mjs +28 -0
  32. package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-job-marker.mjs +252 -0
  33. package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-job-supervisor.mjs +559 -0
  34. package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-job-worker.mjs +411 -0
  35. package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-update-policy-evaluator.mjs +185 -0
  36. package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-update-policy.mjs +165 -0
  37. package/lib/memorax-code-adapter-common/src/repo-memory/repo-procedure-memory-context.mjs +181 -0
  38. package/lib/memorax-code-adapter-common/src/repo-memory/repo-user-profile-context.mjs +251 -0
  39. package/lib/memorax-code-adapter-common/src/runtime-record.d.mts +55 -0
  40. package/lib/memorax-code-adapter-common/src/runtime-record.mjs +152 -0
  41. package/lib/memorax-code-adapter-common/src/windows-cli-invocation.mjs +100 -0
  42. package/lib/memorax-code-backend/dist/active-client-selection.js +35 -0
  43. package/lib/memorax-code-backend/dist/adapter-lifecycle-participant.js +1 -0
  44. package/lib/memorax-code-backend/dist/automatic-memory-retrieval.js +113 -0
  45. package/lib/memorax-code-backend/dist/automatic-memory-writeback.js +297 -0
  46. package/lib/memorax-code-backend/dist/backend-env.js +13 -0
  47. package/lib/memorax-code-backend/dist/backend-lifecycle-lock.js +42 -0
  48. package/lib/memorax-code-backend/dist/backend-process.js +147 -0
  49. package/lib/memorax-code-backend/dist/backend-service-cleanup.js +18 -0
  50. package/lib/memorax-code-backend/dist/backend-service-record.js +206 -0
  51. package/lib/memorax-code-backend/dist/backend-service-result.js +37 -0
  52. package/lib/memorax-code-backend/dist/backend-service-token.js +11 -0
  53. package/lib/memorax-code-backend/dist/backend-shutdown-request.js +133 -0
  54. package/lib/memorax-code-backend/dist/backend-state.js +58 -0
  55. package/lib/memorax-code-backend/dist/backend-status.js +53 -0
  56. package/lib/memorax-code-backend/dist/backend-token-record.js +79 -0
  57. package/lib/memorax-code-backend/dist/claude-adapter-lifecycle.js +134 -0
  58. package/lib/memorax-code-backend/dist/claude-local-transcript.js +648 -0
  59. package/lib/memorax-code-backend/dist/claude-memory-hook-runtime.js +472 -0
  60. package/lib/memorax-code-backend/dist/claude-transcript-turn.js +876 -0
  61. package/lib/memorax-code-backend/dist/client-plugin-removal.js +67 -0
  62. package/lib/memorax-code-backend/dist/client-selection.js +36 -0
  63. package/lib/memorax-code-backend/dist/codex-adapter-lifecycle.js +131 -0
  64. package/lib/memorax-code-backend/dist/codex-effective-prompt.js +54 -0
  65. package/lib/memorax-code-backend/dist/codex-memory-hook-runtime.js +541 -0
  66. package/lib/memorax-code-backend/dist/codex-plugin-hooks.js +421 -0
  67. package/lib/memorax-code-backend/dist/codex-plugin-install.js +523 -0
  68. package/lib/memorax-code-backend/dist/codex-rollout-turn.js +402 -0
  69. package/lib/memorax-code-backend/dist/codex-session-turn-index.js +88 -0
  70. package/lib/memorax-code-backend/dist/codex-workspace-links.js +55 -0
  71. package/lib/memorax-code-backend/dist/debug-log.js +21 -0
  72. package/lib/memorax-code-backend/dist/entrypoint.js +14 -0
  73. package/lib/memorax-code-backend/dist/incremental-jsonl-projection.js +271 -0
  74. package/lib/memorax-code-backend/dist/install-watchdog.js +71 -0
  75. package/lib/memorax-code-backend/dist/jsonl-append.js +75 -0
  76. package/lib/memorax-code-backend/dist/memorax-adapter.js +451 -0
  77. package/lib/memorax-code-backend/dist/memorax-cli.js +14 -0
  78. package/lib/memorax-code-backend/dist/memorax-code-config.js +279 -0
  79. package/lib/memorax-code-backend/dist/memorax-code-lifecycle.js +523 -0
  80. package/lib/memorax-code-backend/dist/memorax-code.js +3 -0
  81. package/lib/memorax-code-backend/dist/memorax-config.js +283 -0
  82. package/lib/memorax-code-backend/dist/memorax-http.js +142 -0
  83. package/lib/memorax-code-backend/dist/memory-cli.js +345 -0
  84. package/lib/memorax-code-backend/dist/memory-hook-command.js +200 -0
  85. package/lib/memorax-code-backend/dist/memory-observability.js +1 -0
  86. package/lib/memorax-code-backend/dist/memory-project.js +89 -0
  87. package/lib/memorax-code-backend/dist/memory-reminder-trace-recorder.js +58 -0
  88. package/lib/memorax-code-backend/dist/memory-service.js +66 -0
  89. package/lib/memorax-code-backend/dist/memory-turn-coordinator.js +139 -0
  90. package/lib/memorax-code-backend/dist/memory-viewer-activity.js +113 -0
  91. package/lib/memorax-code-backend/dist/memory-viewer-data-projection-cache.js +69 -0
  92. package/lib/memorax-code-backend/dist/memory-viewer-event-identity.js +3 -0
  93. package/lib/memorax-code-backend/dist/memory-viewer-history-projection.js +79 -0
  94. package/lib/memorax-code-backend/dist/memory-viewer-logo.js +1 -0
  95. package/lib/memorax-code-backend/dist/memory-viewer-observability.js +8 -0
  96. package/lib/memorax-code-backend/dist/memory-viewer-redaction.js +52 -0
  97. package/lib/memorax-code-backend/dist/memory-viewer-session-title.js +93 -0
  98. package/lib/memorax-code-backend/dist/memory-viewer-store.js +964 -0
  99. package/lib/memorax-code-backend/dist/memory-viewer-turn-reference.js +12 -0
  100. package/lib/memorax-code-backend/dist/memory-viewer-user-html.js +115 -0
  101. package/lib/memorax-code-backend/dist/memory-viewer-user-projection.js +168 -0
  102. package/lib/memorax-code-backend/dist/memory-viewer-writeback-status.js +97 -0
  103. package/lib/memorax-code-backend/dist/memory-writeback-buffer.js +217 -0
  104. package/lib/memorax-code-backend/dist/memory-writeback-chunk.js +120 -0
  105. package/lib/memorax-code-backend/dist/memory-writeback-reconciler.js +244 -0
  106. package/lib/memorax-code-backend/dist/memory-writeback-task-projection.js +377 -0
  107. package/lib/memorax-code-backend/dist/proxy-env.js +54 -0
  108. package/lib/memorax-code-backend/dist/repo-memory-readiness.js +188 -0
  109. package/lib/memorax-code-backend/dist/repository-memory-context.js +134 -0
  110. package/lib/memorax-code-backend/dist/repository-memory-scope.js +490 -0
  111. package/lib/memorax-code-backend/dist/server-cli.js +787 -0
  112. package/lib/memorax-code-backend/dist/server-health.js +16 -0
  113. package/lib/memorax-code-backend/dist/server-http.js +110 -0
  114. package/lib/memorax-code-backend/dist/server-json.js +4 -0
  115. package/lib/memorax-code-backend/dist/server-memory-hook.js +32 -0
  116. package/lib/memorax-code-backend/dist/server-memory-viewer.js +135 -0
  117. package/lib/memorax-code-backend/dist/server-observability.js +102 -0
  118. package/lib/memorax-code-backend/dist/server.js +220 -0
  119. package/lib/memorax-code-backend/dist/service-entrypoint.js +10 -0
  120. package/lib/memorax-code-backend/dist/service.js +567 -0
  121. package/lib/memorax-code-backend/dist/trace-config.js +112 -0
  122. package/lib/memorax-code-backend/dist/trace-context.js +111 -0
  123. package/lib/memorax-code-backend/dist/trace-store.js +571 -0
  124. package/lib/memorax-code-backend/dist/utils.js +3 -0
  125. package/lib/memorax-code-backend/dist/windows-cli-invocation.js +148 -0
  126. package/lib/memorax-code-backend/package.json +26 -0
  127. package/lib/memorax-code-claude-adapter/.claude-plugin/plugin.json +15 -0
  128. package/lib/memorax-code-claude-adapter/hooks/hook-launcher.mjs +27 -0
  129. package/lib/memorax-code-claude-adapter/hooks/hooks.json +66 -0
  130. package/lib/memorax-code-claude-adapter/hooks/repo-memory-job.mjs +37 -0
  131. package/lib/memorax-code-claude-adapter/hooks/runtime-hook.mjs +4 -0
  132. package/lib/memorax-code-claude-adapter/hooks/runtime-shell.json +5 -0
  133. package/lib/memorax-code-claude-adapter/package.json +13 -0
  134. package/lib/memorax-code-claude-adapter/runtime-hooks/capture-cwd.mjs +17 -0
  135. package/lib/memorax-code-claude-adapter/runtime-hooks/ensure-backend.mjs +59 -0
  136. package/lib/memorax-code-claude-adapter/runtime-hooks/memory-cli-session.mjs +33 -0
  137. package/lib/memorax-code-claude-adapter/runtime-hooks/memory-skill-reminder.mjs +73 -0
  138. package/lib/memorax-code-claude-adapter/runtime-hooks/memory-turn.mjs +91 -0
  139. package/lib/memorax-code-claude-adapter/scripts/build-marketplace.mjs +99 -0
  140. package/lib/memorax-code-claude-adapter/skills/memorax-code/SKILL.md +83 -0
  141. package/lib/memorax-code-claude-adapter/skills/memorax-code/agents/claude.yaml +10 -0
  142. package/lib/memorax-code-claude-adapter/skills/memorax-code/agents/openai.yaml +7 -0
  143. package/lib/memorax-code-claude-adapter/skills/memorax-code/defaults.json +9 -0
  144. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +82 -0
  145. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +61 -0
  146. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/personal-read.md +46 -0
  147. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/personal-write.md +100 -0
  148. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-build.md +270 -0
  149. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-read.md +96 -0
  150. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-templates.md +270 -0
  151. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-update.md +116 -0
  152. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/collect_all.py +496 -0
  153. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/detect_updates.py +856 -0
  154. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
  155. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/github_resource_facets.py +504 -0
  156. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +509 -0
  157. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
  158. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
  159. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/validate_memory.py +226 -0
  160. package/lib/memorax-code-claude-adapter/src/adapter-paths.mjs +46 -0
  161. package/lib/memorax-code-claude-adapter/src/cli.mjs +363 -0
  162. package/lib/memorax-code-claude-adapter/src/config-utils.mjs +1 -0
  163. package/lib/memorax-code-claude-adapter/src/config.mjs +544 -0
  164. package/lib/memorax-code-claude-adapter/src/plugin-artifact-contract.mjs +148 -0
  165. package/lib/memorax-code-claude-adapter/src/plugin-install.mjs +566 -0
  166. package/lib/memorax-code-claude-marketplace/.claude-plugin/marketplace.json +15 -0
  167. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/.claude-plugin/plugin.json +15 -0
  168. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/hook-launcher.mjs +27 -0
  169. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/hooks.json +66 -0
  170. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/repo-memory-job.mjs +37 -0
  171. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/runtime-hook.mjs +4 -0
  172. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/runtime-shell.json +5 -0
  173. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/backend-connection.d.mts +111 -0
  174. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/backend-connection.mjs +304 -0
  175. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/clients/claude-command.mjs +38 -0
  176. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/clients/codex-command.mjs +41 -0
  177. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/clients/codex-plugin-artifact.d.mts +3 -0
  178. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/clients/codex-plugin-artifact.mjs +38 -0
  179. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/config-utils.d.mts +27 -0
  180. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/config-utils.mjs +391 -0
  181. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/capture-cwd-hook.mjs +137 -0
  182. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/client-hook-launcher.mjs +324 -0
  183. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/ensure-backend-runner.mjs +142 -0
  184. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/hook-runtime-generation.d.mts +38 -0
  185. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/hook-runtime-generation.mjs +501 -0
  186. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +277 -0
  187. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/memorax-code-config-file.d.mts +28 -0
  188. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/memorax-code-config-file.mjs +296 -0
  189. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/memorax-defaults.d.mts +10 -0
  190. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/memorax-defaults.mjs +12 -0
  191. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-job-context.mjs +28 -0
  192. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-job-marker.mjs +252 -0
  193. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-job-supervisor.mjs +559 -0
  194. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-job-worker.mjs +411 -0
  195. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-update-policy-evaluator.mjs +185 -0
  196. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-update-policy.mjs +165 -0
  197. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-procedure-memory-context.mjs +181 -0
  198. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-user-profile-context.mjs +251 -0
  199. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/runtime-record.d.mts +55 -0
  200. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/runtime-record.mjs +152 -0
  201. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/windows-cli-invocation.mjs +100 -0
  202. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/package.json +13 -0
  203. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/capture-cwd.mjs +17 -0
  204. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/ensure-backend.mjs +59 -0
  205. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/memory-cli-session.mjs +33 -0
  206. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/memory-skill-reminder.mjs +73 -0
  207. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/memory-turn.mjs +91 -0
  208. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/scripts/build-marketplace.mjs +99 -0
  209. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/SKILL.md +83 -0
  210. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/agents/claude.yaml +10 -0
  211. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/agents/openai.yaml +7 -0
  212. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/defaults.json +9 -0
  213. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +82 -0
  214. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +61 -0
  215. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/personal-read.md +46 -0
  216. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/personal-write.md +100 -0
  217. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-build.md +270 -0
  218. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-read.md +96 -0
  219. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-templates.md +270 -0
  220. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-update.md +116 -0
  221. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/collect_all.py +496 -0
  222. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/detect_updates.py +856 -0
  223. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
  224. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/github_resource_facets.py +504 -0
  225. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +509 -0
  226. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
  227. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
  228. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/validate_memory.py +226 -0
  229. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/adapter-paths.mjs +46 -0
  230. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/cli.mjs +363 -0
  231. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/config-utils.mjs +1 -0
  232. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/config.mjs +544 -0
  233. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/plugin-artifact-contract.mjs +148 -0
  234. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/plugin-install.mjs +566 -0
  235. package/lib/memorax-code-codex-adapter/.codex-plugin/plugin.json +33 -0
  236. package/lib/memorax-code-codex-adapter/assets/composer-icon.png +0 -0
  237. package/lib/memorax-code-codex-adapter/assets/logo.png +0 -0
  238. package/lib/memorax-code-codex-adapter/hooks/hook-launcher.mjs +26 -0
  239. package/lib/memorax-code-codex-adapter/hooks/hooks.json +61 -0
  240. package/lib/memorax-code-codex-adapter/hooks/repo-memory-job.mjs +38 -0
  241. package/lib/memorax-code-codex-adapter/hooks/repo-memory-update-policy.mjs +10 -0
  242. package/lib/memorax-code-codex-adapter/hooks/runtime-hook.mjs +4 -0
  243. package/lib/memorax-code-codex-adapter/hooks/runtime-shell.json +5 -0
  244. package/lib/memorax-code-codex-adapter/package.json +13 -0
  245. package/lib/memorax-code-codex-adapter/runtime-hooks/capture-cwd.mjs +18 -0
  246. package/lib/memorax-code-codex-adapter/runtime-hooks/ensure-backend.mjs +82 -0
  247. package/lib/memorax-code-codex-adapter/runtime-hooks/memory-skill-reminder.mjs +125 -0
  248. package/lib/memorax-code-codex-adapter/runtime-hooks/memory-writeback.mjs +52 -0
  249. package/lib/memorax-code-codex-adapter/skills/memorax-code/SKILL.md +83 -0
  250. package/lib/memorax-code-codex-adapter/skills/memorax-code/agents/claude.yaml +10 -0
  251. package/lib/memorax-code-codex-adapter/skills/memorax-code/agents/openai.yaml +7 -0
  252. package/lib/memorax-code-codex-adapter/skills/memorax-code/defaults.json +9 -0
  253. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-add.md +82 -0
  254. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-search.md +61 -0
  255. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/personal-read.md +46 -0
  256. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/personal-write.md +100 -0
  257. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-build.md +270 -0
  258. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-read.md +96 -0
  259. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-templates.md +270 -0
  260. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-update.md +116 -0
  261. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/collect_all.py +496 -0
  262. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/detect_updates.py +856 -0
  263. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
  264. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/github_resource_facets.py +504 -0
  265. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +509 -0
  266. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
  267. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
  268. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/validate_memory.py +226 -0
  269. package/lib/memorax-code-codex-adapter/src/adapter-paths.mjs +29 -0
  270. package/lib/memorax-code-codex-adapter/src/cli.mjs +368 -0
  271. package/lib/memorax-code-codex-adapter/src/config-utils.mjs +1 -0
  272. package/lib/memorax-code-codex-adapter/src/config.mjs +226 -0
  273. package/lib/memorax-code-codex-adapter/src/session-registry.mjs +331 -0
  274. package/lib/memorax-code-codex-adapter/src/workspace-kind.mjs +68 -0
  275. package/lib/node-version.mjs +11 -0
  276. package/lib/npm-invocation.mjs +31 -0
  277. package/lib/resolve-claude-command.mjs +47 -0
  278. package/lib/resolve-codex-command.mjs +94 -0
  279. package/lib/run-entrypoint.mjs +83 -0
  280. package/lib/vscode-extension-command.mjs +119 -0
  281. package/lib/windows-cli-invocation.mjs +100 -0
  282. package/package.json +45 -0
@@ -0,0 +1,12 @@
1
+ export function memoryViewerEventTurnIds(event) {
2
+ return [...new Set([
3
+ safeTurnId(event.turnId),
4
+ ...(event.turnReferences ?? []).map((reference) => safeTurnId(reference.turnId)),
5
+ ].filter(Boolean))];
6
+ }
7
+ function safeTurnId(value) {
8
+ const candidate = typeof value === "string" ? value.trim() : "";
9
+ if (!candidate || candidate.length > 512 || /[\u0000-\u001f\u007f\\/]/.test(candidate))
10
+ return "";
11
+ return candidate;
12
+ }
@@ -0,0 +1,115 @@
1
+ export function memoryViewerUserHtml() {
2
+ return `<!doctype html>
3
+ <html lang="en" data-theme="light">
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <meta name="viewport" content="width=device-width,initial-scale=1">
7
+ <meta name="theme-color" content="#f7f8fc">
8
+ <title>MemoraX Code Memory Viewer</title>
9
+ <script>
10
+ const THEME_STORAGE_KEY='memorax-code-memory-viewer-theme',LANGUAGE_STORAGE_KEY='memorax-code-memory-viewer-language';
11
+ function readPreference(key,allowed,fallback){try{const value=localStorage.getItem(key);return allowed.includes(value)?value:fallback}catch{return fallback}}
12
+ function writePreference(key,value){try{localStorage.setItem(key,value)}catch{}}
13
+ let theme=readPreference(THEME_STORAGE_KEY,['light','dark'],'light'),language=readPreference(LANGUAGE_STORAGE_KEY,['zh','en'],'en');
14
+ document.documentElement.dataset.theme=theme;
15
+ document.documentElement.lang=language==='en'?'en':'zh-CN';
16
+ document.querySelector('meta[name="theme-color"]').content=theme==='dark'?'#10121a':'#f7f8fc';
17
+ window.addEventListener('DOMContentLoaded',()=>{
18
+ const E=id=>document.getElementById(id),project=E('project'),clientButtons=[...document.querySelectorAll('[data-client]')],bootstrapUrl=new URL(location.href),params=bootstrapUrl.searchParams;
19
+ if(params.has('token')){bootstrapUrl.searchParams.delete('token');history.replaceState(null,'',bootstrapUrl)}
20
+ let selected=params.get('projectId')||'',client=['claude','claude-code','cc'].includes((params.get('client')||'').toLowerCase())?'claude-code':'codex',controller,lastBody=null,connectionState=null;
21
+ const esc=value=>String(value??'').replace(/[&<>"']/g,char=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[char]));
22
+ const COPY={
23
+ zh:{
24
+ pageTitle:'MemoraX Code 记忆概览',productName:'Memory Viewer',clientGroup:'选择客户端',refresh:'刷新记忆活动',languageSwitch:'Switch to English',themeDark:'切换为深色模式',themeLight:'切换为浅色模式',
25
+ connecting:'正在连接',connected:'已连接',disconnected:'连接中断',updated:'· 刚刚更新',
26
+ eyebrow:'记忆概览',heading:'记忆使用情况',intro:'快速了解客户端会话如何使用项目记忆,以及仓库知识是否已经准备就绪。',scopeLabel:'查看范围',projectAria:'选择仓库',allProjects:'全部仓库',summaryAria:'记忆摘要',
27
+ cardTurns:'会话',cardSearch:'搜索',cardAdd:'写入',cardRepo:'仓库记忆',loading:'正在加载',checking:'正在检查',repoLoading:'仓库知识状态',recentActivity:'最近活动',
28
+ empty:'当前范围还没有会话、搜索或写入活动',error:'暂时无法加载记忆活动,请稍后重试。',selectProject:'选择仓库',selectProjectForStatus:'选择仓库后查看状态',noProjects:'暂无可识别仓库',unassignedProject:'未归属仓库',systemActivity:'系统活动',
29
+ turnNote:'轮客户端会话',searchUnit:'次搜索',addUnit:'次写入',processingUnit:'个处理中',unknownUnit:'个数量未知',activityUnit:'条',
30
+ repoStates:{ready:'可用',preparing:'准备中',not_ready:'未就绪',unknown:'未知'},
31
+ reasons:{usable:'仓库知识可以使用',active_job:'正在生成或更新',bundle_missing:'尚未生成仓库知识',bundle_invalid:'仓库知识需要重新生成',project_unresolved:'无法定位仓库',validator_unavailable:'暂时无法检查'},
32
+ statuses:{completed:'完成',saved:'已保存',skipped:'未写入',processing:'进行中',interrupted:'已中断',failed:'失败',unknown:'数量未知'},
33
+ sources:{client:'客户端会话',assistant:'助手主动',automatic:'系统自动'}
34
+ },
35
+ en:{
36
+ pageTitle:'MemoraX Code Memory Viewer',productName:'Memory Viewer',clientGroup:'Select client',refresh:'Refresh memory activity',languageSwitch:'切换到中文',themeDark:'Switch to dark mode',themeLight:'Switch to light mode',
37
+ connecting:'Connecting',connected:'Connected',disconnected:'Disconnected',updated:'· Updated just now',
38
+ eyebrow:'Memory at a glance',heading:'Memory usage',intro:'See how client sessions use project memory and whether repository knowledge is ready.',scopeLabel:'View scope',projectAria:'Select repository',allProjects:'All repositories',summaryAria:'Memory summary',
39
+ cardTurns:'Turns',cardSearch:'Search',cardAdd:'Add',cardRepo:'Repo Memory',loading:'Loading',checking:'Checking',repoLoading:'Repository knowledge status',recentActivity:'Recent activity',
40
+ empty:'No turn, Search, or Add activity in the current scope',error:'Memory activity is temporarily unavailable. Please try again later.',selectProject:'Select a repository',selectProjectForStatus:'Select a repository to view its status',noProjects:'No repositories found',unassignedProject:'Unassigned repository',systemActivity:'System activity',
41
+ turnNote:'client turns',searchUnit:'searches',addUnit:'adds',processingUnit:'processing',unknownUnit:'with unknown counts',activityUnit:'items',
42
+ repoStates:{ready:'Ready',preparing:'Preparing',not_ready:'Not Ready',unknown:'Unknown'},
43
+ reasons:{usable:'Repository knowledge is ready',active_job:'Generating or updating repository knowledge',bundle_missing:'Repository knowledge has not been generated',bundle_invalid:'Repository knowledge needs to be regenerated',project_unresolved:'Repository could not be resolved',validator_unavailable:'Status is temporarily unavailable'},
44
+ statuses:{completed:'Completed',saved:'Saved',skipped:'No Add',processing:'Processing',interrupted:'Interrupted',failed:'Failed',unknown:'Count unknown'},
45
+ sources:{client:'Client session',assistant:'Assistant initiated',automatic:'Automatic'}
46
+ }
47
+ };
48
+ const icons={turn:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9"><path d="M5 6h14v10H9l-4 3z" stroke-linejoin="round"/></svg>',search:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9"><circle cx="10.5" cy="10.5" r="5.5"/><path d="m15 15 4 4" stroke-linecap="round"/></svg>',add:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9"><path d="M12 7v10M7 12h10" stroke-linecap="round"/></svg>'};
49
+ const copy=()=>COPY[language],locale=()=>language==='en'?'en-US':'zh-CN',number=value=>Number(value||0).toLocaleString(locale()),date=value=>new Intl.DateTimeFormat(locale(),{month:'short',day:'numeric',hour:'2-digit',minute:'2-digit'}).format(new Date(value));
50
+ function endpoint(){const next=new URL('/memory-viewer/api/summary',location.href);next.searchParams.set('client',client);if(selected)next.searchParams.set('projectId',selected);return next.pathname+next.search}
51
+ function syncClient(){clientButtons.forEach(button=>button.setAttribute('aria-pressed',String(button.dataset.client===client)))}
52
+ function syncStaticCopy(){const current=copy();document.title=current.pageTitle;document.documentElement.lang=language==='en'?'en':'zh-CN';document.querySelectorAll('[data-i18n]').forEach(node=>{const value=current[node.dataset.i18n];if(typeof value==='string')node.textContent=value});document.querySelectorAll('[data-i18n-aria]').forEach(node=>{const value=current[node.dataset.i18nAria];if(typeof value==='string')node.setAttribute('aria-label',value)});document.querySelectorAll('[data-i18n-title]').forEach(node=>{const value=current[node.dataset.i18nTitle];if(typeof value==='string')node.setAttribute('title',value)});E('language-toggle').textContent=language==='zh'?'EN':'中';E('language-toggle').setAttribute('aria-label',current.languageSwitch);E('language-toggle').title=current.languageSwitch;syncThemeButton()}
53
+ function syncThemeButton(){const label=theme==='dark'?copy().themeLight:copy().themeDark;E('theme-toggle').setAttribute('aria-label',label);E('theme-toggle').title=label}
54
+ function setTheme(next,persist=true){theme=next;document.documentElement.dataset.theme=theme;document.querySelector('meta[name="theme-color"]').content=theme==='dark'?'#10121a':'#f7f8fc';if(persist)writePreference(THEME_STORAGE_KEY,theme);syncThemeButton()}
55
+ function setLanguage(next,persist=true){language=next;if(persist)writePreference(LANGUAGE_STORAGE_KEY,language);syncStaticCopy();if(lastBody)render(lastBody);if(connectionState!==null)connection(connectionState)}
56
+ function syncProjects(items){const current=selected;project.innerHTML='<option value="">'+esc(copy().allProjects)+'</option>'+items.map(item=>'<option value="'+esc(item.projectId)+'">'+esc(item.projectLabel)+'</option>').join('');project.value=items.some(item=>item.projectId===current)?current:'';selected=project.value}
57
+ function repoState(items){const current=copy(),target=selected?items.find(item=>item.projectId===selected):items.length===1?items[0]:null,state=target?.repoMemory||{status:'unknown',reason:'project_unresolved'};E('repo-state').className='repo-state';E('repo-dot').className='state-dot '+state.status;E('repo-label').textContent=target?(current.repoStates[state.status]||current.repoStates.unknown):current.selectProject;E('repo-note').classList.remove('skeleton','loading-copy');E('repo-note').textContent=target?(target.projectLabel+' · '+(current.reasons[state.reason]||current.reasons.validator_unavailable)):items.length?current.selectProjectForStatus:current.noProjects}
58
+ function memoryCount(value){if(language==='zh')return value+' 条记忆';return value+' '+(value===1?'memory':'memories')}
59
+ function activityTitle(item){if(language==='zh'){if(item.kind==='turn')return item.status==='processing'?'会话进行中':item.status==='interrupted'?'会话已中断':'完成一轮会话';if(item.kind==='search')return item.status==='failed'?'搜索失败':'搜索 · '+memoryCount(item.count??0);if(item.status==='saved')return item.count===null?'写入 · 数量未知':'写入 · '+memoryCount(item.count);if(item.status==='skipped')return '写入 · 没有新记忆';if(item.status==='processing')return '写入处理中';if(item.status==='failed')return '写入失败';return '写入完成 · 数量未知'}if(item.kind==='turn')return item.status==='processing'?'Session in progress':item.status==='interrupted'?'Session interrupted':'Session turn completed';if(item.kind==='search')return item.status==='failed'?'Search failed':'Search · '+memoryCount(item.count??0);if(item.status==='saved')return item.count===null?'Add · Count unknown':'Add · '+memoryCount(item.count);if(item.status==='skipped')return 'Add · No new memory';if(item.status==='processing')return 'Add in progress';if(item.status==='failed')return 'Add failed';return 'Add completed · Count unknown'}
60
+ function metaItem(value){return '<span class="meta-item">'+esc(value)+'</span>'}
61
+ function render(body){lastBody=body;const current=copy(),summary=body.summary||{};E('turns').classList.remove('skeleton');E('turns').textContent=number(summary.turnCount);E('turn-note').classList.remove('skeleton','loading-copy');E('turn-note').textContent=language==='en'&&summary.turnCount===1?'client turn':current.turnNote;E('searched').classList.remove('skeleton');E('searched').textContent=number(summary.searchedMemoryCount);E('search-note').classList.remove('skeleton','loading-copy');E('search-note').textContent=number(summary.searchOperationCount)+' '+(language==='en'&&summary.searchOperationCount===1?'search':current.searchUnit);E('added').classList.remove('skeleton');E('added').textContent=number(summary.addedMemoryCount);E('add-note').classList.remove('skeleton','loading-copy');const addParts=[number(summary.addOperationCount)+' '+(language==='en'&&summary.addOperationCount===1?'add':current.addUnit)];if(summary.processingCount)addParts.push(number(summary.processingCount)+' '+current.processingUnit);if(summary.unknownCount)addParts.push(number(summary.unknownCount)+' '+current.unknownUnit);E('add-note').textContent=addParts.join(' · ');syncProjects(body.projects||[]);repoState(body.projects||[]);const activities=body.activities||[];E('activity-note').textContent=number(activities.length)+' '+(language==='en'&&activities.length===1?'item':current.activityUnit);E('activity').innerHTML=activities.map(item=>'<article class="row"><span class="timeline"><span class="event-icon '+esc(item.kind)+'">'+icons[item.kind]+'</span></span><div class="row-main"><div class="row-title">'+esc(activityTitle(item))+'</div><div class="row-meta">'+metaItem(item.projectLabel||current.unassignedProject)+'<span class="meta-separator"></span>'+metaItem(current.sources[item.source]||current.systemActivity)+'<span class="meta-separator"></span>'+metaItem(date(item.occurredAt))+'</div></div><span class="status '+esc(item.status)+'">'+esc(current.statuses[item.status]||item.status)+'</span></article>').join('');E('empty').hidden=activities.length>0;E('error').hidden=true}
62
+ function connection(ok){connectionState=ok;const current=copy(),pill=E('connection-pill');pill.classList.toggle('offline',!ok);E('connection').textContent=ok?current.connected:current.disconnected;E('connection-time').textContent=ok?current.updated:''}
63
+ async function refresh(){if(controller)controller.abort();const request=new AbortController();controller=request;E('refresh').classList.add('loading');E('refresh').disabled=true;try{const response=await fetch(endpoint(),{signal:request.signal,credentials:'same-origin'});if(!response.ok)throw new Error('HTTP '+response.status);render(await response.json());connection(true)}catch(error){if(error.name==='AbortError')return;connection(false);E('error').hidden=false}finally{if(controller===request){E('refresh').classList.remove('loading');E('refresh').disabled=false}}}
64
+ async function poll(){if(document.visibilityState==='visible')await refresh();setTimeout(poll,10000)}
65
+ clientButtons.forEach(button=>button.onclick=()=>{if(button.dataset.client===client)return;client=button.dataset.client;selected='';syncClient();const next=new URL(location.href);next.searchParams.set('client',client);next.searchParams.delete('projectId');history.replaceState(null,'',next);refresh()});
66
+ project.onchange=()=>{selected=project.value;const next=new URL(location.href);next.searchParams.set('client',client);if(selected)next.searchParams.set('projectId',selected);else next.searchParams.delete('projectId');history.replaceState(null,'',next);refresh()};
67
+ E('language-toggle').onclick=()=>setLanguage(language==='zh'?'en':'zh');
68
+ E('theme-toggle').onclick=()=>setTheme(theme==='light'?'dark':'light');
69
+ E('refresh').onclick=refresh;
70
+ syncClient();
71
+ syncStaticCopy();
72
+ poll();
73
+ });
74
+ </script>
75
+ <style>
76
+ :root{color-scheme:light;--canvas:#f7f8fc;--surface:#fff;--surface-soft:#fafbfe;--ink:#171b27;--muted:#687084;--quiet:#9299aa;--line:#e7e9f1;--line-strong:#d9dce8;--violet:#7156d9;--violet-soft:#f0edff;--cyan:#167c9d;--cyan-soft:#e8f7fb;--green:#168452;--green-soft:#e9f8f0;--amber:#a56818;--amber-soft:#fff4df;--red:#c23b50;--red-soft:#fff0f2;--shadow:0 18px 50px rgba(40,43,65,.07),0 2px 8px rgba(40,43,65,.04);--header-border:rgba(225,227,236,.82);--header-bg:rgba(247,248,252,.82);--control-bg:rgba(255,255,255,.7);--control-bg-strong:#fff;--select-bg:rgba(255,255,255,.88);--card-bg:rgba(255,255,255,.9);--panel-bg:rgba(255,255,255,.83);--product-ink:#464d60;--card-label:#555d70;--section-icon:#6f768a;--row-line:#edeef4;--timeline-line:#e5e7ef;--chip-bg:#f1f2f7;--chip-ink:#747b8d;--empty-icon-bg:#f1f2f6;--empty-icon-ink:#81889a;--skeleton-a:#eef0f5;--skeleton-b:#f7f8fb;--glow-violet:rgba(113,86,217,.07);--glow-cyan:rgba(22,124,157,.055);--active-shadow:0 1px 5px rgba(40,43,65,.11);--hover-shadow:0 22px 58px rgba(40,43,65,.1),0 3px 10px rgba(40,43,65,.05);font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif}
77
+ [data-theme="dark"]{color-scheme:dark;--canvas:#10121a;--surface:#181b25;--surface-soft:#1e222e;--ink:#f2f3f7;--muted:#adb4c4;--quiet:#858da1;--line:#292e3c;--line-strong:#3a4051;--violet:#a995ff;--violet-soft:rgba(132,108,238,.18);--cyan:#68cbe6;--cyan-soft:rgba(42,153,184,.16);--green:#55cf91;--green-soft:rgba(38,167,101,.16);--amber:#e8b45f;--amber-soft:rgba(195,129,33,.17);--red:#f17a8d;--red-soft:rgba(205,65,87,.16);--shadow:0 18px 50px rgba(0,0,0,.2),0 2px 8px rgba(0,0,0,.14);--header-border:rgba(48,53,69,.88);--header-bg:rgba(16,18,26,.84);--control-bg:rgba(28,32,43,.82);--control-bg-strong:#242936;--select-bg:rgba(27,31,42,.94);--card-bg:rgba(25,28,39,.94);--panel-bg:rgba(24,27,37,.9);--product-ink:#c9ceda;--card-label:#c4cad7;--section-icon:#a6adbd;--row-line:#292e3c;--timeline-line:#303646;--chip-bg:#252a38;--chip-ink:#aeb5c5;--empty-icon-bg:#252a38;--empty-icon-ink:#a6adbd;--skeleton-a:#242936;--skeleton-b:#303646;--glow-violet:rgba(132,108,238,.12);--glow-cyan:rgba(42,153,184,.08);--active-shadow:0 1px 6px rgba(0,0,0,.3);--hover-shadow:0 22px 58px rgba(0,0,0,.26),0 3px 10px rgba(0,0,0,.18)}
78
+ *{box-sizing:border-box}html{background:var(--canvas)}body{margin:0;min-height:100vh;background:radial-gradient(circle at 7% 2%,var(--glow-violet),transparent 25rem),radial-gradient(circle at 96% 28%,var(--glow-cyan),transparent 24rem),var(--canvas);color:var(--ink);-webkit-font-smoothing:antialiased}button,select{font:inherit}button{color:inherit}
79
+ .shell{width:min(1080px,calc(100% - 48px));margin:0 auto}
80
+ header{position:sticky;top:0;z-index:5;border-bottom:1px solid var(--header-border);background:var(--header-bg);backdrop-filter:blur(18px) saturate(150%)}
81
+ .header-inner{height:72px;display:flex;align-items:center}.brand{display:flex;align-items:center;gap:14px;min-width:0}.logo{display:block;height:27px;max-width:168px;transition:filter .18s}.brand-divider{width:1px;height:22px;background:var(--line-strong)}.product-name{font-size:13px;font-weight:650;letter-spacing:.01em;color:var(--product-ink);white-space:nowrap}[data-theme="dark"] .logo{filter:brightness(0) invert(1)}
82
+ .header-actions{margin-left:auto;display:flex;align-items:center;gap:10px}.client-switch{display:flex;padding:3px;border:1px solid var(--line);border-radius:10px;background:var(--control-bg)}.client-button{height:28px;padding:0 11px;border:0;border-radius:7px;background:transparent;color:var(--muted);font-size:11px;font-weight:680;cursor:pointer}.client-button[aria-pressed="true"]{background:var(--control-bg-strong);color:var(--ink);box-shadow:var(--active-shadow)}.connection{display:flex;align-items:center;gap:8px;min-height:34px;padding:0 12px;border:1px solid var(--line);border-radius:999px;background:var(--control-bg);color:var(--muted);font-size:11px;font-weight:600}.connection-dot{position:relative;width:7px;height:7px;border-radius:50%;background:var(--green);box-shadow:0 0 0 4px rgba(22,132,82,.1)}.connection.offline{color:var(--red);border-color:color-mix(in srgb,var(--red) 35%,var(--line));background:var(--red-soft)}.connection.offline .connection-dot{background:var(--red);box-shadow:0 0 0 4px rgba(194,59,80,.1)}
83
+ .preference-actions{display:flex;align-items:center;gap:6px}.icon-button{display:grid;width:34px;height:34px;padding:0;place-items:center;border:1px solid var(--line);border-radius:10px;background:var(--control-bg);cursor:pointer;transition:border-color .18s,background-color .18s,transform .18s}.icon-button:hover{border-color:var(--line-strong);background:var(--control-bg-strong);transform:translateY(-1px)}.icon-button:active{transform:translateY(0)}.icon-button svg{width:15px;height:15px}.icon-button.loading svg{animation:spin .8s linear infinite}.language-button{font-size:10px;font-weight:760;letter-spacing:.02em}.theme-sun{display:none}[data-theme="dark"] .theme-sun{display:block}[data-theme="dark"] .theme-moon{display:none}
84
+ main{padding:56px 0 80px}.hero{display:grid;grid-template-columns:minmax(0,1fr) 280px;align-items:end;gap:40px;margin-bottom:28px}.eyebrow{display:flex;align-items:center;gap:8px;margin-bottom:11px;color:var(--violet);font-size:11px;font-weight:760;letter-spacing:.11em;text-transform:uppercase}.eyebrow:before{content:"";width:19px;height:2px;border-radius:2px;background:currentColor}.hero h1{margin:0;font-size:clamp(30px,4vw,42px);font-weight:730;line-height:1.12;letter-spacing:-.04em}.hero p{max-width:620px;margin:13px 0 0;color:var(--muted);font-size:14px;line-height:1.7}
85
+ .scope label{display:block;margin:0 0 8px;color:var(--muted);font-size:11px;font-weight:650}.select-wrap{position:relative}.select-wrap svg{position:absolute;right:13px;top:50%;width:14px;height:14px;pointer-events:none;transform:translateY(-50%);color:var(--quiet)}.scope select{width:100%;height:44px;padding:0 40px 0 13px;appearance:none;border:1px solid var(--line-strong);border-radius:12px;outline:none;background:var(--select-bg);color:var(--ink);font-size:13px;font-weight:570;box-shadow:0 1px 2px rgba(25,27,39,.025);transition:border-color .18s,box-shadow .18s}.scope select:hover{border-color:color-mix(in srgb,var(--violet) 28%,var(--line-strong))}.scope select:focus{border-color:color-mix(in srgb,var(--violet) 60%,transparent);box-shadow:0 0 0 4px color-mix(in srgb,var(--violet) 12%,transparent)}
86
+ .cards{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}.card{position:relative;min-height:178px;padding:20px 21px 19px;overflow:hidden;border:1px solid var(--line);border-radius:18px;background:var(--card-bg);box-shadow:var(--shadow);transition:transform .2s,box-shadow .2s}.card:after{content:"";position:absolute;right:-34px;bottom:-48px;width:130px;height:130px;border-radius:50%;opacity:.55}.card:hover{transform:translateY(-2px);box-shadow:var(--hover-shadow)}.card.turn:after{background:radial-gradient(circle,rgba(165,104,24,.12),transparent 68%)}.card.search:after{background:radial-gradient(circle,rgba(113,86,217,.14),transparent 68%)}.card.add:after{background:radial-gradient(circle,rgba(22,124,157,.13),transparent 68%)}.card.repo:after{background:radial-gradient(circle,rgba(22,132,82,.12),transparent 68%)}
87
+ .card-head{position:relative;z-index:1;display:flex;align-items:center;gap:10px}.card-icon{display:grid;width:31px;height:31px;place-items:center;border-radius:10px}.card-icon svg{width:15px;height:15px}.turn .card-icon{background:var(--amber-soft);color:var(--amber)}.search .card-icon{background:var(--violet-soft);color:var(--violet)}.add .card-icon{background:var(--cyan-soft);color:var(--cyan)}.repo .card-icon{background:var(--green-soft);color:var(--green)}.card-label{color:var(--card-label);font-size:12px;font-weight:680}.metric{position:relative;z-index:1;margin:19px 0 4px;font-size:40px;font-weight:730;line-height:1;font-variant-numeric:tabular-nums;letter-spacing:-.045em}.metric-note{position:relative;z-index:1;color:var(--muted);font-size:11px;line-height:1.45}.repo-state{position:relative;z-index:1;display:flex;align-items:center;gap:9px;margin:22px 0 6px;font-size:21px;font-weight:700;letter-spacing:-.025em}.state-dot{width:9px;height:9px;border-radius:50%;background:var(--quiet);box-shadow:0 0 0 4px rgba(146,153,170,.11)}.state-dot.ready{background:var(--green);box-shadow:0 0 0 4px rgba(22,132,82,.1)}.state-dot.preparing{background:var(--amber);box-shadow:0 0 0 4px rgba(165,104,24,.1)}.state-dot.not_ready{background:var(--red);box-shadow:0 0 0 4px rgba(194,59,80,.1)}
88
+ .activity-section{margin-top:32px;border:1px solid var(--line);border-radius:20px;background:var(--panel-bg);box-shadow:0 14px 44px rgba(40,43,65,.045);overflow:hidden}.section-head{display:flex;align-items:center;gap:12px;padding:20px 22px;border-bottom:1px solid var(--line)}.section-title{display:flex;align-items:center;gap:10px}.section-title svg{width:17px;height:17px;color:var(--section-icon)}.section-head h2{margin:0;font-size:15px;font-weight:700;letter-spacing:-.01em}.section-note{margin-left:auto;padding:4px 8px;border-radius:999px;background:var(--chip-bg);color:var(--muted);font-size:10px;font-weight:650;font-variant-numeric:tabular-nums}.activity{padding:4px 22px}.row{position:relative;display:grid;grid-template-columns:34px minmax(0,1fr) auto;align-items:center;gap:13px;min-height:82px;padding:14px 0;border-bottom:1px solid var(--row-line)}.row:last-child{border-bottom:0}.timeline{position:relative;align-self:stretch;display:grid;place-items:center}.timeline:after{content:"";position:absolute;left:50%;top:calc(50% + 17px);bottom:-31px;width:1px;background:var(--timeline-line)}.row:last-child .timeline:after{display:none}.event-icon{position:relative;z-index:1;display:grid;width:30px;height:30px;place-items:center;border:4px solid var(--surface);border-radius:50%;box-shadow:0 0 0 1px var(--line)}.event-icon svg{width:12px;height:12px}.event-icon.turn{background:var(--amber-soft);color:var(--amber)}.event-icon.search{background:var(--violet-soft);color:var(--violet)}.event-icon.add{background:var(--cyan-soft);color:var(--cyan)}.row-main{min-width:0}.row-title{font-size:13px;font-weight:670;line-height:1.4}.row-meta{display:flex;align-items:center;gap:7px;margin-top:6px;color:var(--quiet);font-size:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.meta-separator{width:2px;height:2px;flex:0 0 auto;border-radius:50%;background:var(--quiet)}.status{padding:5px 9px;border-radius:999px;background:var(--chip-bg);color:var(--muted);font-size:10px;font-weight:680;white-space:nowrap}.status.failed,.status.interrupted{background:var(--red-soft);color:var(--red)}.status.processing{background:var(--amber-soft);color:var(--amber)}.status.saved{background:var(--green-soft);color:var(--green)}.status.completed{background:var(--violet-soft);color:var(--violet)}.status.skipped{background:var(--chip-bg);color:var(--chip-ink)}
89
+ .empty,.error{margin:22px;padding:36px 20px;border:1px dashed var(--line-strong);border-radius:14px;color:var(--muted);font-size:12px;text-align:center}.empty-icon{display:grid;width:38px;height:38px;margin:0 auto 10px;place-items:center;border-radius:12px;background:var(--empty-icon-bg);color:var(--empty-icon-ink)}.empty-icon svg{width:17px;height:17px}.error{border-color:color-mix(in srgb,var(--red) 35%,var(--line));background:var(--red-soft);color:var(--red)}[hidden]{display:none!important}
90
+ .skeleton{overflow:hidden;color:transparent!important;border-radius:6px;background:linear-gradient(90deg,var(--skeleton-a) 25%,var(--skeleton-b) 50%,var(--skeleton-a) 75%);background-size:200% 100%;animation:shimmer 1.2s infinite}.metric.skeleton{width:70px;height:40px}.repo-state.skeleton{width:110px;height:25px}.loading-copy{width:90px;height:13px;margin-top:7px}
91
+ :focus-visible{outline:2px solid var(--violet);outline-offset:3px}@keyframes spin{to{transform:rotate(360deg)}}@keyframes shimmer{to{background-position:-200% 0}}
92
+ @media(max-width:780px){.shell{width:min(100% - 28px,1080px)}main{padding:38px 0 60px}.hero{grid-template-columns:1fr;gap:24px}.scope{max-width:none}.cards{grid-template-columns:1fr}.card{min-height:150px}.metric{margin-top:15px}.repo-state{margin-top:18px}.activity{padding:3px 16px}.section-head{padding:18px}.row{grid-template-columns:32px minmax(0,1fr);gap:11px}.status{grid-column:2;justify-self:start;margin-top:-7px}.brand-divider,.product-name{display:none}}
93
+ @media(max-width:720px){.header-inner{height:auto;min-height:108px;display:grid;grid-template-columns:minmax(0,1fr) auto;align-content:center;gap:10px 12px;padding:10px 0}.header-actions{display:contents}.client-switch{grid-column:1/-1;grid-row:2}.client-button{flex:1}.connection{display:none}.preference-actions{grid-column:2;grid-row:1;justify-self:end}}
94
+ @media(max-width:440px){.shell{width:calc(100% - 22px)}.logo{height:24px;max-width:145px}.hero h1{font-size:29px}.hero p{font-size:13px}.card{border-radius:16px}.activity-section{border-radius:16px}.row-meta{display:block;white-space:normal;line-height:1.55}.meta-separator{display:none}.meta-item{margin-right:6px}}
95
+ @media(prefers-reduced-motion:reduce){*,*:before,*:after{scroll-behavior:auto!important;animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}
96
+ </style>
97
+ </head>
98
+ <body>
99
+ <header><div class="header-inner shell"><div class="brand"><img class="logo" src="/memory-viewer/logo" alt="MemoraX AI"><span class="brand-divider" aria-hidden="true"></span><span class="product-name" data-i18n="productName">Memory Viewer</span></div><div class="header-actions"><div class="client-switch" role="group" aria-label="Select client" data-i18n-aria="clientGroup"><button class="client-button" type="button" data-client="codex" aria-pressed="true">Codex</button><button class="client-button" type="button" data-client="claude-code" aria-pressed="false">Claude Code</button></div><div id="connection-pill" class="connection" role="status"><span class="connection-dot"></span><span id="connection" data-i18n="connecting">Connecting</span><span id="connection-time" class="connection-time"></span></div><div class="preference-actions"><button id="language-toggle" class="icon-button language-button" type="button" aria-label="切换到中文" title="切换到中文">中</button><button id="theme-toggle" class="icon-button" type="button" aria-label="Switch to dark mode" title="Switch to dark mode"><svg class="theme-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M20 15.1A8.5 8.5 0 0 1 8.9 4a8.5 8.5 0 1 0 11.1 11.1Z" stroke-linecap="round" stroke-linejoin="round"/></svg><svg class="theme-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="3.5"/><path d="M12 2v2M12 20v2M4.93 4.93l1.42 1.42M17.65 17.65l1.42 1.42M2 12h2M20 12h2M4.93 19.07l1.42-1.42M17.65 6.35l1.42-1.42" stroke-linecap="round"/></svg></button><button id="refresh" class="icon-button" type="button" aria-label="Refresh memory activity" title="Refresh memory activity" data-i18n-aria="refresh" data-i18n-title="refresh"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M20 11a8 8 0 1 0-2.34 5.66M20 4v7h-7" stroke-linecap="round" stroke-linejoin="round"/></svg></button></div></div></div></header>
100
+ <main class="shell">
101
+ <section class="hero">
102
+ <div class="hero-copy"><div class="eyebrow" data-i18n="eyebrow">Memory at a glance</div><h1 data-i18n="heading">Memory usage</h1><p data-i18n="intro">See how client sessions use project memory and whether repository knowledge is ready.</p></div>
103
+ <div class="scope"><label for="project" data-i18n="scopeLabel">View scope</label><div class="select-wrap"><select id="project" aria-label="Select repository" data-i18n-aria="projectAria"><option value="" data-i18n="allProjects">All repositories</option></select><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="m7 9 5 5 5-5" stroke-linecap="round" stroke-linejoin="round"/></svg></div></div>
104
+ </section>
105
+ <section class="cards" aria-label="Memory summary" data-i18n-aria="summaryAria">
106
+ <article class="card turn"><div class="card-head"><span class="card-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M5 6h14v10H9l-4 3z" stroke-linejoin="round"/></svg></span><span class="card-label" data-i18n="cardTurns">Turns</span></div><div id="turns" class="metric skeleton" aria-live="polite">—</div><div id="turn-note" class="metric-note skeleton loading-copy" data-i18n="loading">Loading</div></article>
107
+ <article class="card search"><div class="card-head"><span class="card-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="10.5" cy="10.5" r="5.5"/><path d="m15 15 4 4" stroke-linecap="round"/></svg></span><span class="card-label" data-i18n="cardSearch">Search</span></div><div id="searched" class="metric skeleton" aria-live="polite">—</div><div id="search-note" class="metric-note skeleton loading-copy" data-i18n="loading">Loading</div></article>
108
+ <article class="card add"><div class="card-head"><span class="card-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M12 5v14M5 12h14" stroke-linecap="round"/><circle cx="12" cy="12" r="9"/></svg></span><span class="card-label" data-i18n="cardAdd">Add</span></div><div id="added" class="metric skeleton" aria-live="polite">—</div><div id="add-note" class="metric-note skeleton loading-copy" data-i18n="loading">Loading</div></article>
109
+ <article class="card repo"><div class="card-head"><span class="card-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 7.5 12 3l8 4.5v9L12 21l-8-4.5z" stroke-linejoin="round"/><path d="m4 7.5 8 4.5 8-4.5M12 12v9"/></svg></span><span class="card-label" data-i18n="cardRepo">Repo Memory</span></div><div id="repo-state" class="repo-state skeleton"><span id="repo-dot" class="state-dot unknown"></span><span id="repo-label" data-i18n="checking">Checking</span></div><div id="repo-note" class="metric-note skeleton loading-copy" data-i18n="repoLoading">Repository knowledge status</div></article>
110
+ </section>
111
+ <section class="activity-section"><div class="section-head"><div class="section-title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 6h16M4 12h16M4 18h10" stroke-linecap="round"/></svg><h2 data-i18n="recentActivity">Recent activity</h2></div><span id="activity-note" class="section-note" data-i18n="loading">Loading</span></div><div id="activity" class="activity" aria-live="polite"></div><div id="empty" class="empty" hidden><span class="empty-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M5 5h14v14H5zM8 9h8M8 13h5" stroke-linecap="round"/></svg></span><span data-i18n="empty">No turn, Search, or Add activity in the current scope</span></div><div id="error" class="error" hidden data-i18n="error">Memory activity is temporarily unavailable. Please try again later.</div></section>
112
+ </main>
113
+ </body>
114
+ </html>`;
115
+ }
@@ -0,0 +1,168 @@
1
+ import { isTraceClient } from "./trace-context.js";
2
+ /**
3
+ * Projects raw Viewer events into the deliberately small user-facing summary contract.
4
+ * Conversation, memory, session, turn, and diagnostic fields never cross this boundary.
5
+ */
6
+ export function projectMemoryViewerUserData(events) {
7
+ const turnActivities = projectTurnActivities(events);
8
+ const activities = [
9
+ ...turnActivities,
10
+ ...events.flatMap((event) => {
11
+ if (event.type === "memory_retrieve" || event.type === "memory_cli_search") {
12
+ const occurredAt = canonicalUserActivityTimestamp(event.timestamp);
13
+ if (!occurredAt)
14
+ return [];
15
+ const nativeTranscriptActivity = isClaudeNativeTranscriptMemoryActivity(event);
16
+ return [{
17
+ kind: "search",
18
+ occurredAt,
19
+ source: event.type === "memory_cli_search" ? "assistant" : "automatic",
20
+ status: event.ok ? "completed" : "failed",
21
+ count: event.ok
22
+ ? nativeTranscriptActivity
23
+ ? safeNativeTranscriptSearchItemCount(event)
24
+ : event.itemCount ?? event.results?.length ?? 0
25
+ : 0,
26
+ ...safeProjectFields(event),
27
+ }];
28
+ }
29
+ if (event.type !== "memory_cli_add" && event.type !== "memory_writeback")
30
+ return [];
31
+ const occurredAt = canonicalUserActivityTimestamp(event.timestamp);
32
+ if (!occurredAt)
33
+ return [];
34
+ const nativeTranscriptActivity = isClaudeNativeTranscriptMemoryActivity(event);
35
+ return [{
36
+ kind: "add",
37
+ occurredAt,
38
+ source: event.type === "memory_cli_add" ? "assistant" : "automatic",
39
+ status: nativeTranscriptActivity && event.ok ? "unknown" : addStatus(event),
40
+ count: nativeTranscriptActivity && event.ok ? null : addCount(event),
41
+ ...safeProjectFields(event),
42
+ }];
43
+ }),
44
+ ].sort(compareUserActivitiesNewestFirst);
45
+ return {
46
+ activities,
47
+ summary: {
48
+ turnCount: turnActivities.length,
49
+ searchOperationCount: countActivities(activities, "search"),
50
+ searchedMemoryCount: sumActivityCounts(activities, "search"),
51
+ addOperationCount: countActivities(activities, "add"),
52
+ addedMemoryCount: activities
53
+ .filter((activity) => activity.kind === "add" && activity.status === "saved")
54
+ .reduce((total, activity) => total + (activity.count ?? 0), 0),
55
+ processingCount: activities.filter((activity) => activity.status === "processing").length,
56
+ unknownCount: activities.filter((activity) => (activity.kind !== "turn"
57
+ && activity.count === null
58
+ && activity.status !== "processing"
59
+ && activity.status !== "failed")).length,
60
+ failedCount: activities.filter((activity) => activity.status === "failed").length,
61
+ },
62
+ };
63
+ }
64
+ function isClaudeNativeTranscriptMemoryActivity(event) {
65
+ return event.client === "claude"
66
+ && event.id.startsWith("claude-local:")
67
+ && (event.type === "memory_cli_search" || event.type === "memory_cli_add");
68
+ }
69
+ function safeNativeTranscriptSearchItemCount(event) {
70
+ return Number.isSafeInteger(event.itemCount)
71
+ && (event.itemCount ?? -1) >= 0
72
+ && (event.itemCount ?? 101) <= 100
73
+ ? event.itemCount
74
+ : null;
75
+ }
76
+ function projectTurnActivities(events) {
77
+ const turns = new Map();
78
+ for (const event of events) {
79
+ if (!event.sessionId || !event.turnId || (event.type !== "turn_start" && event.type !== "turn_end"))
80
+ continue;
81
+ const key = `${traceClient(event)}\u0000${event.sessionId}\u0000${event.turnId}`;
82
+ const turn = turns.get(key) ?? {};
83
+ if (event.type === "turn_start")
84
+ turn.start = event;
85
+ else
86
+ turn.end = event;
87
+ turns.set(key, turn);
88
+ }
89
+ return [...turns.values()].flatMap((turn) => {
90
+ const anchor = turn.start ?? turn.end;
91
+ if (!anchor)
92
+ return [];
93
+ const occurredAt = canonicalUserActivityTimestamp(turn.start?.timestamp)
94
+ ?? canonicalUserActivityTimestamp(turn.end?.timestamp)
95
+ ?? canonicalUserActivityTimestamp(anchor.timestamp);
96
+ if (!occurredAt)
97
+ return [];
98
+ return [{
99
+ kind: "turn",
100
+ occurredAt,
101
+ source: "client",
102
+ status: turn.end?.turnOutcome === "interrupted"
103
+ || (!turn.end && turn.start?.turnOutcome === "interrupted")
104
+ ? "interrupted"
105
+ : turn.end
106
+ ? "completed"
107
+ : "processing",
108
+ count: null,
109
+ ...safeProjectFields(anchor),
110
+ }];
111
+ });
112
+ }
113
+ function canonicalUserActivityTimestamp(value) {
114
+ if (typeof value !== "string" || value.length > 512)
115
+ return undefined;
116
+ const parsed = Date.parse(value.trim());
117
+ if (!Number.isFinite(parsed))
118
+ return undefined;
119
+ return new Date(parsed).toISOString();
120
+ }
121
+ function traceClient(event) {
122
+ return isTraceClient(event.client) ? event.client : "codex";
123
+ }
124
+ function safeProjectFields(event) {
125
+ return {
126
+ ...(event.projectId ? { projectId: event.projectId } : {}),
127
+ ...(event.projectLabel ? { projectLabel: event.projectLabel } : {}),
128
+ };
129
+ }
130
+ function addStatus(event) {
131
+ if (!event.ok || event.writebackOutcome === "failed")
132
+ return "failed";
133
+ if (event.writebackOutcome === "pending")
134
+ return "processing";
135
+ if (event.writebackOutcome === "saved")
136
+ return "saved";
137
+ if (event.writebackOutcome === "skipped")
138
+ return "skipped";
139
+ if (event.writebackOutcome === "completed")
140
+ return "completed";
141
+ if (event.savedMemoryCount !== undefined)
142
+ return event.savedMemoryCount > 0 ? "saved" : "skipped";
143
+ return "unknown";
144
+ }
145
+ function addCount(event) {
146
+ if (!event.ok || event.writebackOutcome === "failed")
147
+ return 0;
148
+ if (event.savedMemoryCount !== undefined)
149
+ return event.savedMemoryCount;
150
+ if (event.writebackOutcome === "skipped")
151
+ return 0;
152
+ return null;
153
+ }
154
+ function compareUserActivitiesNewestFirst(left, right) {
155
+ return timestampOrder(right.occurredAt) - timestampOrder(left.occurredAt);
156
+ }
157
+ function timestampOrder(value) {
158
+ const parsed = Date.parse(value);
159
+ return Number.isFinite(parsed) ? parsed : 0;
160
+ }
161
+ function countActivities(activities, kind) {
162
+ return activities.filter((activity) => activity.kind === kind).length;
163
+ }
164
+ function sumActivityCounts(activities, kind) {
165
+ return activities
166
+ .filter((activity) => activity.kind === kind)
167
+ .reduce((total, activity) => total + (activity.count ?? 0), 0);
168
+ }
@@ -0,0 +1,97 @@
1
+ import { completeMemoryWritebackTask, memoryText, memoryWritebackTaskEventKey, memoryWritebackTaskOutcome, memoryWritebackTaskOutcomeForStatus, nonNegativeInteger, projectMemoryWritebackTasks, stringArray, } from "./memory-writeback-task-projection.js";
2
+ export { memoryText, nonNegativeInteger, stringArray, };
3
+ export function pendingMemoryViewerWritebacks(eventsToCheck) {
4
+ const tasks = new Map(projectMemoryWritebackTasks(eventsToCheck.flatMap(memoryViewerWritebackProjectionRecord)).map((task) => [memoryWritebackTaskEventKey(task), task]));
5
+ return eventsToCheck.filter((event) => {
6
+ const task = tasks.get(memoryViewerWritebackEventKey(event));
7
+ return task?.accepted === true && task.completion.outcome === "pending";
8
+ });
9
+ }
10
+ export function completeMemoryViewerWriteback(event, status) {
11
+ return applyMemoryWritebackTaskCompletion(event, completeMemoryWritebackTask(status), false);
12
+ }
13
+ export function foldMemoryViewerWritebackStatuses(allEvents) {
14
+ const tasks = new Map(projectMemoryWritebackTasks(allEvents.flatMap(memoryViewerWritebackProjectionRecord)).map((task) => [memoryWritebackTaskEventKey(task), task]));
15
+ return allEvents
16
+ .filter((event) => event.type !== "memory_writeback_status")
17
+ .map((event) => {
18
+ const task = tasks.get(memoryViewerWritebackEventKey(event));
19
+ return task?.statusEventId
20
+ ? applyMemoryWritebackTaskCompletion(event, task.completion, true)
21
+ : event;
22
+ });
23
+ }
24
+ export function memoryViewerWritebackOutcome(value) {
25
+ return memoryWritebackTaskOutcome(value);
26
+ }
27
+ export function writebackOutcomeForStatus(status, result = {}) {
28
+ return memoryWritebackTaskOutcomeForStatus(status, result);
29
+ }
30
+ function memoryViewerWritebackProjectionRecord(event) {
31
+ if ((event.type === "memory_writeback" || event.type === "memory_cli_add")
32
+ && event.taskId
33
+ && event.writebackStatus) {
34
+ return [{
35
+ kind: "task",
36
+ eventId: event.id,
37
+ timestamp: event.timestamp,
38
+ client: event.client,
39
+ ...(event.sessionId ? { sessionId: event.sessionId } : {}),
40
+ ...(event.turnId ? { turnId: event.turnId } : {}),
41
+ ok: event.ok,
42
+ taskId: event.taskId,
43
+ status: event.writebackStatus,
44
+ }];
45
+ }
46
+ if (event.type !== "memory_writeback_status" || !event.writebackStatus)
47
+ return [];
48
+ if (!event.originalEventId && (!event.sessionId || !event.taskId))
49
+ return [];
50
+ return [{
51
+ kind: "status",
52
+ eventId: event.id,
53
+ timestamp: event.timestamp,
54
+ client: event.client,
55
+ ...(event.sessionId ? { sessionId: event.sessionId } : {}),
56
+ ...(event.turnId ? { turnId: event.turnId } : {}),
57
+ ...(event.taskId ? { taskId: event.taskId } : {}),
58
+ ...(event.originalEventId ? { originalEventId: event.originalEventId } : {}),
59
+ completion: completeMemoryWritebackTask({
60
+ status: event.writebackStatus,
61
+ outcome: event.writebackOutcome,
62
+ savedMemoryCount: event.savedMemoryCount,
63
+ savedMemoryIds: event.savedMemoryIds,
64
+ savedMemories: event.savedMemories,
65
+ error: event.error,
66
+ }),
67
+ }];
68
+ }
69
+ function memoryViewerWritebackEventKey(event) {
70
+ return memoryWritebackTaskEventKey({
71
+ eventId: event.id,
72
+ client: event.client,
73
+ ...(event.sessionId ? { sessionId: event.sessionId } : {}),
74
+ });
75
+ }
76
+ function applyMemoryWritebackTaskCompletion(event, completion, replaceError) {
77
+ const base = replaceError
78
+ ? (({ error: _previousError, ...remaining }) => remaining)(event)
79
+ : event;
80
+ return {
81
+ ...base,
82
+ ok: completion.ok,
83
+ writebackStatus: completion.status,
84
+ writebackOutcome: completion.outcome,
85
+ ...(completion.savedMemories?.length ? {
86
+ content: completion.savedMemories.join("\n\n"),
87
+ savedMemories: completion.savedMemories,
88
+ } : {}),
89
+ ...(completion.savedMemoryIds?.length ? {
90
+ savedMemoryIds: completion.savedMemoryIds,
91
+ } : {}),
92
+ ...(completion.savedMemoryCount === undefined ? {} : {
93
+ savedMemoryCount: completion.savedMemoryCount,
94
+ }),
95
+ ...(completion.error ? { error: completion.error } : {}),
96
+ };
97
+ }