@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,66 @@
1
+ import { createAutomaticMemoryWritebackRuntime } from "./automatic-memory-writeback.js";
2
+ import { createCodexMemoryHookRuntime, } from "./codex-memory-hook-runtime.js";
3
+ import { createClaudeMemoryHookRuntime, } from "./claude-memory-hook-runtime.js";
4
+ import { createMemoryTurnCoordinator } from "./memory-turn-coordinator.js";
5
+ import { createRepositoryMemorySessionRuntime, } from "./repository-memory-context.js";
6
+ export function createMemoryService(options = {}) {
7
+ const automaticWriteback = createAutomaticMemoryWritebackRuntime({
8
+ diagnosticLogger: options.diagnosticLogger,
9
+ });
10
+ const repositoryMemorySession = createRepositoryMemorySessionRuntime();
11
+ const turnCoordinator = createMemoryTurnCoordinator({
12
+ automaticWriteback: automaticWriteback.enqueue,
13
+ now: options.now,
14
+ ttlMs: options.ttlMs,
15
+ maxEntries: options.maxEntries,
16
+ cleanupIntervalMs: options.cleanupIntervalMs,
17
+ });
18
+ const codexHook = createCodexMemoryHookRuntime({
19
+ ...options,
20
+ repositoryMemorySession,
21
+ turnCoordinator,
22
+ });
23
+ const claudeHook = createClaudeMemoryHookRuntime({
24
+ ...options,
25
+ repositoryMemorySession,
26
+ turnCoordinator,
27
+ });
28
+ let closed = false;
29
+ return {
30
+ async recordTurnStart(command) {
31
+ switch (command.client) {
32
+ case "codex":
33
+ return await codexHook.recordTurnStart(command);
34
+ case "claude-code":
35
+ return await claudeHook.recordTurnStart(command);
36
+ }
37
+ return unsupportedMemoryHookCommand(command);
38
+ },
39
+ async writebackTurn(command) {
40
+ switch (command.client) {
41
+ case "codex":
42
+ return await codexHook.writeback(command);
43
+ case "claude-code":
44
+ return await claudeHook.writeback(command);
45
+ }
46
+ return unsupportedMemoryHookCommand(command);
47
+ },
48
+ async drain() {
49
+ await automaticWriteback.drain();
50
+ },
51
+ close() {
52
+ if (closed)
53
+ return;
54
+ closed = true;
55
+ codexHook.close();
56
+ claudeHook.close();
57
+ turnCoordinator.close();
58
+ repositoryMemorySession.close();
59
+ automaticWriteback.close();
60
+ },
61
+ };
62
+ }
63
+ function unsupportedMemoryHookCommand(command) {
64
+ void command;
65
+ throw new Error("unsupported memory Hook command");
66
+ }
@@ -0,0 +1,139 @@
1
+ import { repositoryMemoryScopesMatch, } from "./repository-memory-scope.js";
2
+ const DEFAULT_TTL_MS = 5 * 60 * 1000;
3
+ const DEFAULT_MAX_ENTRIES = 256;
4
+ const DEFAULT_CLEANUP_INTERVAL_MS = 60 * 1000;
5
+ export function createMemoryTurnCoordinator(options) {
6
+ const turns = new Map();
7
+ const now = options.now ?? (() => Date.now());
8
+ const ttlMs = positiveInteger(options.ttlMs, DEFAULT_TTL_MS);
9
+ const maxEntries = positiveInteger(options.maxEntries, DEFAULT_MAX_ENTRIES);
10
+ const cleanupIntervalMs = positiveInteger(options.cleanupIntervalMs, DEFAULT_CLEANUP_INTERVAL_MS);
11
+ const timer = setInterval(() => cleanupExpired(turns, now(), ttlMs), cleanupIntervalMs);
12
+ timer.unref?.();
13
+ return {
14
+ recordTurnStart(input) {
15
+ const state = {
16
+ client: input.client,
17
+ sessionId: input.sessionId,
18
+ clientTurnId: input.clientTurnId,
19
+ cwd: input.cwd,
20
+ workspaceKind: input.workspaceKind,
21
+ transcriptPath: input.transcriptPath,
22
+ createdAt: input.createdAt,
23
+ sessionTurnIndex: input.sessionTurnIndex,
24
+ traceContext: input.traceContext,
25
+ ...(input.repositoryMemory.ok && input.repositoryMemory.memory.scope
26
+ ? { repositoryScope: input.repositoryMemory.memory.scope }
27
+ : {}),
28
+ ...(!input.repositoryMemory.ok
29
+ ? {
30
+ repositoryScopeError: input.repositoryMemory.error,
31
+ repositoryScopeReason: input.repositoryMemory.reason,
32
+ }
33
+ : {}),
34
+ };
35
+ turns.set(turnKey(state), state);
36
+ evictOldest(turns, maxEntries);
37
+ return state;
38
+ },
39
+ getTurn(key) {
40
+ return turns.get(turnKey(key));
41
+ },
42
+ latestTurn(input) {
43
+ return [...turns.values()]
44
+ .filter((turn) => (turn.client === input.client
45
+ && turn.sessionId === input.sessionId
46
+ && turn.clientTurnId !== input.excludeClientTurnId))
47
+ .sort((left, right) => right.createdAt - left.createdAt)[0];
48
+ },
49
+ discardTurn(key, reason) {
50
+ switch (reason) {
51
+ case "interrupted":
52
+ case "rolled_back":
53
+ return turns.delete(turnKey(key));
54
+ }
55
+ },
56
+ async completeMaterializedTurn(input) {
57
+ const reject = (reason) => ({
58
+ scheduled: false,
59
+ reason,
60
+ metadataDisposition: turnMetadataDisposition(turns, input, false),
61
+ });
62
+ if (input.metadata && turnKey(input.metadata) !== turnKey(input.key)) {
63
+ return reject("turn_metadata_mismatch");
64
+ }
65
+ if (input.metadata?.repositoryScopeReason || (input.metadata && !input.metadata.repositoryScope)) {
66
+ return reject(input.metadata.repositoryScopeReason ?? "workspace_scope_unavailable");
67
+ }
68
+ const current = await input.resolveRepositoryMemory();
69
+ if (!current.ok)
70
+ return reject(current.reason);
71
+ const currentScope = current.memory.scope;
72
+ if (!currentScope) {
73
+ return reject(input.metadata ? "workspace_scope_mismatch" : "workspace_scope_unavailable");
74
+ }
75
+ const repositoryScope = input.metadata?.repositoryScope ?? currentScope;
76
+ if (input.metadata?.repositoryScope
77
+ && !repositoryMemoryScopesMatch(input.metadata.repositoryScope, currentScope)) {
78
+ return reject("workspace_scope_mismatch");
79
+ }
80
+ const acceptance = options.automaticWriteback({
81
+ ...input.writeback,
82
+ userText: input.userText,
83
+ assistantText: input.assistantText,
84
+ repositoryScope,
85
+ });
86
+ if (!acceptance.accepted) {
87
+ return reject(acceptance.reason);
88
+ }
89
+ return {
90
+ scheduled: true,
91
+ metadataDisposition: turnMetadataDisposition(turns, input, true),
92
+ };
93
+ },
94
+ pruneExpired() {
95
+ cleanupExpired(turns, now(), ttlMs);
96
+ },
97
+ size(client) {
98
+ cleanupExpired(turns, now(), ttlMs);
99
+ return client === undefined
100
+ ? turns.size
101
+ : [...turns.values()].filter((turn) => turn.client === client).length;
102
+ },
103
+ close() {
104
+ clearInterval(timer);
105
+ turns.clear();
106
+ },
107
+ };
108
+ }
109
+ function turnKey(key) {
110
+ return JSON.stringify([key.client, key.sessionId, key.clientTurnId.trim()]);
111
+ }
112
+ function turnMetadataDisposition(turns, completion, consume) {
113
+ const key = turnKey(completion.key);
114
+ const current = turns.get(key);
115
+ if (!current)
116
+ return "absent";
117
+ if (!consume || !completion.metadata || current !== completion.metadata)
118
+ return "retained";
119
+ turns.delete(key);
120
+ return "consumed";
121
+ }
122
+ function cleanupExpired(turns, nowMs, ttlMs) {
123
+ for (const [key, turn] of turns.entries()) {
124
+ if (nowMs - turn.createdAt > ttlMs)
125
+ turns.delete(key);
126
+ }
127
+ }
128
+ function evictOldest(turns, maxEntries) {
129
+ while (turns.size > maxEntries) {
130
+ const oldest = turns.keys().next().value;
131
+ if (typeof oldest !== "string")
132
+ return;
133
+ turns.delete(oldest);
134
+ }
135
+ }
136
+ function positiveInteger(value, fallback) {
137
+ const parsed = Number(value);
138
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
139
+ }
@@ -0,0 +1,113 @@
1
+ import { UNCLASSIFIED_PROJECT_ID } from "./memory-project.js";
2
+ import { memoryViewerEventTurnIds } from "./memory-viewer-turn-reference.js";
3
+ export function memoryViewerActivitySummary(allEvents) {
4
+ let recalledCount = 0;
5
+ let addCount = 0;
6
+ let searchCount = 0;
7
+ for (const event of allEvents) {
8
+ if (event.type === "memory_retrieve" || event.type === "memory_cli_search") {
9
+ searchCount += 1;
10
+ recalledCount += event.itemCount ?? event.results?.length ?? 0;
11
+ }
12
+ if (event.type === "memory_cli_add" || event.type === "memory_writeback")
13
+ addCount += 1;
14
+ }
15
+ return {
16
+ activityCount: allEvents.length,
17
+ recalledCount,
18
+ addCount,
19
+ searchCount,
20
+ };
21
+ }
22
+ export function memoryViewerActivityProjection(allEvents) {
23
+ const turns = new Map();
24
+ for (const event of allEvents) {
25
+ if (!event.sessionId)
26
+ continue;
27
+ const order = timestampOrder(event.timestamp);
28
+ for (const turnId of memoryViewerEventTurnIds(event)) {
29
+ const key = `${event.client}\u0000${event.sessionId}\u0000${turnId}`;
30
+ const current = turns.get(key);
31
+ if (!current) {
32
+ turns.set(key, {
33
+ firstOrder: order,
34
+ firstTimestamp: event.timestamp,
35
+ ...(event.type === "turn_start" && Number.isFinite(order)
36
+ ? { startOrder: order, startTimestamp: event.timestamp }
37
+ : {}),
38
+ });
39
+ continue;
40
+ }
41
+ if (Number.isFinite(order)
42
+ && (!Number.isFinite(current.firstOrder) || order < current.firstOrder)) {
43
+ current.firstOrder = order;
44
+ current.firstTimestamp = event.timestamp;
45
+ }
46
+ if (event.type === "turn_start"
47
+ && Number.isFinite(order)
48
+ && (current.startOrder === undefined || order < current.startOrder)) {
49
+ current.startOrder = order;
50
+ current.startTimestamp = event.timestamp;
51
+ }
52
+ }
53
+ }
54
+ const eventActivityOrder = new Map();
55
+ const entries = new Map();
56
+ for (const event of allEvents) {
57
+ let turn;
58
+ if (event.sessionId) {
59
+ for (const turnId of memoryViewerEventTurnIds(event)) {
60
+ const candidate = turns.get(`${event.client}\u0000${event.sessionId}\u0000${turnId}`);
61
+ if (!candidate)
62
+ continue;
63
+ const candidateOrder = candidate.startOrder ?? candidate.firstOrder;
64
+ const turnOrder = turn ? turn.startOrder ?? turn.firstOrder : Number.NEGATIVE_INFINITY;
65
+ if (!turn || candidateOrder > turnOrder)
66
+ turn = candidate;
67
+ }
68
+ }
69
+ const activityOrder = turn?.startOrder ?? turn?.firstOrder ?? timestampOrder(event.timestamp);
70
+ const activityTimestamp = turn?.startTimestamp ?? turn?.firstTimestamp ?? event.timestamp;
71
+ eventActivityOrder.set(event.eventKey, activityOrder);
72
+ const projectId = event.projectId ?? UNCLASSIFIED_PROJECT_ID;
73
+ const key = `${event.client}\u0000${projectId}\u0000${event.sessionId ?? ""}`;
74
+ const current = entries.get(key);
75
+ if (!current) {
76
+ entries.set(key, {
77
+ value: {
78
+ client: event.client,
79
+ projectId,
80
+ ...(event.sessionId ? { sessionId: event.sessionId } : { unscoped: true }),
81
+ eventCount: 1,
82
+ lastSeenAt: activityTimestamp,
83
+ },
84
+ lastSeenOrder: activityOrder,
85
+ });
86
+ continue;
87
+ }
88
+ const lastSeenAt = activityOrder >= current.lastSeenOrder
89
+ ? activityTimestamp
90
+ : current.value.lastSeenAt;
91
+ entries.set(key, {
92
+ value: {
93
+ ...current.value,
94
+ eventCount: current.value.eventCount + 1,
95
+ lastSeenAt,
96
+ },
97
+ lastSeenOrder: Math.max(current.lastSeenOrder, activityOrder),
98
+ });
99
+ }
100
+ return {
101
+ eventActivityOrder,
102
+ projectSessions: [...entries.values()]
103
+ .map((entry) => entry.value)
104
+ .sort((left, right) => (left.projectId.localeCompare(right.projectId)
105
+ || left.client.localeCompare(right.client)
106
+ || timestampOrder(right.lastSeenAt) - timestampOrder(left.lastSeenAt)
107
+ || (left.sessionId ?? "").localeCompare(right.sessionId ?? ""))),
108
+ };
109
+ }
110
+ function timestampOrder(value) {
111
+ const parsed = Date.parse(value);
112
+ return Number.isFinite(parsed) ? parsed : Number.NEGATIVE_INFINITY;
113
+ }
@@ -0,0 +1,69 @@
1
+ export const MEMORY_VIEWER_DATA_PROJECTION_CAPACITY = 64;
2
+ const dataProjections = new Map();
3
+ const sharedDataProjections = new Map();
4
+ const projectionHistories = new Map();
5
+ export function prepareMemoryViewerDataProjectionHistory(projectionKey, historical) {
6
+ if (projectionHistories.get(projectionKey) === historical)
7
+ return;
8
+ dataProjections.delete(projectionKey);
9
+ sharedDataProjections.delete(projectionKey);
10
+ projectionHistories.set(projectionKey, historical);
11
+ }
12
+ export function shareMemoryViewerDataProjectionValue(projectionKey, valueKey, historical, liveVersion, create) {
13
+ let projections = sharedDataProjections.get(projectionKey);
14
+ if (!projections) {
15
+ projections = new Map();
16
+ sharedDataProjections.set(projectionKey, projections);
17
+ }
18
+ const cached = projections.get(valueKey);
19
+ if (cached && cached.historical === historical && cached.liveVersion === liveVersion)
20
+ return cached.value;
21
+ const value = create();
22
+ projections.set(valueKey, { historical, liveVersion, value });
23
+ return value;
24
+ }
25
+ export function readMemoryViewerDataProjection(projectionKey, filterKey, historical, liveVersion) {
26
+ const projections = dataProjections.get(projectionKey);
27
+ const cached = projections?.get(filterKey);
28
+ if (!cached || cached.historical !== historical || cached.liveVersion !== liveVersion)
29
+ return undefined;
30
+ projections?.delete(filterKey);
31
+ projections?.set(filterKey, cached);
32
+ return cached.data;
33
+ }
34
+ export function writeMemoryViewerDataProjection(projectionKey, filterKey, historical, liveVersion, data) {
35
+ let projections = dataProjections.get(projectionKey);
36
+ if (!projections) {
37
+ projections = new Map();
38
+ dataProjections.set(projectionKey, projections);
39
+ }
40
+ projections.set(filterKey, { historical, liveVersion, data });
41
+ while (projections.size > MEMORY_VIEWER_DATA_PROJECTION_CAPACITY) {
42
+ const oldestKey = projections.keys().next().value;
43
+ if (!oldestKey)
44
+ break;
45
+ projections.delete(oldestKey);
46
+ }
47
+ }
48
+ export function clearMemoryViewerDataProjections() {
49
+ dataProjections.clear();
50
+ sharedDataProjections.clear();
51
+ }
52
+ export function clearMemoryViewerDataProjectionCache() {
53
+ dataProjections.clear();
54
+ sharedDataProjections.clear();
55
+ projectionHistories.clear();
56
+ }
57
+ export function memoryViewerDataProjectionCacheSize(projectionKey) {
58
+ return dataProjections.get(projectionKey)?.size ?? 0;
59
+ }
60
+ export function memoryViewerSharedDataProjectionCacheSize(projectionKey) {
61
+ return sharedDataProjections.get(projectionKey)?.size ?? 0;
62
+ }
63
+ export function shouldCacheMemoryViewerDataProjection(filter, data) {
64
+ if (filter.sessionId && !data.projectSessions.some((entry) => entry.sessionId === filter.sessionId))
65
+ return false;
66
+ if (filter.projectId && data.projectFilterStatus !== "resolved")
67
+ return false;
68
+ return true;
69
+ }
@@ -0,0 +1,3 @@
1
+ export function memoryViewerEventKey(event) {
2
+ return JSON.stringify([event.client ?? "codex", event.sessionId ?? "", event.id]);
3
+ }
@@ -0,0 +1,79 @@
1
+ import { memoryViewerEventKey } from "./memory-viewer-event-identity.js";
2
+ /**
3
+ * Marks a retained start without an end as interrupted only when a different
4
+ * Turn demonstrably started later in the same client session.
5
+ *
6
+ * This is a Viewer-only projection. It does not synthesize a trace event or
7
+ * change transcript and writeback authority.
8
+ */
9
+ export function foldMemoryViewerSupersededTurnStarts(allEvents) {
10
+ const endedTurns = new Set();
11
+ const startsBySession = new Map();
12
+ for (const event of allEvents) {
13
+ if (!event.sessionId || !event.turnId)
14
+ continue;
15
+ const turnKey = viewerTurnKey(event);
16
+ if (event.type === "turn_end") {
17
+ endedTurns.add(turnKey);
18
+ continue;
19
+ }
20
+ if (event.type !== "turn_start")
21
+ continue;
22
+ const startedAt = Date.parse(event.timestamp);
23
+ if (!Number.isFinite(startedAt))
24
+ continue;
25
+ const sessionKey = JSON.stringify([event.client, event.sessionId]);
26
+ const starts = startsBySession.get(sessionKey) ?? new Map();
27
+ const current = starts.get(turnKey);
28
+ if (current === undefined || startedAt < current)
29
+ starts.set(turnKey, startedAt);
30
+ startsBySession.set(sessionKey, starts);
31
+ }
32
+ const interruptedTurns = new Set();
33
+ for (const starts of startsBySession.values()) {
34
+ const latestStartedAt = Math.max(...starts.values());
35
+ for (const [turnKey, startedAt] of starts) {
36
+ if (!endedTurns.has(turnKey) && startedAt < latestStartedAt) {
37
+ interruptedTurns.add(turnKey);
38
+ }
39
+ }
40
+ }
41
+ if (interruptedTurns.size === 0)
42
+ return [...allEvents];
43
+ return allEvents.map((event) => (event.type === "turn_start"
44
+ && !event.turnOutcome
45
+ && interruptedTurns.has(viewerTurnKey(event))
46
+ ? { ...event, turnOutcome: "interrupted" }
47
+ : event));
48
+ }
49
+ export function foldMemoryViewerTurnMaterializations(allEvents) {
50
+ const byOriginalEventKey = new Map();
51
+ for (const event of allEvents) {
52
+ if (event.type === "turn_materialized" && event.originalEventId) {
53
+ byOriginalEventKey.set(memoryViewerEventKey({
54
+ id: event.originalEventId,
55
+ client: event.client,
56
+ ...(event.sessionId ? { sessionId: event.sessionId } : {}),
57
+ }), event);
58
+ }
59
+ }
60
+ return allEvents
61
+ .filter((event) => event.type !== "turn_materialized")
62
+ .map((event) => {
63
+ if (event.type !== "turn_end")
64
+ return event;
65
+ const materialized = byOriginalEventKey.get(event.eventKey);
66
+ if (!materialized)
67
+ return event;
68
+ const answer = materialized.answer ?? event.answer;
69
+ return {
70
+ ...event,
71
+ ...(materialized.turnOutcome ? { turnOutcome: materialized.turnOutcome } : {}),
72
+ ...(answer ? { answer, content: answer } : {}),
73
+ ...(materialized.details === undefined ? {} : { details: materialized.details }),
74
+ };
75
+ });
76
+ }
77
+ function viewerTurnKey(event) {
78
+ return JSON.stringify([event.client, event.sessionId, event.turnId]);
79
+ }
@@ -0,0 +1 @@
1
+ export const MEMORAX_LOGO_DATA_URL = "data:image/png;base64,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";
@@ -0,0 +1,8 @@
1
+ import { recordMemoryViewerEvent } from "./memory-viewer-store.js";
2
+ export function memoryViewerObservabilityHook() {
3
+ return {
4
+ recordEvent(event) {
5
+ recordMemoryViewerEvent(event);
6
+ },
7
+ };
8
+ }
@@ -0,0 +1,52 @@
1
+ export function sanitizeMemoryViewerDetails(value, depth = 0) {
2
+ if (depth > 5)
3
+ return "[truncated]";
4
+ if (typeof value === "string")
5
+ return redactViewerPaths(value.slice(0, 12_000));
6
+ if (value === null || typeof value !== "object")
7
+ return value;
8
+ if (Array.isArray(value)) {
9
+ return value.slice(0, 50).map((item) => sanitizeMemoryViewerDetails(item, depth + 1));
10
+ }
11
+ const output = {};
12
+ for (const [key, item] of Object.entries(value)) {
13
+ if (/authorization|api[-_]?key|token|secret/i.test(key))
14
+ continue;
15
+ if (key.toLowerCase() === "route"
16
+ && typeof item === "string"
17
+ && /^\/api(?:\/[^/\s?#]+)*\/?$/.test(item)) {
18
+ output[key] = item;
19
+ continue;
20
+ }
21
+ if (viewerPathLikeKey(key)) {
22
+ output[key] = "[REDACTED]";
23
+ continue;
24
+ }
25
+ output[key] = sanitizeMemoryViewerDetails(item, depth + 1);
26
+ }
27
+ return output;
28
+ }
29
+ function viewerPathLikeKey(key) {
30
+ const normalized = key.replace(/[^a-z0-9]/gi, "").toLowerCase();
31
+ return normalized === "cwd"
32
+ || normalized === "path"
33
+ || normalized.endsWith("path")
34
+ || normalized === "root"
35
+ || normalized.endsWith("root")
36
+ || normalized === "workspace"
37
+ || normalized === "workingdirectory";
38
+ }
39
+ export function redactViewerPaths(value) {
40
+ return value
41
+ .split(/(\bhttps?:\/\/[^\s)'"`]+)/gi)
42
+ .map((segment) => {
43
+ if (/^https?:\/\//i.test(segment))
44
+ return segment;
45
+ return segment
46
+ .replace(/\bfile:\/\/[^\s)'"`]+/gi, "[REDACTED]")
47
+ .replace(/(^|[\s('"`])\\\\[^\\/\s)'"`]+[\\/][^\s)'"`]+/g, "$1[REDACTED]")
48
+ .replace(/\b[A-Za-z]:[\\/][^\s)'"`]+/g, "[REDACTED]")
49
+ .replace(/(^|[\s('"`])\/(?!\/)[^\s)'"`]+/g, "$1[REDACTED]");
50
+ })
51
+ .join("");
52
+ }