@memorax/memorax-code 0.1.1 → 0.1.3

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 (246) hide show
  1. package/README.md +16 -12
  2. package/bin/memorax-code-npm-preinstall.mjs +7 -2
  3. package/bin/memorax-code-opencode.mjs +4 -0
  4. package/bin/memorax-code-plugin-postinstall.mjs +424 -108
  5. package/docs/configuration.md +153 -29
  6. package/docs/troubleshooting.md +93 -7
  7. package/lib/dsh-plugin-install.mjs +22 -0
  8. package/lib/memorax-code-adapter-common/src/hooks/capture-cwd-hook.mjs +21 -14
  9. package/lib/memorax-code-adapter-common/src/hooks/ensure-backend-runner.mjs +26 -7
  10. package/lib/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +86 -95
  11. package/lib/memorax-code-adapter-common/src/hooks/memory-skill-reminder-policy.mjs +58 -0
  12. package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-auto-build.mjs +38 -0
  13. package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-job-supervisor.mjs +1 -1
  14. package/lib/memorax-code-adapter-common/src/windows-cli-invocation.mjs +13 -1
  15. package/lib/memorax-code-backend/dist/app/backend-server.js +210 -0
  16. package/lib/memorax-code-backend/dist/{server-observability.js → app/memory-observability.js} +4 -4
  17. package/lib/memorax-code-backend/dist/{backend-state.js → app/state.js} +1 -1
  18. package/lib/memorax-code-backend/dist/{claude-adapter-lifecycle.js → clients/claude/lifecycle.js} +2 -2
  19. package/lib/memorax-code-backend/dist/{claude-memory-hook-runtime.js → clients/claude/memory-hook-runtime.js} +16 -9
  20. package/lib/memorax-code-backend/dist/clients/codex/lifecycle.js +131 -0
  21. package/lib/memorax-code-backend/dist/{codex-memory-hook-runtime.js → clients/codex/memory-hook-runtime.js} +18 -11
  22. package/lib/memorax-code-backend/dist/{codex-plugin-hooks.js → clients/codex/plugin-hooks.js} +1 -1
  23. package/lib/memorax-code-backend/dist/{codex-plugin-install.js → clients/codex/plugin-install.js} +6 -6
  24. package/lib/memorax-code-backend/dist/clients/dsh/lifecycle.js +75 -0
  25. package/lib/memorax-code-backend/dist/clients/dsh/memory-hook-runtime.js +258 -0
  26. package/lib/memorax-code-backend/dist/clients/dsh/session-turn.js +249 -0
  27. package/lib/memorax-code-backend/dist/clients/opencode/lifecycle.js +54 -0
  28. package/lib/memorax-code-backend/dist/clients/opencode/memory-hook-runtime.js +277 -0
  29. package/lib/memorax-code-backend/dist/clients/opencode/message-turn.js +78 -0
  30. package/lib/memorax-code-backend/dist/codex-adapter-lifecycle.js +1 -131
  31. package/lib/memorax-code-backend/dist/{memorax-code-config.js → config/memorax-code.js} +32 -4
  32. package/lib/memorax-code-backend/dist/{server-cli.js → entrypoints/backend-cli.js} +157 -34
  33. package/lib/memorax-code-backend/dist/jsonl-append.js +1 -75
  34. package/lib/memorax-code-backend/dist/{active-client-selection.js → lifecycle/active-clients.js} +12 -1
  35. package/lib/memorax-code-backend/dist/{backend-service-cleanup.js → lifecycle/backend/cleanup.js} +1 -1
  36. package/lib/memorax-code-backend/dist/{backend-service-record.js → lifecycle/backend/record.js} +1 -1
  37. package/lib/memorax-code-backend/dist/{backend-service-result.js → lifecycle/backend/result.js} +2 -2
  38. package/lib/memorax-code-backend/dist/{service.js → lifecycle/backend/service.js} +16 -16
  39. package/lib/memorax-code-backend/dist/{backend-token-record.js → lifecycle/backend/token-record.js} +1 -1
  40. package/lib/memorax-code-backend/dist/{backend-service-token.js → lifecycle/backend/token.js} +2 -2
  41. package/lib/memorax-code-backend/dist/lifecycle/client-plugin-removal.js +109 -0
  42. package/lib/memorax-code-backend/dist/{client-selection.js → lifecycle/client-selection.js} +11 -5
  43. package/lib/memorax-code-backend/dist/{backend-lifecycle-lock.js → lifecycle/lock.js} +1 -1
  44. package/lib/memorax-code-backend/dist/{memorax-code-lifecycle.js → lifecycle/orchestrator.js} +325 -39
  45. package/lib/memorax-code-backend/dist/memorax-cli.js +3 -1
  46. package/lib/memorax-code-backend/dist/memorax-code.js +1 -1
  47. package/lib/memorax-code-backend/dist/{automatic-memory-retrieval.js → memory/automatic-retrieval.js} +3 -3
  48. package/lib/memorax-code-backend/dist/{automatic-memory-writeback.js → memory/automatic-writeback.js} +82 -21
  49. package/lib/memorax-code-backend/dist/{memory-cli.js → memory/cli.js} +45 -10
  50. package/lib/memorax-code-backend/dist/{memory-hook-command.js → memory/hook-command.js} +156 -9
  51. package/lib/memorax-code-backend/dist/memory/observability.js +1 -0
  52. package/lib/memorax-code-backend/dist/memory/payload-redaction.js +212 -0
  53. package/lib/memorax-code-backend/dist/{memory-reminder-trace-recorder.js → memory/reminder-trace-recorder.js} +20 -7
  54. package/lib/memorax-code-backend/dist/{repository-memory-context.js → memory/repository-session.js} +25 -4
  55. package/lib/memorax-code-backend/dist/{memory-service.js → memory/service.js} +30 -6
  56. package/lib/memorax-code-backend/dist/{memory-turn-coordinator.js → memory/turn-coordinator.js} +7 -3
  57. package/lib/memorax-code-backend/dist/{memory-writeback-buffer.js → memory/writeback-buffer.js} +31 -2
  58. package/lib/memorax-code-backend/dist/{memory-writeback-chunk.js → memory/writeback-chunk.js} +1 -1
  59. package/lib/memorax-code-backend/dist/{memory-writeback-reconciler.js → memory/writeback-reconciler.js} +6 -6
  60. package/lib/memorax-code-backend/dist/{memory-writeback-task-projection.js → memory/writeback-task-projection.js} +4 -4
  61. package/lib/memorax-code-backend/dist/{memorax-adapter.js → provider/memorax/adapter.js} +5 -5
  62. package/lib/memorax-code-backend/dist/{memorax-config.js → provider/memorax/config.js} +4 -4
  63. package/lib/memorax-code-backend/dist/{memorax-http.js → provider/memorax/http.js} +1 -1
  64. package/lib/memorax-code-backend/dist/{repo-memory-readiness.js → repository/readiness.js} +3 -3
  65. package/lib/memorax-code-backend/dist/{repository-memory-scope.js → repository/scope.js} +81 -33
  66. package/lib/memorax-code-backend/dist/server.js +3 -212
  67. package/lib/memorax-code-backend/dist/service-entrypoint.js +1 -1
  68. package/lib/memorax-code-backend/dist/{debug-log.js → shared/debug-log.js} +1 -1
  69. package/lib/memorax-code-backend/dist/shared/jsonl-append.js +75 -0
  70. package/lib/memorax-code-backend/dist/shared/windows-cli-invocation.js +148 -0
  71. package/lib/memorax-code-backend/dist/{trace-config.js → trace/config.js} +43 -5
  72. package/lib/memorax-code-backend/dist/{trace-context.js → trace/context.js} +53 -2
  73. package/lib/memorax-code-backend/dist/{trace-store.js → trace/store.js} +3 -3
  74. package/lib/memorax-code-backend/dist/{server-health.js → transport/http/health.js} +1 -1
  75. package/lib/memorax-code-backend/dist/{server-memory-hook.js → transport/http/memory-hook.js} +3 -3
  76. package/lib/memorax-code-backend/dist/{server-http.js → transport/http/request.js} +1 -1
  77. package/lib/memorax-code-backend/dist/{claude-local-transcript.js → viewer/history/claude-transcript.js} +3 -3
  78. package/lib/memorax-code-backend/dist/{memory-viewer-session-title.js → viewer/history/session-title.js} +1 -1
  79. package/lib/memorax-code-backend/dist/{server-memory-viewer.js → viewer/http/public-routes.js} +25 -14
  80. package/lib/memorax-code-backend/dist/viewer/model.js +1 -0
  81. package/lib/memorax-code-backend/dist/{memory-viewer-activity.js → viewer/projection/activity.js} +2 -2
  82. package/lib/memorax-code-backend/dist/{memory-viewer-history-projection.js → viewer/projection/history.js} +1 -1
  83. package/lib/memorax-code-backend/dist/{memory-viewer-observability.js → viewer/projection/observability.js} +1 -1
  84. package/lib/memorax-code-backend/dist/{memory-viewer-user-projection.js → viewer/projection/user.js} +1 -1
  85. package/lib/memorax-code-backend/dist/{memory-viewer-writeback-status.js → viewer/projection/writeback-status.js} +1 -1
  86. package/lib/memorax-code-backend/dist/{memory-viewer-store.js → viewer/store.js} +59 -32
  87. package/lib/memorax-code-backend/dist/viewer/ui/icon.js +1 -0
  88. package/lib/memorax-code-backend/dist/{memory-viewer-user-html.js → viewer/ui/user-html.js} +14 -12
  89. package/lib/memorax-code-backend/dist/windows-cli-invocation.js +1 -148
  90. package/lib/memorax-code-backend/package.json +3 -3
  91. package/lib/memorax-code-claude-adapter/.claude-plugin/plugin.json +1 -1
  92. package/lib/memorax-code-claude-adapter/hooks/runtime-shell.json +1 -1
  93. package/lib/memorax-code-claude-adapter/package.json +1 -1
  94. package/lib/memorax-code-claude-adapter/runtime-hooks/memory-turn.mjs +5 -0
  95. package/lib/memorax-code-claude-adapter/skills/memorax-code/SKILL.md +23 -15
  96. package/lib/memorax-code-claude-adapter/skills/memorax-code/defaults.json +8 -5
  97. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +5 -1
  98. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +40 -10
  99. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/personal-read.md +1 -1
  100. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/personal-write.md +33 -13
  101. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-build.md +62 -13
  102. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-read.md +11 -4
  103. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-templates.md +179 -59
  104. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-update.md +18 -7
  105. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/collect_all.py +122 -39
  106. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/detect_updates.py +73 -10
  107. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/github_resource_facets.py +9 -1
  108. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +9 -1
  109. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/validate_memory.py +23 -1
  110. package/lib/memorax-code-claude-adapter/src/plugin-install.mjs +2 -0
  111. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/.claude-plugin/plugin.json +1 -1
  112. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/runtime-shell.json +1 -1
  113. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/capture-cwd-hook.mjs +21 -14
  114. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/ensure-backend-runner.mjs +26 -7
  115. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +86 -95
  116. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/memory-skill-reminder-policy.mjs +58 -0
  117. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-auto-build.mjs +38 -0
  118. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-job-supervisor.mjs +1 -1
  119. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/windows-cli-invocation.mjs +13 -1
  120. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/package.json +1 -1
  121. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/memory-turn.mjs +5 -0
  122. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/SKILL.md +23 -15
  123. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/defaults.json +8 -5
  124. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +5 -1
  125. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +40 -10
  126. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/personal-read.md +1 -1
  127. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/personal-write.md +33 -13
  128. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-build.md +62 -13
  129. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-read.md +11 -4
  130. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-templates.md +179 -59
  131. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-update.md +18 -7
  132. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/collect_all.py +122 -39
  133. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/detect_updates.py +73 -10
  134. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/github_resource_facets.py +9 -1
  135. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +9 -1
  136. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/validate_memory.py +23 -1
  137. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/plugin-install.mjs +2 -0
  138. package/lib/memorax-code-codex-adapter/.codex-plugin/plugin.json +1 -1
  139. package/lib/memorax-code-codex-adapter/hooks/runtime-shell.json +1 -1
  140. package/lib/memorax-code-codex-adapter/package.json +1 -1
  141. package/lib/memorax-code-codex-adapter/runtime-hooks/memory-skill-reminder.mjs +16 -2
  142. package/lib/memorax-code-codex-adapter/skills/memorax-code/SKILL.md +23 -15
  143. package/lib/memorax-code-codex-adapter/skills/memorax-code/defaults.json +8 -5
  144. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-add.md +5 -1
  145. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-search.md +40 -10
  146. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/personal-read.md +1 -1
  147. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/personal-write.md +33 -13
  148. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-build.md +62 -13
  149. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-read.md +11 -4
  150. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-templates.md +179 -59
  151. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-update.md +18 -7
  152. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/collect_all.py +122 -39
  153. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/detect_updates.py +73 -10
  154. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/github_resource_facets.py +9 -1
  155. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +9 -1
  156. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/validate_memory.py +23 -1
  157. package/lib/memorax-code-dsh-adapter/cordis.patch.yml +10 -0
  158. package/lib/memorax-code-dsh-adapter/hooks/repo-memory-job.mjs +68 -0
  159. package/lib/memorax-code-dsh-adapter/package.json +69 -0
  160. package/lib/memorax-code-dsh-adapter/skills/memorax-code/SKILL.md +91 -0
  161. package/lib/memorax-code-dsh-adapter/skills/memorax-code/agents/claude.yaml +10 -0
  162. package/lib/memorax-code-dsh-adapter/skills/memorax-code/agents/openai.yaml +7 -0
  163. package/lib/memorax-code-dsh-adapter/skills/memorax-code/defaults.json +12 -0
  164. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/memorax-add.md +86 -0
  165. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/memorax-search.md +91 -0
  166. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/personal-read.md +46 -0
  167. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/personal-write.md +120 -0
  168. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-build.md +319 -0
  169. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-read.md +103 -0
  170. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-templates.md +390 -0
  171. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-update.md +127 -0
  172. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/collect_all.py +579 -0
  173. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/detect_updates.py +919 -0
  174. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
  175. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/github_resource_facets.py +512 -0
  176. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +517 -0
  177. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
  178. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
  179. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/validate_memory.py +248 -0
  180. package/lib/memorax-code-dsh-adapter/src/backend-client.mjs +119 -0
  181. package/lib/memorax-code-dsh-adapter/src/dsh-message.mjs +32 -0
  182. package/lib/memorax-code-dsh-adapter/src/dsh-version.mjs +18 -0
  183. package/lib/memorax-code-dsh-adapter/src/http-client.mjs +55 -0
  184. package/lib/memorax-code-dsh-adapter/src/index.mjs +72 -0
  185. package/lib/memorax-code-dsh-adapter/src/personal-context-worker.mjs +48 -0
  186. package/lib/memorax-code-dsh-adapter/src/personal-context.mjs +114 -0
  187. package/lib/memorax-code-dsh-adapter/src/plugin.mjs +724 -0
  188. package/lib/memorax-code-dsh-adapter/src/profile-lifecycle.mjs +1289 -0
  189. package/lib/memorax-code-dsh-adapter/src/protocol.mjs +145 -0
  190. package/lib/memorax-code-dsh-adapter/src/runtime-state.mjs +132 -0
  191. package/lib/memorax-code-opencode-adapter/hooks/repo-memory-job.mjs +37 -0
  192. package/lib/memorax-code-opencode-adapter/package.json +10 -0
  193. package/lib/memorax-code-opencode-adapter/skills/memorax-code/SKILL.md +91 -0
  194. package/lib/memorax-code-opencode-adapter/skills/memorax-code/agents/claude.yaml +10 -0
  195. package/lib/memorax-code-opencode-adapter/skills/memorax-code/agents/openai.yaml +7 -0
  196. package/lib/memorax-code-opencode-adapter/skills/memorax-code/defaults.json +12 -0
  197. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/memorax-add.md +86 -0
  198. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/memorax-search.md +91 -0
  199. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/personal-read.md +46 -0
  200. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/personal-write.md +120 -0
  201. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-build.md +319 -0
  202. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-read.md +103 -0
  203. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-templates.md +390 -0
  204. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-update.md +127 -0
  205. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/collect_all.py +579 -0
  206. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/detect_updates.py +919 -0
  207. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
  208. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/github_resource_facets.py +512 -0
  209. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +517 -0
  210. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
  211. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
  212. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/validate_memory.py +248 -0
  213. package/lib/memorax-code-opencode-adapter/src/adapter-paths.mjs +37 -0
  214. package/lib/memorax-code-opencode-adapter/src/cli.mjs +260 -0
  215. package/lib/memorax-code-opencode-adapter/src/diagnostics.mjs +31 -0
  216. package/lib/memorax-code-opencode-adapter/src/plugin-install.mjs +673 -0
  217. package/lib/memorax-code-opencode-adapter/src/plugin.mjs +536 -0
  218. package/lib/memorax-code-opencode-adapter/src/repo-memory-server-runner.mjs +207 -0
  219. package/lib/resolve-claude-command.mjs +154 -1
  220. package/lib/resolve-codex-command.mjs +56 -1
  221. package/lib/run-entrypoint.mjs +6 -0
  222. package/package.json +7 -3
  223. package/lib/memorax-code-backend/dist/client-plugin-removal.js +0 -67
  224. /package/lib/memorax-code-backend/dist/{claude-transcript-turn.js → clients/claude/transcript-turn.js} +0 -0
  225. /package/lib/memorax-code-backend/dist/{codex-effective-prompt.js → clients/codex/effective-prompt.js} +0 -0
  226. /package/lib/memorax-code-backend/dist/{codex-rollout-turn.js → clients/codex/rollout-turn.js} +0 -0
  227. /package/lib/memorax-code-backend/dist/{codex-session-turn-index.js → clients/codex/session-turn-index.js} +0 -0
  228. /package/lib/memorax-code-backend/dist/{codex-workspace-links.js → clients/codex/workspace-links.js} +0 -0
  229. /package/lib/memorax-code-backend/dist/{backend-env.js → config/backend-env.js} +0 -0
  230. /package/lib/memorax-code-backend/dist/{proxy-env.js → config/proxy-env.js} +0 -0
  231. /package/lib/memorax-code-backend/dist/{entrypoint.js → entrypoints/main.js} +0 -0
  232. /package/lib/memorax-code-backend/dist/{backend-process.js → lifecycle/backend/process.js} +0 -0
  233. /package/lib/memorax-code-backend/dist/{backend-shutdown-request.js → lifecycle/backend/shutdown-request.js} +0 -0
  234. /package/lib/memorax-code-backend/dist/{backend-status.js → lifecycle/backend/status.js} +0 -0
  235. /package/lib/memorax-code-backend/dist/{adapter-lifecycle-participant.js → lifecycle/contracts.js} +0 -0
  236. /package/lib/memorax-code-backend/dist/{install-watchdog.js → lifecycle/install-watchdog.js} +0 -0
  237. /package/lib/memorax-code-backend/dist/{memory-observability.js → lifecycle/participant.js} +0 -0
  238. /package/lib/memorax-code-backend/dist/{memory-project.js → memory/project.js} +0 -0
  239. /package/lib/memorax-code-backend/dist/{incremental-jsonl-projection.js → shared/incremental-jsonl-projection.js} +0 -0
  240. /package/lib/memorax-code-backend/dist/{utils.js → shared/record.js} +0 -0
  241. /package/lib/memorax-code-backend/dist/{server-json.js → transport/http/json.js} +0 -0
  242. /package/lib/memorax-code-backend/dist/{memory-viewer-data-projection-cache.js → viewer/projection/cache.js} +0 -0
  243. /package/lib/memorax-code-backend/dist/{memory-viewer-event-identity.js → viewer/projection/event-identity.js} +0 -0
  244. /package/lib/memorax-code-backend/dist/{memory-viewer-redaction.js → viewer/projection/redaction.js} +0 -0
  245. /package/lib/memorax-code-backend/dist/{memory-viewer-turn-reference.js → viewer/projection/turn-reference.js} +0 -0
  246. /package/lib/memorax-code-backend/dist/{memory-viewer-logo.js → viewer/ui/logo.js} +0 -0
