@memorax/memorax-code 0.1.2 → 0.1.4

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 (242) 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 +342 -93
  5. package/docs/configuration.md +148 -35
  6. package/docs/troubleshooting.md +73 -13
  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 +2 -2
  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} +7 -7
  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} +9 -9
  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} +137 -37
  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 +1 -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} +75 -21
  49. package/lib/memorax-code-backend/dist/{memory-cli.js → memory/cli.js} +23 -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} +2 -2
  55. package/lib/memorax-code-backend/dist/{memory-service.js → memory/service.js} +27 -5
  56. package/lib/memorax-code-backend/dist/{memory-turn-coordinator.js → memory/turn-coordinator.js} +2 -1
  57. package/lib/memorax-code-backend/dist/{memory-writeback-buffer.js → memory/writeback-buffer.js} +3 -3
  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/server.js +3 -212
  66. package/lib/memorax-code-backend/dist/service-entrypoint.js +1 -1
  67. package/lib/memorax-code-backend/dist/{debug-log.js → shared/debug-log.js} +1 -1
  68. package/lib/memorax-code-backend/dist/shared/jsonl-append.js +75 -0
  69. package/lib/memorax-code-backend/dist/shared/windows-cli-invocation.js +148 -0
  70. package/lib/memorax-code-backend/dist/{trace-config.js → trace/config.js} +43 -5
  71. package/lib/memorax-code-backend/dist/{trace-context.js → trace/context.js} +53 -2
  72. package/lib/memorax-code-backend/dist/{trace-store.js → trace/store.js} +3 -3
  73. package/lib/memorax-code-backend/dist/{server-health.js → transport/http/health.js} +1 -1
  74. package/lib/memorax-code-backend/dist/{server-memory-hook.js → transport/http/memory-hook.js} +3 -3
  75. package/lib/memorax-code-backend/dist/{server-http.js → transport/http/request.js} +1 -1
  76. package/lib/memorax-code-backend/dist/{claude-local-transcript.js → viewer/history/claude-transcript.js} +3 -3
  77. package/lib/memorax-code-backend/dist/{memory-viewer-session-title.js → viewer/history/session-title.js} +1 -1
  78. package/lib/memorax-code-backend/dist/{server-memory-viewer.js → viewer/http/public-routes.js} +15 -15
  79. package/lib/memorax-code-backend/dist/viewer/model.js +1 -0
  80. package/lib/memorax-code-backend/dist/{memory-viewer-activity.js → viewer/projection/activity.js} +2 -2
  81. package/lib/memorax-code-backend/dist/{memory-viewer-history-projection.js → viewer/projection/history.js} +1 -1
  82. package/lib/memorax-code-backend/dist/{memory-viewer-observability.js → viewer/projection/observability.js} +1 -1
  83. package/lib/memorax-code-backend/dist/{memory-viewer-user-projection.js → viewer/projection/user.js} +1 -1
  84. package/lib/memorax-code-backend/dist/{memory-viewer-writeback-status.js → viewer/projection/writeback-status.js} +1 -1
  85. package/lib/memorax-code-backend/dist/{memory-viewer-store.js → viewer/store.js} +59 -32
  86. package/lib/memorax-code-backend/dist/{memory-viewer-user-html.js → viewer/ui/user-html.js} +11 -10
  87. package/lib/memorax-code-backend/dist/windows-cli-invocation.js +1 -148
  88. package/lib/memorax-code-backend/package.json +3 -3
  89. package/lib/memorax-code-claude-adapter/.claude-plugin/plugin.json +1 -1
  90. package/lib/memorax-code-claude-adapter/hooks/runtime-shell.json +1 -1
  91. package/lib/memorax-code-claude-adapter/package.json +1 -1
  92. package/lib/memorax-code-claude-adapter/skills/memorax-code/SKILL.md +11 -2
  93. package/lib/memorax-code-claude-adapter/skills/memorax-code/defaults.json +8 -5
  94. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +1 -1
  95. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +37 -9
  96. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/personal-read.md +1 -1
  97. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/personal-write.md +33 -13
  98. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-build.md +62 -13
  99. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-read.md +11 -4
  100. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-templates.md +179 -59
  101. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-update.md +18 -7
  102. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/collect_all.py +122 -39
  103. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/detect_updates.py +73 -10
  104. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/github_resource_facets.py +9 -1
  105. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +9 -1
  106. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/validate_memory.py +23 -1
  107. package/lib/memorax-code-claude-adapter/src/plugin-install.mjs +1 -0
  108. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/.claude-plugin/plugin.json +1 -1
  109. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/runtime-shell.json +1 -1
  110. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/capture-cwd-hook.mjs +21 -14
  111. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/ensure-backend-runner.mjs +26 -7
  112. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +86 -95
  113. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/memory-skill-reminder-policy.mjs +58 -0
  114. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-auto-build.mjs +2 -2
  115. 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
  116. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/windows-cli-invocation.mjs +13 -1
  117. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/package.json +1 -1
  118. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/SKILL.md +11 -2
  119. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/defaults.json +8 -5
  120. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +1 -1
  121. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +37 -9
  122. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/personal-read.md +1 -1
  123. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/personal-write.md +33 -13
  124. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-build.md +62 -13
  125. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-read.md +11 -4
  126. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-templates.md +179 -59
  127. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-update.md +18 -7
  128. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/collect_all.py +122 -39
  129. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/detect_updates.py +73 -10
  130. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/github_resource_facets.py +9 -1
  131. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +9 -1
  132. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/validate_memory.py +23 -1
  133. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/plugin-install.mjs +1 -0
  134. package/lib/memorax-code-codex-adapter/.codex-plugin/plugin.json +1 -1
  135. package/lib/memorax-code-codex-adapter/hooks/runtime-shell.json +1 -1
  136. package/lib/memorax-code-codex-adapter/package.json +1 -1
  137. package/lib/memorax-code-codex-adapter/runtime-hooks/memory-skill-reminder.mjs +10 -2
  138. package/lib/memorax-code-codex-adapter/skills/memorax-code/SKILL.md +11 -2
  139. package/lib/memorax-code-codex-adapter/skills/memorax-code/defaults.json +8 -5
  140. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-add.md +1 -1
  141. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-search.md +37 -9
  142. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/personal-read.md +1 -1
  143. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/personal-write.md +33 -13
  144. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-build.md +62 -13
  145. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-read.md +11 -4
  146. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-templates.md +179 -59
  147. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-update.md +18 -7
  148. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/collect_all.py +122 -39
  149. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/detect_updates.py +73 -10
  150. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/github_resource_facets.py +9 -1
  151. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +9 -1
  152. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/validate_memory.py +23 -1
  153. package/lib/memorax-code-dsh-adapter/cordis.patch.yml +10 -0
  154. package/lib/memorax-code-dsh-adapter/hooks/repo-memory-job.mjs +68 -0
  155. package/lib/memorax-code-dsh-adapter/package.json +69 -0
  156. package/lib/memorax-code-dsh-adapter/skills/memorax-code/SKILL.md +91 -0
  157. package/lib/memorax-code-dsh-adapter/skills/memorax-code/agents/claude.yaml +10 -0
  158. package/lib/memorax-code-dsh-adapter/skills/memorax-code/agents/openai.yaml +7 -0
  159. package/lib/memorax-code-dsh-adapter/skills/memorax-code/defaults.json +12 -0
  160. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/memorax-add.md +86 -0
  161. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/memorax-search.md +91 -0
  162. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/personal-read.md +46 -0
  163. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/personal-write.md +120 -0
  164. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-build.md +319 -0
  165. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-read.md +103 -0
  166. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-templates.md +390 -0
  167. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-update.md +127 -0
  168. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/collect_all.py +579 -0
  169. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/detect_updates.py +919 -0
  170. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
  171. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/github_resource_facets.py +512 -0
  172. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +517 -0
  173. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
  174. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
  175. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/validate_memory.py +248 -0
  176. package/lib/memorax-code-dsh-adapter/src/backend-client.mjs +119 -0
  177. package/lib/memorax-code-dsh-adapter/src/dsh-message.mjs +32 -0
  178. package/lib/memorax-code-dsh-adapter/src/dsh-version.mjs +18 -0
  179. package/lib/memorax-code-dsh-adapter/src/http-client.mjs +55 -0
  180. package/lib/memorax-code-dsh-adapter/src/index.mjs +72 -0
  181. package/lib/memorax-code-dsh-adapter/src/personal-context-worker.mjs +48 -0
  182. package/lib/memorax-code-dsh-adapter/src/personal-context.mjs +114 -0
  183. package/lib/memorax-code-dsh-adapter/src/plugin.mjs +724 -0
  184. package/lib/memorax-code-dsh-adapter/src/profile-lifecycle.mjs +1358 -0
  185. package/lib/memorax-code-dsh-adapter/src/protocol.mjs +145 -0
  186. package/lib/memorax-code-dsh-adapter/src/runtime-state.mjs +132 -0
  187. package/lib/memorax-code-opencode-adapter/hooks/repo-memory-job.mjs +37 -0
  188. package/lib/memorax-code-opencode-adapter/package.json +10 -0
  189. package/lib/memorax-code-opencode-adapter/skills/memorax-code/SKILL.md +91 -0
  190. package/lib/memorax-code-opencode-adapter/skills/memorax-code/agents/claude.yaml +10 -0
  191. package/lib/memorax-code-opencode-adapter/skills/memorax-code/agents/openai.yaml +7 -0
  192. package/lib/memorax-code-opencode-adapter/skills/memorax-code/defaults.json +12 -0
  193. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/memorax-add.md +86 -0
  194. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/memorax-search.md +91 -0
  195. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/personal-read.md +46 -0
  196. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/personal-write.md +120 -0
  197. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-build.md +319 -0
  198. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-read.md +103 -0
  199. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-templates.md +390 -0
  200. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-update.md +127 -0
  201. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/collect_all.py +579 -0
  202. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/detect_updates.py +919 -0
  203. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
  204. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/github_resource_facets.py +512 -0
  205. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +517 -0
  206. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
  207. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
  208. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/validate_memory.py +248 -0
  209. package/lib/memorax-code-opencode-adapter/src/adapter-paths.mjs +37 -0
  210. package/lib/memorax-code-opencode-adapter/src/cli.mjs +260 -0
  211. package/lib/memorax-code-opencode-adapter/src/diagnostics.mjs +31 -0
  212. package/lib/memorax-code-opencode-adapter/src/plugin-install.mjs +673 -0
  213. package/lib/memorax-code-opencode-adapter/src/plugin.mjs +539 -0
  214. package/lib/memorax-code-opencode-adapter/src/repo-memory-server-runner.mjs +442 -0
  215. package/lib/run-entrypoint.mjs +6 -0
  216. package/package.json +7 -3
  217. package/lib/memorax-code-backend/dist/client-plugin-removal.js +0 -67
  218. /package/lib/memorax-code-backend/dist/{claude-transcript-turn.js → clients/claude/transcript-turn.js} +0 -0
  219. /package/lib/memorax-code-backend/dist/{codex-effective-prompt.js → clients/codex/effective-prompt.js} +0 -0
  220. /package/lib/memorax-code-backend/dist/{codex-rollout-turn.js → clients/codex/rollout-turn.js} +0 -0
  221. /package/lib/memorax-code-backend/dist/{codex-session-turn-index.js → clients/codex/session-turn-index.js} +0 -0
  222. /package/lib/memorax-code-backend/dist/{codex-workspace-links.js → clients/codex/workspace-links.js} +0 -0
  223. /package/lib/memorax-code-backend/dist/{backend-env.js → config/backend-env.js} +0 -0
  224. /package/lib/memorax-code-backend/dist/{proxy-env.js → config/proxy-env.js} +0 -0
  225. /package/lib/memorax-code-backend/dist/{entrypoint.js → entrypoints/main.js} +0 -0
  226. /package/lib/memorax-code-backend/dist/{backend-process.js → lifecycle/backend/process.js} +0 -0
  227. /package/lib/memorax-code-backend/dist/{backend-shutdown-request.js → lifecycle/backend/shutdown-request.js} +0 -0
  228. /package/lib/memorax-code-backend/dist/{backend-status.js → lifecycle/backend/status.js} +0 -0
  229. /package/lib/memorax-code-backend/dist/{adapter-lifecycle-participant.js → lifecycle/contracts.js} +0 -0
  230. /package/lib/memorax-code-backend/dist/{install-watchdog.js → lifecycle/install-watchdog.js} +0 -0
  231. /package/lib/memorax-code-backend/dist/{memory-observability.js → lifecycle/participant.js} +0 -0
  232. /package/lib/memorax-code-backend/dist/{memory-project.js → memory/project.js} +0 -0
  233. /package/lib/memorax-code-backend/dist/{repository-memory-scope.js → repository/scope.js} +0 -0
  234. /package/lib/memorax-code-backend/dist/{incremental-jsonl-projection.js → shared/incremental-jsonl-projection.js} +0 -0
  235. /package/lib/memorax-code-backend/dist/{utils.js → shared/record.js} +0 -0
  236. /package/lib/memorax-code-backend/dist/{server-json.js → transport/http/json.js} +0 -0
  237. /package/lib/memorax-code-backend/dist/{memory-viewer-data-projection-cache.js → viewer/projection/cache.js} +0 -0
  238. /package/lib/memorax-code-backend/dist/{memory-viewer-event-identity.js → viewer/projection/event-identity.js} +0 -0
  239. /package/lib/memorax-code-backend/dist/{memory-viewer-redaction.js → viewer/projection/redaction.js} +0 -0
  240. /package/lib/memorax-code-backend/dist/{memory-viewer-turn-reference.js → viewer/projection/turn-reference.js} +0 -0
  241. /package/lib/memorax-code-backend/dist/{memory-viewer-icon.js → viewer/ui/icon.js} +0 -0
  242. /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;
