@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.
- package/README.md +16 -12
- package/bin/memorax-code-npm-preinstall.mjs +7 -2
- package/bin/memorax-code-opencode.mjs +4 -0
- package/bin/memorax-code-plugin-postinstall.mjs +424 -108
- package/docs/configuration.md +153 -29
- package/docs/troubleshooting.md +93 -7
- package/lib/dsh-plugin-install.mjs +22 -0
- package/lib/memorax-code-adapter-common/src/hooks/capture-cwd-hook.mjs +21 -14
- package/lib/memorax-code-adapter-common/src/hooks/ensure-backend-runner.mjs +26 -7
- package/lib/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +86 -95
- package/lib/memorax-code-adapter-common/src/hooks/memory-skill-reminder-policy.mjs +58 -0
- package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-auto-build.mjs +38 -0
- package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-job-supervisor.mjs +1 -1
- package/lib/memorax-code-adapter-common/src/windows-cli-invocation.mjs +13 -1
- package/lib/memorax-code-backend/dist/app/backend-server.js +210 -0
- package/lib/memorax-code-backend/dist/{server-observability.js → app/memory-observability.js} +4 -4
- package/lib/memorax-code-backend/dist/{backend-state.js → app/state.js} +1 -1
- package/lib/memorax-code-backend/dist/{claude-adapter-lifecycle.js → clients/claude/lifecycle.js} +2 -2
- package/lib/memorax-code-backend/dist/{claude-memory-hook-runtime.js → clients/claude/memory-hook-runtime.js} +16 -9
- package/lib/memorax-code-backend/dist/clients/codex/lifecycle.js +131 -0
- package/lib/memorax-code-backend/dist/{codex-memory-hook-runtime.js → clients/codex/memory-hook-runtime.js} +18 -11
- package/lib/memorax-code-backend/dist/{codex-plugin-hooks.js → clients/codex/plugin-hooks.js} +1 -1
- package/lib/memorax-code-backend/dist/{codex-plugin-install.js → clients/codex/plugin-install.js} +6 -6
- package/lib/memorax-code-backend/dist/clients/dsh/lifecycle.js +75 -0
- package/lib/memorax-code-backend/dist/clients/dsh/memory-hook-runtime.js +258 -0
- package/lib/memorax-code-backend/dist/clients/dsh/session-turn.js +249 -0
- package/lib/memorax-code-backend/dist/clients/opencode/lifecycle.js +54 -0
- package/lib/memorax-code-backend/dist/clients/opencode/memory-hook-runtime.js +277 -0
- package/lib/memorax-code-backend/dist/clients/opencode/message-turn.js +78 -0
- package/lib/memorax-code-backend/dist/codex-adapter-lifecycle.js +1 -131
- package/lib/memorax-code-backend/dist/{memorax-code-config.js → config/memorax-code.js} +32 -4
- package/lib/memorax-code-backend/dist/{server-cli.js → entrypoints/backend-cli.js} +157 -34
- package/lib/memorax-code-backend/dist/jsonl-append.js +1 -75
- package/lib/memorax-code-backend/dist/{active-client-selection.js → lifecycle/active-clients.js} +12 -1
- package/lib/memorax-code-backend/dist/{backend-service-cleanup.js → lifecycle/backend/cleanup.js} +1 -1
- package/lib/memorax-code-backend/dist/{backend-service-record.js → lifecycle/backend/record.js} +1 -1
- package/lib/memorax-code-backend/dist/{backend-service-result.js → lifecycle/backend/result.js} +2 -2
- package/lib/memorax-code-backend/dist/{service.js → lifecycle/backend/service.js} +16 -16
- package/lib/memorax-code-backend/dist/{backend-token-record.js → lifecycle/backend/token-record.js} +1 -1
- package/lib/memorax-code-backend/dist/{backend-service-token.js → lifecycle/backend/token.js} +2 -2
- package/lib/memorax-code-backend/dist/lifecycle/client-plugin-removal.js +109 -0
- package/lib/memorax-code-backend/dist/{client-selection.js → lifecycle/client-selection.js} +11 -5
- package/lib/memorax-code-backend/dist/{backend-lifecycle-lock.js → lifecycle/lock.js} +1 -1
- package/lib/memorax-code-backend/dist/{memorax-code-lifecycle.js → lifecycle/orchestrator.js} +325 -39
- package/lib/memorax-code-backend/dist/memorax-cli.js +3 -1
- package/lib/memorax-code-backend/dist/memorax-code.js +1 -1
- package/lib/memorax-code-backend/dist/{automatic-memory-retrieval.js → memory/automatic-retrieval.js} +3 -3
- package/lib/memorax-code-backend/dist/{automatic-memory-writeback.js → memory/automatic-writeback.js} +82 -21
- package/lib/memorax-code-backend/dist/{memory-cli.js → memory/cli.js} +45 -10
- package/lib/memorax-code-backend/dist/{memory-hook-command.js → memory/hook-command.js} +156 -9
- package/lib/memorax-code-backend/dist/memory/observability.js +1 -0
- package/lib/memorax-code-backend/dist/memory/payload-redaction.js +212 -0
- package/lib/memorax-code-backend/dist/{memory-reminder-trace-recorder.js → memory/reminder-trace-recorder.js} +20 -7
- package/lib/memorax-code-backend/dist/{repository-memory-context.js → memory/repository-session.js} +25 -4
- package/lib/memorax-code-backend/dist/{memory-service.js → memory/service.js} +30 -6
- package/lib/memorax-code-backend/dist/{memory-turn-coordinator.js → memory/turn-coordinator.js} +7 -3
- package/lib/memorax-code-backend/dist/{memory-writeback-buffer.js → memory/writeback-buffer.js} +31 -2
- package/lib/memorax-code-backend/dist/{memory-writeback-chunk.js → memory/writeback-chunk.js} +1 -1
- package/lib/memorax-code-backend/dist/{memory-writeback-reconciler.js → memory/writeback-reconciler.js} +6 -6
- package/lib/memorax-code-backend/dist/{memory-writeback-task-projection.js → memory/writeback-task-projection.js} +4 -4
- package/lib/memorax-code-backend/dist/{memorax-adapter.js → provider/memorax/adapter.js} +5 -5
- package/lib/memorax-code-backend/dist/{memorax-config.js → provider/memorax/config.js} +4 -4
- package/lib/memorax-code-backend/dist/{memorax-http.js → provider/memorax/http.js} +1 -1
- package/lib/memorax-code-backend/dist/{repo-memory-readiness.js → repository/readiness.js} +3 -3
- package/lib/memorax-code-backend/dist/{repository-memory-scope.js → repository/scope.js} +81 -33
- package/lib/memorax-code-backend/dist/server.js +3 -212
- package/lib/memorax-code-backend/dist/service-entrypoint.js +1 -1
- package/lib/memorax-code-backend/dist/{debug-log.js → shared/debug-log.js} +1 -1
- package/lib/memorax-code-backend/dist/shared/jsonl-append.js +75 -0
- package/lib/memorax-code-backend/dist/shared/windows-cli-invocation.js +148 -0
- package/lib/memorax-code-backend/dist/{trace-config.js → trace/config.js} +43 -5
- package/lib/memorax-code-backend/dist/{trace-context.js → trace/context.js} +53 -2
- package/lib/memorax-code-backend/dist/{trace-store.js → trace/store.js} +3 -3
- package/lib/memorax-code-backend/dist/{server-health.js → transport/http/health.js} +1 -1
- package/lib/memorax-code-backend/dist/{server-memory-hook.js → transport/http/memory-hook.js} +3 -3
- package/lib/memorax-code-backend/dist/{server-http.js → transport/http/request.js} +1 -1
- package/lib/memorax-code-backend/dist/{claude-local-transcript.js → viewer/history/claude-transcript.js} +3 -3
- package/lib/memorax-code-backend/dist/{memory-viewer-session-title.js → viewer/history/session-title.js} +1 -1
- package/lib/memorax-code-backend/dist/{server-memory-viewer.js → viewer/http/public-routes.js} +25 -14
- package/lib/memorax-code-backend/dist/viewer/model.js +1 -0
- package/lib/memorax-code-backend/dist/{memory-viewer-activity.js → viewer/projection/activity.js} +2 -2
- package/lib/memorax-code-backend/dist/{memory-viewer-history-projection.js → viewer/projection/history.js} +1 -1
- package/lib/memorax-code-backend/dist/{memory-viewer-observability.js → viewer/projection/observability.js} +1 -1
- package/lib/memorax-code-backend/dist/{memory-viewer-user-projection.js → viewer/projection/user.js} +1 -1
- package/lib/memorax-code-backend/dist/{memory-viewer-writeback-status.js → viewer/projection/writeback-status.js} +1 -1
- package/lib/memorax-code-backend/dist/{memory-viewer-store.js → viewer/store.js} +59 -32
- package/lib/memorax-code-backend/dist/viewer/ui/icon.js +1 -0
- package/lib/memorax-code-backend/dist/{memory-viewer-user-html.js → viewer/ui/user-html.js} +14 -12
- package/lib/memorax-code-backend/dist/windows-cli-invocation.js +1 -148
- package/lib/memorax-code-backend/package.json +3 -3
- package/lib/memorax-code-claude-adapter/.claude-plugin/plugin.json +1 -1
- package/lib/memorax-code-claude-adapter/hooks/runtime-shell.json +1 -1
- package/lib/memorax-code-claude-adapter/package.json +1 -1
- package/lib/memorax-code-claude-adapter/runtime-hooks/memory-turn.mjs +5 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/SKILL.md +23 -15
- package/lib/memorax-code-claude-adapter/skills/memorax-code/defaults.json +8 -5
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +5 -1
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +40 -10
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/personal-read.md +1 -1
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/personal-write.md +33 -13
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-build.md +62 -13
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-read.md +11 -4
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-templates.md +179 -59
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-update.md +18 -7
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/collect_all.py +122 -39
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/detect_updates.py +73 -10
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/github_resource_facets.py +9 -1
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +9 -1
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/validate_memory.py +23 -1
- package/lib/memorax-code-claude-adapter/src/plugin-install.mjs +2 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/.claude-plugin/plugin.json +1 -1
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/runtime-shell.json +1 -1
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/capture-cwd-hook.mjs +21 -14
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/ensure-backend-runner.mjs +26 -7
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +86 -95
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/memory-skill-reminder-policy.mjs +58 -0
- 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
- 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
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/windows-cli-invocation.mjs +13 -1
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/package.json +1 -1
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/memory-turn.mjs +5 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/SKILL.md +23 -15
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/defaults.json +8 -5
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +5 -1
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +40 -10
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/personal-read.md +1 -1
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/personal-write.md +33 -13
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-build.md +62 -13
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-read.md +11 -4
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-templates.md +179 -59
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-update.md +18 -7
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/collect_all.py +122 -39
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/detect_updates.py +73 -10
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/github_resource_facets.py +9 -1
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +9 -1
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/validate_memory.py +23 -1
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/plugin-install.mjs +2 -0
- package/lib/memorax-code-codex-adapter/.codex-plugin/plugin.json +1 -1
- package/lib/memorax-code-codex-adapter/hooks/runtime-shell.json +1 -1
- package/lib/memorax-code-codex-adapter/package.json +1 -1
- package/lib/memorax-code-codex-adapter/runtime-hooks/memory-skill-reminder.mjs +16 -2
- package/lib/memorax-code-codex-adapter/skills/memorax-code/SKILL.md +23 -15
- package/lib/memorax-code-codex-adapter/skills/memorax-code/defaults.json +8 -5
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-add.md +5 -1
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-search.md +40 -10
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/personal-read.md +1 -1
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/personal-write.md +33 -13
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-build.md +62 -13
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-read.md +11 -4
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-templates.md +179 -59
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-update.md +18 -7
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/collect_all.py +122 -39
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/detect_updates.py +73 -10
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/github_resource_facets.py +9 -1
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +9 -1
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/validate_memory.py +23 -1
- package/lib/memorax-code-dsh-adapter/cordis.patch.yml +10 -0
- package/lib/memorax-code-dsh-adapter/hooks/repo-memory-job.mjs +68 -0
- package/lib/memorax-code-dsh-adapter/package.json +69 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/SKILL.md +91 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/agents/claude.yaml +10 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/agents/openai.yaml +7 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/defaults.json +12 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/memorax-add.md +86 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/memorax-search.md +91 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/personal-read.md +46 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/personal-write.md +120 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-build.md +319 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-read.md +103 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-templates.md +390 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-update.md +127 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/collect_all.py +579 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/detect_updates.py +919 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/github_resource_facets.py +512 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +517 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
- package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/validate_memory.py +248 -0
- package/lib/memorax-code-dsh-adapter/src/backend-client.mjs +119 -0
- package/lib/memorax-code-dsh-adapter/src/dsh-message.mjs +32 -0
- package/lib/memorax-code-dsh-adapter/src/dsh-version.mjs +18 -0
- package/lib/memorax-code-dsh-adapter/src/http-client.mjs +55 -0
- package/lib/memorax-code-dsh-adapter/src/index.mjs +72 -0
- package/lib/memorax-code-dsh-adapter/src/personal-context-worker.mjs +48 -0
- package/lib/memorax-code-dsh-adapter/src/personal-context.mjs +114 -0
- package/lib/memorax-code-dsh-adapter/src/plugin.mjs +724 -0
- package/lib/memorax-code-dsh-adapter/src/profile-lifecycle.mjs +1289 -0
- package/lib/memorax-code-dsh-adapter/src/protocol.mjs +145 -0
- package/lib/memorax-code-dsh-adapter/src/runtime-state.mjs +132 -0
- package/lib/memorax-code-opencode-adapter/hooks/repo-memory-job.mjs +37 -0
- package/lib/memorax-code-opencode-adapter/package.json +10 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/SKILL.md +91 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/agents/claude.yaml +10 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/agents/openai.yaml +7 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/defaults.json +12 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/memorax-add.md +86 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/memorax-search.md +91 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/personal-read.md +46 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/personal-write.md +120 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-build.md +319 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-read.md +103 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-templates.md +390 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-update.md +127 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/collect_all.py +579 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/detect_updates.py +919 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/github_resource_facets.py +512 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +517 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
- package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/validate_memory.py +248 -0
- package/lib/memorax-code-opencode-adapter/src/adapter-paths.mjs +37 -0
- package/lib/memorax-code-opencode-adapter/src/cli.mjs +260 -0
- package/lib/memorax-code-opencode-adapter/src/diagnostics.mjs +31 -0
- package/lib/memorax-code-opencode-adapter/src/plugin-install.mjs +673 -0
- package/lib/memorax-code-opencode-adapter/src/plugin.mjs +536 -0
- package/lib/memorax-code-opencode-adapter/src/repo-memory-server-runner.mjs +207 -0
- package/lib/resolve-claude-command.mjs +154 -1
- package/lib/resolve-codex-command.mjs +56 -1
- package/lib/run-entrypoint.mjs +6 -0
- package/package.json +7 -3
- package/lib/memorax-code-backend/dist/client-plugin-removal.js +0 -67
- /package/lib/memorax-code-backend/dist/{claude-transcript-turn.js → clients/claude/transcript-turn.js} +0 -0
- /package/lib/memorax-code-backend/dist/{codex-effective-prompt.js → clients/codex/effective-prompt.js} +0 -0
- /package/lib/memorax-code-backend/dist/{codex-rollout-turn.js → clients/codex/rollout-turn.js} +0 -0
- /package/lib/memorax-code-backend/dist/{codex-session-turn-index.js → clients/codex/session-turn-index.js} +0 -0
- /package/lib/memorax-code-backend/dist/{codex-workspace-links.js → clients/codex/workspace-links.js} +0 -0
- /package/lib/memorax-code-backend/dist/{backend-env.js → config/backend-env.js} +0 -0
- /package/lib/memorax-code-backend/dist/{proxy-env.js → config/proxy-env.js} +0 -0
- /package/lib/memorax-code-backend/dist/{entrypoint.js → entrypoints/main.js} +0 -0
- /package/lib/memorax-code-backend/dist/{backend-process.js → lifecycle/backend/process.js} +0 -0
- /package/lib/memorax-code-backend/dist/{backend-shutdown-request.js → lifecycle/backend/shutdown-request.js} +0 -0
- /package/lib/memorax-code-backend/dist/{backend-status.js → lifecycle/backend/status.js} +0 -0
- /package/lib/memorax-code-backend/dist/{adapter-lifecycle-participant.js → lifecycle/contracts.js} +0 -0
- /package/lib/memorax-code-backend/dist/{install-watchdog.js → lifecycle/install-watchdog.js} +0 -0
- /package/lib/memorax-code-backend/dist/{memory-observability.js → lifecycle/participant.js} +0 -0
- /package/lib/memorax-code-backend/dist/{memory-project.js → memory/project.js} +0 -0
- /package/lib/memorax-code-backend/dist/{incremental-jsonl-projection.js → shared/incremental-jsonl-projection.js} +0 -0
- /package/lib/memorax-code-backend/dist/{utils.js → shared/record.js} +0 -0
- /package/lib/memorax-code-backend/dist/{server-json.js → transport/http/json.js} +0 -0
- /package/lib/memorax-code-backend/dist/{memory-viewer-data-projection-cache.js → viewer/projection/cache.js} +0 -0
- /package/lib/memorax-code-backend/dist/{memory-viewer-event-identity.js → viewer/projection/event-identity.js} +0 -0
- /package/lib/memorax-code-backend/dist/{memory-viewer-redaction.js → viewer/projection/redaction.js} +0 -0
- /package/lib/memorax-code-backend/dist/{memory-viewer-turn-reference.js → viewer/projection/turn-reference.js} +0 -0
- /package/lib/memorax-code-backend/dist/{memory-viewer-logo.js → viewer/ui/logo.js} +0 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Validate authored repo-memory bundles."""
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import json
|
|
6
|
+
import re
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
BASELINE_FILES = [
|
|
13
|
+
Path("PROFILE.md"),
|
|
14
|
+
Path("resources/commits.md"),
|
|
15
|
+
Path("resources/prs.md"),
|
|
16
|
+
Path("resources/issues.md"),
|
|
17
|
+
Path("raw/git-commits.json"),
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
PROVIDER_RAW_FILES = [Path("raw/github-facets.json"), Path("raw/gitlab-facets.json")]
|
|
21
|
+
PROVIDER_RESOURCE_FILES = [Path("resources/prs.md"), Path("resources/issues.md")]
|
|
22
|
+
DISABLED_RESOURCE_SOURCES = {"history_disabled", "provider_skipped_local_only", "provider_unavailable", "github_resource_facets_unavailable", "gitlab_resource_facets_unavailable", "provider_unavailable_local_only"}
|
|
23
|
+
USER_PROFILE_SIDECAR = Path("user-profile/preferences.md")
|
|
24
|
+
PROCEDURE_SIDECAR_DIRECTORY = "procedure-memory"
|
|
25
|
+
PLACEHOLDER_RE = re.compile(r"\[([^\]\n]+)\]")
|
|
26
|
+
LINK_TARGET_AFTER_BRACKET_RE = re.compile(r"[ \t\r\n]*\(")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def relative(path: Path, memory: Path) -> str:
|
|
30
|
+
return path.relative_to(memory).as_posix()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def resolve_memory_root(path: Path) -> Path:
|
|
34
|
+
candidate = path.expanduser().resolve()
|
|
35
|
+
if candidate.name == ".repo_memory":
|
|
36
|
+
return candidate
|
|
37
|
+
return candidate / ".repo_memory"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def parse_frontmatter(text: str) -> dict[str, Any]:
|
|
41
|
+
if not text.startswith("---\n"):
|
|
42
|
+
return {}
|
|
43
|
+
end = text.find("\n---", 4)
|
|
44
|
+
if end == -1:
|
|
45
|
+
return {}
|
|
46
|
+
values: dict[str, Any] = {}
|
|
47
|
+
for line in text[4:end].splitlines():
|
|
48
|
+
if ":" not in line:
|
|
49
|
+
continue
|
|
50
|
+
key, value = line.split(":", 1)
|
|
51
|
+
key = key.strip()
|
|
52
|
+
value = value.strip()
|
|
53
|
+
if not key:
|
|
54
|
+
continue
|
|
55
|
+
if (value.startswith('"') and value.endswith('"')) or (value.startswith("'") and value.endswith("'")):
|
|
56
|
+
values[key] = value[1:-1]
|
|
57
|
+
elif re.fullmatch(r"-?\d+", value):
|
|
58
|
+
values[key] = int(value)
|
|
59
|
+
elif value.lower() == "true":
|
|
60
|
+
values[key] = True
|
|
61
|
+
elif value.lower() == "false":
|
|
62
|
+
values[key] = False
|
|
63
|
+
else:
|
|
64
|
+
values[key] = value
|
|
65
|
+
return values
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def body_after_frontmatter(text: str) -> str:
|
|
69
|
+
if not text.startswith("---\n"):
|
|
70
|
+
return text
|
|
71
|
+
end = text.find("\n---", 4)
|
|
72
|
+
if end == -1:
|
|
73
|
+
return text
|
|
74
|
+
return text[end + 4 :].lstrip("\n")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def item_section_count(text: str) -> int:
|
|
78
|
+
body = body_after_frontmatter(text)
|
|
79
|
+
lines = body.splitlines()
|
|
80
|
+
title_seen = False
|
|
81
|
+
count = 0
|
|
82
|
+
for line in lines:
|
|
83
|
+
if line.startswith("# ") and not title_seen:
|
|
84
|
+
title_seen = True
|
|
85
|
+
continue
|
|
86
|
+
if title_seen and line.startswith("## "):
|
|
87
|
+
count += 1
|
|
88
|
+
return count
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def placeholder_matches(text: str) -> list[str]:
|
|
92
|
+
text = strip_markdown_code(text)
|
|
93
|
+
matches: list[str] = []
|
|
94
|
+
for match in PLACEHOLDER_RE.finditer(text):
|
|
95
|
+
if LINK_TARGET_AFTER_BRACKET_RE.match(text, match.end()):
|
|
96
|
+
continue
|
|
97
|
+
value = match.group(1).strip()
|
|
98
|
+
if not value or value.startswith("#"):
|
|
99
|
+
continue
|
|
100
|
+
if re.search(r"[A-Za-z]", value):
|
|
101
|
+
matches.append(f"[{value}]")
|
|
102
|
+
return matches
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def strip_markdown_code(text: str) -> str:
|
|
106
|
+
without_fences = re.sub(r"```.*?```", "", text, flags=re.DOTALL)
|
|
107
|
+
return re.sub(r"`[^`\n]*`", "", without_fences)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def check_exists(memory: Path, rel_path: Path, errors: list[str], checked: list[str]) -> bool:
|
|
111
|
+
path = memory / rel_path
|
|
112
|
+
checked.append(rel_path.as_posix())
|
|
113
|
+
if not path.exists():
|
|
114
|
+
errors.append(f"{rel_path.as_posix()}: required file is missing")
|
|
115
|
+
return False
|
|
116
|
+
if not path.is_file():
|
|
117
|
+
errors.append(f"{rel_path.as_posix()}: expected a file")
|
|
118
|
+
return False
|
|
119
|
+
return True
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def validate_json(path: Path, memory: Path, errors: list[str], checked: list[str]) -> None:
|
|
123
|
+
checked.append(relative(path, memory))
|
|
124
|
+
try:
|
|
125
|
+
json.loads(path.read_text(encoding="utf-8"))
|
|
126
|
+
except json.JSONDecodeError as exc:
|
|
127
|
+
errors.append(f"{relative(path, memory)}: invalid JSON at line {exc.lineno}, column {exc.colno}: {exc.msg}")
|
|
128
|
+
except OSError as exc:
|
|
129
|
+
errors.append(f"{relative(path, memory)}: could not read JSON: {exc}")
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def raw_source_points_to_provider(raw_source: Any) -> bool:
|
|
133
|
+
return isinstance(raw_source, str) and raw_source.endswith(("github-facets.json", "gitlab-facets.json"))
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def validate_markdown(path: Path, memory: Path, errors: list[str], warnings: list[str], checked: list[str]) -> None:
|
|
137
|
+
checked.append(relative(path, memory))
|
|
138
|
+
try:
|
|
139
|
+
text = path.read_text(encoding="utf-8")
|
|
140
|
+
except OSError as exc:
|
|
141
|
+
errors.append(f"{relative(path, memory)}: could not read Markdown: {exc}")
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
frontmatter = parse_frontmatter(text)
|
|
145
|
+
rel = relative(path, memory)
|
|
146
|
+
if not frontmatter.get("schema"):
|
|
147
|
+
errors.append(f"{rel}: frontmatter field 'schema' is missing")
|
|
148
|
+
|
|
149
|
+
placeholders = placeholder_matches(text)
|
|
150
|
+
if placeholders:
|
|
151
|
+
errors.append(f"{rel}: unresolved bracket placeholder(s): {', '.join(placeholders)}")
|
|
152
|
+
|
|
153
|
+
if path.parent.name != "resources":
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
for field in ["source", "resource_count", "trust_state", "raw_source"]:
|
|
157
|
+
if field not in frontmatter:
|
|
158
|
+
errors.append(f"{rel}: frontmatter field '{field}' is missing")
|
|
159
|
+
|
|
160
|
+
expected = frontmatter.get("resource_count")
|
|
161
|
+
actual = item_section_count(text)
|
|
162
|
+
if isinstance(expected, int):
|
|
163
|
+
if expected != actual:
|
|
164
|
+
errors.append(f"{rel}: resource_count is {expected}, but found {actual} item section(s)")
|
|
165
|
+
elif expected is not None:
|
|
166
|
+
errors.append(f"{rel}: resource_count must be an integer")
|
|
167
|
+
|
|
168
|
+
source = frontmatter.get("source")
|
|
169
|
+
raw_source = frontmatter.get("raw_source")
|
|
170
|
+
if "source" in frontmatter and not source:
|
|
171
|
+
errors.append(f"{rel}: frontmatter field 'source' must not be empty")
|
|
172
|
+
if "trust_state" in frontmatter and not frontmatter.get("trust_state"):
|
|
173
|
+
errors.append(f"{rel}: frontmatter field 'trust_state' must not be empty")
|
|
174
|
+
if source in DISABLED_RESOURCE_SOURCES and isinstance(expected, int) and expected != 0:
|
|
175
|
+
errors.append(f"{rel}: disabled or unavailable resource source {source!r} must use resource_count 0")
|
|
176
|
+
if source in DISABLED_RESOURCE_SOURCES and raw_source:
|
|
177
|
+
errors.append(f"{rel}: disabled or unavailable resource source {source!r} must use an empty raw_source")
|
|
178
|
+
if path.name in {"commits.md", "prs.md", "issues.md"} and source not in DISABLED_RESOURCE_SOURCES and raw_source == "":
|
|
179
|
+
errors.append(f"{rel}: empty raw_source requires a disabled or unavailable source")
|
|
180
|
+
if path.name in {"prs.md", "issues.md"} and raw_source_points_to_provider(raw_source):
|
|
181
|
+
provider_path = (path.parent / raw_source).resolve()
|
|
182
|
+
if not provider_path.exists():
|
|
183
|
+
errors.append(f"{rel}: provider raw evidence is missing for raw_source {raw_source!r}")
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def provider_raw_paths(memory: Path) -> list[Path]:
|
|
187
|
+
return [memory / rel for rel in PROVIDER_RAW_FILES if (memory / rel).exists()]
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def validate(memory: Path) -> dict[str, Any]:
|
|
191
|
+
errors: list[str] = []
|
|
192
|
+
warnings: list[str] = []
|
|
193
|
+
checked: list[str] = []
|
|
194
|
+
|
|
195
|
+
if not memory.exists():
|
|
196
|
+
errors.append(f"{memory}: .repo_memory directory is missing")
|
|
197
|
+
return {"ok": False, "errors": errors, "warnings": warnings, "checked": checked}
|
|
198
|
+
if not memory.is_dir():
|
|
199
|
+
errors.append(f"{memory}: expected .repo_memory to be a directory")
|
|
200
|
+
return {"ok": False, "errors": errors, "warnings": warnings, "checked": checked}
|
|
201
|
+
|
|
202
|
+
for rel_path in BASELINE_FILES:
|
|
203
|
+
check_exists(memory, rel_path, errors, checked)
|
|
204
|
+
|
|
205
|
+
markdown_paths = sorted(
|
|
206
|
+
path
|
|
207
|
+
for path in memory.rglob("*.md")
|
|
208
|
+
if path.is_file()
|
|
209
|
+
and path.relative_to(memory) != USER_PROFILE_SIDECAR
|
|
210
|
+
and path.relative_to(memory).parts[0] != PROCEDURE_SIDECAR_DIRECTORY
|
|
211
|
+
)
|
|
212
|
+
for path in markdown_paths:
|
|
213
|
+
if path.exists() and path.is_file():
|
|
214
|
+
validate_markdown(path, memory, errors, warnings, checked)
|
|
215
|
+
|
|
216
|
+
json_paths = sorted(path for path in (memory / "raw").rglob("*.json") if path.is_file())
|
|
217
|
+
provider_raw = provider_raw_paths(memory)
|
|
218
|
+
|
|
219
|
+
if provider_raw:
|
|
220
|
+
for rel_path in PROVIDER_RESOURCE_FILES:
|
|
221
|
+
check_exists(memory, rel_path, errors, checked)
|
|
222
|
+
|
|
223
|
+
seen_json: set[Path] = set()
|
|
224
|
+
for path in json_paths:
|
|
225
|
+
if path.exists() and path.is_file() and path not in seen_json:
|
|
226
|
+
seen_json.add(path)
|
|
227
|
+
validate_json(path, memory, errors, checked)
|
|
228
|
+
|
|
229
|
+
checked = sorted(dict.fromkeys(checked))
|
|
230
|
+
return {"ok": not errors, "errors": errors, "warnings": warnings, "checked": checked}
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def parse_args(argv: list[str]) -> argparse.Namespace:
|
|
234
|
+
parser = argparse.ArgumentParser(description="Validate a repo-memory bundle.")
|
|
235
|
+
parser.add_argument("path", help="Path to a repository or its .repo_memory directory")
|
|
236
|
+
parser.add_argument("--pretty", action="store_true", help="Pretty-print JSON output")
|
|
237
|
+
return parser.parse_args(argv)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def main(argv: list[str]) -> int:
|
|
241
|
+
args = parse_args(argv)
|
|
242
|
+
report = validate(resolve_memory_root(Path(args.path)))
|
|
243
|
+
print(json.dumps(report, ensure_ascii=False, indent=2 if args.pretty else None))
|
|
244
|
+
return 0 if report["ok"] else 1
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
if __name__ == "__main__":
|
|
248
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { dirname } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
|
|
4
|
+
import { resolveBackendConnection } from "../memorax-code-adapter-common/src/backend-connection.mjs";
|
|
5
|
+
import {
|
|
6
|
+
ensureBackendAvailable,
|
|
7
|
+
stringValue,
|
|
8
|
+
} from "../memorax-code-adapter-common/src/hooks/ensure-backend-runner.mjs";
|
|
9
|
+
import { createHttpBackendClient } from "./http-client.mjs";
|
|
10
|
+
import { requireEnabledDshRuntime } from "./runtime-state.mjs";
|
|
11
|
+
|
|
12
|
+
// The package assembler materializes adapter-common inside this DSH bundle so
|
|
13
|
+
// a profile-local file: install never depends on the parent npm package tree.
|
|
14
|
+
const pluginRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
15
|
+
|
|
16
|
+
export function createDshBackendClient(options = {}) {
|
|
17
|
+
const env = options.env ?? process.env;
|
|
18
|
+
const root = options.pluginRoot ?? pluginRoot;
|
|
19
|
+
const resolveRuntime = options.resolveRuntime
|
|
20
|
+
?? (() => requireEnabledDshRuntime(root));
|
|
21
|
+
const resolveConnection = options.resolveConnection
|
|
22
|
+
?? ((runtime) => resolveBackendConnection({ memoraxCodeHome: runtime.memoraxCodeHome, env }));
|
|
23
|
+
const ensureBackend = options.ensureBackend ?? ensureBackendAvailable;
|
|
24
|
+
const httpClient = options.httpClient ?? createHttpBackendClient({
|
|
25
|
+
env,
|
|
26
|
+
resolveConnection: () => resolveConnection(resolveRuntime()),
|
|
27
|
+
});
|
|
28
|
+
let ensureInFlight;
|
|
29
|
+
let ensureRevision;
|
|
30
|
+
|
|
31
|
+
async function ensureReady() {
|
|
32
|
+
// This read intentionally precedes the in-flight fast path. A running DSH
|
|
33
|
+
// process must observe stop/uninstall before it can reuse Backend recovery.
|
|
34
|
+
const runtime = resolveRuntime();
|
|
35
|
+
if (ensureInFlight) {
|
|
36
|
+
if (ensureRevision === runtime.revision) return ensureInFlight;
|
|
37
|
+
await ensureInFlight.catch(() => undefined);
|
|
38
|
+
return ensureReady();
|
|
39
|
+
}
|
|
40
|
+
const connection = resolveConnection(runtime);
|
|
41
|
+
ensureRevision = runtime.revision;
|
|
42
|
+
const pending = Promise.resolve(ensureBackend({
|
|
43
|
+
backendConnection: connection,
|
|
44
|
+
ensureBackendValue: env.MEMORAX_CODE_DSH_ENSURE_BACKEND,
|
|
45
|
+
healthTimeoutValue: env.MEMORAX_CODE_DSH_ENSURE_TIMEOUT_MS,
|
|
46
|
+
startTimeoutValue: env.MEMORAX_CODE_DSH_START_TIMEOUT_MS,
|
|
47
|
+
memoraxCodeCommand: stringValue(env.MEMORAX_CODE_DSH_LIFECYCLE_COMMAND)
|
|
48
|
+
?? stringValue(env.MEMORAX_CODE_COMMAND)
|
|
49
|
+
?? runtime.memoraxCodeCommand,
|
|
50
|
+
nodePath: process.execPath,
|
|
51
|
+
pluginRoot: root,
|
|
52
|
+
resolveHomes: () => ({ memoraxCodeHome: runtime.memoraxCodeHome }),
|
|
53
|
+
buildStartArgs: (homes, recoveryArguments) => [
|
|
54
|
+
"start",
|
|
55
|
+
"--home",
|
|
56
|
+
homes.memoraxCodeHome,
|
|
57
|
+
...recoveryArguments,
|
|
58
|
+
],
|
|
59
|
+
recoveryEnv: {
|
|
60
|
+
MEMORAX_CODE_DSH_ADAPTER_RECOVERY: "1",
|
|
61
|
+
MEMORAX_CODE_DSH_ADAPTER_EXPECTED_REVISION: runtime.revision,
|
|
62
|
+
},
|
|
63
|
+
debug: options.debug ?? debugEnsure,
|
|
64
|
+
}));
|
|
65
|
+
const tracked = pending.finally(() => {
|
|
66
|
+
if (ensureInFlight === tracked) {
|
|
67
|
+
ensureInFlight = undefined;
|
|
68
|
+
ensureRevision = undefined;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
ensureInFlight = tracked;
|
|
72
|
+
return ensureInFlight;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return Object.freeze({
|
|
76
|
+
ensureReady,
|
|
77
|
+
async recordTurnStart(command, request) {
|
|
78
|
+
await waitForEnsure(ensureReady(), request?.signal, 12_000);
|
|
79
|
+
return httpClient.recordTurnStart(command, request);
|
|
80
|
+
},
|
|
81
|
+
async recordSkillReminder(command, request) {
|
|
82
|
+
await waitForEnsure(ensureReady(), request?.signal, 5_000);
|
|
83
|
+
return httpClient.recordSkillReminder(command, request);
|
|
84
|
+
},
|
|
85
|
+
async writebackTurn(command, request) {
|
|
86
|
+
await waitForEnsure(ensureReady(), request?.signal, 5_000);
|
|
87
|
+
return httpClient.writebackTurn(command, request);
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const backendClient = createDshBackendClient();
|
|
93
|
+
|
|
94
|
+
async function waitForEnsure(promise, signal, timeoutMs) {
|
|
95
|
+
signal?.throwIfAborted();
|
|
96
|
+
let timer;
|
|
97
|
+
let abort;
|
|
98
|
+
const boundary = new Promise((_, reject) => {
|
|
99
|
+
timer = setTimeout(() => reject(new Error("MemoraX Code Backend recovery timed out")), timeoutMs);
|
|
100
|
+
if (signal) {
|
|
101
|
+
abort = () => reject(signal.reason instanceof Error ? signal.reason : new Error("aborted"));
|
|
102
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
try {
|
|
106
|
+
await Promise.race([promise, boundary]);
|
|
107
|
+
} finally {
|
|
108
|
+
clearTimeout(timer);
|
|
109
|
+
if (abort) signal.removeEventListener("abort", abort);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function debugEnsure(message) {
|
|
114
|
+
if (process.env.MEMORAX_CODE_DSH_DEBUG === "1") {
|
|
115
|
+
console.error(message);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export default backendClient;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
/** Create the same detached, identified, deeply frozen UserMessage as DSH. */
|
|
4
|
+
export function createDshUserMessage(input) {
|
|
5
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
6
|
+
throw new TypeError("DSH UserMessage input must be an object");
|
|
7
|
+
}
|
|
8
|
+
if (Object.hasOwn(input, "id") || Object.hasOwn(input, "role")) {
|
|
9
|
+
throw new TypeError("DSH UserMessage input must not supply id or role");
|
|
10
|
+
}
|
|
11
|
+
return deepFreeze(structuredClone({
|
|
12
|
+
...input,
|
|
13
|
+
role: "user",
|
|
14
|
+
id: randomUUID(),
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Mirrors DSH's public createUserMessage -> freezeMessage -> deepFreeze
|
|
19
|
+
// construction contract without depending on DSH internals.
|
|
20
|
+
function deepFreeze(value) {
|
|
21
|
+
const seen = new WeakSet();
|
|
22
|
+
const pending = [value];
|
|
23
|
+
while (pending.length > 0) {
|
|
24
|
+
const node = pending.pop();
|
|
25
|
+
if (node === null || typeof node !== "object" || node instanceof AbortSignal) continue;
|
|
26
|
+
if (seen.has(node)) continue;
|
|
27
|
+
seen.add(node);
|
|
28
|
+
Object.freeze(node);
|
|
29
|
+
for (const key of Object.keys(node)) pending.push(node[key]);
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const DSH_TESTED_VERSIONS = Object.freeze(["0.1.0-rc.6"]);
|
|
2
|
+
|
|
3
|
+
const DSH_VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
4
|
+
const DSH_VERSION_MAX_LENGTH = 128;
|
|
5
|
+
|
|
6
|
+
export function parseDshVersion(value) {
|
|
7
|
+
const version = typeof value === "string" ? value.trim() : "";
|
|
8
|
+
return version
|
|
9
|
+
&& version.length <= DSH_VERSION_MAX_LENGTH
|
|
10
|
+
&& DSH_VERSION_PATTERN.test(version)
|
|
11
|
+
? version
|
|
12
|
+
: undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function isTestedDshVersion(value) {
|
|
16
|
+
const version = parseDshVersion(value);
|
|
17
|
+
return version !== undefined && DSH_TESTED_VERSIONS.includes(version);
|
|
18
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const RETRIEVAL_BACKEND_TIMEOUT_MS = 12_000;
|
|
2
|
+
const DEFAULT_BACKEND_TIMEOUT_MS = 5_000;
|
|
3
|
+
|
|
4
|
+
/** Create the narrow Backend port consumed by the Cordis plugin. */
|
|
5
|
+
export function createHttpBackendClient(options) {
|
|
6
|
+
const resolveConnection = options?.resolveConnection;
|
|
7
|
+
const fetchImpl = options?.fetchImpl ?? globalThis.fetch;
|
|
8
|
+
const env = options?.env ?? process.env;
|
|
9
|
+
if (typeof resolveConnection !== "function") {
|
|
10
|
+
throw new TypeError("DSH Backend client requires resolveConnection");
|
|
11
|
+
}
|
|
12
|
+
if (typeof fetchImpl !== "function") throw new TypeError("DSH Backend client requires fetch");
|
|
13
|
+
|
|
14
|
+
return Object.freeze({
|
|
15
|
+
recordTurnStart(command, request = {}) {
|
|
16
|
+
return post("/memory/turn-start", command, request.signal);
|
|
17
|
+
},
|
|
18
|
+
recordSkillReminder(command, request = {}) {
|
|
19
|
+
return post("/memory/skill-reminder", command, request.signal);
|
|
20
|
+
},
|
|
21
|
+
writebackTurn(command, request = {}) {
|
|
22
|
+
return post("/memory/writeback", command, request.signal);
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
async function post(path, body, callerSignal) {
|
|
27
|
+
const connection = resolveConnection();
|
|
28
|
+
const timeoutMs = positiveInteger(
|
|
29
|
+
env.MEMORAX_CODE_DSH_MEMORY_HOOK_TIMEOUT_MS,
|
|
30
|
+
path === "/memory/turn-start" ? RETRIEVAL_BACKEND_TIMEOUT_MS : DEFAULT_BACKEND_TIMEOUT_MS,
|
|
31
|
+
);
|
|
32
|
+
const headers = { "content-type": "application/json", connection: "close" };
|
|
33
|
+
if (connection.token) headers["x-memorax-code-backend-token"] = connection.token;
|
|
34
|
+
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
|
35
|
+
const signal = callerSignal
|
|
36
|
+
? AbortSignal.any([callerSignal, timeoutSignal])
|
|
37
|
+
: timeoutSignal;
|
|
38
|
+
const response = await fetchImpl(new URL(path, connection.url), {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers,
|
|
41
|
+
body: JSON.stringify(body),
|
|
42
|
+
signal,
|
|
43
|
+
});
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
await response.arrayBuffer().catch(() => undefined);
|
|
46
|
+
throw new Error(`MemoraX Code Backend ${path} returned HTTP ${response.status}`);
|
|
47
|
+
}
|
|
48
|
+
return await response.json().catch(() => undefined);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function positiveInteger(value, fallback) {
|
|
53
|
+
const parsed = Number(value);
|
|
54
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
|
|
55
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
isMemorySkillReminderDue,
|
|
7
|
+
memorySkillReminderContext,
|
|
8
|
+
personalMemoryReminderContext,
|
|
9
|
+
resolveMemorySkillReminderIntervalTurns,
|
|
10
|
+
} from "../memorax-code-adapter-common/src/hooks/memory-skill-reminder-policy.mjs";
|
|
11
|
+
import { scheduleMissingRepoMemoryBuild } from "../memorax-code-adapter-common/src/repo-memory/repo-memory-auto-build.mjs";
|
|
12
|
+
import { isRepoMemoryJobWorker } from "../memorax-code-adapter-common/src/repo-memory/repo-memory-job-context.mjs";
|
|
13
|
+
import backendClient from "./backend-client.mjs";
|
|
14
|
+
import { createDshUserMessage } from "./dsh-message.mjs";
|
|
15
|
+
import { loadDshPersonalContext } from "./personal-context.mjs";
|
|
16
|
+
import { PLUGIN_NAME, registerMemoraxCodePlugin } from "./plugin.mjs";
|
|
17
|
+
import { requireEnabledDshRuntime } from "./runtime-state.mjs";
|
|
18
|
+
|
|
19
|
+
export const name = PLUGIN_NAME;
|
|
20
|
+
export const inject = ["agents", "sessions", "sessionPersistence"];
|
|
21
|
+
|
|
22
|
+
const pluginRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
23
|
+
|
|
24
|
+
export function apply(ctx) {
|
|
25
|
+
if (isRepoMemoryJobWorker()) return;
|
|
26
|
+
let runtime;
|
|
27
|
+
try {
|
|
28
|
+
runtime = requireEnabledDshRuntime(pluginRoot);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
if (error?.code === "MEMORAX_CODE_DSH_DISABLED") return;
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
const runtimeEnv = {
|
|
34
|
+
...process.env,
|
|
35
|
+
MEMORAX_CODE_HOME: runtime.memoraxCodeHome,
|
|
36
|
+
};
|
|
37
|
+
const intervalTurns = resolveMemorySkillReminderIntervalTurns({
|
|
38
|
+
environmentValue: runtimeEnv.MEMORAX_CODE_MEMORY_SKILL_REMINDER_INTERVAL_TURNS,
|
|
39
|
+
configText: readConfig(join(runtime.memoraxCodeHome, "config.toml")),
|
|
40
|
+
});
|
|
41
|
+
registerMemoraxCodePlugin(ctx, {
|
|
42
|
+
assertEnabled: () => requireEnabledDshRuntime(pluginRoot),
|
|
43
|
+
backendClient,
|
|
44
|
+
createUserMessage: createDshUserMessage,
|
|
45
|
+
intervalTurns,
|
|
46
|
+
isReminderDue: isMemorySkillReminderDue,
|
|
47
|
+
memoryReminderContext: memorySkillReminderContext("/memorax-code"),
|
|
48
|
+
loadPersonalContext: (input, options) => loadDshPersonalContext(input, {
|
|
49
|
+
...options,
|
|
50
|
+
env: runtimeEnv,
|
|
51
|
+
}),
|
|
52
|
+
personalMemoryReminderContext: personalMemoryReminderContext("/memorax-code"),
|
|
53
|
+
scheduleRepoMemoryBuild: (repo) => scheduleMissingRepoMemoryBuild(repo, {
|
|
54
|
+
pluginRoot,
|
|
55
|
+
env: runtimeEnv,
|
|
56
|
+
debugEnv: "MEMORAX_CODE_DSH_DEBUG",
|
|
57
|
+
}),
|
|
58
|
+
});
|
|
59
|
+
void backendClient.ensureReady().catch((error) => {
|
|
60
|
+
if (process.env.MEMORAX_CODE_DSH_DEBUG !== "1") return;
|
|
61
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
62
|
+
ctx.logger?.warn?.(`memorax-code Backend recovery failed: ${detail}`);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function readConfig(path) {
|
|
67
|
+
try {
|
|
68
|
+
return readFileSync(path, "utf8");
|
|
69
|
+
} catch {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { buildRepoProcedureMemoryContext } from "../memorax-code-adapter-common/src/repo-memory/repo-procedure-memory-context.mjs";
|
|
2
|
+
import { buildRepoUserProfilePreferencesContext } from "../memorax-code-adapter-common/src/repo-memory/repo-user-profile-context.mjs";
|
|
3
|
+
|
|
4
|
+
const MAX_INPUT_BYTES = 16 * 1024;
|
|
5
|
+
const contextOptions = {
|
|
6
|
+
adapterDir: "dsh",
|
|
7
|
+
debugEnv: "MEMORAX_CODE_DSH_DEBUG",
|
|
8
|
+
sessionKeyPrefix: "dsh",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
const input = await readInput();
|
|
13
|
+
const profileContext = input.includeProfile
|
|
14
|
+
? buildRepoUserProfilePreferencesContext({ cwd: input.cwd }, contextOptions)
|
|
15
|
+
: undefined;
|
|
16
|
+
const procedureContext = input.includeProcedure
|
|
17
|
+
? buildRepoProcedureMemoryContext({ cwd: input.cwd }, contextOptions)
|
|
18
|
+
: undefined;
|
|
19
|
+
process.stdout.write(`${JSON.stringify({
|
|
20
|
+
...(profileContext ? { profileContext } : {}),
|
|
21
|
+
...(procedureContext ? { procedureContext } : {}),
|
|
22
|
+
})}\n`);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function readInput() {
|
|
29
|
+
const chunks = [];
|
|
30
|
+
let bytes = 0;
|
|
31
|
+
for await (const chunk of process.stdin) {
|
|
32
|
+
bytes += chunk.length;
|
|
33
|
+
if (bytes > MAX_INPUT_BYTES) throw new Error("DSH personal context worker input exceeded its limit");
|
|
34
|
+
chunks.push(chunk);
|
|
35
|
+
}
|
|
36
|
+
const value = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
37
|
+
const cwd = nonEmptyString(value?.cwd);
|
|
38
|
+
const includeProfile = value?.includeProfile === true;
|
|
39
|
+
const includeProcedure = value?.includeProcedure === true;
|
|
40
|
+
if (!cwd || (!includeProfile && !includeProcedure)) {
|
|
41
|
+
throw new Error("DSH personal context worker received invalid input");
|
|
42
|
+
}
|
|
43
|
+
return { cwd, includeProfile, includeProcedure };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function nonEmptyString(value) {
|
|
47
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
48
|
+
}
|