@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,111 @@
|
|
|
1
|
+
import { memoryProjectFromUnknown, resolveMemoryProject, } from "./memory-project.js";
|
|
2
|
+
export function traceContextFromHookBody(body, capturedAt = new Date().toISOString()) {
|
|
3
|
+
if (!isRecord(body))
|
|
4
|
+
return undefined;
|
|
5
|
+
const sessionId = stringField(body, "session_id") ?? stringField(body, "sessionId");
|
|
6
|
+
if (!sessionId)
|
|
7
|
+
return undefined;
|
|
8
|
+
const cwd = stringField(body, "cwd");
|
|
9
|
+
return pruneTraceContext({
|
|
10
|
+
schemaVersion: "1",
|
|
11
|
+
client: "codex",
|
|
12
|
+
sessionId,
|
|
13
|
+
turnId: stringField(body, "turn_id") ?? stringField(body, "turnId"),
|
|
14
|
+
threadId: stringField(body, "thread_id") ?? stringField(body, "threadId"),
|
|
15
|
+
nativeRequestId: stringField(body, "native_request_id") ?? stringField(body, "nativeRequestId"),
|
|
16
|
+
requestId: stringField(body, "request_id") ?? stringField(body, "requestId"),
|
|
17
|
+
transcriptPath: stringField(body, "transcript_path") ?? stringField(body, "transcriptPath"),
|
|
18
|
+
cwd,
|
|
19
|
+
memoryProject: resolveMemoryProject(cwd),
|
|
20
|
+
workspaceKind: stringField(body, "workspace_kind") ?? stringField(body, "workspaceKind"),
|
|
21
|
+
contextOrigin: "codex-hook-body",
|
|
22
|
+
capturedAt,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export function traceContextFromClaudeHookBody(body, capturedAt = new Date().toISOString()) {
|
|
26
|
+
if (!isRecord(body))
|
|
27
|
+
return undefined;
|
|
28
|
+
const sessionId = stringField(body, "session_id") ?? stringField(body, "sessionId");
|
|
29
|
+
if (!sessionId)
|
|
30
|
+
return undefined;
|
|
31
|
+
const cwd = stringField(body, "cwd");
|
|
32
|
+
return pruneTraceContext({
|
|
33
|
+
schemaVersion: "1",
|
|
34
|
+
client: "claude",
|
|
35
|
+
sessionId,
|
|
36
|
+
turnId: stringField(body, "prompt_id") ?? stringField(body, "promptId"),
|
|
37
|
+
transcriptPath: stringField(body, "transcript_path") ?? stringField(body, "transcriptPath"),
|
|
38
|
+
cwd,
|
|
39
|
+
memoryProject: resolveMemoryProject(cwd),
|
|
40
|
+
workspaceKind: stringField(body, "workspace_kind") ?? stringField(body, "workspaceKind"),
|
|
41
|
+
contextOrigin: "claude-hook-body",
|
|
42
|
+
capturedAt,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
export function traceContextFromCurrentTurnRecord(value) {
|
|
46
|
+
if (!isRecord(value))
|
|
47
|
+
return undefined;
|
|
48
|
+
const trace = isRecord(value.trace) ? value.trace : value;
|
|
49
|
+
const sessionId = stringField(trace, "session_id") ?? stringField(trace, "sessionId");
|
|
50
|
+
if (!sessionId)
|
|
51
|
+
return undefined;
|
|
52
|
+
const capturedAt = stringField(trace, "captured_at") ?? stringField(trace, "capturedAt");
|
|
53
|
+
if (!capturedAt || !Number.isFinite(Date.parse(capturedAt)))
|
|
54
|
+
return undefined;
|
|
55
|
+
const cwd = stringField(trace, "cwd");
|
|
56
|
+
const client = stringField(trace, "client");
|
|
57
|
+
if (!isTraceClient(client))
|
|
58
|
+
return undefined;
|
|
59
|
+
return pruneTraceContext({
|
|
60
|
+
schemaVersion: "1",
|
|
61
|
+
client,
|
|
62
|
+
sessionId,
|
|
63
|
+
turnId: stringField(trace, "turn_id") ?? stringField(trace, "turnId"),
|
|
64
|
+
threadId: stringField(trace, "thread_id") ?? stringField(trace, "threadId"),
|
|
65
|
+
nativeRequestId: stringField(trace, "native_request_id") ?? stringField(trace, "nativeRequestId"),
|
|
66
|
+
requestId: stringField(trace, "request_id") ?? stringField(trace, "requestId"),
|
|
67
|
+
transcriptPath: stringField(trace, "transcript_path") ?? stringField(trace, "transcriptPath"),
|
|
68
|
+
cwd,
|
|
69
|
+
memoryProject: memoryProjectFromUnknown(trace.memory_project)
|
|
70
|
+
?? memoryProjectFromUnknown(trace.memoryProject)
|
|
71
|
+
?? resolveMemoryProject(cwd),
|
|
72
|
+
workspaceKind: stringField(trace, "workspace_kind") ?? stringField(trace, "workspaceKind"),
|
|
73
|
+
contextOrigin: "current-turn-file",
|
|
74
|
+
capturedAt,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
export function traceContextJson(context) {
|
|
78
|
+
return pruneRecord({
|
|
79
|
+
client: context.client,
|
|
80
|
+
session_id: context.sessionId,
|
|
81
|
+
turn_id: context.turnId,
|
|
82
|
+
thread_id: context.threadId,
|
|
83
|
+
native_request_id: context.nativeRequestId,
|
|
84
|
+
request_id: context.requestId,
|
|
85
|
+
transcript_path: context.transcriptPath,
|
|
86
|
+
cwd: context.cwd,
|
|
87
|
+
memory_project: context.memoryProject ? {
|
|
88
|
+
project_id: context.memoryProject.projectId,
|
|
89
|
+
project_label: context.memoryProject.projectLabel,
|
|
90
|
+
} : undefined,
|
|
91
|
+
workspace_kind: context.workspaceKind,
|
|
92
|
+
context_origin: context.contextOrigin,
|
|
93
|
+
captured_at: context.capturedAt,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function pruneTraceContext(value) {
|
|
97
|
+
return pruneRecord(value);
|
|
98
|
+
}
|
|
99
|
+
function pruneRecord(value) {
|
|
100
|
+
return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
|
|
101
|
+
}
|
|
102
|
+
export function isTraceClient(value) {
|
|
103
|
+
return value === "codex" || value === "claude";
|
|
104
|
+
}
|
|
105
|
+
function stringField(record, key) {
|
|
106
|
+
const value = record[key];
|
|
107
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
108
|
+
}
|
|
109
|
+
function isRecord(value) {
|
|
110
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
111
|
+
}
|
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { TRACE_CLEANUP_DEBOUNCE_MS, TRACE_CURRENT_TURN_TTL_MS, clientTraceConfigFromEnv, clientTracePaths, memoraxCodeHomeForTrace, } from "./trace-config.js";
|
|
5
|
+
import { isTraceClient, traceContextFromCurrentTurnRecord, traceContextJson, } from "./trace-context.js";
|
|
6
|
+
import { appendRepairingJsonl } from "./jsonl-append.js";
|
|
7
|
+
const eventCounters = new Map();
|
|
8
|
+
const lastCleanupByRoot = new Map();
|
|
9
|
+
const currentTurnPathOperations = new Map();
|
|
10
|
+
const traceEventPathOperations = new Map();
|
|
11
|
+
const eventIdsByPath = new Map();
|
|
12
|
+
export async function recordTraceEvent(input) {
|
|
13
|
+
const client = input.traceContext?.client;
|
|
14
|
+
if (!client)
|
|
15
|
+
return { written: false, reason: "missing_trace_context" };
|
|
16
|
+
if (!isTraceClient(client))
|
|
17
|
+
return { written: false, reason: "unsupported_client" };
|
|
18
|
+
return recordTraceEventForClient(client, input);
|
|
19
|
+
}
|
|
20
|
+
async function recordTraceEventForClient(client, input) {
|
|
21
|
+
if (input.traceContext && input.traceContext.client !== client) {
|
|
22
|
+
return { written: false, reason: "client_mismatch" };
|
|
23
|
+
}
|
|
24
|
+
const env = input.env ?? process.env;
|
|
25
|
+
const memoraxCodeHome = input.memoraxCodeHome ?? memoraxCodeHomeForTrace(env);
|
|
26
|
+
const config = input.config ?? clientTraceConfigFromEnv(client, traceEnv(env, memoraxCodeHome));
|
|
27
|
+
if (!config.enabled)
|
|
28
|
+
return { written: false, reason: "disabled" };
|
|
29
|
+
const traceContext = input.traceContext;
|
|
30
|
+
if (!traceContext?.sessionId)
|
|
31
|
+
return { written: false, reason: "missing_trace_context" };
|
|
32
|
+
const now = input.now?.() ?? new Date();
|
|
33
|
+
const paths = clientTracePaths(client, memoraxCodeHome);
|
|
34
|
+
await pruneExpiredTraceSessions(paths.root, config, now, { debounce: true }).catch(() => undefined);
|
|
35
|
+
const sessionDir = paths.sessionDir(traceContext.sessionId);
|
|
36
|
+
await mkdir(sessionDir, { recursive: true });
|
|
37
|
+
const eventsPath = paths.eventsJsonl(traceContext.sessionId);
|
|
38
|
+
if (await exceedsMaxFileBytes(eventsPath, config.maxFileBytes)) {
|
|
39
|
+
await writeMaxFileWarningEvent({
|
|
40
|
+
input,
|
|
41
|
+
config,
|
|
42
|
+
now,
|
|
43
|
+
sessionDir,
|
|
44
|
+
eventsPath,
|
|
45
|
+
}).catch(() => undefined);
|
|
46
|
+
return { written: false, reason: "max_file_bytes" };
|
|
47
|
+
}
|
|
48
|
+
await writeTraceJson(paths.traceJson(traceContext.sessionId), traceContext, config, now);
|
|
49
|
+
const explicitEventId = normalizedString(input.eventId)?.slice(0, 200);
|
|
50
|
+
const eventId = explicitEventId || nextEventId(sessionDir, now);
|
|
51
|
+
const event = buildTraceEvent(input, config, now, eventId);
|
|
52
|
+
const appended = await appendJsonlEvent(eventsPath, event, explicitEventId);
|
|
53
|
+
if (!appended)
|
|
54
|
+
return { written: false, reason: "duplicate_event" };
|
|
55
|
+
return { written: true, path: eventsPath };
|
|
56
|
+
}
|
|
57
|
+
export async function recordCodexTraceEvent(input) {
|
|
58
|
+
return recordTraceEventForClient("codex", input);
|
|
59
|
+
}
|
|
60
|
+
export async function recordClaudeTraceEvent(input) {
|
|
61
|
+
return recordTraceEventForClient("claude", input);
|
|
62
|
+
}
|
|
63
|
+
export function traceTurnEventId(traceContext, type) {
|
|
64
|
+
if (!traceContext?.sessionId || !traceContext.turnId)
|
|
65
|
+
return undefined;
|
|
66
|
+
const digest = createHash("sha256")
|
|
67
|
+
.update(`${traceContext.client}\u0000${traceContext.sessionId}\u0000${traceContext.turnId}\u0000${type}`)
|
|
68
|
+
.digest("hex")
|
|
69
|
+
.slice(0, 32);
|
|
70
|
+
return `trace-${type.replaceAll("_", "-")}-${digest}`;
|
|
71
|
+
}
|
|
72
|
+
export async function writeCurrentTraceTurn(traceContext, options = {}) {
|
|
73
|
+
const client = options.client ?? traceContext?.client;
|
|
74
|
+
if (!client)
|
|
75
|
+
return { written: false, reason: "missing_trace_context" };
|
|
76
|
+
if (!isTraceClient(client))
|
|
77
|
+
return { written: false, reason: "unsupported_client" };
|
|
78
|
+
if (traceContext && traceContext.client !== client) {
|
|
79
|
+
return { written: false, reason: "client_mismatch" };
|
|
80
|
+
}
|
|
81
|
+
const env = options.env ?? process.env;
|
|
82
|
+
const memoraxCodeHome = options.memoraxCodeHome ?? memoraxCodeHomeForTrace(env);
|
|
83
|
+
const config = options.config ?? clientTraceConfigFromEnv(client, traceEnv(env, memoraxCodeHome));
|
|
84
|
+
if (!config.enabled)
|
|
85
|
+
return { written: false, reason: "disabled" };
|
|
86
|
+
if (!traceContext?.sessionId)
|
|
87
|
+
return { written: false, reason: "missing_trace_context" };
|
|
88
|
+
const paths = clientTracePaths(client, memoraxCodeHome);
|
|
89
|
+
const capturedAt = (options.now?.() ?? new Date()).toISOString();
|
|
90
|
+
const record = `${JSON.stringify({
|
|
91
|
+
schema_version: "1",
|
|
92
|
+
turn_state: "open",
|
|
93
|
+
trace: traceContextJson({
|
|
94
|
+
...traceContext,
|
|
95
|
+
capturedAt,
|
|
96
|
+
}),
|
|
97
|
+
}, null, 2)}\n`;
|
|
98
|
+
await mkdir(paths.root, { recursive: true });
|
|
99
|
+
await mkdir(paths.sessionDir(traceContext.sessionId), { recursive: true });
|
|
100
|
+
await Promise.all([
|
|
101
|
+
serializeCurrentTurnPath(paths.currentTurnPath, () => writeFile(paths.currentTurnPath, record, "utf8")),
|
|
102
|
+
serializeCurrentTurnPath(paths.sessionCurrentTurnPath(traceContext.sessionId), () => writeFile(paths.sessionCurrentTurnPath(traceContext.sessionId), record, "utf8")),
|
|
103
|
+
]);
|
|
104
|
+
return { written: true };
|
|
105
|
+
}
|
|
106
|
+
export async function writeCurrentCodexTurn(traceContext, options = {}) {
|
|
107
|
+
return writeCurrentTraceTurn(traceContext, { ...options, client: "codex" });
|
|
108
|
+
}
|
|
109
|
+
export async function writeCurrentClaudeTurn(traceContext, options = {}) {
|
|
110
|
+
return writeCurrentTraceTurn(traceContext, { ...options, client: "claude" });
|
|
111
|
+
}
|
|
112
|
+
export async function readCurrentTraceTurn(options) {
|
|
113
|
+
const current = await readCurrentTraceTurnRecord(options);
|
|
114
|
+
return current.ok
|
|
115
|
+
? { ok: true, traceContext: current.traceContext }
|
|
116
|
+
: current;
|
|
117
|
+
}
|
|
118
|
+
export async function readCurrentCodexTurn(options = {}) {
|
|
119
|
+
return readCurrentTraceTurn({ ...options, client: "codex" });
|
|
120
|
+
}
|
|
121
|
+
export async function readCurrentClaudeTurn(options = {}) {
|
|
122
|
+
return readCurrentTraceTurn({ ...options, client: "claude" });
|
|
123
|
+
}
|
|
124
|
+
export async function readOpenTraceTurn(options) {
|
|
125
|
+
const current = await readCurrentTraceTurnRecord(options);
|
|
126
|
+
if (!current.ok)
|
|
127
|
+
return current;
|
|
128
|
+
if (current.turnState !== "open") {
|
|
129
|
+
return { ok: false, reason: "closed", outcome: current.turnState };
|
|
130
|
+
}
|
|
131
|
+
return { ok: true, traceContext: current.traceContext };
|
|
132
|
+
}
|
|
133
|
+
export async function readOpenCodexTurn(options = {}) {
|
|
134
|
+
return readOpenTraceTurn({ ...options, client: "codex" });
|
|
135
|
+
}
|
|
136
|
+
export async function readOpenClaudeTurn(options = {}) {
|
|
137
|
+
return readOpenTraceTurn({ ...options, client: "claude" });
|
|
138
|
+
}
|
|
139
|
+
export async function markCurrentTraceTurnOutcome(traceContext, outcome, options = {}) {
|
|
140
|
+
const client = options.client ?? traceContext?.client;
|
|
141
|
+
if (!client)
|
|
142
|
+
return { updated: false, reason: "missing_trace_context" };
|
|
143
|
+
if (!isTraceClient(client))
|
|
144
|
+
return { updated: false, reason: "unsupported_client" };
|
|
145
|
+
if (traceContext && traceContext.client !== client) {
|
|
146
|
+
return { updated: false, reason: "client_mismatch" };
|
|
147
|
+
}
|
|
148
|
+
const env = options.env ?? process.env;
|
|
149
|
+
const memoraxCodeHome = options.memoraxCodeHome ?? memoraxCodeHomeForTrace(env);
|
|
150
|
+
const config = options.config ?? clientTraceConfigFromEnv(client, traceEnv(env, memoraxCodeHome));
|
|
151
|
+
if (!config.enabled)
|
|
152
|
+
return { updated: false, reason: "disabled" };
|
|
153
|
+
if (!traceContext?.sessionId || !traceContext.turnId) {
|
|
154
|
+
return { updated: false, reason: "missing_trace_context" };
|
|
155
|
+
}
|
|
156
|
+
const paths = clientTracePaths(client, memoraxCodeHome);
|
|
157
|
+
const updated = await Promise.all([
|
|
158
|
+
markCurrentTraceTurnPath(paths.currentTurnPath, traceContext, outcome),
|
|
159
|
+
markCurrentTraceTurnPath(paths.sessionCurrentTurnPath(traceContext.sessionId), traceContext, outcome),
|
|
160
|
+
]);
|
|
161
|
+
return updated.some(Boolean)
|
|
162
|
+
? { updated: true }
|
|
163
|
+
: { updated: false, reason: "not_current_turn" };
|
|
164
|
+
}
|
|
165
|
+
export async function markCurrentCodexTurnOutcome(traceContext, outcome, options = {}) {
|
|
166
|
+
return markCurrentTraceTurnOutcome(traceContext, outcome, { ...options, client: "codex" });
|
|
167
|
+
}
|
|
168
|
+
export async function markCurrentClaudeTurnOutcome(traceContext, outcome, options = {}) {
|
|
169
|
+
return markCurrentTraceTurnOutcome(traceContext, outcome, { ...options, client: "claude" });
|
|
170
|
+
}
|
|
171
|
+
async function readCurrentTraceTurnRecord(options) {
|
|
172
|
+
const client = options.client;
|
|
173
|
+
if (!isTraceClient(client))
|
|
174
|
+
return { ok: false, reason: "invalid" };
|
|
175
|
+
const env = options.env ?? process.env;
|
|
176
|
+
const memoraxCodeHome = options.memoraxCodeHome ?? memoraxCodeHomeForTrace(env);
|
|
177
|
+
const config = options.config ?? clientTraceConfigFromEnv(client, traceEnv(env, memoraxCodeHome));
|
|
178
|
+
if (!config.enabled)
|
|
179
|
+
return { ok: false, reason: "disabled" };
|
|
180
|
+
const paths = clientTracePaths(client, memoraxCodeHome);
|
|
181
|
+
const now = options.now?.() ?? new Date();
|
|
182
|
+
const expectedSessionId = normalizedString(options.expectedSessionId);
|
|
183
|
+
if (expectedSessionId) {
|
|
184
|
+
const sessionCurrent = await readCurrentTraceTurnPath(paths.sessionCurrentTurnPath(expectedSessionId), now, options.allowStale ?? false, client);
|
|
185
|
+
if (sessionCurrent.ok) {
|
|
186
|
+
if (sessionCurrent.traceContext.sessionId !== expectedSessionId) {
|
|
187
|
+
return { ok: false, reason: "session_mismatch" };
|
|
188
|
+
}
|
|
189
|
+
return sessionCurrent;
|
|
190
|
+
}
|
|
191
|
+
if (sessionCurrent.reason !== "missing")
|
|
192
|
+
return sessionCurrent;
|
|
193
|
+
const globalCurrent = await readCurrentTraceTurnPath(paths.currentTurnPath, now, options.allowStale ?? false, client);
|
|
194
|
+
if (!globalCurrent.ok)
|
|
195
|
+
return globalCurrent;
|
|
196
|
+
if (globalCurrent.traceContext.sessionId !== expectedSessionId) {
|
|
197
|
+
return { ok: false, reason: "session_mismatch" };
|
|
198
|
+
}
|
|
199
|
+
return globalCurrent;
|
|
200
|
+
}
|
|
201
|
+
return await readCurrentTraceTurnPath(paths.currentTurnPath, now, options.allowStale ?? false, client);
|
|
202
|
+
}
|
|
203
|
+
async function readCurrentTraceTurnPath(path, now, allowStale, expectedClient) {
|
|
204
|
+
let raw;
|
|
205
|
+
try {
|
|
206
|
+
raw = JSON.parse(await readFile(path, "utf8"));
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
return { ok: false, reason: "missing" };
|
|
210
|
+
}
|
|
211
|
+
if (!isRecord(raw) || raw.schema_version !== "1" || !isRecord(raw.trace)) {
|
|
212
|
+
return { ok: false, reason: "invalid" };
|
|
213
|
+
}
|
|
214
|
+
const traceContext = traceContextFromCurrentTurnRecord(raw);
|
|
215
|
+
if (!traceContext || traceContext.client !== expectedClient)
|
|
216
|
+
return { ok: false, reason: "invalid" };
|
|
217
|
+
if (!allowStale && now.getTime() - Date.parse(traceContext.capturedAt) > TRACE_CURRENT_TURN_TTL_MS) {
|
|
218
|
+
return { ok: false, reason: "stale" };
|
|
219
|
+
}
|
|
220
|
+
const turnState = currentTurnState(raw);
|
|
221
|
+
if (!turnState)
|
|
222
|
+
return { ok: false, reason: "invalid" };
|
|
223
|
+
return {
|
|
224
|
+
ok: true,
|
|
225
|
+
traceContext,
|
|
226
|
+
turnState,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
async function markCurrentTraceTurnPath(path, expected, outcome) {
|
|
230
|
+
return await serializeCurrentTurnPath(path, async () => {
|
|
231
|
+
let raw;
|
|
232
|
+
try {
|
|
233
|
+
raw = JSON.parse(await readFile(path, "utf8"));
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
if (!isRecord(raw) || raw.schema_version !== "1" || !isRecord(raw.trace))
|
|
239
|
+
return false;
|
|
240
|
+
const current = traceContextFromCurrentTurnRecord(raw);
|
|
241
|
+
if (!current
|
|
242
|
+
|| current.client !== expected.client
|
|
243
|
+
|| current.sessionId !== expected.sessionId
|
|
244
|
+
|| current.turnId !== expected.turnId) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
await writeFile(path, `${JSON.stringify({
|
|
248
|
+
...raw,
|
|
249
|
+
turn_state: outcome,
|
|
250
|
+
}, null, 2)}\n`, "utf8");
|
|
251
|
+
return true;
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
function currentTurnState(value) {
|
|
255
|
+
if (!isRecord(value))
|
|
256
|
+
return undefined;
|
|
257
|
+
const state = normalizedString(value.turn_state);
|
|
258
|
+
return state === "open" || state === "completed" || state === "interrupted"
|
|
259
|
+
? state
|
|
260
|
+
: undefined;
|
|
261
|
+
}
|
|
262
|
+
async function serializeCurrentTurnPath(path, operation) {
|
|
263
|
+
const previous = currentTurnPathOperations.get(path) ?? Promise.resolve();
|
|
264
|
+
const current = previous.catch(() => undefined).then(operation);
|
|
265
|
+
currentTurnPathOperations.set(path, current);
|
|
266
|
+
try {
|
|
267
|
+
return await current;
|
|
268
|
+
}
|
|
269
|
+
finally {
|
|
270
|
+
if (currentTurnPathOperations.get(path) === current)
|
|
271
|
+
currentTurnPathOperations.delete(path);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
export async function pruneExpiredTraceSessionsForClient(options) {
|
|
275
|
+
const client = options.client;
|
|
276
|
+
if (!isTraceClient(client))
|
|
277
|
+
return;
|
|
278
|
+
const env = options.env ?? process.env;
|
|
279
|
+
const memoraxCodeHome = options.memoraxCodeHome ?? memoraxCodeHomeForTrace(env);
|
|
280
|
+
const config = options.config ?? clientTraceConfigFromEnv(client, traceEnv(env, memoraxCodeHome));
|
|
281
|
+
if (!config.enabled)
|
|
282
|
+
return;
|
|
283
|
+
const now = options.now?.() ?? new Date();
|
|
284
|
+
const paths = clientTracePaths(client, memoraxCodeHome);
|
|
285
|
+
await pruneExpiredTraceSessions(paths.root, config, now, { debounce: false });
|
|
286
|
+
}
|
|
287
|
+
export async function pruneExpiredCodexTraceSessions(options = {}) {
|
|
288
|
+
return pruneExpiredTraceSessionsForClient({ ...options, client: "codex" });
|
|
289
|
+
}
|
|
290
|
+
export async function pruneExpiredClaudeTraceSessions(options = {}) {
|
|
291
|
+
return pruneExpiredTraceSessionsForClient({ ...options, client: "claude" });
|
|
292
|
+
}
|
|
293
|
+
function buildTraceEvent(input, config, now, eventId) {
|
|
294
|
+
const captureContent = config.captureContent;
|
|
295
|
+
return pruneRecord({
|
|
296
|
+
schema_version: "1",
|
|
297
|
+
event_id: eventId,
|
|
298
|
+
type: input.type,
|
|
299
|
+
timestamp: now.toISOString(),
|
|
300
|
+
trace: input.traceContext ? traceContextJson(input.traceContext) : undefined,
|
|
301
|
+
source: input.source ?? "unknown",
|
|
302
|
+
operation: input.operation,
|
|
303
|
+
ok: input.ok,
|
|
304
|
+
outcome: input.outcome,
|
|
305
|
+
related_turns: input.relatedTurns?.map(relatedTurnJson),
|
|
306
|
+
activities: input.activities,
|
|
307
|
+
usage: input.usage,
|
|
308
|
+
session_turn_index: input.sessionTurnIndex,
|
|
309
|
+
request: input.request === undefined ? undefined : sanitizeTraceValue(input.request, config, captureContent),
|
|
310
|
+
response: input.response === undefined ? undefined : sanitizeTraceValue(input.response, config, captureContent),
|
|
311
|
+
error: input.error ? truncate(input.error, Math.min(config.maxEventChars, 2000)) : undefined,
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
function relatedTurnJson(turn) {
|
|
315
|
+
return pruneRecord({
|
|
316
|
+
turn_id: turn.turnId,
|
|
317
|
+
request_id: turn.requestId,
|
|
318
|
+
native_request_id: turn.nativeRequestId,
|
|
319
|
+
context_origin: turn.contextOrigin,
|
|
320
|
+
captured_at: turn.capturedAt,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
function sanitizeTraceValue(value, config, captureContent) {
|
|
324
|
+
if (!captureContent)
|
|
325
|
+
return metadataValue(value);
|
|
326
|
+
if (typeof value === "string")
|
|
327
|
+
return truncate(value, config.maxEventChars);
|
|
328
|
+
if (value === null || typeof value !== "object")
|
|
329
|
+
return value;
|
|
330
|
+
if (Array.isArray(value))
|
|
331
|
+
return value.slice(0, 100).map((item) => sanitizeTraceValue(item, config, captureContent));
|
|
332
|
+
const output = {};
|
|
333
|
+
for (const [key, item] of Object.entries(value)) {
|
|
334
|
+
if (/authorization|api[-_]?key|token|secret/i.test(key))
|
|
335
|
+
continue;
|
|
336
|
+
output[key] = sanitizeTraceValue(item, config, captureContent);
|
|
337
|
+
}
|
|
338
|
+
return output;
|
|
339
|
+
}
|
|
340
|
+
function metadataValue(value) {
|
|
341
|
+
if (typeof value === "string") {
|
|
342
|
+
return {
|
|
343
|
+
content_mode: "metadata",
|
|
344
|
+
chars: value.length,
|
|
345
|
+
hash: `sha256:${hashText(value)}`,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
if (value === null || typeof value !== "object")
|
|
349
|
+
return value;
|
|
350
|
+
if (Array.isArray(value)) {
|
|
351
|
+
return {
|
|
352
|
+
content_mode: "metadata",
|
|
353
|
+
kind: "array",
|
|
354
|
+
count: value.length,
|
|
355
|
+
items: value.slice(0, 20).map(metadataValue),
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
const output = { content_mode: "metadata" };
|
|
359
|
+
for (const [key, item] of Object.entries(value)) {
|
|
360
|
+
if (/authorization|api[-_]?key|token|secret/i.test(key))
|
|
361
|
+
continue;
|
|
362
|
+
output[key] = metadataValue(item);
|
|
363
|
+
}
|
|
364
|
+
return output;
|
|
365
|
+
}
|
|
366
|
+
async function writeTraceJson(path, context, config, now) {
|
|
367
|
+
const existing = await readExistingTraceJson(path);
|
|
368
|
+
const existingClient = existing?.[context.client];
|
|
369
|
+
const trace = {
|
|
370
|
+
schema_version: "1",
|
|
371
|
+
client: context.client,
|
|
372
|
+
session_id: context.sessionId,
|
|
373
|
+
created_at: typeof existing?.created_at === "string" ? existing.created_at : now.toISOString(),
|
|
374
|
+
updated_at: now.toISOString(),
|
|
375
|
+
capture: {
|
|
376
|
+
capture_content: config.captureContent,
|
|
377
|
+
max_event_chars: config.maxEventChars,
|
|
378
|
+
max_file_bytes: config.maxFileBytes,
|
|
379
|
+
},
|
|
380
|
+
[context.client]: isRecord(existingClient) ? existingClient : pruneRecord({
|
|
381
|
+
transcript_path: context.transcriptPath,
|
|
382
|
+
}),
|
|
383
|
+
};
|
|
384
|
+
await writeFile(path, `${JSON.stringify(trace, null, 2)}\n`, "utf8");
|
|
385
|
+
}
|
|
386
|
+
async function readExistingTraceJson(path) {
|
|
387
|
+
try {
|
|
388
|
+
const value = JSON.parse(await readFile(path, "utf8"));
|
|
389
|
+
return isRecord(value) ? value : undefined;
|
|
390
|
+
}
|
|
391
|
+
catch {
|
|
392
|
+
return undefined;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
async function pruneExpiredTraceSessions(root, config, now, options) {
|
|
396
|
+
if (options.debounce) {
|
|
397
|
+
const lastCleanup = lastCleanupByRoot.get(root) ?? 0;
|
|
398
|
+
if (now.getTime() - lastCleanup < TRACE_CLEANUP_DEBOUNCE_MS)
|
|
399
|
+
return;
|
|
400
|
+
if (await hasFreshCleanupMarker(root, now))
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
lastCleanupByRoot.set(root, now.getTime());
|
|
404
|
+
const sessionsRoot = join(root, "sessions");
|
|
405
|
+
let entries;
|
|
406
|
+
try {
|
|
407
|
+
entries = await readdir(sessionsRoot);
|
|
408
|
+
}
|
|
409
|
+
catch {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
const cutoff = now.getTime() - config.retentionDays * 24 * 60 * 60 * 1000;
|
|
413
|
+
for (const entry of entries) {
|
|
414
|
+
const path = join(sessionsRoot, entry);
|
|
415
|
+
try {
|
|
416
|
+
const info = await stat(path);
|
|
417
|
+
if (!info.isDirectory())
|
|
418
|
+
continue;
|
|
419
|
+
const activityMs = await sessionActivityMs(path, info.mtimeMs);
|
|
420
|
+
if (activityMs < cutoff) {
|
|
421
|
+
await rm(path, { recursive: true, force: true });
|
|
422
|
+
eventIdsByPath.delete(join(path, "events.jsonl"));
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
catch {
|
|
426
|
+
// Ignore cleanup races.
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
await writeCleanupMarker(root, now).catch(() => undefined);
|
|
430
|
+
}
|
|
431
|
+
async function exceedsMaxFileBytes(path, maxFileBytes) {
|
|
432
|
+
try {
|
|
433
|
+
return (await stat(path)).size >= maxFileBytes;
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
async function writeMaxFileWarningEvent(input) {
|
|
440
|
+
const markerPath = join(input.sessionDir, ".max-file-bytes-warning");
|
|
441
|
+
try {
|
|
442
|
+
await writeFile(markerPath, input.now.toISOString(), { encoding: "utf8", flag: "wx" });
|
|
443
|
+
}
|
|
444
|
+
catch (error) {
|
|
445
|
+
if (isNodeErrorCode(error, "EEXIST"))
|
|
446
|
+
return;
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
const event = buildTraceEvent({
|
|
450
|
+
...input.input,
|
|
451
|
+
type: "trace_warning",
|
|
452
|
+
source: "trace-store",
|
|
453
|
+
operation: "max_file_bytes",
|
|
454
|
+
ok: false,
|
|
455
|
+
request: undefined,
|
|
456
|
+
response: { reason: "max_file_bytes", max_file_bytes: input.config.maxFileBytes },
|
|
457
|
+
error: undefined,
|
|
458
|
+
}, input.config, input.now, nextEventId(input.sessionDir, input.now));
|
|
459
|
+
await appendJsonlEvent(input.eventsPath, event);
|
|
460
|
+
}
|
|
461
|
+
async function appendJsonlEvent(path, event, explicitEventId) {
|
|
462
|
+
return await serializeTraceEventPath(path, async () => {
|
|
463
|
+
const knownEventIds = await traceEventIds(path);
|
|
464
|
+
if (explicitEventId && knownEventIds.has(explicitEventId))
|
|
465
|
+
return false;
|
|
466
|
+
await appendRepairingJsonl(path, `${JSON.stringify(event)}\n`);
|
|
467
|
+
const eventId = normalizedString(event.event_id);
|
|
468
|
+
if (eventId)
|
|
469
|
+
knownEventIds.add(eventId);
|
|
470
|
+
return true;
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
async function traceEventIds(path) {
|
|
474
|
+
const cached = eventIdsByPath.get(path);
|
|
475
|
+
if (cached)
|
|
476
|
+
return cached;
|
|
477
|
+
const eventIds = new Set();
|
|
478
|
+
let text = "";
|
|
479
|
+
try {
|
|
480
|
+
text = await readFile(path, "utf8");
|
|
481
|
+
}
|
|
482
|
+
catch {
|
|
483
|
+
eventIdsByPath.set(path, eventIds);
|
|
484
|
+
return eventIds;
|
|
485
|
+
}
|
|
486
|
+
for (const line of text.split(/\r?\n/)) {
|
|
487
|
+
if (!line.trim())
|
|
488
|
+
continue;
|
|
489
|
+
try {
|
|
490
|
+
const event = JSON.parse(line);
|
|
491
|
+
if (!isRecord(event))
|
|
492
|
+
continue;
|
|
493
|
+
const eventId = normalizedString(event.event_id);
|
|
494
|
+
if (eventId)
|
|
495
|
+
eventIds.add(eventId);
|
|
496
|
+
}
|
|
497
|
+
catch {
|
|
498
|
+
// appendRepairingJsonl owns incomplete-tail recovery.
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
eventIdsByPath.set(path, eventIds);
|
|
502
|
+
return eventIds;
|
|
503
|
+
}
|
|
504
|
+
async function serializeTraceEventPath(path, operation) {
|
|
505
|
+
const previous = traceEventPathOperations.get(path) ?? Promise.resolve();
|
|
506
|
+
const current = previous.catch(() => undefined).then(operation);
|
|
507
|
+
traceEventPathOperations.set(path, current);
|
|
508
|
+
try {
|
|
509
|
+
return await current;
|
|
510
|
+
}
|
|
511
|
+
finally {
|
|
512
|
+
if (traceEventPathOperations.get(path) === current)
|
|
513
|
+
traceEventPathOperations.delete(path);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
async function hasFreshCleanupMarker(root, now) {
|
|
517
|
+
try {
|
|
518
|
+
const info = await stat(cleanupMarkerPath(root));
|
|
519
|
+
return now.getTime() - info.mtimeMs < TRACE_CLEANUP_DEBOUNCE_MS;
|
|
520
|
+
}
|
|
521
|
+
catch {
|
|
522
|
+
return false;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
async function writeCleanupMarker(root, now) {
|
|
526
|
+
await mkdir(root, { recursive: true });
|
|
527
|
+
await writeFile(cleanupMarkerPath(root), `${JSON.stringify({ cleaned_at: now.toISOString() })}\n`, "utf8");
|
|
528
|
+
}
|
|
529
|
+
function cleanupMarkerPath(root) {
|
|
530
|
+
return join(root, ".retention-cleanup.json");
|
|
531
|
+
}
|
|
532
|
+
async function sessionActivityMs(sessionDir, fallbackMs) {
|
|
533
|
+
const trace = await readExistingTraceJson(join(sessionDir, "trace.json"));
|
|
534
|
+
const updatedAt = typeof trace?.updated_at === "string" ? Date.parse(trace.updated_at) : NaN;
|
|
535
|
+
const candidates = [fallbackMs, Number.isFinite(updatedAt) ? updatedAt : 0];
|
|
536
|
+
for (const filename of ["trace.json", "events.jsonl"]) {
|
|
537
|
+
try {
|
|
538
|
+
candidates.push((await stat(join(sessionDir, filename))).mtimeMs);
|
|
539
|
+
}
|
|
540
|
+
catch {
|
|
541
|
+
// Missing trace files should fall back to directory mtime.
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return Math.max(...candidates);
|
|
545
|
+
}
|
|
546
|
+
function nextEventId(sessionKey, now) {
|
|
547
|
+
const counter = (eventCounters.get(sessionKey) ?? 0) + 1;
|
|
548
|
+
eventCounters.set(sessionKey, counter);
|
|
549
|
+
return `evt_${now.getTime()}_${counter}`;
|
|
550
|
+
}
|
|
551
|
+
function hashText(value) {
|
|
552
|
+
return createHash("sha256").update(value).digest("hex");
|
|
553
|
+
}
|
|
554
|
+
function truncate(value, maxChars) {
|
|
555
|
+
return value.length <= maxChars ? value : `${value.slice(0, maxChars)}...`;
|
|
556
|
+
}
|
|
557
|
+
function pruneRecord(value) {
|
|
558
|
+
return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
|
|
559
|
+
}
|
|
560
|
+
function isRecord(value) {
|
|
561
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
562
|
+
}
|
|
563
|
+
function traceEnv(env, memoraxCodeHome) {
|
|
564
|
+
return { ...env, MEMORAX_CODE_HOME: memoraxCodeHome };
|
|
565
|
+
}
|
|
566
|
+
function normalizedString(value) {
|
|
567
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
568
|
+
}
|
|
569
|
+
function isNodeErrorCode(error, code) {
|
|
570
|
+
return Boolean(error && typeof error === "object" && "code" in error && error.code === code);
|
|
571
|
+
}
|