@@ -1,8 +1,9 @@
1
1
  import { createHash } from "node:crypto";
2
- import { createMemoryWritebackBufferRuntime, } from "./memory-writeback-buffer.js";
3
- import { memoryWritebackAddParts, } from "./memory-writeback-chunk.js";
4
- import { invokeMemoraxMemoryProvider, } from "./memorax-adapter.js";
5
- import { memoryWritebackBufferEnabled, memoryWritebackEnabled, memoryWritebackMaxMessageChars, } from "./memorax-config.js";
2
+ import { createMemoryWritebackBufferRuntime, } from "./writeback-buffer.js";
3
+ import { memoryWritebackAddParts, } from "./writeback-chunk.js";
4
+ import { invokeMemoraxMemoryProvider, } from "../provider/memorax/adapter.js";
5
+ import { memoryWritebackBufferEnabled, memoryWritebackEnabled, memoryWritebackMaxMessageChars, } from "../provider/memorax/config.js";
6
+ import { hasMeaningfulMemoryPayloadText, redactMemoryPayloadText, } from "./payload-redaction.js";
6
7
  const WRITEBACK_DEDUPE_TTL_MS = 5 * 60 * 1000;
7
8
  const WRITEBACK_DEDUPE_MAX = 1024;
8
9
  const AUTOMATIC_MEMORY_WRITEBACK_MAX_ATTEMPTS = 2;
