@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,134 @@
|
|
|
1
|
+
import { memoraxConfigFromEnv, } from "./memorax-config.js";
|
|
2
|
+
import { repositoryMemoryScopeContainsWorkspace, repositoryMemoryScopeKind, repositoryMemoryScopesMatch, resolveRepositoryMemoryScope, } from "./repository-memory-scope.js";
|
|
3
|
+
const sessionScopes = new WeakMap();
|
|
4
|
+
const scopeResolutionQueues = new WeakMap();
|
|
5
|
+
export function createRepositoryMemorySessionRuntime() {
|
|
6
|
+
const owner = {};
|
|
7
|
+
return {
|
|
8
|
+
async resolve(input) {
|
|
9
|
+
return await resolveConfiguredRepositoryMemoryForSession({ owner, ...input });
|
|
10
|
+
},
|
|
11
|
+
close() {
|
|
12
|
+
sessionScopes.delete(owner);
|
|
13
|
+
scopeResolutionQueues.delete(owner);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export async function resolveConfiguredRepositoryMemory(input) {
|
|
18
|
+
const sourceEnv = input.env ?? process.env;
|
|
19
|
+
const env = input.memoraxCodeHome ? { ...sourceEnv, MEMORAX_CODE_HOME: input.memoraxCodeHome } : sourceEnv;
|
|
20
|
+
const configResult = memoraxConfigFromEnv(env);
|
|
21
|
+
if (!configResult.ok)
|
|
22
|
+
return { ok: false, reason: "config_missing", error: configResult.error };
|
|
23
|
+
const scopeResult = await resolveRepositoryMemoryScope({
|
|
24
|
+
workspaceRoot: input.workspaceRoot,
|
|
25
|
+
workspaceKind: input.workspaceKind,
|
|
26
|
+
baseUserId: configResult.config.userId,
|
|
27
|
+
});
|
|
28
|
+
if (!scopeResult.ok)
|
|
29
|
+
return scopeResult;
|
|
30
|
+
return { ok: true, memory: { config: configResult.config, scope: scopeResult.scope } };
|
|
31
|
+
}
|
|
32
|
+
export async function resolveConfiguredRepositoryMemoryForSession(input) {
|
|
33
|
+
const sourceEnv = input.env ?? process.env;
|
|
34
|
+
const env = input.memoraxCodeHome ? { ...sourceEnv, MEMORAX_CODE_HOME: input.memoraxCodeHome } : sourceEnv;
|
|
35
|
+
const configResult = memoraxConfigFromEnv(env);
|
|
36
|
+
if (!configResult.ok)
|
|
37
|
+
return { ok: false, reason: "config_missing", error: configResult.error };
|
|
38
|
+
const sessionId = input.sessionId?.trim();
|
|
39
|
+
if (!sessionId) {
|
|
40
|
+
return await resolveConfiguredRepositoryMemory({
|
|
41
|
+
workspaceRoot: input.workspaceRoot,
|
|
42
|
+
workspaceKind: input.workspaceKind,
|
|
43
|
+
memoraxCodeHome: input.memoraxCodeHome,
|
|
44
|
+
env,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const bindingKey = JSON.stringify([input.client, sessionId]);
|
|
48
|
+
return await withScopeResolution(input.owner, `session:${bindingKey}`, async () => {
|
|
49
|
+
let scopes = sessionScopes.get(input.owner);
|
|
50
|
+
if (!scopes) {
|
|
51
|
+
scopes = new Map();
|
|
52
|
+
sessionScopes.set(input.owner, scopes);
|
|
53
|
+
}
|
|
54
|
+
const cached = scopes.get(bindingKey);
|
|
55
|
+
if (cached?.scope.baseUserId === configResult.config.userId && cached.mismatch) {
|
|
56
|
+
return repositoryScopeMismatch();
|
|
57
|
+
}
|
|
58
|
+
const cachedScope = cached?.scope.baseUserId === configResult.config.userId ? cached.scope : undefined;
|
|
59
|
+
if (input.requireBoundScope === true && !cachedScope) {
|
|
60
|
+
return {
|
|
61
|
+
ok: false,
|
|
62
|
+
reason: "workspace_scope_unavailable",
|
|
63
|
+
error: "memory scope authority is unavailable for this session",
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const workspaceKind = input.workspaceKind?.trim().toLowerCase();
|
|
67
|
+
let workspaceRoot = input.workspaceRoot?.trim() ? input.workspaceRoot : undefined;
|
|
68
|
+
if (cachedScope
|
|
69
|
+
&& repositoryMemoryScopeKind(cachedScope) === "local-directory"
|
|
70
|
+
&& workspaceKind !== "projectless"
|
|
71
|
+
&& await repositoryMemoryScopeContainsWorkspace(cachedScope, workspaceRoot)) {
|
|
72
|
+
workspaceRoot = cachedScope.boundWorkspaceRoot;
|
|
73
|
+
}
|
|
74
|
+
if (!workspaceRoot && cachedScope?.boundWorkspaceRoot)
|
|
75
|
+
workspaceRoot = cachedScope.boundWorkspaceRoot;
|
|
76
|
+
const effectiveWorkspaceKind = input.workspaceKind
|
|
77
|
+
?? (cachedScope && repositoryMemoryScopeKind(cachedScope) === "codex-projectless"
|
|
78
|
+
? "projectless"
|
|
79
|
+
: undefined);
|
|
80
|
+
if (!workspaceRoot && effectiveWorkspaceKind?.trim().toLowerCase() !== "projectless") {
|
|
81
|
+
return {
|
|
82
|
+
ok: false,
|
|
83
|
+
reason: "workspace_scope_unavailable",
|
|
84
|
+
error: "a session workspace is required for workspace-scoped memory",
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
const scopeResult = await resolveRepositoryMemoryScope({
|
|
88
|
+
workspaceRoot,
|
|
89
|
+
workspaceKind: effectiveWorkspaceKind,
|
|
90
|
+
baseUserId: configResult.config.userId,
|
|
91
|
+
});
|
|
92
|
+
if (!scopeResult.ok)
|
|
93
|
+
return scopeResult;
|
|
94
|
+
if (cached?.scope.baseUserId === configResult.config.userId) {
|
|
95
|
+
if (!repositoryMemoryScopesMatch(cached.scope, scopeResult.scope)) {
|
|
96
|
+
cached.mismatch = true;
|
|
97
|
+
return repositoryScopeMismatch();
|
|
98
|
+
}
|
|
99
|
+
return { ok: true, memory: { config: configResult.config, scope: cached.scope } };
|
|
100
|
+
}
|
|
101
|
+
scopes.set(bindingKey, { scope: scopeResult.scope, mismatch: false });
|
|
102
|
+
return { ok: true, memory: { config: configResult.config, scope: scopeResult.scope } };
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function repositoryScopeMismatch() {
|
|
106
|
+
return {
|
|
107
|
+
ok: false,
|
|
108
|
+
reason: "workspace_scope_mismatch",
|
|
109
|
+
error: "memory scope changed for this session; start a new session for the other workspace",
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
async function withScopeResolution(owner, key, fn) {
|
|
113
|
+
let queues = scopeResolutionQueues.get(owner);
|
|
114
|
+
if (!queues) {
|
|
115
|
+
queues = new Map();
|
|
116
|
+
scopeResolutionQueues.set(owner, queues);
|
|
117
|
+
}
|
|
118
|
+
const previous = queues.get(key) ?? Promise.resolve();
|
|
119
|
+
let release = () => undefined;
|
|
120
|
+
const current = new Promise((resolveCurrent) => {
|
|
121
|
+
release = resolveCurrent;
|
|
122
|
+
});
|
|
123
|
+
const tail = previous.then(() => current);
|
|
124
|
+
queues.set(key, tail);
|
|
125
|
+
await previous;
|
|
126
|
+
try {
|
|
127
|
+
return await fn();
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
release();
|
|
131
|
+
if (queues.get(key) === tail)
|
|
132
|
+
queues.delete(key);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
|
|
4
|
+
const CODEX_PROJECTLESS_SLUG = "Codex-General";
|
|
5
|
+
const MAX_GIT_POINTER_BYTES = 64 * 1024;
|
|
6
|
+
const MAX_GIT_CONFIG_BYTES = 1024 * 1024;
|
|
7
|
+
export async function resolveRepositoryMemoryScope(input) {
|
|
8
|
+
const baseUserId = input.baseUserId.trim();
|
|
9
|
+
if (!baseUserId) {
|
|
10
|
+
return {
|
|
11
|
+
ok: false,
|
|
12
|
+
reason: "effective_user_id_invalid",
|
|
13
|
+
error: "base MemoraX user id is required for workspace-scoped memory",
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const workspaceKind = input.workspaceKind?.trim().toLowerCase();
|
|
17
|
+
if (workspaceKind === "projectless") {
|
|
18
|
+
const workspace = await resolveWorkspace(input.workspaceRoot);
|
|
19
|
+
return {
|
|
20
|
+
ok: true,
|
|
21
|
+
scope: memoryScope({
|
|
22
|
+
baseUserId,
|
|
23
|
+
repositoryKey: identityKey("codex-projectless", CODEX_PROJECTLESS_SLUG),
|
|
24
|
+
repositorySlug: CODEX_PROJECTLESS_SLUG,
|
|
25
|
+
identitySource: "codex-projectless",
|
|
26
|
+
scopeKind: "codex-projectless",
|
|
27
|
+
boundWorkspaceRoot: workspace,
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const workspace = await resolveWorkspace(input.workspaceRoot);
|
|
32
|
+
if (!workspace) {
|
|
33
|
+
return {
|
|
34
|
+
ok: false,
|
|
35
|
+
reason: "workspace_scope_unavailable",
|
|
36
|
+
error: "a readable workspace directory is required for workspace-scoped memory",
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const gitRepository = await resolveGitRepository(workspace);
|
|
40
|
+
if (gitRepository.kind === "invalid") {
|
|
41
|
+
return {
|
|
42
|
+
ok: false,
|
|
43
|
+
reason: "workspace_scope_unavailable",
|
|
44
|
+
error: "Git repository metadata is invalid or unavailable",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (gitRepository.kind === "repository") {
|
|
48
|
+
return {
|
|
49
|
+
ok: true,
|
|
50
|
+
scope: memoryScope({
|
|
51
|
+
baseUserId,
|
|
52
|
+
repositoryKey: identityKey("git-common-dir", gitRepository.commonDir),
|
|
53
|
+
repositorySlug: gitRepository.repositoryName,
|
|
54
|
+
identitySource: gitRepository.identitySource,
|
|
55
|
+
scopeKind: "git-repository",
|
|
56
|
+
boundWorkspaceRoot: gitRepository.workspaceRoot,
|
|
57
|
+
}),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const workspaceName = sanitizeWorkspaceName(basename(workspace));
|
|
61
|
+
if (!workspaceName) {
|
|
62
|
+
return {
|
|
63
|
+
ok: false,
|
|
64
|
+
reason: "workspace_scope_unavailable",
|
|
65
|
+
error: "the workspace root must have a usable folder name",
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
ok: true,
|
|
70
|
+
scope: memoryScope({
|
|
71
|
+
baseUserId,
|
|
72
|
+
repositoryKey: identityKey("workspace-directory", workspace),
|
|
73
|
+
repositorySlug: workspaceName,
|
|
74
|
+
identitySource: "workspace-directory",
|
|
75
|
+
scopeKind: "local-directory",
|
|
76
|
+
boundWorkspaceRoot: workspace,
|
|
77
|
+
}),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export function repositoryMemoryScopesMatch(left, right) {
|
|
81
|
+
return left.repositoryKey === right.repositoryKey
|
|
82
|
+
&& left.baseUserId === right.baseUserId
|
|
83
|
+
&& left.effectiveUserId === right.effectiveUserId;
|
|
84
|
+
}
|
|
85
|
+
export async function repositoryMemoryScopeContainsWorkspace(scope, workspaceRoot) {
|
|
86
|
+
if (!scope.boundWorkspaceRoot || !workspaceRoot?.trim())
|
|
87
|
+
return false;
|
|
88
|
+
const workspace = await resolveWorkspace(workspaceRoot);
|
|
89
|
+
if (!workspace)
|
|
90
|
+
return false;
|
|
91
|
+
if (scope.scopeKind === "git-repository") {
|
|
92
|
+
const gitRepository = await resolveGitRepository(workspace);
|
|
93
|
+
return gitRepository.kind === "repository"
|
|
94
|
+
&& identityKey("git-common-dir", gitRepository.commonDir) === scope.repositoryKey
|
|
95
|
+
&& gitRepository.repositoryName === scope.repositorySlug;
|
|
96
|
+
}
|
|
97
|
+
if (!pathContains(scope.boundWorkspaceRoot, workspace))
|
|
98
|
+
return false;
|
|
99
|
+
return scope.scopeKind !== "local-directory"
|
|
100
|
+
|| !await hasGitMarkerBetween(workspace, scope.boundWorkspaceRoot);
|
|
101
|
+
}
|
|
102
|
+
export function repositoryMemoryScopeKind(scope) {
|
|
103
|
+
return scope.scopeKind;
|
|
104
|
+
}
|
|
105
|
+
function memoryScope(input) {
|
|
106
|
+
return {
|
|
107
|
+
schemaVersion: "workspace-memory-scope.v1",
|
|
108
|
+
baseUserId: input.baseUserId,
|
|
109
|
+
effectiveUserId: `${input.baseUserId}@${input.repositorySlug}`,
|
|
110
|
+
repositoryKey: input.repositoryKey,
|
|
111
|
+
repositorySlug: input.repositorySlug,
|
|
112
|
+
repositoryName: input.repositorySlug,
|
|
113
|
+
identitySource: input.identitySource,
|
|
114
|
+
scopeKind: input.scopeKind,
|
|
115
|
+
...(input.boundWorkspaceRoot ? { boundWorkspaceRoot: input.boundWorkspaceRoot } : {}),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function sanitizeWorkspaceName(value) {
|
|
119
|
+
const normalized = value
|
|
120
|
+
.normalize("NFKC")
|
|
121
|
+
.trim()
|
|
122
|
+
.replace(/[@/\\\s\p{Cc}]+/gu, "-")
|
|
123
|
+
.replace(/[^\p{L}\p{N}._~-]+/gu, "-")
|
|
124
|
+
.replace(/^-+|-+$/g, "");
|
|
125
|
+
return [...normalized].slice(0, 120).join("").replace(/-+$/g, "");
|
|
126
|
+
}
|
|
127
|
+
async function resolveGitRepository(workspace) {
|
|
128
|
+
let marker;
|
|
129
|
+
try {
|
|
130
|
+
marker = await findNearestGitMarker(workspace);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return { kind: "invalid" };
|
|
134
|
+
}
|
|
135
|
+
if (!marker)
|
|
136
|
+
return { kind: "none" };
|
|
137
|
+
try {
|
|
138
|
+
const gitDir = await resolveGitDir(marker.path);
|
|
139
|
+
await validateGitHead(gitDir);
|
|
140
|
+
const commonDir = await resolveGitCommonDir(gitDir);
|
|
141
|
+
await validateGitCommonDir(commonDir);
|
|
142
|
+
const remotes = await readCommonConfigRemotes(commonDir);
|
|
143
|
+
const remoteName = selectedRemoteRepositoryName(remotes);
|
|
144
|
+
return {
|
|
145
|
+
kind: "repository",
|
|
146
|
+
commonDir,
|
|
147
|
+
repositoryName: remoteName ?? repositoryNameFromCommonDir(commonDir),
|
|
148
|
+
identitySource: remoteName ? "origin-remote" : "git-common-dir",
|
|
149
|
+
workspaceRoot: marker.workspaceRoot,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return { kind: "invalid" };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async function findNearestGitMarker(workspace) {
|
|
157
|
+
let current = workspace;
|
|
158
|
+
while (true) {
|
|
159
|
+
const marker = join(current, ".git");
|
|
160
|
+
try {
|
|
161
|
+
await fs.lstat(marker);
|
|
162
|
+
return { path: marker, workspaceRoot: current };
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
if (!isNodeErrorCode(error, "ENOENT"))
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
const parent = dirname(current);
|
|
169
|
+
if (parent === current)
|
|
170
|
+
return undefined;
|
|
171
|
+
current = parent;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async function hasGitMarkerBetween(workspace, boundary) {
|
|
175
|
+
let current = workspace;
|
|
176
|
+
while (true) {
|
|
177
|
+
try {
|
|
178
|
+
await fs.lstat(join(current, ".git"));
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
if (!isNodeErrorCode(error, "ENOENT"))
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
if (current === boundary)
|
|
186
|
+
return false;
|
|
187
|
+
const parent = dirname(current);
|
|
188
|
+
if (parent === current)
|
|
189
|
+
return true;
|
|
190
|
+
current = parent;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
async function resolveGitDir(marker) {
|
|
194
|
+
if ((await fs.lstat(marker)).isSymbolicLink())
|
|
195
|
+
throw new Error("symbolic Git metadata marker is not allowed");
|
|
196
|
+
const markerStat = await fs.stat(marker);
|
|
197
|
+
if (markerStat.isDirectory())
|
|
198
|
+
return await canonicalDirectory(marker);
|
|
199
|
+
if (!markerStat.isFile())
|
|
200
|
+
throw new Error("invalid Git metadata marker");
|
|
201
|
+
const line = await readSingleLine(marker, MAX_GIT_POINTER_BYTES);
|
|
202
|
+
const match = /^gitdir:[ \t]*(.+)$/i.exec(line);
|
|
203
|
+
const gitDir = match?.[1]?.trim();
|
|
204
|
+
if (!gitDir)
|
|
205
|
+
throw new Error("invalid Git metadata pointer");
|
|
206
|
+
return await canonicalDirectory(resolveMetadataPath(dirname(marker), gitDir));
|
|
207
|
+
}
|
|
208
|
+
async function resolveGitCommonDir(gitDir) {
|
|
209
|
+
const path = join(gitDir, "commondir");
|
|
210
|
+
try {
|
|
211
|
+
await fs.lstat(path);
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
if (isNodeErrorCode(error, "ENOENT"))
|
|
215
|
+
return gitDir;
|
|
216
|
+
throw error;
|
|
217
|
+
}
|
|
218
|
+
const commonDir = (await readSingleLine(path, MAX_GIT_POINTER_BYTES)).trim();
|
|
219
|
+
if (!commonDir)
|
|
220
|
+
throw new Error("invalid Git common directory pointer");
|
|
221
|
+
return await canonicalDirectory(resolveMetadataPath(gitDir, commonDir));
|
|
222
|
+
}
|
|
223
|
+
function resolveMetadataPath(base, value) {
|
|
224
|
+
if (value.includes("\0"))
|
|
225
|
+
throw new Error("invalid Git metadata path");
|
|
226
|
+
return isAbsolute(value) ? value : resolve(base, value);
|
|
227
|
+
}
|
|
228
|
+
async function canonicalDirectory(path) {
|
|
229
|
+
const canonical = await fs.realpath(path);
|
|
230
|
+
if (!(await fs.stat(canonical)).isDirectory())
|
|
231
|
+
throw new Error("Git metadata path is not a directory");
|
|
232
|
+
return canonical;
|
|
233
|
+
}
|
|
234
|
+
async function validateGitHead(gitDir) {
|
|
235
|
+
const head = (await readSingleLine(join(gitDir, "HEAD"), MAX_GIT_POINTER_BYTES)).trim();
|
|
236
|
+
if (!/^ref: refs\/[^\0\r\n]+$/.test(head) && !/^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/.test(head)) {
|
|
237
|
+
throw new Error("invalid Git HEAD");
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async function validateGitCommonDir(commonDir) {
|
|
241
|
+
if (!(await fs.stat(join(commonDir, "objects"))).isDirectory()) {
|
|
242
|
+
throw new Error("invalid Git objects directory");
|
|
243
|
+
}
|
|
244
|
+
const hasRefs = await isDirectory(join(commonDir, "refs"));
|
|
245
|
+
const hasReftable = await isDirectory(join(commonDir, "reftable"));
|
|
246
|
+
if (!hasRefs && !hasReftable)
|
|
247
|
+
throw new Error("invalid Git references directory");
|
|
248
|
+
}
|
|
249
|
+
async function isDirectory(path) {
|
|
250
|
+
try {
|
|
251
|
+
return (await fs.stat(path)).isDirectory();
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
if (isNodeErrorCode(error, "ENOENT"))
|
|
255
|
+
return false;
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async function readSingleLine(path, maxBytes) {
|
|
260
|
+
let value = await readBoundedTextFile(path, maxBytes);
|
|
261
|
+
if (value.endsWith("\r\n"))
|
|
262
|
+
value = value.slice(0, -2);
|
|
263
|
+
else if (value.endsWith("\n"))
|
|
264
|
+
value = value.slice(0, -1);
|
|
265
|
+
if (!value || value.includes("\0") || value.includes("\r") || value.includes("\n")) {
|
|
266
|
+
throw new Error("invalid single-line Git metadata");
|
|
267
|
+
}
|
|
268
|
+
return value;
|
|
269
|
+
}
|
|
270
|
+
async function readBoundedTextFile(path, maxBytes) {
|
|
271
|
+
const file = await fs.stat(path);
|
|
272
|
+
if (!file.isFile() || file.size > maxBytes)
|
|
273
|
+
throw new Error("invalid Git metadata file");
|
|
274
|
+
const value = await fs.readFile(path, "utf8");
|
|
275
|
+
if (Buffer.byteLength(value, "utf8") > maxBytes || value.includes("\0")) {
|
|
276
|
+
throw new Error("invalid Git metadata file");
|
|
277
|
+
}
|
|
278
|
+
return value;
|
|
279
|
+
}
|
|
280
|
+
async function readCommonConfigRemotes(commonDir) {
|
|
281
|
+
const path = join(commonDir, "config");
|
|
282
|
+
let source;
|
|
283
|
+
try {
|
|
284
|
+
source = await readBoundedTextFile(path, MAX_GIT_CONFIG_BYTES);
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
if (isNodeErrorCode(error, "ENOENT"))
|
|
288
|
+
return new Map();
|
|
289
|
+
throw error;
|
|
290
|
+
}
|
|
291
|
+
return parseDirectRemoteUrls(source);
|
|
292
|
+
}
|
|
293
|
+
function parseDirectRemoteUrls(source) {
|
|
294
|
+
const remotes = new Map();
|
|
295
|
+
let remote;
|
|
296
|
+
for (const line of logicalGitConfigLines(source)) {
|
|
297
|
+
const trimmed = line.trim();
|
|
298
|
+
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith(";"))
|
|
299
|
+
continue;
|
|
300
|
+
if (trimmed.startsWith("[")) {
|
|
301
|
+
const section = parseGitConfigSection(trimmed);
|
|
302
|
+
remote = section?.name.toLowerCase() === "remote" ? section.subsection : undefined;
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
if (!remote)
|
|
306
|
+
continue;
|
|
307
|
+
const assignment = /^[ \t]*([A-Za-z][A-Za-z0-9-]*)[ \t]*(?:=[ \t]*)?(.*)$/.exec(line);
|
|
308
|
+
if (!assignment)
|
|
309
|
+
throw new Error("invalid Git config assignment");
|
|
310
|
+
if (assignment[1]?.toLowerCase() !== "url")
|
|
311
|
+
continue;
|
|
312
|
+
remotes.set(remote, parseGitConfigValue(assignment[2] ?? ""));
|
|
313
|
+
}
|
|
314
|
+
return remotes;
|
|
315
|
+
}
|
|
316
|
+
function logicalGitConfigLines(source) {
|
|
317
|
+
const lines = [];
|
|
318
|
+
let pending = "";
|
|
319
|
+
for (const physical of source.split("\n")) {
|
|
320
|
+
const line = physical.endsWith("\r") ? physical.slice(0, -1) : physical;
|
|
321
|
+
const combined = `${pending}${line}`;
|
|
322
|
+
if (hasUnescapedTrailingBackslash(combined)) {
|
|
323
|
+
pending = combined.slice(0, -1);
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
lines.push(combined);
|
|
327
|
+
pending = "";
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
if (pending)
|
|
331
|
+
throw new Error("unterminated Git config continuation");
|
|
332
|
+
return lines;
|
|
333
|
+
}
|
|
334
|
+
function hasUnescapedTrailingBackslash(value) {
|
|
335
|
+
let count = 0;
|
|
336
|
+
for (let index = value.length - 1; index >= 0 && value[index] === "\\"; index -= 1)
|
|
337
|
+
count += 1;
|
|
338
|
+
return count % 2 === 1;
|
|
339
|
+
}
|
|
340
|
+
function parseGitConfigSection(line) {
|
|
341
|
+
const match = /^\[[ \t]*([A-Za-z0-9][A-Za-z0-9.-]*)[ \t]*(?:"((?:[^"\\]|\\.)*)")?[ \t]*\](?:[ \t]*[#;].*)?$/.exec(line);
|
|
342
|
+
if (!match?.[1])
|
|
343
|
+
throw new Error("invalid Git config section");
|
|
344
|
+
if (!match[2] && match[1].includes(".")) {
|
|
345
|
+
const separator = match[1].indexOf(".");
|
|
346
|
+
return {
|
|
347
|
+
name: match[1].slice(0, separator),
|
|
348
|
+
subsection: match[1].slice(separator + 1),
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
return {
|
|
352
|
+
name: match[1],
|
|
353
|
+
...(match[2] !== undefined ? { subsection: unescapeGitConfigText(match[2]) } : {}),
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
function parseGitConfigValue(value) {
|
|
357
|
+
const input = value.trimStart();
|
|
358
|
+
if (!input.startsWith('"')) {
|
|
359
|
+
const comment = input.search(/[#;]/);
|
|
360
|
+
return unescapeGitConfigText((comment >= 0 ? input.slice(0, comment) : input).trimEnd());
|
|
361
|
+
}
|
|
362
|
+
let result = "";
|
|
363
|
+
let escaped = false;
|
|
364
|
+
for (let index = 1; index < input.length; index += 1) {
|
|
365
|
+
const character = input[index];
|
|
366
|
+
if (escaped) {
|
|
367
|
+
result += unescapeGitConfigCharacter(character);
|
|
368
|
+
escaped = false;
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
if (character === "\\") {
|
|
372
|
+
escaped = true;
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
if (character !== '"') {
|
|
376
|
+
result += character;
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
const trailing = input.slice(index + 1).trim();
|
|
380
|
+
if (trailing && !trailing.startsWith("#") && !trailing.startsWith(";")) {
|
|
381
|
+
throw new Error("invalid Git config value");
|
|
382
|
+
}
|
|
383
|
+
return result;
|
|
384
|
+
}
|
|
385
|
+
throw new Error("unterminated Git config value");
|
|
386
|
+
}
|
|
387
|
+
function unescapeGitConfigText(value) {
|
|
388
|
+
let result = "";
|
|
389
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
390
|
+
const character = value[index];
|
|
391
|
+
if (character !== "\\") {
|
|
392
|
+
result += character;
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
const escaped = value[index + 1];
|
|
396
|
+
if (escaped === undefined)
|
|
397
|
+
throw new Error("invalid Git config escape");
|
|
398
|
+
result += unescapeGitConfigCharacter(escaped);
|
|
399
|
+
index += 1;
|
|
400
|
+
}
|
|
401
|
+
return result;
|
|
402
|
+
}
|
|
403
|
+
function unescapeGitConfigCharacter(value) {
|
|
404
|
+
if (value === "n")
|
|
405
|
+
return "\n";
|
|
406
|
+
if (value === "t")
|
|
407
|
+
return "\t";
|
|
408
|
+
if (value === "b")
|
|
409
|
+
return "\b";
|
|
410
|
+
if (value === '"' || value === "\\")
|
|
411
|
+
return value;
|
|
412
|
+
throw new Error("invalid Git config escape");
|
|
413
|
+
}
|
|
414
|
+
function selectedRemoteRepositoryName(remotes) {
|
|
415
|
+
const origin = remotes.get("origin");
|
|
416
|
+
if (origin !== undefined)
|
|
417
|
+
return repositoryNameFromRemoteUrl(origin);
|
|
418
|
+
if (remotes.size !== 1)
|
|
419
|
+
return undefined;
|
|
420
|
+
return repositoryNameFromRemoteUrl(remotes.values().next().value ?? "");
|
|
421
|
+
}
|
|
422
|
+
function repositoryNameFromRemoteUrl(value) {
|
|
423
|
+
const raw = value.trim();
|
|
424
|
+
if (!raw
|
|
425
|
+
|| raw.startsWith("/")
|
|
426
|
+
|| raw.startsWith("./")
|
|
427
|
+
|| raw.startsWith("../")
|
|
428
|
+
|| raw.startsWith("\\\\")
|
|
429
|
+
|| /^[a-zA-Z]:[\\/]/.test(raw))
|
|
430
|
+
return undefined;
|
|
431
|
+
try {
|
|
432
|
+
const parsed = new URL(raw);
|
|
433
|
+
if (!["http:", "https:", "ssh:", "git:", "git+ssh:", "git+https:"].includes(parsed.protocol)) {
|
|
434
|
+
return undefined;
|
|
435
|
+
}
|
|
436
|
+
if (!parsed.hostname.trim())
|
|
437
|
+
return undefined;
|
|
438
|
+
return repositoryNameFromRemotePath(parsed.pathname);
|
|
439
|
+
}
|
|
440
|
+
catch {
|
|
441
|
+
const scp = /^(?:[^@/:\s]+@)?[^/:\s]+:(.+)$/.exec(raw);
|
|
442
|
+
return scp?.[1] ? repositoryNameFromRemotePath(scp[1]) : undefined;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
function repositoryNameFromRemotePath(value) {
|
|
446
|
+
const path = value
|
|
447
|
+
.split(/[?#]/, 1)[0]
|
|
448
|
+
?.replace(/[\\/]+$/, "");
|
|
449
|
+
let name = path?.split(/[\\/]/).filter(Boolean).at(-1);
|
|
450
|
+
if (!name)
|
|
451
|
+
return undefined;
|
|
452
|
+
try {
|
|
453
|
+
name = decodeURIComponent(name);
|
|
454
|
+
}
|
|
455
|
+
catch {
|
|
456
|
+
return undefined;
|
|
457
|
+
}
|
|
458
|
+
name = name.replace(/\.git$/i, "");
|
|
459
|
+
return sanitizeWorkspaceName(name) || undefined;
|
|
460
|
+
}
|
|
461
|
+
function repositoryNameFromCommonDir(commonDir) {
|
|
462
|
+
const commonName = basename(commonDir);
|
|
463
|
+
const name = commonName.toLowerCase() === ".git"
|
|
464
|
+
? basename(dirname(commonDir))
|
|
465
|
+
: commonName.replace(/\.git$/i, "");
|
|
466
|
+
const normalized = sanitizeWorkspaceName(name);
|
|
467
|
+
if (!normalized)
|
|
468
|
+
throw new Error("Git common directory has no usable repository name");
|
|
469
|
+
return normalized;
|
|
470
|
+
}
|
|
471
|
+
function identityKey(source, value) {
|
|
472
|
+
return createHash("sha256").update(`${source}:${value}`).digest("hex");
|
|
473
|
+
}
|
|
474
|
+
async function resolveWorkspace(value) {
|
|
475
|
+
if (!value?.trim())
|
|
476
|
+
return undefined;
|
|
477
|
+
try {
|
|
478
|
+
const path = await fs.realpath(value);
|
|
479
|
+
return (await fs.stat(path)).isDirectory() ? path : undefined;
|
|
480
|
+
}
|
|
481
|
+
catch {
|
|
482
|
+
return undefined;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
function pathContains(root, candidate) {
|
|
486
|
+
return candidate === root || candidate.startsWith(root.endsWith(sep) ? root : `${root}${sep}`);
|
|
487
|
+
}
|
|
488
|
+
function isNodeErrorCode(error, code) {
|
|
489
|
+
return Boolean(error && typeof error === "object" && "code" in error && error.code === code);
|
|
490
|
+
}
|