@@ -47,7 +48,7 @@ function enqueueAutomaticMemoryWritebackForRuntime(state, options) {
47
48
  state.diagnosticLogger("memory.automatic_writeback", {
48
49
  scheduled: false,
49
50
  skipReason: "runtime_closed",
50
- sessionKey: options.sessionKey,
51
+ sessionKeyHash: hashOptionalText(options.sessionKey),
51
52
  });
52
53
  return { accepted: false, reason: "runtime_closed" };
53
54
  }
@@ -57,7 +58,7 @@ function enqueueAutomaticMemoryWritebackForRuntime(state, options) {
57
58
  state.diagnosticLogger("memory.automatic_writeback", {
58
59
  scheduled: false,
59
60
  skipReason: decision.skipReason,
60
- sessionKey: options.sessionKey,
61
+ sessionKeyHash: hashOptionalText(options.sessionKey),
61
62
  });
62
63
  return decision.skipReason === "duplicate_pending"
63
64
  ? { accepted: true }
@@ -65,7 +66,7 @@ function enqueueAutomaticMemoryWritebackForRuntime(state, options) {
65
66
  }
66
67
  if (memoryWritebackBufferEnabled(options.env ?? process.env)) {
67
68
  state.writebackBuffer.enqueue(decision, options, {
68
- debug: state.diagnosticLogger,
69
+ debug: redactAutomaticMemoryWritebackDiagnosticIdentifiers(state.diagnosticLogger),
69
70
  flush: (bufferedDecision, bufferedOptions) => flushAutomaticMemoryWritebackBuffer(state, bufferedDecision, bufferedOptions),
70
71
  hasPendingWriteback: (idempotencyKey) => hasPendingWriteback(state, idempotencyKey),
71
72
  reservePendingWritebacks: (idempotencyKeys) => reservePendingWritebacks(state, idempotencyKeys),
@@ -76,8 +77,8 @@ function enqueueAutomaticMemoryWritebackForRuntime(state, options) {
76
77
  reservePendingWriteback(state, decision.idempotencyKey);
77
78
  state.diagnosticLogger("memory.automatic_writeback", {
78
79
  scheduled: true,
79
- sessionKey: options.sessionKey,
80
- idempotencyKey: decision.idempotencyKey,
80
+ sessionKeyHash: hashText(decision.sessionKey),
81
+ idempotencyKeyHash: hashText(decision.idempotencyKey),
81
82
  messageCount: decision.messages.length,
82
83
  userChars: decision.messages[0]?.content.length ?? 0,
83
84
  assistantChars: decision.messages[1]?.content.length ?? 0,
@@ -89,12 +90,23 @@ function enqueueAutomaticMemoryWritebackForRuntime(state, options) {
89
90
  state.diagnosticLogger("memory.automatic_writeback", {
90
91
  scheduled: false,
91
92
  skipReason: "decision_error",
92
- sessionKey: options.sessionKey,
93
+ sessionKeyHash: hashOptionalText(options.sessionKey),
93
94
  error: error instanceof Error ? error.message : String(error),
94
95
  });
95
96
  return { accepted: false, reason: "decision_error" };
96
97
  }
97
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
+ }
98
110
  function automaticMemoryWritebackDecision(state, options) {
99
111
  const env = options.env ?? process.env;
100
112
  if (!memoryWritebackEnabled(env))
@@ -110,17 +122,35 @@ function automaticMemoryWritebackDecision(state, options) {
110
122
  }
111
123
  const sessionKey = options.sessionKey.trim();
112
124
  const maxMessageChars = memoryWritebackMaxMessageChars(env);
113
- 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, {
114
144
  role: "user",
115
145
  sessionKey,
116
146
  }, state.diagnosticLogger);
117
- const assistantText = limitMessageContent(options.assistantText?.trim() ?? "", maxMessageChars, {
147
+ const assistantText = limitMessageContent(assistantRedaction.text, maxMessageChars, {
118
148
  role: "assistant",
119
149
  sessionKey,
120
150
  }, state.diagnosticLogger);
121
- if (!userText)
151
+ if (!hasMeaningfulMemoryPayloadText(userText))
122
152
  return { write: false, skipReason: "user_prompt_empty" };
123
- if (!assistantText)
153
+ if (!hasMeaningfulMemoryPayloadText(assistantText))
124
154
  return { write: false, skipReason: "assistant_text_empty" };
125
155
  const idempotencyKey = `automatic:${options.client}:${hashText(options.repositoryScope.effectiveUserId)}:${sessionKey}:${hashText(userText)}:${hashText(assistantText)}`;
126
156
  if (hasPendingWriteback(state, idempotencyKey))
@@ -136,8 +166,26 @@ function automaticMemoryWritebackDecision(state, options) {
136
166
  ],
137
167
  };
138
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
+ }
139
180
  async function enqueueAutomaticMemoryWritebackAsync(state, decision, options) {
140
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
+ }
141
189
  const parts = memoryWritebackAddParts(decision, options.env ?? process.env);
142
190
  for (const [index, part] of parts.entries()) {
143
191
  for (let attempt = 1; attempt <= AUTOMATIC_MEMORY_WRITEBACK_MAX_ATTEMPTS; attempt += 1) {
@@ -179,9 +227,9 @@ async function enqueueAutomaticMemoryWritebackAsync(state, decision, options) {
179
227
  state.diagnosticLogger("memory.automatic_writeback", {
180
228
  scheduled: true,
181
229
  accepted: response.ok,
182
- sessionKey: decision.sessionKey,
183
- idempotencyKey: part.idempotencyKey,
184
- 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),
185
233
  flushReason: decision.flushReason,
186
234
  turnCount: decision.turnCount,
187
235
  partIndex: parts.length > 1 ? index : undefined,
@@ -210,8 +258,8 @@ async function enqueueAutomaticMemoryWritebackAsync(state, decision, options) {
210
258
  state.diagnosticLogger("memory.automatic_writeback", {
211
259
  scheduled: true,
212
260
  accepted: false,
213
- sessionKey: decision.sessionKey,
214
- idempotencyKey: decision.idempotencyKey,
261
+ sessionKeyHash: hashText(decision.sessionKey),
262
+ idempotencyKeyHash: hashText(decision.idempotencyKey),
215
263
  flushReason: decision.flushReason,
216
264
  turnCount: decision.turnCount,
217
265
  error: error instanceof Error ? error.message : String(error),
@@ -271,9 +319,12 @@ function prunePendingWritebacks(state, now = Date.now()) {
271
319
  function limitMessageContent(content, maxChars, fields, diagnosticLogger = () => { }) {
272
320
  if (content.length <= maxChars)
273
321
  return content;
274
- 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();
275
326
  diagnosticLogger("memory.automatic_writeback.truncated", {
276
- sessionKey: fields?.sessionKey,
327
+ sessionKeyHash: hashOptionalText(fields?.sessionKey),
277
328
  role: fields?.role,
278
329
  originalChars: content.length,
279
330
  keptChars: kept.length,
@@ -284,6 +335,9 @@ function limitMessageContent(content, maxChars, fields, diagnosticLogger = () =>
284
335
  function hashText(text) {
285
336
  return createHash("sha256").update(text).digest("hex").slice(0, 16);
286
337
  }
338
+ function hashOptionalText(text) {
339
+ return text?.trim() ? hashText(text.trim()) : undefined;
340
+ }
287
341
  function automaticMemoryWritebackRetryDelayMs(failure, attempt) {
288
342
  if (!isRetryableAutomaticMemoryWritebackFailure(failure))
289
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;
@@ -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",
@@ -228,9 +228,9 @@ async function resolveMemoryCliRepositoryMemory(options) {
228
228
  }
229
229
  function memoryCliRepositoryFailure(action, failure, fields = {}) {
230
230
  const userAction = failure.reason === "workspace_scope_mismatch"
231
- ? "Start a new Codex or Claude Code session from the target repository or local workspace."
231
+ ? "Start a new Codex, Claude Code, DSH, or OpenCode session from the target repository or local workspace."
232
232
  : failure.reason === "workspace_scope_unavailable"
233
- ? "Start a new Codex or Claude Code session from the target repository or local workspace. If the problem continues, make sure its .git metadata is readable and valid."
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
234
  : undefined;
235
235
  return {
236
236
  ok: false,
@@ -298,6 +298,10 @@ async function memoryCliObservability(env = process.env) {
298
298
  };
299
299
  }
300
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
+ }
301
305
  const explicitClientRaw = env.MEMORAX_CODE_MEMORY_CLI_TRACE_CLIENT;
302
306
  const explicitSessionIdRaw = env.MEMORAX_CODE_MEMORY_CLI_TRACE_SESSION_ID;
303
307
  if (explicitClientRaw !== undefined || explicitSessionIdRaw !== undefined) {
@@ -315,6 +319,15 @@ function memoryCliTraceBinding(env) {
315
319
  function memoryCliTraceEventType(event) {
316
320
  return event.operation === "writeback" ? "memory_cli_add" : "memory_cli_search";
317
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
+ }
318
331
  function memoryAddContentOptions(args) {
319
332
  const contentType = argValue(args, "--content-type")?.trim();
320
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;