@@ -20,6 +21,13 @@ export function createAutomaticMemoryWritebackRuntime(options = {}) {
20
21
  enqueue(options) {
21
22
  return enqueueAutomaticMemoryWritebackForRuntime(state, options);
22
23
  },
24
+ discardForScopeUpgrade(upgrade) {
25
+ return state.writebackBuffer.discardForScopeUpgrade({
26
+ client: upgrade.client,
27
+ sessionKey: upgrade.sessionId,
28
+ currentScope: upgrade.currentScope,
29
+ });
30
+ },
23
31
  drain() {
24
32
  if (state.drainPromise)
25
33
  return state.drainPromise;
@@ -40,7 +48,7 @@ function enqueueAutomaticMemoryWritebackForRuntime(state, options) {
40
48
  state.diagnosticLogger("memory.automatic_writeback", {
41
49
  scheduled: false,
42
50
  skipReason: "runtime_closed",
43
- sessionKey: options.sessionKey,
51
+ sessionKeyHash: hashOptionalText(options.sessionKey),
44
52
  });
45
53
  return { accepted: false, reason: "runtime_closed" };
46
54
  }
@@ -50,7 +58,7 @@ function enqueueAutomaticMemoryWritebackForRuntime(state, options) {
50
58
  state.diagnosticLogger("memory.automatic_writeback", {
51
59
  scheduled: false,
52
60
  skipReason: decision.skipReason,
53
- sessionKey: options.sessionKey,
61
+ sessionKeyHash: hashOptionalText(options.sessionKey),
54
62
  });
55
63
  return decision.skipReason === "duplicate_pending"
56
64
  ? { accepted: true }
@@ -58,7 +66,7 @@ function enqueueAutomaticMemoryWritebackForRuntime(state, options) {
58
66
  }
59
67
  if (memoryWritebackBufferEnabled(options.env ?? process.env)) {
60
68
  state.writebackBuffer.enqueue(decision, options, {
61
- debug: state.diagnosticLogger,
69
+ debug: redactAutomaticMemoryWritebackDiagnosticIdentifiers(state.diagnosticLogger),
62
70
  flush: (bufferedDecision, bufferedOptions) => flushAutomaticMemoryWritebackBuffer(state, bufferedDecision, bufferedOptions),
63
71
  hasPendingWriteback: (idempotencyKey) => hasPendingWriteback(state, idempotencyKey),
64
72
  reservePendingWritebacks: (idempotencyKeys) => reservePendingWritebacks(state, idempotencyKeys),
@@ -69,8 +77,8 @@ function enqueueAutomaticMemoryWritebackForRuntime(state, options) {
69
77
  reservePendingWriteback(state, decision.idempotencyKey);
70
78
  state.diagnosticLogger("memory.automatic_writeback", {
71
79
  scheduled: true,
72
- sessionKey: options.sessionKey,
73
- idempotencyKey: decision.idempotencyKey,
80
+ sessionKeyHash: hashText(decision.sessionKey),
81
+ idempotencyKeyHash: hashText(decision.idempotencyKey),
74
82
  messageCount: decision.messages.length,
75
83
  userChars: decision.messages[0]?.content.length ?? 0,
76
84
  assistantChars: decision.messages[1]?.content.length ?? 0,
@@ -82,12 +90,23 @@ function enqueueAutomaticMemoryWritebackForRuntime(state, options) {
82
90
  state.diagnosticLogger("memory.automatic_writeback", {
83
91
  scheduled: false,
84
92
  skipReason: "decision_error",
85
- sessionKey: options.sessionKey,
93
+ sessionKeyHash: hashOptionalText(options.sessionKey),
86
94
  error: error instanceof Error ? error.message : String(error),
87
95
  });
88
96
  return { accepted: false, reason: "decision_error" };
89
97
  }
90
98
  }
99
+ function redactAutomaticMemoryWritebackDiagnosticIdentifiers(diagnosticLogger) {
100
+ return (message, fields = {}) => {
101
+ const { sessionKey, idempotencyKey, parentIdempotencyKey, ...rest } = fields;
102
+ diagnosticLogger(message, {
103
+ ...rest,
104
+ ...(typeof sessionKey === "string" ? { sessionKeyHash: hashText(sessionKey) } : {}),
105
+ ...(typeof idempotencyKey === "string" ? { idempotencyKeyHash: hashText(idempotencyKey) } : {}),
106
+ ...(typeof parentIdempotencyKey === "string" ? { parentIdempotencyKeyHash: hashText(parentIdempotencyKey) } : {}),
107
+ });
108
+ };
109
+ }
91
110
  function automaticMemoryWritebackDecision(state, options) {
92
111
  const env = options.env ?? process.env;
93
112
  if (!memoryWritebackEnabled(env))
@@ -103,17 +122,35 @@ function automaticMemoryWritebackDecision(state, options) {
103
122
  }
104
123
  const sessionKey = options.sessionKey.trim();
105
124
  const maxMessageChars = memoryWritebackMaxMessageChars(env);
106
- const userText = limitMessageContent(options.userText?.trim() ?? "", maxMessageChars, {
125
+ const rawUserText = options.userText?.trim() ?? "";
126
+ const rawAssistantText = options.assistantText?.trim() ?? "";
127
+ if (!rawUserText)
128
+ return { write: false, skipReason: "user_prompt_empty" };
129
+ if (!rawAssistantText)
130
+ return { write: false, skipReason: "assistant_text_empty" };
131
+ const boundedUserText = limitMessageContent(rawUserText, maxMessageChars, {
132
+ role: "user",
133
+ sessionKey,
134
+ }, state.diagnosticLogger);
135
+ const boundedAssistantText = limitMessageContent(rawAssistantText, maxMessageChars, {
136
+ role: "assistant",
137
+ sessionKey,
138
+ }, state.diagnosticLogger);
139
+ const userRedaction = redactMemoryPayloadText(boundedUserText);
140
+ const assistantRedaction = redactMemoryPayloadText(boundedAssistantText);
141
+ logAutomaticMemoryPayloadRedaction(state, sessionKey, "user", rawUserText, userRedaction);
142
+ logAutomaticMemoryPayloadRedaction(state, sessionKey, "assistant", rawAssistantText, assistantRedaction);
143
+ const userText = limitMessageContent(userRedaction.text, maxMessageChars, {
107
144
  role: "user",
108
145
  sessionKey,
109
146
  }, state.diagnosticLogger);
110
- const assistantText = limitMessageContent(options.assistantText?.trim() ?? "", maxMessageChars, {
147
+ const assistantText = limitMessageContent(assistantRedaction.text, maxMessageChars, {
111
148
  role: "assistant",
112
149
  sessionKey,
113
150
  }, state.diagnosticLogger);
114
- if (!userText)
151
+ if (!hasMeaningfulMemoryPayloadText(userText))
115
152
  return { write: false, skipReason: "user_prompt_empty" };
116
- if (!assistantText)
153
+ if (!hasMeaningfulMemoryPayloadText(assistantText))
117
154
  return { write: false, skipReason: "assistant_text_empty" };
118
155
  const idempotencyKey = `automatic:${options.client}:${hashText(options.repositoryScope.effectiveUserId)}:${sessionKey}:${hashText(userText)}:${hashText(assistantText)}`;
119
156
  if (hasPendingWriteback(state, idempotencyKey))
@@ -129,8 +166,26 @@ function automaticMemoryWritebackDecision(state, options) {
129
166
  ],
130
167
  };
131
168
  }
169
+ function logAutomaticMemoryPayloadRedaction(state, sessionKey, role, originalText, result) {
170
+ if (!result.redacted)
171
+ return;
172
+ state.diagnosticLogger("memory.automatic_writeback.redacted", {
173
+ sessionKeyHash: hashText(sessionKey),
174
+ role,
175
+ originalChars: originalText.length,
176
+ redactedChars: result.text.length,
177
+ counts: result.counts,
178
+ });
179
+ }
132
180
  async function enqueueAutomaticMemoryWritebackAsync(state, decision, options) {
133
181
  try {
182
+ if (decision.messages.some((message) => redactMemoryPayloadText(message.content).redacted)) {
183
+ state.diagnosticLogger("memory.writeback.redaction_rejected", {
184
+ source: options.memoryObservabilitySource ?? "automatic_writeback",
185
+ messageCount: decision.messages.length,
186
+ });
187
+ throw new Error("automatic writeback content must be redacted before provider dispatch");
188
+ }
134
189
  const parts = memoryWritebackAddParts(decision, options.env ?? process.env);
135
190
  for (const [index, part] of parts.entries()) {
136
191
  for (let attempt = 1; attempt <= AUTOMATIC_MEMORY_WRITEBACK_MAX_ATTEMPTS; attempt += 1) {
@@ -172,9 +227,9 @@ async function enqueueAutomaticMemoryWritebackAsync(state, decision, options) {
172
227
  state.diagnosticLogger("memory.automatic_writeback", {
173
228
  scheduled: true,
174
229
  accepted: response.ok,
175
- sessionKey: decision.sessionKey,
176
- idempotencyKey: part.idempotencyKey,
177
- parentIdempotencyKey: part.idempotencyKey === decision.idempotencyKey ? undefined : decision.idempotencyKey,
230
+ sessionKeyHash: hashText(decision.sessionKey),
231
+ idempotencyKeyHash: hashText(part.idempotencyKey),
232
+ parentIdempotencyKeyHash: part.idempotencyKey === decision.idempotencyKey ? undefined : hashText(decision.idempotencyKey),
178
233
  flushReason: decision.flushReason,
179
234
  turnCount: decision.turnCount,
180
235
  partIndex: parts.length > 1 ? index : undefined,
@@ -203,8 +258,8 @@ async function enqueueAutomaticMemoryWritebackAsync(state, decision, options) {
203
258
  state.diagnosticLogger("memory.automatic_writeback", {
204
259
  scheduled: true,
205
260
  accepted: false,
206
- sessionKey: decision.sessionKey,
207
- idempotencyKey: decision.idempotencyKey,
261
+ sessionKeyHash: hashText(decision.sessionKey),
262
+ idempotencyKeyHash: hashText(decision.idempotencyKey),
208
263
  flushReason: decision.flushReason,
209
264
  turnCount: decision.turnCount,
210
265
  error: error instanceof Error ? error.message : String(error),
@@ -264,9 +319,12 @@ function prunePendingWritebacks(state, now = Date.now()) {
264
319
  function limitMessageContent(content, maxChars, fields, diagnosticLogger = () => { }) {
265
320
  if (content.length <= maxChars)
266
321
  return content;
267
- const kept = content.slice(0, maxChars).trim();
322
+ const prefix = content.slice(0, maxChars);
323
+ const kept = (/\S$/.test(prefix) && /^\S/.test(content.slice(maxChars)))
324
+ ? prefix.replace(/\S+$/, "").trim()
325
+ : prefix.trim();
268
326
  diagnosticLogger("memory.automatic_writeback.truncated", {
269
- sessionKey: fields?.sessionKey,
327
+ sessionKeyHash: hashOptionalText(fields?.sessionKey),
270
328
  role: fields?.role,
271
329
  originalChars: content.length,
272
330
  keptChars: kept.length,
@@ -277,6 +335,9 @@ function limitMessageContent(content, maxChars, fields, diagnosticLogger = () =>
277
335
  function hashText(text) {
278
336
  return createHash("sha256").update(text).digest("hex").slice(0, 16);
279
337
  }
338
+ function hashOptionalText(text) {
339
+ return text?.trim() ? hashText(text.trim()) : undefined;
340
+ }
280
341
  function automaticMemoryWritebackRetryDelayMs(failure, attempt) {
281
342
  if (!isRetryableAutomaticMemoryWritebackFailure(failure))
282
343
  return undefined;
@@ -1,12 +1,12 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { readFile } from "node:fs/promises";
3
- import { backendDebug } from "./debug-log.js";
4
- import { invokeMemoraxMemoryProvider } from "./memorax-adapter.js";
5
- import { defaultMemoraxCodeHome, memoryCliAddEnabled, memoryCliMaxMemoryChars, memoryCliSessionId, memoryConfigStatus, } from "./memorax-config.js";
6
- import { resolveConfiguredRepositoryMemory, } from "./repository-memory-context.js";
7
- import { repositoryMemoryScopeContainsWorkspace, repositoryMemoryScopeKind, repositoryMemoryScopesMatch, } from "./repository-memory-scope.js";
8
- import { isTraceClient } from "./trace-context.js";
9
- import { readCurrentTraceTurn, recordTraceEvent } from "./trace-store.js";
3
+ import { backendDebug } from "../shared/debug-log.js";
4
+ import { invokeMemoraxMemoryProvider } from "../provider/memorax/adapter.js";
5
+ import { defaultMemoraxCodeHome, memoryCliAddEnabled, memoryCliMaxMemoryChars, memoryCliSessionId, memoryConfigStatus, } from "../provider/memorax/config.js";
6
+ import { resolveConfiguredRepositoryMemory, } from "./repository-session.js";
7
+ import { repositoryMemoryScopeContainsWorkspace, repositoryMemoryScopeKind, repositoryMemoryScopesMatch, } from "../repository/scope.js";
8
+ import { isTraceClient } from "../trace/context.js";
9
+ import { readCurrentTraceTurn, recordTraceEvent } from "../trace/store.js";
10
10
  export async function runMemoryCli(args, options = {}) {
11
11
  const command = args[0] || "status";
12
12
  const env = options.env ?? process.env;
@@ -72,7 +72,7 @@ async function memorySearch(args, options) {
72
72
  const query = queryResult.text;
73
73
  const repositoryMemory = await resolveMemoryCliRepositoryMemory(options);
74
74
  if (!repositoryMemory.ok) {
75
- return { ok: false, action: "memory.search", query, error: repositoryMemory.error };
75
+ return memoryCliRepositoryFailure("memory.search", repositoryMemory, { query });
76
76
  }
77
77
  const observability = await memoryCliObservability(options.env);
78
78
  const response = await invokeMemoraxMemoryProvider({ sessionId: memoryCliSessionId(args, options.env), prompt: query }, {
@@ -135,7 +135,7 @@ async function memoryAdd(args, options) {
135
135
  return { ok: false, action: "memory.add", error: contentOptions.error };
136
136
  const repositoryMemory = await resolveMemoryCliRepositoryMemory(options);
137
137
  if (!repositoryMemory.ok)
138
- return { ok: false, action: "memory.add", error: repositoryMemory.error };
138
+ return memoryCliRepositoryFailure("memory.add", repositoryMemory);
139
139
  const sessionId = memoryCliSessionId(args, env);
140
140
  const observability = await memoryCliObservability(env);
141
141
  const response = await invokeMemoraxMemoryProvider({ sessionId, prompt: memory }, {
@@ -217,7 +217,7 @@ async function resolveMemoryCliRepositoryMemory(options) {
217
217
  if (!commandMemory.ok || !commandMemory.memory.scope)
218
218
  return commandMemory;
219
219
  if (turnMemory?.ok && (!turnMemory.memory.scope || !repositoryMemoryScopesMatch(commandMemory.memory.scope, turnMemory.memory.scope))) {
220
- const clientLabel = traceBinding?.client === "claude" ? "Claude" : "Codex";
220
+ const clientLabel = traceClientLabel(traceBinding?.client);
221
221
  return {
222
222
  ok: false,
223
223
  reason: "workspace_scope_mismatch",
@@ -226,6 +226,24 @@ async function resolveMemoryCliRepositoryMemory(options) {
226
226
  }
227
227
  return commandMemory;
228
228
  }
229
+ function memoryCliRepositoryFailure(action, failure, fields = {}) {
230
+ const userAction = failure.reason === "workspace_scope_mismatch"
231
+ ? "Start a new Codex, Claude Code, DSH, or OpenCode session from the target repository or local workspace."
232
+ : failure.reason === "workspace_scope_unavailable"
233
+ ? "Start a new Codex, Claude Code, DSH, or OpenCode session from the target repository or local workspace. If the problem continues, make sure its .git metadata is readable and valid."
234
+ : undefined;
235
+ return {
236
+ ok: false,
237
+ action,
238
+ ...fields,
239
+ ...(userAction ? {
240
+ workspaceScope: "unavailable",
241
+ workspaceScopeReason: failure.reason,
242
+ userAction,
243
+ } : {}),
244
+ error: failure.error,
245
+ };
246
+ }
229
247
  function memoryCliIdentityFields(memory) {
230
248
  return {
231
249
  baseUserId: memory.config.userId,
@@ -234,6 +252,10 @@ function memoryCliIdentityFields(memory) {
234
252
  scopeKind: repositoryMemoryScopeKind(memory.scope),
235
253
  effectiveUserId: memory.scope.effectiveUserId,
236
254
  workspaceScope: "bound",
255
+ ...(memory.scope.fallbackReason === "git_metadata_invalid" ? {
256
+ workspaceScopeFallbackReason: memory.scope.fallbackReason,
257
+ userNotice: `Git repository metadata is invalid or incomplete. MemoraX Code is using the local folder name "${memory.scope.repositorySlug}" for memory scope, so Search and Add use "${memory.scope.effectiveUserId}". Repair the repository or restore valid .git metadata. Later Search, Add, and automatic writeback in the same client session will automatically use the restored Git repository scope.`,
258
+ } : {}),
237
259
  } : {
238
260
  workspaceScope: "unavailable",
239
261
  }),
@@ -276,6 +298,10 @@ async function memoryCliObservability(env = process.env) {
276
298
  };
277
299
  }
278
300
  function memoryCliTraceBinding(env) {
301
+ if (env.DSH_SHELL === "1") {
302
+ const expectedSessionId = env.DSH_SESSION_ID?.trim();
303
+ return expectedSessionId ? { client: "dsh", expectedSessionId } : undefined;
304
+ }
279
305
  const explicitClientRaw = env.MEMORAX_CODE_MEMORY_CLI_TRACE_CLIENT;
280
306
  const explicitSessionIdRaw = env.MEMORAX_CODE_MEMORY_CLI_TRACE_SESSION_ID;
281
307
  if (explicitClientRaw !== undefined || explicitSessionIdRaw !== undefined) {
@@ -293,6 +319,15 @@ function memoryCliTraceBinding(env) {
293
319
  function memoryCliTraceEventType(event) {
294
320
  return event.operation === "writeback" ? "memory_cli_add" : "memory_cli_search";
295
321
  }
322
+ function traceClientLabel(client) {
323
+ if (client === "claude")
324
+ return "Claude";
325
+ if (client === "dsh")
326
+ return "DSH";
327
+ if (client === "opencode")
328
+ return "OpenCode";
329
+ return client === "codex" ? "Codex" : "coding agent";
330
+ }
296
331
  function memoryAddContentOptions(args) {
297
332
  const contentType = argValue(args, "--content-type")?.trim();
298
333
  const mode = argValue(args, "--mode")?.trim();
@@ -1,4 +1,4 @@
1
- import { isRecord } from "./utils.js";
1
+ import { isRecord } from "../shared/record.js";
2
2
  export const MEMORY_HOOK_COMMAND_VERSION = 1;
3
3
  export const INVALID_MEMORY_HOOK_COMMAND = "invalid memory Hook command";
4
4
  const BASE_COMMAND_KEYS = [
@@ -11,6 +11,8 @@ const BASE_COMMAND_KEYS = [
11
11
  const TURN_START_KEYS = {
12
12
  codex: new Set([...BASE_COMMAND_KEYS, "turnId", "prompt", "transcriptPath"]),
13
13
  "claude-code": new Set([...BASE_COMMAND_KEYS, "promptId", "prompt", "transcriptPath"]),
14
+ opencode: new Set([...BASE_COMMAND_KEYS, "userMessageId", "prompt"]),
15
+ dsh: new Set(["version", "client", "sessionId", "turn", "startSeq", "cwd", "prompt"]),
14
16
  };
15
17
  const WRITEBACK_KEYS = {
16
18
  codex: new Set([...BASE_COMMAND_KEYS, "turnId", "lastAssistantMessage", "transcriptPath"]),
@@ -20,10 +22,29 @@ const WRITEBACK_KEYS = {
20
22
  "lastAssistantMessage",
21
23
  "transcriptPath",
22
24
  ]),
25
+ opencode: new Set([
26
+ ...BASE_COMMAND_KEYS,
27
+ "userMessageId",
28
+ "assistantMessageId",
29
+ "messages",
30
+ ]),
31
+ dsh: new Set([
32
+ "version",
33
+ "client",
34
+ "sessionId",
35
+ "turn",
36
+ "startSeq",
37
+ "endSeq",
38
+ "cwd",
39
+ "sessionHeader",
40
+ "events",
41
+ ]),
23
42
  };
24
43
  const SKILL_REMINDER_KEYS = {
25
44
  codex: new Set([...BASE_COMMAND_KEYS, "turnId", "transcriptPath", "content", "triggers"]),
26
45
  "claude-code": new Set([...BASE_COMMAND_KEYS, "promptId", "transcriptPath", "content", "triggers"]),
46
+ dsh: new Set(["version", "client", "sessionId", "turn", "cwd", "content", "triggers"]),
47
+ opencode: new Set([...BASE_COMMAND_KEYS, "userMessageId", "content", "triggers"]),
27
48
  };
28
49
  export function parseTurnStartCommand(value) {
29
50
  if (!isRecord(value))
@@ -32,12 +53,29 @@ export function parseTurnStartCommand(value) {
32
53
  if (!base)
33
54
  return invalidCommand();
34
55
  const prompt = requiredStringField(value, "prompt");
35
- const transcriptPath = requiredStringField(value, "transcriptPath");
36
- if (!prompt || !transcriptPath)
56
+ if (!prompt)
37
57
  return invalidCommand();
58
+ if (base.client === "dsh") {
59
+ const turn = positiveSafeIntegerField(value, "turn");
60
+ const startSeq = nonNegativeSafeIntegerField(value, "startSeq");
61
+ if (!turn || startSeq === undefined || !base.cwd)
62
+ return invalidCommand();
63
+ return {
64
+ ok: true,
65
+ command: {
66
+ ...base,
67
+ client: "dsh",
68
+ turn,
69
+ startSeq,
70
+ cwd: base.cwd,
71
+ prompt,
72
+ },
73
+ };
74
+ }
38
75
  if (base.client === "codex") {
76
+ const transcriptPath = requiredStringField(value, "transcriptPath");
39
77
  const turnId = optionalStringField(value, "turnId");
40
- if (!turnId.ok)
78
+ if (!transcriptPath || !turnId.ok)
41
79
  return invalidCommand();
42
80
  return {
43
81
  ok: true,
@@ -50,8 +88,23 @@ export function parseTurnStartCommand(value) {
50
88
  },
51
89
  };
52
90
  }
91
+ if (base.client === "opencode") {
92
+ const userMessageId = requiredStringField(value, "userMessageId");
93
+ if (!userMessageId)
94
+ return invalidCommand();
95
+ return {
96
+ ok: true,
97
+ command: {
98
+ ...base,
99
+ client: "opencode",
100
+ userMessageId,
101
+ prompt,
102
+ },
103
+ };
104
+ }
53
105
  const promptId = requiredStringField(value, "promptId");
54
- if (!promptId)
106
+ const transcriptPath = requiredStringField(value, "transcriptPath");
107
+ if (!promptId || !transcriptPath)
55
108
  return invalidCommand();
56
109
  return {
57
110
  ok: true,
@@ -70,6 +123,49 @@ export function parseWritebackCommand(value) {
70
123
  const base = parseCommandBase(value, WRITEBACK_KEYS);
71
124
  if (!base)
72
125
  return invalidCommand();
126
+ if (base.client === "dsh") {
127
+ const turn = positiveSafeIntegerField(value, "turn");
128
+ const startSeq = nonNegativeSafeIntegerField(value, "startSeq");
129
+ const endSeq = nonNegativeSafeIntegerField(value, "endSeq");
130
+ if (!turn
131
+ || startSeq === undefined
132
+ || endSeq === undefined
133
+ || endSeq < startSeq
134
+ || !base.cwd
135
+ || !isRecord(value.sessionHeader)
136
+ || !Array.isArray(value.events))
137
+ return invalidCommand();
138
+ return {
139
+ ok: true,
140
+ command: {
141
+ ...base,
142
+ client: "dsh",
143
+ turn,
144
+ startSeq,
145
+ endSeq,
146
+ cwd: base.cwd,
147
+ sessionHeader: value.sessionHeader,
148
+ events: value.events,
149
+ },
150
+ };
151
+ }
152
+ if (base.client === "opencode") {
153
+ const userMessageId = requiredStringField(value, "userMessageId");
154
+ const assistantMessageId = requiredStringField(value, "assistantMessageId");
155
+ if (!userMessageId || !assistantMessageId || !Array.isArray(value.messages)) {
156
+ return invalidCommand();
157
+ }
158
+ return {
159
+ ok: true,
160
+ command: {
161
+ ...base,
162
+ client: "opencode",
163
+ userMessageId,
164
+ assistantMessageId,
165
+ messages: value.messages,
166
+ },
167
+ };
168
+ }
73
169
  const lastAssistantMessage = requiredStringField(value, "lastAssistantMessage");
74
170
  if (!lastAssistantMessage)
75
171
  return invalidCommand();
@@ -110,10 +206,43 @@ export function parseSkillReminderCommand(value) {
110
206
  const base = parseCommandBase(value, SKILL_REMINDER_KEYS);
111
207
  if (!base)
112
208
  return invalidCommand();
113
- const transcriptPath = requiredStringField(value, "transcriptPath");
114
209
  const content = requiredContentField(value, "content");
115
210
  const triggers = skillReminderTriggers(value.triggers);
116
- if (!transcriptPath || !content || !triggers)
211
+ if (!content || !triggers)
212
+ return invalidCommand();
213
+ if (base.client === "dsh") {
214
+ const turn = positiveSafeIntegerField(value, "turn");
215
+ if (!turn || !base.cwd)
216
+ return invalidCommand();
217
+ return {
218
+ ok: true,
219
+ command: {
220
+ ...base,
221
+ client: "dsh",
222
+ turn,
223
+ cwd: base.cwd,
224
+ content,
225
+ triggers,
226
+ },
227
+ };
228
+ }
229
+ if (base.client === "opencode") {
230
+ const userMessageId = requiredStringField(value, "userMessageId");
231
+ if (!userMessageId)
232
+ return invalidCommand();
233
+ return {
234
+ ok: true,
235
+ command: {
236
+ ...base,
237
+ client: "opencode",
238
+ userMessageId,
239
+ content,
240
+ triggers,
241
+ },
242
+ };
243
+ }
244
+ const transcriptPath = requiredStringField(value, "transcriptPath");
245
+ if (!transcriptPath)
117
246
  return invalidCommand();
118
247
  if (base.client === "codex") {
119
248
  const turnId = requiredStringField(value, "turnId");
@@ -131,6 +260,8 @@ export function parseSkillReminderCommand(value) {
131
260
  },
132
261
  };
133
262
  }
263
+ if (base.client !== "claude-code")
264
+ return invalidCommand();
134
265
  const promptId = requiredStringField(value, "promptId");
135
266
  if (!promptId)
136
267
  return invalidCommand();
@@ -150,9 +281,13 @@ function parseCommandBase(value, allowedKeys) {
150
281
  if (value.version !== MEMORY_HOOK_COMMAND_VERSION)
151
282
  return undefined;
152
283
  const client = value.client;
153
- if (client !== "codex" && client !== "claude-code")
284
+ if (client !== "codex"
285
+ && client !== "claude-code"
286
+ && client !== "opencode"
287
+ && client !== "dsh")
154
288
  return undefined;
155
- if (Object.keys(value).some((key) => !allowedKeys[client].has(key)))
289
+ const clientKeys = allowedKeys[client];
290
+ if (!clientKeys || Object.keys(value).some((key) => !clientKeys.has(key)))
156
291
  return undefined;
157
292
  const sessionId = requiredStringField(value, "sessionId");
158
293
  if (!sessionId)
@@ -169,6 +304,18 @@ function parseCommandBase(value, allowedKeys) {
169
304
  ...(workspaceKind.value ? { workspaceKind: workspaceKind.value } : {}),
170
305
  };
171
306
  }
307
+ function positiveSafeIntegerField(value, key) {
308
+ const field = value[key];
309
+ return typeof field === "number" && Number.isSafeInteger(field) && field > 0
310
+ ? field
311
+ : undefined;
312
+ }
313
+ function nonNegativeSafeIntegerField(value, key) {
314
+ const field = value[key];
315
+ return typeof field === "number" && Number.isSafeInteger(field) && field >= 0
316
+ ? field
317
+ : undefined;
318
+ }
172
319
  function requiredStringField(value, key) {
173
320
  const field = value[key];
174
321
  return typeof field === "string" && field.trim() ? field.trim() : undefined;