@memorax/memorax-code 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +53 -0
- package/bin/memorax-cli.mjs +28 -0
- package/bin/memorax-code-backend.mjs +4 -0
- package/bin/memorax-code-claude.mjs +4 -0
- package/bin/memorax-code-codex.mjs +4 -0
- package/bin/memorax-code-npm-preinstall.mjs +55 -0
- package/bin/memorax-code-plugin-postinstall.mjs +1236 -0
- package/bin/memorax-code.mjs +204 -0
- package/docs/configuration.md +232 -0
- package/docs/troubleshooting.md +179 -0
- package/lib/client-hook-runtime.mjs +32 -0
- package/lib/memorax-code-adapter-common/src/backend-connection.d.mts +111 -0
- package/lib/memorax-code-adapter-common/src/backend-connection.mjs +304 -0
- package/lib/memorax-code-adapter-common/src/clients/claude-command.mjs +38 -0
- package/lib/memorax-code-adapter-common/src/clients/codex-command.mjs +41 -0
- package/lib/memorax-code-adapter-common/src/clients/codex-plugin-artifact.d.mts +3 -0
- package/lib/memorax-code-adapter-common/src/clients/codex-plugin-artifact.mjs +38 -0
- package/lib/memorax-code-adapter-common/src/config-utils.d.mts +27 -0
- package/lib/memorax-code-adapter-common/src/config-utils.mjs +391 -0
- package/lib/memorax-code-adapter-common/src/hooks/capture-cwd-hook.mjs +137 -0
- package/lib/memorax-code-adapter-common/src/hooks/client-hook-launcher.mjs +324 -0
- package/lib/memorax-code-adapter-common/src/hooks/ensure-backend-runner.mjs +142 -0
- package/lib/memorax-code-adapter-common/src/hooks/hook-runtime-generation.d.mts +38 -0
- package/lib/memorax-code-adapter-common/src/hooks/hook-runtime-generation.mjs +501 -0
- package/lib/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +277 -0
- package/lib/memorax-code-adapter-common/src/memorax-code-config-file.d.mts +28 -0
- package/lib/memorax-code-adapter-common/src/memorax-code-config-file.mjs +296 -0
- package/lib/memorax-code-adapter-common/src/memorax-defaults.d.mts +10 -0
- package/lib/memorax-code-adapter-common/src/memorax-defaults.mjs +12 -0
- package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-job-context.mjs +28 -0
- package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-job-marker.mjs +252 -0
- package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-job-supervisor.mjs +559 -0
- package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-job-worker.mjs +411 -0
- package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-update-policy-evaluator.mjs +185 -0
- package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-update-policy.mjs +165 -0
- package/lib/memorax-code-adapter-common/src/repo-memory/repo-procedure-memory-context.mjs +181 -0
- package/lib/memorax-code-adapter-common/src/repo-memory/repo-user-profile-context.mjs +251 -0
- package/lib/memorax-code-adapter-common/src/runtime-record.d.mts +55 -0
- package/lib/memorax-code-adapter-common/src/runtime-record.mjs +152 -0
- package/lib/memorax-code-adapter-common/src/windows-cli-invocation.mjs +100 -0
- package/lib/memorax-code-backend/dist/active-client-selection.js +35 -0
- package/lib/memorax-code-backend/dist/adapter-lifecycle-participant.js +1 -0
- package/lib/memorax-code-backend/dist/automatic-memory-retrieval.js +113 -0
- package/lib/memorax-code-backend/dist/automatic-memory-writeback.js +297 -0
- package/lib/memorax-code-backend/dist/backend-env.js +13 -0
- package/lib/memorax-code-backend/dist/backend-lifecycle-lock.js +42 -0
- package/lib/memorax-code-backend/dist/backend-process.js +147 -0
- package/lib/memorax-code-backend/dist/backend-service-cleanup.js +18 -0
- package/lib/memorax-code-backend/dist/backend-service-record.js +206 -0
- package/lib/memorax-code-backend/dist/backend-service-result.js +37 -0
- package/lib/memorax-code-backend/dist/backend-service-token.js +11 -0
- package/lib/memorax-code-backend/dist/backend-shutdown-request.js +133 -0
- package/lib/memorax-code-backend/dist/backend-state.js +58 -0
- package/lib/memorax-code-backend/dist/backend-status.js +53 -0
- package/lib/memorax-code-backend/dist/backend-token-record.js +79 -0
- package/lib/memorax-code-backend/dist/claude-adapter-lifecycle.js +134 -0
- package/lib/memorax-code-backend/dist/claude-local-transcript.js +648 -0
- package/lib/memorax-code-backend/dist/claude-memory-hook-runtime.js +472 -0
- package/lib/memorax-code-backend/dist/claude-transcript-turn.js +876 -0
- package/lib/memorax-code-backend/dist/client-plugin-removal.js +67 -0
- package/lib/memorax-code-backend/dist/client-selection.js +36 -0
- package/lib/memorax-code-backend/dist/codex-adapter-lifecycle.js +131 -0
- package/lib/memorax-code-backend/dist/codex-effective-prompt.js +54 -0
- package/lib/memorax-code-backend/dist/codex-memory-hook-runtime.js +541 -0
- package/lib/memorax-code-backend/dist/codex-plugin-hooks.js +421 -0
- package/lib/memorax-code-backend/dist/codex-plugin-install.js +523 -0
- package/lib/memorax-code-backend/dist/codex-rollout-turn.js +402 -0
- package/lib/memorax-code-backend/dist/codex-session-turn-index.js +88 -0
- package/lib/memorax-code-backend/dist/codex-workspace-links.js +55 -0
- package/lib/memorax-code-backend/dist/debug-log.js +21 -0
- package/lib/memorax-code-backend/dist/entrypoint.js +14 -0
- package/lib/memorax-code-backend/dist/incremental-jsonl-projection.js +271 -0
- package/lib/memorax-code-backend/dist/install-watchdog.js +71 -0
- package/lib/memorax-code-backend/dist/jsonl-append.js +75 -0
- package/lib/memorax-code-backend/dist/memorax-adapter.js +451 -0
- package/lib/memorax-code-backend/dist/memorax-cli.js +14 -0
- package/lib/memorax-code-backend/dist/memorax-code-config.js +279 -0
- package/lib/memorax-code-backend/dist/memorax-code-lifecycle.js +523 -0
- package/lib/memorax-code-backend/dist/memorax-code.js +3 -0
- package/lib/memorax-code-backend/dist/memorax-config.js +283 -0
- package/lib/memorax-code-backend/dist/memorax-http.js +142 -0
- package/lib/memorax-code-backend/dist/memory-cli.js +345 -0
- package/lib/memorax-code-backend/dist/memory-hook-command.js +200 -0
- package/lib/memorax-code-backend/dist/memory-observability.js +1 -0
- package/lib/memorax-code-backend/dist/memory-project.js +89 -0
- package/lib/memorax-code-backend/dist/memory-reminder-trace-recorder.js +58 -0
- package/lib/memorax-code-backend/dist/memory-service.js +66 -0
- package/lib/memorax-code-backend/dist/memory-turn-coordinator.js +139 -0
- package/lib/memorax-code-backend/dist/memory-viewer-activity.js +113 -0
- package/lib/memorax-code-backend/dist/memory-viewer-data-projection-cache.js +69 -0
- package/lib/memorax-code-backend/dist/memory-viewer-event-identity.js +3 -0
- package/lib/memorax-code-backend/dist/memory-viewer-history-projection.js +79 -0
- package/lib/memorax-code-backend/dist/memory-viewer-logo.js +1 -0
- package/lib/memorax-code-backend/dist/memory-viewer-observability.js +8 -0
- package/lib/memorax-code-backend/dist/memory-viewer-redaction.js +52 -0
- package/lib/memorax-code-backend/dist/memory-viewer-session-title.js +93 -0
- package/lib/memorax-code-backend/dist/memory-viewer-store.js +964 -0
- package/lib/memorax-code-backend/dist/memory-viewer-turn-reference.js +12 -0
- package/lib/memorax-code-backend/dist/memory-viewer-user-html.js +115 -0
- package/lib/memorax-code-backend/dist/memory-viewer-user-projection.js +168 -0
- package/lib/memorax-code-backend/dist/memory-viewer-writeback-status.js +97 -0
- package/lib/memorax-code-backend/dist/memory-writeback-buffer.js +217 -0
- package/lib/memorax-code-backend/dist/memory-writeback-chunk.js +120 -0
- package/lib/memorax-code-backend/dist/memory-writeback-reconciler.js +244 -0
- package/lib/memorax-code-backend/dist/memory-writeback-task-projection.js +377 -0
- package/lib/memorax-code-backend/dist/proxy-env.js +54 -0
- package/lib/memorax-code-backend/dist/repo-memory-readiness.js +188 -0
- package/lib/memorax-code-backend/dist/repository-memory-context.js +134 -0
- package/lib/memorax-code-backend/dist/repository-memory-scope.js +490 -0
- package/lib/memorax-code-backend/dist/server-cli.js +787 -0
- package/lib/memorax-code-backend/dist/server-health.js +16 -0
- package/lib/memorax-code-backend/dist/server-http.js +110 -0
- package/lib/memorax-code-backend/dist/server-json.js +4 -0
- package/lib/memorax-code-backend/dist/server-memory-hook.js +32 -0
- package/lib/memorax-code-backend/dist/server-memory-viewer.js +135 -0
- package/lib/memorax-code-backend/dist/server-observability.js +102 -0
- package/lib/memorax-code-backend/dist/server.js +220 -0
- package/lib/memorax-code-backend/dist/service-entrypoint.js +10 -0
- package/lib/memorax-code-backend/dist/service.js +567 -0
- package/lib/memorax-code-backend/dist/trace-config.js +112 -0
- package/lib/memorax-code-backend/dist/trace-context.js +111 -0
- package/lib/memorax-code-backend/dist/trace-store.js +571 -0
- package/lib/memorax-code-backend/dist/utils.js +3 -0
- package/lib/memorax-code-backend/dist/windows-cli-invocation.js +148 -0
- package/lib/memorax-code-backend/package.json +26 -0
- package/lib/memorax-code-claude-adapter/.claude-plugin/plugin.json +15 -0
- package/lib/memorax-code-claude-adapter/hooks/hook-launcher.mjs +27 -0
- package/lib/memorax-code-claude-adapter/hooks/hooks.json +66 -0
- package/lib/memorax-code-claude-adapter/hooks/repo-memory-job.mjs +37 -0
- package/lib/memorax-code-claude-adapter/hooks/runtime-hook.mjs +4 -0
- package/lib/memorax-code-claude-adapter/hooks/runtime-shell.json +5 -0
- package/lib/memorax-code-claude-adapter/package.json +13 -0
- package/lib/memorax-code-claude-adapter/runtime-hooks/capture-cwd.mjs +17 -0
- package/lib/memorax-code-claude-adapter/runtime-hooks/ensure-backend.mjs +59 -0
- package/lib/memorax-code-claude-adapter/runtime-hooks/memory-cli-session.mjs +33 -0
- package/lib/memorax-code-claude-adapter/runtime-hooks/memory-skill-reminder.mjs +73 -0
- package/lib/memorax-code-claude-adapter/runtime-hooks/memory-turn.mjs +91 -0
- package/lib/memorax-code-claude-adapter/scripts/build-marketplace.mjs +99 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/SKILL.md +83 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/agents/claude.yaml +10 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/agents/openai.yaml +7 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/defaults.json +9 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +82 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +61 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/personal-read.md +46 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/personal-write.md +100 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-build.md +270 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-read.md +96 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-templates.md +270 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-update.md +116 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/collect_all.py +496 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/detect_updates.py +856 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/github_resource_facets.py +504 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +509 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
- package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/validate_memory.py +226 -0
- package/lib/memorax-code-claude-adapter/src/adapter-paths.mjs +46 -0
- package/lib/memorax-code-claude-adapter/src/cli.mjs +363 -0
- package/lib/memorax-code-claude-adapter/src/config-utils.mjs +1 -0
- package/lib/memorax-code-claude-adapter/src/config.mjs +544 -0
- package/lib/memorax-code-claude-adapter/src/plugin-artifact-contract.mjs +148 -0
- package/lib/memorax-code-claude-adapter/src/plugin-install.mjs +566 -0
- package/lib/memorax-code-claude-marketplace/.claude-plugin/marketplace.json +15 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/.claude-plugin/plugin.json +15 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/hook-launcher.mjs +27 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/hooks.json +66 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/repo-memory-job.mjs +37 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/runtime-hook.mjs +4 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/runtime-shell.json +5 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/backend-connection.d.mts +111 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/backend-connection.mjs +304 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/clients/claude-command.mjs +38 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/clients/codex-command.mjs +41 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/clients/codex-plugin-artifact.d.mts +3 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/clients/codex-plugin-artifact.mjs +38 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/config-utils.d.mts +27 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/config-utils.mjs +391 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/capture-cwd-hook.mjs +137 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/client-hook-launcher.mjs +324 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/ensure-backend-runner.mjs +142 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/hook-runtime-generation.d.mts +38 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/hook-runtime-generation.mjs +501 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +277 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/memorax-code-config-file.d.mts +28 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/memorax-code-config-file.mjs +296 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/memorax-defaults.d.mts +10 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/memorax-defaults.mjs +12 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-job-context.mjs +28 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-job-marker.mjs +252 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-job-supervisor.mjs +559 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-job-worker.mjs +411 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-update-policy-evaluator.mjs +185 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-update-policy.mjs +165 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-procedure-memory-context.mjs +181 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-user-profile-context.mjs +251 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/runtime-record.d.mts +55 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/runtime-record.mjs +152 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/windows-cli-invocation.mjs +100 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/package.json +13 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/capture-cwd.mjs +17 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/ensure-backend.mjs +59 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/memory-cli-session.mjs +33 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/memory-skill-reminder.mjs +73 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/memory-turn.mjs +91 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/scripts/build-marketplace.mjs +99 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/SKILL.md +83 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/agents/claude.yaml +10 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/agents/openai.yaml +7 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/defaults.json +9 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +82 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +61 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/personal-read.md +46 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/personal-write.md +100 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-build.md +270 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-read.md +96 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-templates.md +270 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-update.md +116 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/collect_all.py +496 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/detect_updates.py +856 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/github_resource_facets.py +504 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +509 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/validate_memory.py +226 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/adapter-paths.mjs +46 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/cli.mjs +363 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/config-utils.mjs +1 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/config.mjs +544 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/plugin-artifact-contract.mjs +148 -0
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/plugin-install.mjs +566 -0
- package/lib/memorax-code-codex-adapter/.codex-plugin/plugin.json +33 -0
- package/lib/memorax-code-codex-adapter/assets/composer-icon.png +0 -0
- package/lib/memorax-code-codex-adapter/assets/logo.png +0 -0
- package/lib/memorax-code-codex-adapter/hooks/hook-launcher.mjs +26 -0
- package/lib/memorax-code-codex-adapter/hooks/hooks.json +61 -0
- package/lib/memorax-code-codex-adapter/hooks/repo-memory-job.mjs +38 -0
- package/lib/memorax-code-codex-adapter/hooks/repo-memory-update-policy.mjs +10 -0
- package/lib/memorax-code-codex-adapter/hooks/runtime-hook.mjs +4 -0
- package/lib/memorax-code-codex-adapter/hooks/runtime-shell.json +5 -0
- package/lib/memorax-code-codex-adapter/package.json +13 -0
- package/lib/memorax-code-codex-adapter/runtime-hooks/capture-cwd.mjs +18 -0
- package/lib/memorax-code-codex-adapter/runtime-hooks/ensure-backend.mjs +82 -0
- package/lib/memorax-code-codex-adapter/runtime-hooks/memory-skill-reminder.mjs +125 -0
- package/lib/memorax-code-codex-adapter/runtime-hooks/memory-writeback.mjs +52 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/SKILL.md +83 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/agents/claude.yaml +10 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/agents/openai.yaml +7 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/defaults.json +9 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-add.md +82 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-search.md +61 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/personal-read.md +46 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/personal-write.md +100 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-build.md +270 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-read.md +96 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-templates.md +270 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-update.md +116 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/collect_all.py +496 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/detect_updates.py +856 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/github_resource_facets.py +504 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +509 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
- package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/validate_memory.py +226 -0
- package/lib/memorax-code-codex-adapter/src/adapter-paths.mjs +29 -0
- package/lib/memorax-code-codex-adapter/src/cli.mjs +368 -0
- package/lib/memorax-code-codex-adapter/src/config-utils.mjs +1 -0
- package/lib/memorax-code-codex-adapter/src/config.mjs +226 -0
- package/lib/memorax-code-codex-adapter/src/session-registry.mjs +331 -0
- package/lib/memorax-code-codex-adapter/src/workspace-kind.mjs +68 -0
- package/lib/node-version.mjs +11 -0
- package/lib/npm-invocation.mjs +31 -0
- package/lib/resolve-claude-command.mjs +47 -0
- package/lib/resolve-codex-command.mjs +94 -0
- package/lib/run-entrypoint.mjs +83 -0
- package/lib/vscode-extension-command.mjs +119 -0
- package/lib/windows-cli-invocation.mjs +100 -0
- package/package.json +45 -0
|
@@ -0,0 +1,1236 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
import { createInterface } from "node:readline/promises";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { parse } from "smol-toml";
|
|
9
|
+
import {
|
|
10
|
+
setTomlField,
|
|
11
|
+
updateConfigFileAtomically,
|
|
12
|
+
} from "../lib/memorax-code-adapter-common/src/memorax-code-config-file.mjs";
|
|
13
|
+
import {
|
|
14
|
+
MEMORAX_ACCOUNT_URL,
|
|
15
|
+
MEMORAX_DEFAULT_BASE_URL,
|
|
16
|
+
MEMORAX_DEFAULT_MEMORY_OUTPUT_LANGUAGE,
|
|
17
|
+
normalizeMemoraxBaseUrl,
|
|
18
|
+
normalizeMemoraxMemoryOutputLanguage,
|
|
19
|
+
} from "../lib/memorax-code-adapter-common/src/memorax-defaults.mjs";
|
|
20
|
+
import { stagePackagedClientHookRuntime } from "../lib/client-hook-runtime.mjs";
|
|
21
|
+
import { ensureClaudeCommandEnv } from "../lib/resolve-claude-command.mjs";
|
|
22
|
+
import { ensureCodexCommandEnv } from "../lib/resolve-codex-command.mjs";
|
|
23
|
+
import { resolveWindowsCliInvocation } from "../lib/windows-cli-invocation.mjs";
|
|
24
|
+
|
|
25
|
+
const PLUGIN_NAME = "memorax-code-codex-adapter";
|
|
26
|
+
const CLI_MARKETPLACE_NAME = "memorax-code";
|
|
27
|
+
const PERSONAL_MARKETPLACE_NAME = "personal";
|
|
28
|
+
const PREVIOUS_HOOKS_ENV = "MEMORAX_CODE_CODEX_PREVIOUS_HOOKS_JSON";
|
|
29
|
+
const HOOK_TRUST_SELECTION_ENV = "MEMORAX_CODE_CODEX_HOOK_TRUST_SELECTION_JSON";
|
|
30
|
+
const PREFIX = "[MemoraX Code Install]:";
|
|
31
|
+
const BACKEND_PREFIX = "[MemoraX Code Backend]:";
|
|
32
|
+
const GREEN = "\x1b[32m";
|
|
33
|
+
const BLUE = "\x1b[34m";
|
|
34
|
+
const RED = "\x1b[31m";
|
|
35
|
+
const BOLD = "\x1b[1m";
|
|
36
|
+
const RESET = "\x1b[0m";
|
|
37
|
+
|
|
38
|
+
if (truthyEnv(process.env.MEMORAX_CODE_SKIP_POSTINSTALL)) process.exit(0);
|
|
39
|
+
const skipCodexPluginInstall = truthyEnv(process.env.MEMORAX_CODE_SKIP_CODEX_PLUGIN_INSTALL);
|
|
40
|
+
const skipClaudeAdapterInstall = truthyEnv(process.env.MEMORAX_CODE_SKIP_CLAUDE_ADAPTER_INSTALL);
|
|
41
|
+
|
|
42
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
43
|
+
const memoraxCodeBin = join(scriptDir, "memorax-code.mjs");
|
|
44
|
+
const memoraxCliBin = join(scriptDir, "memorax-cli.mjs");
|
|
45
|
+
const verbose = process.env.MEMORAX_CODE_NPM_POSTINSTALL_VERBOSE === "1";
|
|
46
|
+
const codexRuntime = ensureCodexCommandEnv();
|
|
47
|
+
const codexCommand = codexRuntime.command;
|
|
48
|
+
const claudeRuntime = ensureClaudeCommandEnv();
|
|
49
|
+
const claudeCommand = claudeRuntime.command;
|
|
50
|
+
const updatePostinstall = postinstallUpdateMode();
|
|
51
|
+
const scriptedAnswers = (canPrompt() || canPromptForHookUpdate()) && process.stdin.isTTY !== true
|
|
52
|
+
? parseScriptedAnswers(readFileSync(0, "utf8"))
|
|
53
|
+
: undefined;
|
|
54
|
+
const previousClients = readPersistedClientSelection();
|
|
55
|
+
if (seedMissingMemoraxCodeConfig() === "failed") {
|
|
56
|
+
printPostinstallSummary("not-verified");
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
|
59
|
+
let stagedHookRuntime;
|
|
60
|
+
try {
|
|
61
|
+
stagedHookRuntime = await stagePackagedClientHookRuntime({
|
|
62
|
+
packageRoot: dirname(scriptDir),
|
|
63
|
+
memoraxCodeHome: memoraxCodeHome(),
|
|
64
|
+
});
|
|
65
|
+
process.env.MEMORAX_CODE_DEFER_CLIENT_HOOK_RUNTIME_ACTIVATION = "1";
|
|
66
|
+
} catch (error) {
|
|
67
|
+
logRed(`Client Hook runtime staging failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
68
|
+
logRed("Backend and plugin mutation were skipped; the previously active runtime remains authoritative.");
|
|
69
|
+
printPostinstallSummary("not-verified");
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
runCommonPreflight();
|
|
73
|
+
const requestedClients = previousClients ?? ["codex", "claude"];
|
|
74
|
+
const codexPreflight = requestedClients.includes("codex") && !skipCodexPluginInstall
|
|
75
|
+
? runCodexPreflight()
|
|
76
|
+
: { ok: true, pluginCache: { marketplaceName: CLI_MARKETPLACE_NAME, versions: [] } };
|
|
77
|
+
const claudePreflight = requestedClients.includes("claude") && !skipClaudeAdapterInstall
|
|
78
|
+
? runClaudePreflight()
|
|
79
|
+
: { ok: true };
|
|
80
|
+
const installClients = requestedClients.filter((client) => {
|
|
81
|
+
if (client === "codex") return !skipCodexPluginInstall && codexPreflight.ok;
|
|
82
|
+
return !skipClaudeAdapterInstall && claudePreflight.ok;
|
|
83
|
+
});
|
|
84
|
+
const selectedClients = previousClients ?? installClients;
|
|
85
|
+
if (previousClients) {
|
|
86
|
+
log(clientSelectionMessage(previousClients));
|
|
87
|
+
} else {
|
|
88
|
+
log(detectedClientMessage(installClients));
|
|
89
|
+
}
|
|
90
|
+
if (requestedClients.includes("codex") && !skipCodexPluginInstall && !codexPreflight.ok) {
|
|
91
|
+
log("Codex runtime was not detected; skipping its adapter setup.");
|
|
92
|
+
}
|
|
93
|
+
if (requestedClients.includes("claude") && !skipClaudeAdapterInstall && !claudePreflight.ok) {
|
|
94
|
+
log("Claude Code runtime was not detected; skipping its adapter setup.");
|
|
95
|
+
}
|
|
96
|
+
if (writeClientSelectionConfig(selectedClients) === "failed") {
|
|
97
|
+
printPostinstallSummary("not-verified");
|
|
98
|
+
process.exit(0);
|
|
99
|
+
}
|
|
100
|
+
const clientMode = clientModeFor(installClients);
|
|
101
|
+
let memoraxConfigResult = "skipped";
|
|
102
|
+
if (installClients.length > 0) {
|
|
103
|
+
memoraxConfigResult = await maybeConfigureMemoraxMemory(scriptedAnswers);
|
|
104
|
+
}
|
|
105
|
+
if (memoraxConfigResult === "configured") {
|
|
106
|
+
if (seedMissingMemoraxCodeConfig() === "failed") {
|
|
107
|
+
printPostinstallSummary("not-verified");
|
|
108
|
+
process.exit(0);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const codexClientEnabled = installClients.includes("codex");
|
|
112
|
+
const claudeClientEnabled = installClients.includes("claude");
|
|
113
|
+
const codexHooksBeforeUpdate = codexClientEnabled && updatePostinstall
|
|
114
|
+
? inspectCodexPluginHooksForUpdate()
|
|
115
|
+
: undefined;
|
|
116
|
+
const result = codexClientEnabled
|
|
117
|
+
? runNodeMemoraxCodeCommand(["codex-plugin", "install", "--json"], { print: verbose })
|
|
118
|
+
: { status: 0 };
|
|
119
|
+
|
|
120
|
+
if (codexClientEnabled && result.status !== 0 && process.env.npm_lifecycle_event) {
|
|
121
|
+
logRed("MemoraX Code Codex plugin registration was skipped or failed. Run `memorax-code codex-plugin install` after installation.");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (codexClientEnabled && result.status === 0) {
|
|
125
|
+
if (updatePostinstall) await maybeTrustUpdatedCodexPluginHooks(scriptedAnswers, codexHooksBeforeUpdate);
|
|
126
|
+
else await maybeActivateCodexPluginHooks(scriptedAnswers);
|
|
127
|
+
}
|
|
128
|
+
const skipCodexAdapter = !codexClientEnabled;
|
|
129
|
+
const skipClaudeAdapter = !claudeClientEnabled;
|
|
130
|
+
const codexSkipReason = postinstallClientSkipReason({
|
|
131
|
+
explicitlySkipped: skipCodexPluginInstall,
|
|
132
|
+
selected: selectedClients.includes("codex"),
|
|
133
|
+
enabled: codexClientEnabled,
|
|
134
|
+
});
|
|
135
|
+
const claudeSkipReason = postinstallClientSkipReason({
|
|
136
|
+
explicitlySkipped: skipClaudeAdapterInstall,
|
|
137
|
+
selected: selectedClients.includes("claude"),
|
|
138
|
+
enabled: claudeClientEnabled,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
let backendAndAdaptersStatus = startBackendAndCheck({
|
|
142
|
+
skipCodexAdapter,
|
|
143
|
+
clientMode,
|
|
144
|
+
codexSkipReason,
|
|
145
|
+
skipClaudeAdapter,
|
|
146
|
+
claudeAdapterRequired: !skipClaudeAdapter,
|
|
147
|
+
claudeSkipReason,
|
|
148
|
+
});
|
|
149
|
+
if (backendAndAdaptersStatus === "enabled") {
|
|
150
|
+
logGreen(`Client Hook runtime ${stagedHookRuntime.generationId} activated.`);
|
|
151
|
+
}
|
|
152
|
+
if (backendAndAdaptersStatus === "enabled") {
|
|
153
|
+
printNextSteps({ codexAdapterEnabled: !skipCodexAdapter, claudeAdapterEnabled: !skipClaudeAdapter });
|
|
154
|
+
printCommonCommands({ codexAdapterEnabled: !skipCodexAdapter, claudeAdapterEnabled: !skipClaudeAdapter });
|
|
155
|
+
}
|
|
156
|
+
printPostinstallSummary(backendAndAdaptersStatus);
|
|
157
|
+
if (backendAndAdaptersStatus === "enabled") {
|
|
158
|
+
log("View local memory activity: http://127.0.0.1:8787/memory-viewer");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Do not fail npm installation: users can register the plugin explicitly later.
|
|
162
|
+
process.exit(0);
|
|
163
|
+
|
|
164
|
+
async function maybeConfigureMemoraxMemory(scriptedAnswers) {
|
|
165
|
+
printMemoraxDisclosure();
|
|
166
|
+
if (!canPrompt()) {
|
|
167
|
+
log(`This install cannot prompt for a MemoraX ID and key. Register at ${MEMORAX_ACCOUNT_URL}, then edit \`~/.memorax-code/config.toml\` or rerun interactively with \`--foreground-scripts\`.`);
|
|
168
|
+
return "skipped";
|
|
169
|
+
}
|
|
170
|
+
if (scriptedAnswers) {
|
|
171
|
+
return await configureMemoraxMemoryFromAnswers(scriptedAnswers);
|
|
172
|
+
}
|
|
173
|
+
let rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
174
|
+
try {
|
|
175
|
+
const configureNow = await rl.question(`${PREFIX} Connect MemoraX Code to MemoraX now? [Y/n] `);
|
|
176
|
+
if (/^n(?:o)?$/i.test(configureNow.trim())) {
|
|
177
|
+
log("MemoraX connection skipped. MemoraX Code memory is not fully configured until valid credentials are supplied.");
|
|
178
|
+
return "skipped";
|
|
179
|
+
}
|
|
180
|
+
log(`If you do not have a MemoraX account/API key, register at ${MEMORAX_ACCOUNT_URL}.`);
|
|
181
|
+
const userId = (await rl.question(`${PREFIX} MemoraX base user ID: `)).trim();
|
|
182
|
+
const outputLanguage = await questionPreferredLanguage(rl);
|
|
183
|
+
rl.close();
|
|
184
|
+
rl = undefined;
|
|
185
|
+
const apiKey = (await questionMasked(`${PREFIX} MemoraX API key: `)).trim();
|
|
186
|
+
return await writeMemoraxConfigFromInput({
|
|
187
|
+
userId,
|
|
188
|
+
apiKey,
|
|
189
|
+
endpoint: memoraxInstallEndpoint(),
|
|
190
|
+
outputLanguage,
|
|
191
|
+
});
|
|
192
|
+
} finally {
|
|
193
|
+
rl?.close();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async function configureMemoraxMemoryFromAnswers(answers) {
|
|
198
|
+
if (answers.length === 0) {
|
|
199
|
+
log(`No MemoraX connection response was received. Register at ${MEMORAX_ACCOUNT_URL}, then edit \`~/.memorax-code/config.toml\` or rerun interactively with \`--foreground-scripts\`.`);
|
|
200
|
+
return "skipped";
|
|
201
|
+
}
|
|
202
|
+
log("Connect MemoraX Code to MemoraX now? [Y/n]");
|
|
203
|
+
const configureNow = String(answers.shift() ?? "").trim();
|
|
204
|
+
if (/^n(?:o)?$/i.test(configureNow)) {
|
|
205
|
+
log("MemoraX connection skipped. MemoraX Code memory is not fully configured until valid credentials are supplied.");
|
|
206
|
+
return "skipped";
|
|
207
|
+
}
|
|
208
|
+
log(`If you do not have a MemoraX account/API key, register at ${MEMORAX_ACCOUNT_URL}.`);
|
|
209
|
+
log("MemoraX base user ID: <provided>");
|
|
210
|
+
const userId = String(answers.shift() ?? "").trim();
|
|
211
|
+
const outputLanguageAnswer = String(answers.shift() ?? "").trim();
|
|
212
|
+
log(`Preferred language [ZH/en] (used for Memory extraction): ${outputLanguageAnswer ? "<provided>" : "<default>"}`);
|
|
213
|
+
log("MemoraX API key: <provided>");
|
|
214
|
+
const apiKey = String(answers.shift() ?? "").trim();
|
|
215
|
+
return await writeMemoraxConfigFromInput({
|
|
216
|
+
userId,
|
|
217
|
+
apiKey,
|
|
218
|
+
endpoint: memoraxInstallEndpoint(),
|
|
219
|
+
outputLanguage: preferredLanguage(outputLanguageAnswer),
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function printMemoraxDisclosure() {
|
|
224
|
+
log("MemoraX Code requires MemoraX for its core remote-memory functionality.");
|
|
225
|
+
log("After connection, trusted repository sessions automatically send selected user prompts and final assistant answers to MemoraX after replies.");
|
|
226
|
+
log("Newly generated configuration enables automatic writeback. Existing configuration is never enabled implicitly; disable it with `[memory.writeback] enabled = false` or `MEMORAX_CODE_MEMORAX_WRITEBACK_ENABLED=false`.");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function writeMemoraxConfigFromInput({ userId, apiKey, endpoint, outputLanguage }) {
|
|
230
|
+
if (!userId || !apiKey) {
|
|
231
|
+
logRed("MemoraX config was not written because base user ID or API key was empty.");
|
|
232
|
+
return "skipped";
|
|
233
|
+
}
|
|
234
|
+
if (!outputLanguage) {
|
|
235
|
+
logRed("MemoraX config was not written because preferred language must be zh or en.");
|
|
236
|
+
return "skipped";
|
|
237
|
+
}
|
|
238
|
+
if (writeMemoraxConfig({ userId, apiKey, endpoint, outputLanguage }) === "failed") {
|
|
239
|
+
logRed("MemoraX config was not written because the existing config could not be safely updated.");
|
|
240
|
+
return "skipped";
|
|
241
|
+
}
|
|
242
|
+
logGreen(`MemoraX config written to ${memoraxCodeConfigPath()}.`);
|
|
243
|
+
log("MemoraX network access will be checked by the first workspace-scoped memory request from a trusted workspace.");
|
|
244
|
+
return "configured";
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async function questionPreferredLanguage(rl) {
|
|
248
|
+
while (true) {
|
|
249
|
+
const answer = await rl.question(`${PREFIX} Preferred language [ZH/en] (used for Memory extraction): `);
|
|
250
|
+
const language = preferredLanguage(answer);
|
|
251
|
+
if (language) return language;
|
|
252
|
+
logRed("Preferred language must be zh or en.");
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function preferredLanguage(value) {
|
|
257
|
+
const trimmed = String(value ?? "").trim();
|
|
258
|
+
return trimmed
|
|
259
|
+
? normalizeMemoraxMemoryOutputLanguage(trimmed)
|
|
260
|
+
: MEMORAX_DEFAULT_MEMORY_OUTPUT_LANGUAGE;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function memoraxInstallEndpoint() {
|
|
264
|
+
return normalizeMemoraxBaseUrl(process.env.MEMORAX_CODE_MEMORAX_ENDPOINT) || MEMORAX_DEFAULT_BASE_URL;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function isRecord(value) {
|
|
268
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async function questionMasked(prompt) {
|
|
272
|
+
if (process.stdin.isTTY !== true || typeof process.stdin.setRawMode !== "function") {
|
|
273
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
274
|
+
try {
|
|
275
|
+
return await rl.question(prompt);
|
|
276
|
+
} finally {
|
|
277
|
+
rl.close();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
process.stderr.write(prompt);
|
|
281
|
+
const wasRaw = process.stdin.isRaw === true;
|
|
282
|
+
process.stdin.setRawMode(true);
|
|
283
|
+
process.stdin.resume();
|
|
284
|
+
return await new Promise((resolve, reject) => {
|
|
285
|
+
let answer = "";
|
|
286
|
+
const cleanup = () => {
|
|
287
|
+
process.stdin.off("data", onData);
|
|
288
|
+
process.stdin.setRawMode(wasRaw);
|
|
289
|
+
if (!wasRaw) process.stdin.pause();
|
|
290
|
+
};
|
|
291
|
+
const finish = () => {
|
|
292
|
+
cleanup();
|
|
293
|
+
process.stderr.write("\n");
|
|
294
|
+
resolve(answer);
|
|
295
|
+
};
|
|
296
|
+
const onData = (chunk) => {
|
|
297
|
+
for (const char of String(chunk)) {
|
|
298
|
+
if (char === "\u0003") {
|
|
299
|
+
cleanup();
|
|
300
|
+
process.stderr.write("\n");
|
|
301
|
+
reject(new Error("Interrupted"));
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (char === "\r" || char === "\n") {
|
|
305
|
+
finish();
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
if (char === "\u0008" || char === "\u007f") {
|
|
309
|
+
if (answer.length > 0) {
|
|
310
|
+
answer = answer.slice(0, -1);
|
|
311
|
+
process.stderr.write("\b \b");
|
|
312
|
+
}
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
if (char >= " " && char !== "\u007f") {
|
|
316
|
+
answer += char;
|
|
317
|
+
process.stderr.write("*");
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
process.stdin.on("data", onData);
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function inspectCodexPluginHooksForUpdate() {
|
|
326
|
+
const result = runNodeMemoraxCodeCommand(codexPluginHookArgs("hooks"), { print: false });
|
|
327
|
+
const report = parseCodexPluginHookReport(result, "codex-plugin-hooks");
|
|
328
|
+
return report?.hooks;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
async function maybeTrustUpdatedCodexPluginHooks(scriptedAnswers, previousHooks) {
|
|
332
|
+
if (!previousHooks) {
|
|
333
|
+
warnUpdatedHookTrustSkipped("Existing Codex hooks could not be inspected before the plugin cache refresh.");
|
|
334
|
+
return "skipped";
|
|
335
|
+
}
|
|
336
|
+
const checkEnv = hookTrustCommandEnv(PREVIOUS_HOOKS_ENV, previousHooks);
|
|
337
|
+
const checked = runNodeMemoraxCodeCommand(codexPluginHookArgs("trust-hooks", ["--check"]), {
|
|
338
|
+
env: checkEnv,
|
|
339
|
+
print: false,
|
|
340
|
+
});
|
|
341
|
+
const report = parseCodexPluginHookReport(checked, "codex-plugin-trust-hooks");
|
|
342
|
+
if (!report) {
|
|
343
|
+
warnUpdatedHookTrustSkipped("Updated Codex hooks could not be inspected after the plugin cache refresh.");
|
|
344
|
+
return "skipped";
|
|
345
|
+
}
|
|
346
|
+
if (report.requiresFullReview) {
|
|
347
|
+
warnUpdatedHookTrustSkipped("The MemoraX Code Codex plugin marketplace identity changed during the update, so incremental Hook authorization was not applied.");
|
|
348
|
+
return "skipped";
|
|
349
|
+
}
|
|
350
|
+
if (report.hooks.length === 0) return "unchanged";
|
|
351
|
+
|
|
352
|
+
printUpdatedCodexHooks(report.hooks, previousHooks);
|
|
353
|
+
if (!canPromptForHookUpdate()) {
|
|
354
|
+
warnUpdatedHookTrustSkipped("This update is running without an interactive terminal, so the new or changed Hooks remain untrusted.");
|
|
355
|
+
return "skipped";
|
|
356
|
+
}
|
|
357
|
+
const answer = await updatedHookTrustAnswer(scriptedAnswers);
|
|
358
|
+
if (answer === undefined) {
|
|
359
|
+
warnUpdatedHookTrustSkipped("No Hook authorization response was received, so the new or changed Hooks remain untrusted.");
|
|
360
|
+
return "skipped";
|
|
361
|
+
}
|
|
362
|
+
const normalizedAnswer = answer.trim();
|
|
363
|
+
if (normalizedAnswer && !/^y(?:es)?$/i.test(normalizedAnswer)) {
|
|
364
|
+
warnUpdatedHookTrustSkipped("Hook authorization was declined, so the new or changed Hooks remain untrusted.");
|
|
365
|
+
return "skipped";
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const trustEnv = hookTrustCommandEnv(HOOK_TRUST_SELECTION_ENV, report.hooks);
|
|
369
|
+
const trusted = runNodeMemoraxCodeCommand(codexPluginHookArgs("trust-hooks", ["--yes"]), {
|
|
370
|
+
env: trustEnv,
|
|
371
|
+
print: verbose,
|
|
372
|
+
});
|
|
373
|
+
if (trusted.status === 0) {
|
|
374
|
+
logGreen(`Trusted ${report.hooks.length} new or changed MemoraX Code Codex Hook${report.hooks.length === 1 ? "" : "s"}.`);
|
|
375
|
+
return "trusted";
|
|
376
|
+
}
|
|
377
|
+
warnUpdatedHookTrustSkipped("The reviewed Hooks changed again or could not be written to Codex config.");
|
|
378
|
+
return "failed";
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function parseCodexPluginHookReport(result, action) {
|
|
382
|
+
if (result.status !== 0) return undefined;
|
|
383
|
+
try {
|
|
384
|
+
const report = JSON.parse(String(result.stdout ?? ""));
|
|
385
|
+
if (!report || report.ok !== true || report.action !== action || !Array.isArray(report.hooks)) return undefined;
|
|
386
|
+
if (!report.hooks.every((hook) => hook
|
|
387
|
+
&& typeof hook === "object"
|
|
388
|
+
&& typeof hook.key === "string"
|
|
389
|
+
&& typeof hook.currentHash === "string"
|
|
390
|
+
&& hook.handlerType === "command"
|
|
391
|
+
&& typeof hook.eventName === "string"
|
|
392
|
+
&& hook.eventName.length > 0
|
|
393
|
+
&& typeof hook.command === "string"
|
|
394
|
+
&& hook.command.length > 0
|
|
395
|
+
&& isCodexHookTrustStatus(hook.trustStatus))) return undefined;
|
|
396
|
+
if (action === "codex-plugin-trust-hooks"
|
|
397
|
+
&& (typeof report.requiresFullReview !== "boolean"
|
|
398
|
+
|| !report.hooks.every((hook) => hook.trustStatus === "untrusted" || hook.trustStatus === "modified"))) {
|
|
399
|
+
return undefined;
|
|
400
|
+
}
|
|
401
|
+
return report;
|
|
402
|
+
} catch {
|
|
403
|
+
return undefined;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function isCodexHookTrustStatus(value) {
|
|
408
|
+
return value === "managed" || value === "untrusted" || value === "trusted" || value === "modified";
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function codexPluginHookArgs(subcommand, extraArgs = []) {
|
|
412
|
+
const args = ["codex-plugin", subcommand, ...extraArgs];
|
|
413
|
+
const codexCommand = stringOption(process.env.MEMORAX_CODE_CODEX_COMMAND);
|
|
414
|
+
if (codexCommand) args.push("--codex-command", codexCommand);
|
|
415
|
+
const workspace = codexHookInspectionWorkspace();
|
|
416
|
+
if (workspace) args.push("--workspace", workspace);
|
|
417
|
+
args.push("--json");
|
|
418
|
+
return args;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function codexHookInspectionWorkspace() {
|
|
422
|
+
for (const candidate of [process.env.INIT_CWD, process.env.HOME, homedir(), process.cwd()]) {
|
|
423
|
+
if (candidate && existsSync(candidate)) return candidate;
|
|
424
|
+
}
|
|
425
|
+
return undefined;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function hookTrustCommandEnv(name, hooks) {
|
|
429
|
+
const env = { ...process.env };
|
|
430
|
+
delete env[PREVIOUS_HOOKS_ENV];
|
|
431
|
+
delete env[HOOK_TRUST_SELECTION_ENV];
|
|
432
|
+
env[name] = JSON.stringify(hooks);
|
|
433
|
+
return env;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function printUpdatedCodexHooks(hooks, previousHooks) {
|
|
437
|
+
const previousByKey = new Map(previousHooks.map((hook) => [hook.key, hook.currentHash]));
|
|
438
|
+
log("This MemoraX Code update includes new or changed Codex Hooks that require authorization:");
|
|
439
|
+
for (const hook of hooks) {
|
|
440
|
+
const change = previousByKey.has(hook.key) ? "changed" : "new";
|
|
441
|
+
const label = hook.statusMessage ? ` (${hook.statusMessage})` : "";
|
|
442
|
+
log(`- ${change}: ${hook.key}${label}`);
|
|
443
|
+
if (hook.eventName) log(` event: ${hook.eventName}`);
|
|
444
|
+
if (hook.command) log(` command: ${hook.command}`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
async function updatedHookTrustAnswer(scriptedAnswers) {
|
|
449
|
+
if (scriptedAnswers) {
|
|
450
|
+
log("Trust these new or changed Codex Hooks? [Y/n]");
|
|
451
|
+
return scriptedAnswers.shift();
|
|
452
|
+
}
|
|
453
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
454
|
+
try {
|
|
455
|
+
return await rl.question(`${PREFIX} Trust these new or changed Codex Hooks? [Y/n] `);
|
|
456
|
+
} finally {
|
|
457
|
+
rl.close();
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function parseScriptedAnswers(input) {
|
|
462
|
+
if (input.length === 0) return [];
|
|
463
|
+
const answers = input.split(/\r?\n/);
|
|
464
|
+
if (answers.at(-1) === "") answers.pop();
|
|
465
|
+
return answers;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function warnUpdatedHookTrustSkipped(message) {
|
|
469
|
+
logRed(message);
|
|
470
|
+
logRed("Review and authorize the current MemoraX Code Codex Hooks with `memorax-code codex-plugin trust-hooks`.");
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
async function maybeActivateCodexPluginHooks(scriptedAnswers) {
|
|
474
|
+
if (!canPrompt()) {
|
|
475
|
+
log("Codex hook activation was not prompted. Run `memorax-code codex-plugin activate --yes` later to activate and trust MemoraX Code Codex Adapter hooks.");
|
|
476
|
+
return "skipped";
|
|
477
|
+
}
|
|
478
|
+
if (scriptedAnswers) {
|
|
479
|
+
return activateCodexPluginHooksFromAnswers(scriptedAnswers);
|
|
480
|
+
}
|
|
481
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
482
|
+
try {
|
|
483
|
+
const activateNow = await rl.question(`${PREFIX} Activate and trust MemoraX Code Codex Adapter hooks now? [Y/n] `);
|
|
484
|
+
return activateCodexPluginHooksFromAnswer(activateNow);
|
|
485
|
+
} finally {
|
|
486
|
+
rl.close();
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function activateCodexPluginHooksFromAnswers(answers) {
|
|
491
|
+
log("Activate and trust MemoraX Code Codex Adapter hooks now? [Y/n]");
|
|
492
|
+
const activateNow = String(answers.shift() ?? "").trim();
|
|
493
|
+
return activateCodexPluginHooksFromAnswer(activateNow);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function activateCodexPluginHooksFromAnswer(answer) {
|
|
497
|
+
if (/^n(?:o)?$/i.test(String(answer ?? "").trim())) {
|
|
498
|
+
log("Codex hook activation skipped; run `memorax-code codex-plugin activate --yes` later if needed.");
|
|
499
|
+
return "skipped";
|
|
500
|
+
}
|
|
501
|
+
const activated = runNodeMemoraxCodeCommand(["codex-plugin", "activate", "--yes"], { print: verbose });
|
|
502
|
+
if (activated.status === 0) {
|
|
503
|
+
logGreen("MemoraX Code Codex Adapter hooks activated and trusted.");
|
|
504
|
+
return "activated";
|
|
505
|
+
}
|
|
506
|
+
logRed("Codex hook activation failed; run `memorax-code codex-plugin activate --yes` after installation.");
|
|
507
|
+
return "failed";
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function canPrompt() {
|
|
511
|
+
if (updatePostinstall) return false;
|
|
512
|
+
return canPromptOnStderr();
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function canPromptForHookUpdate() {
|
|
516
|
+
return updatePostinstall && canPromptOnStderr();
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function canPromptOnStderr() {
|
|
520
|
+
return process.env.MEMORAX_CODE_NPM_POSTINSTALL_ASSUME_INTERACTIVE === "1"
|
|
521
|
+
|| (process.stdin.isTTY === true && process.stderr.isTTY === true);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
function postinstallUpdateMode() {
|
|
525
|
+
return truthyEnv(process.env.MEMORAX_CODE_NPM_POSTINSTALL_UPDATE) || process.env.npm_command === "update";
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
function truthyEnv(value) {
|
|
529
|
+
return ["1", "true", "yes"].includes(String(value ?? "").toLowerCase());
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function memoraxCodeHome() {
|
|
533
|
+
return process.env.MEMORAX_CODE_HOME || join(homedir(), ".memorax-code");
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
function memoraxCodeConfigPath() {
|
|
537
|
+
return join(memoraxCodeHome(), "config.toml");
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
function readPersistedClientSelection() {
|
|
541
|
+
const path = memoraxCodeConfigPath();
|
|
542
|
+
if (!existsSync(path)) return undefined;
|
|
543
|
+
try {
|
|
544
|
+
const clients = parse(readFileSync(path, "utf8"))?.clients;
|
|
545
|
+
if (!clients || typeof clients !== "object" || typeof clients.codex !== "boolean" || typeof clients.claude !== "boolean") return undefined;
|
|
546
|
+
return [clients.codex ? "codex" : undefined, clients.claude ? "claude" : undefined].filter(Boolean);
|
|
547
|
+
} catch {
|
|
548
|
+
return undefined;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
function writeClientSelectionConfig(clients) {
|
|
553
|
+
const path = memoraxCodeConfigPath();
|
|
554
|
+
return updateConfigFileAtomically({
|
|
555
|
+
path,
|
|
556
|
+
defaultText: setManagedClientSelection(defaultMemoraxCodeConfig(), clients),
|
|
557
|
+
transform: (text) => setManagedClientSelection(text, clients),
|
|
558
|
+
parseToml: parse,
|
|
559
|
+
warn: (message) => log(message),
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
function setManagedClientSelection(text, clients) {
|
|
564
|
+
const withClaude = setTomlField(text, "clients", "claude", String(clients.includes("claude")));
|
|
565
|
+
return setTomlField(withClaude, "clients", "codex", String(clients.includes("codex")));
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
function writeMemoraxConfig({ userId, apiKey, endpoint, outputLanguage }) {
|
|
569
|
+
const path = memoraxCodeConfigPath();
|
|
570
|
+
const fields = [
|
|
571
|
+
{
|
|
572
|
+
key: "endpoint",
|
|
573
|
+
line: `endpoint = "${tomlString(endpoint || MEMORAX_DEFAULT_BASE_URL)}" # MemoraX service URL.`,
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
key: "api_key",
|
|
577
|
+
line: `api_key = "${tomlString(apiKey)}" # MemoraX API key used by the local Backend.`,
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
key: "user_id",
|
|
581
|
+
line: `user_id = "${tomlString(userId)}" # MemoraX base user ID; requests derive a workspace-scoped namespace.`,
|
|
582
|
+
},
|
|
583
|
+
];
|
|
584
|
+
const addFields = [{
|
|
585
|
+
key: "output_language",
|
|
586
|
+
line: `output_language = "${outputLanguage}" # Language for newly generated MemoraX memories.`,
|
|
587
|
+
}];
|
|
588
|
+
const applyFields = (text) => setTomlSectionFields(
|
|
589
|
+
setTomlSectionFields(text, "memorax", fields),
|
|
590
|
+
"memory.add",
|
|
591
|
+
addFields,
|
|
592
|
+
);
|
|
593
|
+
return updateConfigFileAtomically({
|
|
594
|
+
path,
|
|
595
|
+
defaultText: applyFields(defaultMemoraxCodeConfig()),
|
|
596
|
+
transform: applyFields,
|
|
597
|
+
parseToml: parse,
|
|
598
|
+
warn: (message) => log(message),
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
function defaultMemoraxCodeConfig() {
|
|
603
|
+
return [
|
|
604
|
+
"# MemoraX Code local config.",
|
|
605
|
+
"# This file is read from $MEMORAX_CODE_HOME/config.toml.",
|
|
606
|
+
"# Environment variables still override values written here.",
|
|
607
|
+
"# See docs/configuration.md for advanced tuning fields and effective defaults.",
|
|
608
|
+
"",
|
|
609
|
+
"[clients]",
|
|
610
|
+
"codex = true # Manage the Codex adapter.",
|
|
611
|
+
"claude = true # Manage the Claude adapter.",
|
|
612
|
+
"",
|
|
613
|
+
"# MemoraX remote-memory connection. Credentials may also come from the environment.",
|
|
614
|
+
"[memorax]",
|
|
615
|
+
`# endpoint = "${MEMORAX_DEFAULT_BASE_URL}" # MemoraX service URL.`,
|
|
616
|
+
'# api_key = "" # MemoraX API key used by the local Backend.',
|
|
617
|
+
'# user_id = "" # MemoraX base user ID; requests derive a workspace-scoped namespace.',
|
|
618
|
+
"",
|
|
619
|
+
"# Automatic Hook retrieval is opt-in.",
|
|
620
|
+
"[memory.retrieval]",
|
|
621
|
+
"enabled = false # Auto-inject retrieved memories into supported client prompts.",
|
|
622
|
+
"",
|
|
623
|
+
"# Automatic writeback sends selected prompts and final answers to MemoraX.",
|
|
624
|
+
"[memory.writeback]",
|
|
625
|
+
"enabled = true # Allow supported client sessions to write memories after replies.",
|
|
626
|
+
"",
|
|
627
|
+
"# Preferred language for newly generated MemoraX memories.",
|
|
628
|
+
"[memory.add]",
|
|
629
|
+
`output_language = "${MEMORAX_DEFAULT_MEMORY_OUTPUT_LANGUAGE}" # Language for newly generated MemoraX memories.`,
|
|
630
|
+
"",
|
|
631
|
+
"# Controls how often Codex and Claude Code native client sessions see the MemoraX Code skill reminder.",
|
|
632
|
+
"[memory.skill_reminder]",
|
|
633
|
+
"interval_turns = 5 # Show the MemoraX Code skill reminder every N native client turns, starting on the first turn.",
|
|
634
|
+
"",
|
|
635
|
+
"# Relevant repo reads batch generated repo-memory updates by commit count or elapsed time.",
|
|
636
|
+
"[memory.repo_update]",
|
|
637
|
+
'policy = "adaptive" # every-commit / commit-count / daily / pull-request / pull-request-or-daily / adaptive.',
|
|
638
|
+
"commit_threshold = 5 # Pending local commits needed by commit-count and adaptive.",
|
|
639
|
+
"cooldown_hours = 24 # Pending-commit age used by daily, pull-request-or-daily, and adaptive.",
|
|
640
|
+
"",
|
|
641
|
+
"# Local traces may contain prompts, responses, recalled memories, and local paths.",
|
|
642
|
+
"[trace.codex]",
|
|
643
|
+
"enabled = true # Enable local Codex session memory trace collection.",
|
|
644
|
+
"capture_content = true # Store content in local Codex trace events.",
|
|
645
|
+
"",
|
|
646
|
+
"[trace.claude]",
|
|
647
|
+
"enabled = true # Enable local Claude session memory trace collection.",
|
|
648
|
+
"capture_content = true # Store content in local Claude trace events.",
|
|
649
|
+
"",
|
|
650
|
+
].join("\n");
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
function seedMissingMemoraxCodeConfig() {
|
|
654
|
+
const path = memoraxCodeConfigPath();
|
|
655
|
+
return updateConfigFileAtomically({
|
|
656
|
+
path,
|
|
657
|
+
defaultText: defaultMemoraxCodeConfig(),
|
|
658
|
+
transform: (text) => text,
|
|
659
|
+
parseToml: parse,
|
|
660
|
+
warn: (message) => log(message),
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
function setTomlSectionFields(text, section, fields) {
|
|
665
|
+
const source = String(text ?? "");
|
|
666
|
+
const newline = source.includes("\r\n") ? "\r\n" : "\n";
|
|
667
|
+
const lines = source.split(/\r?\n/);
|
|
668
|
+
const escaped = section.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
669
|
+
const header = new RegExp(`^\\s*\\[(?:${escaped}|"${escaped}"|'${escaped}')\\]\\s*(?:#.*)?$`);
|
|
670
|
+
const start = lines.findIndex((line) => header.test(line));
|
|
671
|
+
if (start === -1) {
|
|
672
|
+
const separator = source.length === 0
|
|
673
|
+
? ""
|
|
674
|
+
: source.endsWith(`${newline}${newline}`)
|
|
675
|
+
? ""
|
|
676
|
+
: source.endsWith(newline)
|
|
677
|
+
? newline
|
|
678
|
+
: `${newline}${newline}`;
|
|
679
|
+
return `${source}${separator}[${section}]${newline}${fields.map((field) => field.line).join(newline)}${newline}`;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
const nextHeader = lines.findIndex((line, index) => index > start && /^\s*\[/.test(line));
|
|
683
|
+
const end = nextHeader === -1 ? lines.length : nextHeader;
|
|
684
|
+
const keys = fields
|
|
685
|
+
.map(({ key }) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
|
|
686
|
+
.flatMap((key) => [key, `"${key}"`, `'${key}'`])
|
|
687
|
+
.join("|");
|
|
688
|
+
const assignment = new RegExp(`^\\s*#?\\s*(?:${keys})\\s*=`);
|
|
689
|
+
const preservedBody = lines
|
|
690
|
+
.slice(start + 1, end)
|
|
691
|
+
.filter((line) => !assignment.test(line));
|
|
692
|
+
lines.splice(
|
|
693
|
+
start + 1,
|
|
694
|
+
end - start - 1,
|
|
695
|
+
...fields.map((field) => field.line),
|
|
696
|
+
...preservedBody,
|
|
697
|
+
);
|
|
698
|
+
return lines.join(newline);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
function tomlString(value) {
|
|
702
|
+
return String(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
function runCommonPreflight() {
|
|
706
|
+
log("Checking local install state...");
|
|
707
|
+
if (updatePostinstall) {
|
|
708
|
+
log("Package update detected; refreshing MemoraX Code assets without interactive setup prompts.");
|
|
709
|
+
}
|
|
710
|
+
const memoraxCodeVersion = runNodeMemoraxCodeCommand(["--version"], { print: false });
|
|
711
|
+
log(`MemoraX Code backend package: ${commandSummary(memoraxCodeVersion) ?? packageVersionSummary()}`);
|
|
712
|
+
if (skipCodexPluginInstall) {
|
|
713
|
+
log("Codex plugin registration is disabled for this npm postinstall; backend and Claude Code setup can still continue.");
|
|
714
|
+
}
|
|
715
|
+
if (skipClaudeAdapterInstall) {
|
|
716
|
+
log("Claude Code adapter setup is disabled for this npm postinstall; backend and Codex setup can still continue.");
|
|
717
|
+
}
|
|
718
|
+
return {};
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
function runCodexPreflight() {
|
|
722
|
+
const version = runExternalCommand(codexCommand, ["--version"], { print: false, timeout: 10_000 });
|
|
723
|
+
const runtimeLabel = codexRuntime.source === "app-bundled"
|
|
724
|
+
? "Codex App runtime"
|
|
725
|
+
: codexRuntime.source === "vscode-bundled"
|
|
726
|
+
? "Codex VS Code runtime"
|
|
727
|
+
: "Codex CLI";
|
|
728
|
+
log(`${runtimeLabel}: ${commandSummary(version) ?? "not runnable"}`);
|
|
729
|
+
if (version.status !== 0) {
|
|
730
|
+
return { ok: false, pluginCache: { marketplaceName: CLI_MARKETPLACE_NAME, versions: [] } };
|
|
731
|
+
}
|
|
732
|
+
const pluginCache = installedPluginCache();
|
|
733
|
+
log(`Existing Codex plugin cache: ${pluginCache.versions.length > 0 ? `found (${pluginCache.versions.join(", ")})` : "not installed"}`);
|
|
734
|
+
log(`Codex client process: ${codexClientRunning() ? "running" : "not detected"}`);
|
|
735
|
+
log("Keeping Codex provider config unchanged and enabling the shared memory hook integration.");
|
|
736
|
+
return { ok: true, pluginCache };
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
function runClaudePreflight() {
|
|
740
|
+
const version = runExternalCommand(claudeCommand, ["--version"], { print: false, timeout: 10_000 });
|
|
741
|
+
const runtimeLabel = claudeRuntime.source === "vscode-bundled" ? "Claude VS Code runtime" : "Claude CLI";
|
|
742
|
+
log(`${runtimeLabel}: ${commandSummary(version) ?? "not runnable"}`);
|
|
743
|
+
if (version.status !== 0) return { ok: false };
|
|
744
|
+
log("Keeping Claude Code provider config unchanged and enabling the shared memory Hook integration.");
|
|
745
|
+
return { ok: true };
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
function installedPluginCache() {
|
|
749
|
+
for (const marketplaceName of [CLI_MARKETPLACE_NAME, PERSONAL_MARKETPLACE_NAME]) {
|
|
750
|
+
const versions = installedPluginCacheVersions(marketplaceName);
|
|
751
|
+
if (versions.length > 0) {
|
|
752
|
+
return { marketplaceName, versions };
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
return { marketplaceName: CLI_MARKETPLACE_NAME, versions: [] };
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
function installedPluginCacheVersions(marketplaceName) {
|
|
759
|
+
const cacheRoot = join(codexHome(), "plugins", "cache", marketplaceName, PLUGIN_NAME);
|
|
760
|
+
if (!existsSync(cacheRoot)) return [];
|
|
761
|
+
try {
|
|
762
|
+
return readdirSync(cacheRoot, { withFileTypes: true })
|
|
763
|
+
.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."))
|
|
764
|
+
.map((entry) => entry.name)
|
|
765
|
+
.sort();
|
|
766
|
+
} catch {
|
|
767
|
+
return [];
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
function startBackendAndCheck({ skipCodexAdapter = false, clientMode = "all", codexSkipReason, skipClaudeAdapter = false, claudeAdapterRequired = !skipClaudeAdapter, claudeSkipReason } = {}) {
|
|
772
|
+
logGreen("Starting backend with `memorax-code start`...");
|
|
773
|
+
const adapterFlags = clientLifecycleFlags({ clientMode });
|
|
774
|
+
const startArgs = ["start", ...adapterFlags];
|
|
775
|
+
const statusArgs = ["status", ...adapterFlags];
|
|
776
|
+
let started = runMemoraxCodeCommand(startArgs, pendingClientHookRuntimeEnv());
|
|
777
|
+
let recovered = false;
|
|
778
|
+
if (started.status !== 0) {
|
|
779
|
+
logRed("Backend start failed during npm postinstall.");
|
|
780
|
+
if (clientHookRuntimeActivationFailed(started)) {
|
|
781
|
+
logRed("Client Hook runtime activation failed; automatic lifecycle recovery was skipped.");
|
|
782
|
+
logRed("The previously active runtime remains authoritative.");
|
|
783
|
+
return "not-verified";
|
|
784
|
+
}
|
|
785
|
+
if (lifecycleLockFailureCode(started)) {
|
|
786
|
+
logRed("Automatic stop/start recovery is skipped because another MemoraX Code lifecycle command still owns the Backend authority.");
|
|
787
|
+
printLifecycleLockFailureSuggestions();
|
|
788
|
+
return "not-verified";
|
|
789
|
+
}
|
|
790
|
+
const runtimeAuthorityFailure = runtimeAuthorityFailureCode(started);
|
|
791
|
+
if (runtimeAuthorityFailure) {
|
|
792
|
+
logRed("Automatic stop/start recovery is skipped because persisted Backend runtime authority requires explicit repair.");
|
|
793
|
+
printRuntimeAuthorityFailureSuggestions(runtimeAuthorityFailure);
|
|
794
|
+
return "not-verified";
|
|
795
|
+
}
|
|
796
|
+
logRed("Attempting automatic recovery: `memorax-code stop` then `memorax-code start`...");
|
|
797
|
+
runMemoraxCodeCommand(["stop", ...adapterFlags]);
|
|
798
|
+
started = runMemoraxCodeCommand(startArgs, pendingClientHookRuntimeEnv());
|
|
799
|
+
recovered = started.status === 0;
|
|
800
|
+
if (!recovered) {
|
|
801
|
+
logRed("Automatic recovery did not start the backend.");
|
|
802
|
+
logRed("Diagnostic: running `memorax-code status` so the failure is visible.");
|
|
803
|
+
runMemoraxCodeCommand(statusArgs);
|
|
804
|
+
printFailureSuggestions();
|
|
805
|
+
return "not-verified";
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
logGreen(recovered ? "Backend start completed after automatic recovery." : "Backend start completed.");
|
|
809
|
+
log("Checking backend status with `memorax-code status`...");
|
|
810
|
+
const checked = runMemoraxCodeCommand(statusArgs);
|
|
811
|
+
if (checked.status !== 0) {
|
|
812
|
+
logRed("Backend status check failed during npm postinstall.");
|
|
813
|
+
printFailureSuggestions();
|
|
814
|
+
return "not-verified";
|
|
815
|
+
}
|
|
816
|
+
logGreen("Backend status check completed.");
|
|
817
|
+
const enabled = memoraxCodeEnabled(checked, {
|
|
818
|
+
codexAdapterRequired: !skipCodexAdapter,
|
|
819
|
+
claudeAdapterRequired,
|
|
820
|
+
});
|
|
821
|
+
if (!enabled) {
|
|
822
|
+
if (skipCodexAdapter || skipClaudeAdapter) printSkippedAdapterDiagnostics({ codexSkipReason, claudeSkipReason });
|
|
823
|
+
else printUnavailableDiagnostics();
|
|
824
|
+
return "unavailable";
|
|
825
|
+
}
|
|
826
|
+
return "enabled";
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
function pendingClientHookRuntimeEnv() {
|
|
830
|
+
return {
|
|
831
|
+
MEMORAX_CODE_PENDING_CLIENT_HOOK_RUNTIME_V1: JSON.stringify({
|
|
832
|
+
version: 1,
|
|
833
|
+
memoraxCodeHome: resolve(memoraxCodeHome()),
|
|
834
|
+
generation: {
|
|
835
|
+
version: stagedHookRuntime.version,
|
|
836
|
+
runtimeAbi: stagedHookRuntime.runtimeAbi,
|
|
837
|
+
generationId: stagedHookRuntime.generationId,
|
|
838
|
+
packageVersion: stagedHookRuntime.packageVersion,
|
|
839
|
+
contentDigest: stagedHookRuntime.contentDigest,
|
|
840
|
+
createdAt: stagedHookRuntime.createdAt,
|
|
841
|
+
},
|
|
842
|
+
}),
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
function runtimeAuthorityFailureCode(result) {
|
|
847
|
+
const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`;
|
|
848
|
+
return output.match(/\b(BACKEND_(?:(?:CONNECTION_AUTHORITY|TOKEN_RECORD|SERVICE_STATE)_(?:ABSENT|INVALID|UNSUPPORTED)|SERVICE_STATE_CLEANUP_FAILED))\b/)?.[1];
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
function lifecycleLockFailureCode(result) {
|
|
852
|
+
const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`;
|
|
853
|
+
return output.match(/\bBACKEND_LIFECYCLE_LOCK_TIMEOUT\b/)?.[0];
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
function clientHookRuntimeActivationFailed(result) {
|
|
857
|
+
const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`;
|
|
858
|
+
return /client Hook runtime activation failed:/i.test(output);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
function clientLifecycleFlags({ clientMode = "all" } = {}) {
|
|
862
|
+
return ["--clients", clientMode];
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
function clientModeFor(clients) {
|
|
866
|
+
const hasCodex = clients.includes("codex");
|
|
867
|
+
const hasClaude = clients.includes("claude");
|
|
868
|
+
if (hasCodex && hasClaude) return "all";
|
|
869
|
+
if (hasCodex) return "codex";
|
|
870
|
+
if (hasClaude) return "claude";
|
|
871
|
+
return "none";
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
function postinstallClientSkipReason({ explicitlySkipped, selected, enabled }) {
|
|
875
|
+
if (explicitlySkipped) return "postinstall-skip";
|
|
876
|
+
if (selected && !enabled) return "client-not-detected";
|
|
877
|
+
return enabled ? undefined : "client-selection";
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
function clientSelectionMessage(clients) {
|
|
881
|
+
const hasCodex = clients.includes("codex");
|
|
882
|
+
const hasClaude = clients.includes("claude");
|
|
883
|
+
if (hasCodex && hasClaude) return "Configuring MemoraX Code for Codex and Claude Code.";
|
|
884
|
+
if (hasCodex) return "Configuring MemoraX Code for Codex only.";
|
|
885
|
+
if (hasClaude) return "Configuring MemoraX Code for Claude Code only.";
|
|
886
|
+
return "Skipping client adapter setup for this npm postinstall.";
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
function detectedClientMessage(clients) {
|
|
890
|
+
if (clients.length === 0) {
|
|
891
|
+
return "No supported client runtime was detected; starting the shared Backend without client adapters.";
|
|
892
|
+
}
|
|
893
|
+
return `Detected supported client runtimes. ${clientSelectionMessage(clients)}`;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
function codexHome() {
|
|
897
|
+
return process.env.CODEX_HOME || join(homedir(), ".codex");
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
function stringOption(value) {
|
|
901
|
+
if (typeof value !== "string") return undefined;
|
|
902
|
+
const trimmed = value.trim();
|
|
903
|
+
return trimmed ? trimmed : undefined;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
function runMemoraxCodeCommand(args, extraEnv = {}) {
|
|
907
|
+
return runNodeMemoraxCodeCommand(args, {
|
|
908
|
+
env: { ...process.env, ...extraEnv, MEMORAX_CODE_BACKEND_SUPPRESS_GUIDANCE: "1" },
|
|
909
|
+
outputPrefix: BACKEND_PREFIX,
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
function runNodeMemoraxCodeCommand(args, {
|
|
914
|
+
env = process.env,
|
|
915
|
+
print = true,
|
|
916
|
+
outputPrefix = PREFIX,
|
|
917
|
+
timeout,
|
|
918
|
+
} = {}) {
|
|
919
|
+
return runNodeCliCommand(memoraxCodeBin, args, {
|
|
920
|
+
env,
|
|
921
|
+
print,
|
|
922
|
+
outputPrefix,
|
|
923
|
+
timeout,
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
function runNodeMemoraxCliCommand(args, {
|
|
928
|
+
env = process.env,
|
|
929
|
+
print = true,
|
|
930
|
+
outputPrefix = PREFIX,
|
|
931
|
+
timeout,
|
|
932
|
+
} = {}) {
|
|
933
|
+
return runNodeCliCommand(memoraxCliBin, args, {
|
|
934
|
+
env,
|
|
935
|
+
print,
|
|
936
|
+
outputPrefix,
|
|
937
|
+
timeout,
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
function runNodeCliCommand(bin, args, options) {
|
|
942
|
+
return runCommand(process.execPath, [bin, ...args], options);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
function runExternalCommand(command, args, { env = process.env, print = true, outputPrefix = PREFIX, timeout } = {}) {
|
|
946
|
+
return runCommand(command, args, { env, print, outputPrefix, timeout });
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
function runCommand(command, args, { env = process.env, print = true, outputPrefix = PREFIX, timeout } = {}) {
|
|
950
|
+
let invocation;
|
|
951
|
+
try {
|
|
952
|
+
invocation = resolveWindowsCliInvocation(command, args, { env });
|
|
953
|
+
} catch (error) {
|
|
954
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
955
|
+
if (print) logRed(message);
|
|
956
|
+
return { status: 1, stdout: "", stderr: message, error };
|
|
957
|
+
}
|
|
958
|
+
const result = spawnSync(invocation.command, invocation.args, {
|
|
959
|
+
env,
|
|
960
|
+
encoding: "utf8",
|
|
961
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
962
|
+
...(timeout ? { timeout } : {}),
|
|
963
|
+
});
|
|
964
|
+
if (print) {
|
|
965
|
+
printCommandOutput(result.stdout, outputPrefix);
|
|
966
|
+
printCommandOutput(result.stderr, outputPrefix);
|
|
967
|
+
}
|
|
968
|
+
if (result.error && print) logRed(`Failed to run \`${[command, ...args].join(" ")}\`: ${result.error.message}`);
|
|
969
|
+
return result;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
function printCommandOutput(output, outputPrefix) {
|
|
973
|
+
for (const line of String(output ?? "").split(/\r?\n/)) {
|
|
974
|
+
if (!line) continue;
|
|
975
|
+
if (hasMemoraxCodePrefix(line)) console.warn(line);
|
|
976
|
+
else logWithPrefix(outputPrefix, line);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
function hasMemoraxCodePrefix(line) {
|
|
981
|
+
return /^\[MemoraX Code (?:Install|Backend)\]: /.test(stripAnsi(line));
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
function stripAnsi(value) {
|
|
985
|
+
return String(value).replace(/\x1b\[[0-9;]*m/g, "");
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
function firstOutputLine(result) {
|
|
989
|
+
const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`.split(/\r?\n/).map((line) => line.trim()).find(Boolean);
|
|
990
|
+
return output || undefined;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
function commandSummary(result) {
|
|
994
|
+
if (result.status !== 0) return undefined;
|
|
995
|
+
return firstOutputLine(result);
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
function packageVersionSummary() {
|
|
999
|
+
try {
|
|
1000
|
+
const pkg = JSON.parse(readFileSync(join(dirname(scriptDir), "package.json"), "utf8"));
|
|
1001
|
+
if (typeof pkg.version === "string" && pkg.version) return `installed (${pkg.version}), command version unavailable`;
|
|
1002
|
+
} catch {
|
|
1003
|
+
// Ignore package metadata errors; this is a best-effort install preflight.
|
|
1004
|
+
}
|
|
1005
|
+
return "installed, version unavailable";
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
function codexClientRunning() {
|
|
1009
|
+
const result = process.platform === "win32"
|
|
1010
|
+
? runExternalCommand("tasklist.exe", ["/FO", "CSV", "/NH"], { print: false })
|
|
1011
|
+
: runExternalCommand("ps", ["-axo", "comm=,args="], { print: false });
|
|
1012
|
+
if (result.status !== 0) return false;
|
|
1013
|
+
return String(result.stdout ?? "").split(/\r?\n/).some((line) => {
|
|
1014
|
+
const lower = line.toLowerCase();
|
|
1015
|
+
if (!lower.includes("codex")) return false;
|
|
1016
|
+
if (lower.includes("memorax-code-plugin-postinstall")) return false;
|
|
1017
|
+
return process.platform === "win32"
|
|
1018
|
+
? /"codex(?:\.exe)?"/i.test(line)
|
|
1019
|
+
: lower.includes("codex.app") || /(^|[/\s])codex(\s|$)/i.test(line);
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
function printNextSteps({ codexAdapterEnabled = true, claudeAdapterEnabled = true } = {}) {
|
|
1024
|
+
const clientText = enabledClientText({ codexAdapterEnabled, claudeAdapterEnabled });
|
|
1025
|
+
if (clientText && updatePostinstall) {
|
|
1026
|
+
logGreen(`${bold("The new Hook runtime is active")}; existing sessions with the stable shell select it on their next user prompt.`);
|
|
1027
|
+
log(`Restart or refresh ${clientText} only if its plugin shell was installed, changed, or newly enabled, or if MemoraX Code is not active on the next prompt.`);
|
|
1028
|
+
} else if (clientText) {
|
|
1029
|
+
logGreen(`${bold(`Restart or refresh ${clientText}`)} before opening a new MemoraX Code session.`);
|
|
1030
|
+
} else {
|
|
1031
|
+
logGreen(`${bold("MemoraX Code backend is running")}; client adapters were skipped for this install.`);
|
|
1032
|
+
}
|
|
1033
|
+
if (codexAdapterEnabled && !updatePostinstall) {
|
|
1034
|
+
logGreen(`After restart, ${bold("enable the MemoraX Code Codex Adapter plugin")} from Codex Plugins or CLI \`/plugins\` if it is not already enabled.`);
|
|
1035
|
+
}
|
|
1036
|
+
const statusCommands = statusCommandText({ codexAdapterEnabled, claudeAdapterEnabled });
|
|
1037
|
+
log(`If MemoraX Code is not active ${updatePostinstall ? "on the next prompt" : "in new sessions"}, run ${statusCommands}.`);
|
|
1038
|
+
log("If npm hides install details, reinstall with `--foreground-scripts`.");
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
function enabledClientText({ codexAdapterEnabled = true, claudeAdapterEnabled = true } = {}) {
|
|
1042
|
+
if (codexAdapterEnabled && claudeAdapterEnabled) return "Codex or Claude Code";
|
|
1043
|
+
if (codexAdapterEnabled) return "Codex";
|
|
1044
|
+
if (claudeAdapterEnabled) return "Claude Code";
|
|
1045
|
+
return "";
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
function statusCommandText({ codexAdapterEnabled = true, claudeAdapterEnabled = true } = {}) {
|
|
1049
|
+
const commands = ["`memorax-code status`"];
|
|
1050
|
+
if (codexAdapterEnabled) commands.push("`memorax-code-codex status`");
|
|
1051
|
+
if (claudeAdapterEnabled) commands.push("`memorax-code-claude status`");
|
|
1052
|
+
if (commands.length === 1) return commands[0];
|
|
1053
|
+
if (commands.length === 2) return `${commands[0]} and ${commands[1]}`;
|
|
1054
|
+
return `${commands.slice(0, -1).join(", ")}, and ${commands.at(-1)}`;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
function printPostinstallSummary(backendAndAdaptersStatus) {
|
|
1058
|
+
log("Package: Installed");
|
|
1059
|
+
const backendStatusLabel = backendAndAdaptersStatus === "enabled"
|
|
1060
|
+
? blueBold("Enabled")
|
|
1061
|
+
: backendAndAdaptersStatus === "unavailable"
|
|
1062
|
+
? redBold("Unavailable")
|
|
1063
|
+
: "Not verified";
|
|
1064
|
+
log(`Backend and selected adapters: ${backendStatusLabel}`);
|
|
1065
|
+
const memoraxStatus = readMemoraxInstallStatus();
|
|
1066
|
+
if (!memoraxStatus) {
|
|
1067
|
+
logRed("MemoraX memory: Status unavailable");
|
|
1068
|
+
log("Run `memorax-cli status` after installation to inspect the effective configuration.");
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
1071
|
+
if (!memoraxStatus.configured) {
|
|
1072
|
+
log("MemoraX memory: Not configured");
|
|
1073
|
+
log(`Package installed, MemoraX not configured. MemoraX Code memory remains unavailable until you connect an account from ${MEMORAX_ACCOUNT_URL}.`);
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
log(`MemoraX memory: ${blueBold("Configured")}`);
|
|
1077
|
+
if (memoraxStatus.writebackEnabled) {
|
|
1078
|
+
log(`Automatic writeback: ${blueBold("Enabled")}`);
|
|
1079
|
+
} else if (!memoraxStatus.globalWritebackEnabled) {
|
|
1080
|
+
log("Automatic writeback: Disabled by the global kill switch");
|
|
1081
|
+
} else {
|
|
1082
|
+
log("Automatic writeback: Disabled by effective configuration");
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
function readMemoraxInstallStatus() {
|
|
1087
|
+
const result = runNodeMemoraxCliCommand(
|
|
1088
|
+
["status", "--json", "--config-only"],
|
|
1089
|
+
{ print: false, timeout: 10_000 },
|
|
1090
|
+
);
|
|
1091
|
+
if (result.error || result.signal || (result.status !== 0 && result.status !== 1)) {
|
|
1092
|
+
return undefined;
|
|
1093
|
+
}
|
|
1094
|
+
try {
|
|
1095
|
+
const report = JSON.parse(String(result.stdout ?? ""));
|
|
1096
|
+
if (!isRecord(report)
|
|
1097
|
+
|| report.action !== "memory.status"
|
|
1098
|
+
|| report.provider !== "memory.memorax"
|
|
1099
|
+
|| typeof report.ok !== "boolean"
|
|
1100
|
+
|| !isRecord(report.config)
|
|
1101
|
+
|| typeof report.config.configured !== "boolean") {
|
|
1102
|
+
return undefined;
|
|
1103
|
+
}
|
|
1104
|
+
const configuredResult = result.status === 0
|
|
1105
|
+
&& report.ok === true
|
|
1106
|
+
&& report.config.configured === true;
|
|
1107
|
+
const unconfiguredResult = result.status === 1
|
|
1108
|
+
&& report.ok === false
|
|
1109
|
+
&& report.config.configured === false;
|
|
1110
|
+
if (!configuredResult && !unconfiguredResult) {
|
|
1111
|
+
return undefined;
|
|
1112
|
+
}
|
|
1113
|
+
if (unconfiguredResult) {
|
|
1114
|
+
return { configured: false };
|
|
1115
|
+
}
|
|
1116
|
+
if (!isRecord(report.config.writeback)
|
|
1117
|
+
|| typeof report.config.writeback.globalEnabled !== "boolean"
|
|
1118
|
+
|| typeof report.config.writeback.writebackEnabled !== "boolean") {
|
|
1119
|
+
return undefined;
|
|
1120
|
+
}
|
|
1121
|
+
return {
|
|
1122
|
+
configured: true,
|
|
1123
|
+
globalWritebackEnabled: report.config.writeback.globalEnabled,
|
|
1124
|
+
writebackEnabled: report.config.writeback.writebackEnabled,
|
|
1125
|
+
};
|
|
1126
|
+
} catch {
|
|
1127
|
+
return undefined;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
function printUnavailableDiagnostics() {
|
|
1132
|
+
logRed("MemoraX Code is not enabled for new client sessions.");
|
|
1133
|
+
logRed("Check `memorax-code status`, `memorax-code-codex status`, and `memorax-code-claude status` for Backend and adapter details.");
|
|
1134
|
+
logRed("If Codex or Claude Code is open, restart or refresh it after fixing the reported status.");
|
|
1135
|
+
printCommonCommands();
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
function printSkippedAdapterDiagnostics({ codexSkipReason, claudeSkipReason } = {}) {
|
|
1139
|
+
if (codexSkipReason) printCodexSkippedDiagnostics(codexSkipReason);
|
|
1140
|
+
if (claudeSkipReason) printClaudeSkippedDiagnostics(claudeSkipReason);
|
|
1141
|
+
printCommonCommands({
|
|
1142
|
+
codexAdapterEnabled: !codexSkipReason,
|
|
1143
|
+
claudeAdapterEnabled: !claudeSkipReason,
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
function printCodexSkippedDiagnostics(reason) {
|
|
1148
|
+
logRed("Codex plugin registration was skipped for this npm postinstall, so MemoraX Code left the Codex plugin unchanged.");
|
|
1149
|
+
log("Claude Code can still use MemoraX Code when `memorax-code-claude status` reports the Hook integration is enabled.");
|
|
1150
|
+
log("Run `memorax-code start` after installing the Codex plugin, then restart or refresh Codex.");
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
function printClaudeSkippedDiagnostics() {
|
|
1154
|
+
logRed("Claude Code adapter setup was skipped for this npm postinstall, so MemoraX Code left the Claude integration unchanged.");
|
|
1155
|
+
log("Codex can still use MemoraX Code when `memorax-code-codex status` reports the adapter is enabled.");
|
|
1156
|
+
log("Run `memorax-code start` after installing Claude Code, then restart or refresh Claude Code.");
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
function printFailureSuggestions() {
|
|
1160
|
+
logRed("Suggested recovery: run `memorax-code stop`, then `memorax-code start`, then `memorax-code status`.");
|
|
1161
|
+
logRed("If the Backend port is busy, stop the process using 127.0.0.1:8787 and retry `memorax-code start`.");
|
|
1162
|
+
logRed("If client sessions still bypass MemoraX Code, restart or refresh Codex or Claude Code and verify the relevant adapter status.");
|
|
1163
|
+
printCommonCommands();
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
function printRuntimeAuthorityFailureSuggestions(code) {
|
|
1167
|
+
if (code.startsWith("BACKEND_CONNECTION_AUTHORITY_")) {
|
|
1168
|
+
logRed("Confirm the intended local Backend bind, then run `memorax-code start --host 127.0.0.1 --port <intended-port>`.");
|
|
1169
|
+
logRed("The connection authority is replaced only after that Backend starts successfully; then run `memorax-code status`.");
|
|
1170
|
+
} else if (code.startsWith("BACKEND_TOKEN_RECORD_")) {
|
|
1171
|
+
logRed("Inspect `memorax-code status`; after safely stopping the managed Backend, run `memorax-code token --rotate`, then `memorax-code start`.");
|
|
1172
|
+
} else {
|
|
1173
|
+
logRed("Inspect `memorax-code status` and the reported backend.pid.json path; confirm process ownership before repairing or removing that state file.");
|
|
1174
|
+
}
|
|
1175
|
+
printCommonCommands();
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
function printLifecycleLockFailureSuggestions() {
|
|
1179
|
+
logRed("Let the existing lifecycle command finish, then run `memorax-code status`.");
|
|
1180
|
+
logRed("If MemoraX Code is not ready, retry `memorax-code start`; do not stop a Backend started by the concurrent owner.");
|
|
1181
|
+
printCommonCommands();
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
function printCommonCommands({ codexAdapterEnabled = true, claudeAdapterEnabled = true } = {}) {
|
|
1185
|
+
log("Common commands:");
|
|
1186
|
+
log("- `memorax-code status`: check the local backend and adapter state.");
|
|
1187
|
+
log("- `memorax-cli status`: check required MemoraX configuration and effective memory switches.");
|
|
1188
|
+
log("- `memorax-code start`: start or refresh the local memory backend and client integrations.");
|
|
1189
|
+
log("- `memorax-code stop`: stop the local memory backend and disable managed client integrations.");
|
|
1190
|
+
if (codexAdapterEnabled) log("- `memorax-code-codex sessions`: verify recent native Codex session registration.");
|
|
1191
|
+
if (claudeAdapterEnabled) log("- `memorax-code-claude sessions`: verify recent native Claude Code session registration.");
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
function memoraxCodeEnabled(statusResult, { codexAdapterRequired = true, claudeAdapterRequired = true } = {}) {
|
|
1195
|
+
const output = `${statusResult.stdout ?? ""}\n${statusResult.stderr ?? ""}`;
|
|
1196
|
+
const normalized = stripAnsi(output);
|
|
1197
|
+
const backendOk = /MemoraX Code Backend status:\s*Enabled\b/im.test(normalized)
|
|
1198
|
+
|| /MemoraX Code status:\s*Enabled\b/im.test(normalized)
|
|
1199
|
+
|| /memorax-code:\s*ok\b/im.test(normalized);
|
|
1200
|
+
const serviceOk = /Backend status:\s*Enabled\b/im.test(normalized)
|
|
1201
|
+
|| /Backend:\s*(?:running|ok)\b/im.test(normalized);
|
|
1202
|
+
const codexAdapterOk = /Codex adapter:\s*ok\b/im.test(normalized);
|
|
1203
|
+
const claudeAdapterOk = /Claude adapter:\s*ok\b/im.test(normalized);
|
|
1204
|
+
return backendOk
|
|
1205
|
+
&& serviceOk
|
|
1206
|
+
&& (!codexAdapterRequired || codexAdapterOk)
|
|
1207
|
+
&& (!claudeAdapterRequired || claudeAdapterOk);
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
function log(message) {
|
|
1211
|
+
logWithPrefix(PREFIX, message);
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
function logGreen(message) {
|
|
1215
|
+
console.warn(`${GREEN}${PREFIX} ${message}${RESET}`);
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
function logRed(message) {
|
|
1219
|
+
console.warn(`${RED}${PREFIX} ${message}${RESET}`);
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
function logWithPrefix(prefix, message) {
|
|
1223
|
+
console.warn(`${prefix} ${message}`);
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
function bold(message) {
|
|
1227
|
+
return `${BOLD}${message}\x1b[22m`;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
function blueBold(message) {
|
|
1231
|
+
return `${BLUE}${bold(message)}${RESET}`;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
function redBold(message) {
|
|
1235
|
+
return `${RED}${bold(message)}${RESET}`;
|
|
1236
|
+
}
|