oh-my-opencode 4.15.0 → 4.16.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/dist/cli/doctor/checks/tui-plugin-config.d.ts +4 -4
- package/dist/cli/index.js +1149 -1040
- package/dist/cli/install-senpi/index.d.ts +1 -0
- package/dist/cli/run/poll-for-completion.d.ts +4 -0
- package/dist/cli/run/session-resolver.d.ts +1 -0
- package/dist/cli/senpi-platform-flag.d.ts +4 -0
- package/dist/cli/types.d.ts +2 -1
- package/dist/cli-node/index.js +1149 -1040
- package/dist/features/background-agent/manager.d.ts +16 -0
- package/dist/hooks/anthropic-context-window-limit-recovery/aggressive-truncation-strategy.d.ts +1 -0
- package/dist/index.js +1334 -1146
- package/dist/skills/debugging/references/methodology/06-fix.md +6 -0
- package/dist/skills/frontend/ATTRIBUTION.md +13 -3
- package/dist/skills/frontend/SKILL.md +8 -3
- package/dist/skills/frontend/references/design/README.md +1 -1
- package/dist/skills/frontend/references/design/_INDEX.md +1 -1
- package/dist/skills/frontend/references/design/lazyweb.md +77 -0
- package/dist/skills/frontend/references/design/stitch-design-example.md +121 -0
- package/dist/skills/frontend/references/designpowers/EVIDENCE.md +10 -2
- package/dist/skills/frontend/references/designpowers/UPSTREAM.md +1 -1
- package/dist/skills/programming/SKILL.md +10 -1
- package/dist/skills/programming/references/logging.md +91 -0
- package/dist/skills/ulw-plan/SKILL.md +5 -5
- package/dist/skills/ulw-plan/references/full-workflow.md +7 -7
- package/dist/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/dist/skills/ulw-research/ATTRIBUTION.md +2 -2
- package/dist/skills/ulw-research/SKILL.md +28 -7
- package/dist/tools/skill/description-formatter.d.ts +1 -0
- package/dist/tools/skill/description-formatter.test-support.d.ts +9 -0
- package/dist/tools/skill/zauc-mocks-skill-tools/test-support.d.ts +25 -0
- package/dist/tui.js +121 -419
- package/package.json +32 -15
- package/packages/git-bash-mcp/dist/cli.js +2 -2
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/AGENTS.md +55 -0
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +212 -117
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +51 -0
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +936 -248
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +233 -135
- package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/src/cache-gc.ts +29 -0
- package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +13 -0
- package/packages/omo-codex/plugin/components/codegraph/src/hook-sweep.ts +25 -0
- package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +3 -1
- package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +30 -1
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +16 -2
- package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +80 -0
- package/packages/omo-codex/plugin/components/codegraph/test/cache-gc.test.ts +34 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +107 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook-registration.test.ts +26 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook-sweep.test.ts +29 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +8 -21
- package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +108 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-built-wrapper.test.ts +76 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +17 -111
- package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +1 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +45 -67
- package/packages/omo-codex/plugin/components/codegraph/test/sweep-cli.test.ts +56 -0
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +31 -0
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/AGENTS.md +45 -0
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus.md +37 -102
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/AGENTS.md +46 -0
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +6 -0
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +6 -0
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +5 -2
- package/packages/omo-codex/plugin/components/ultrawork/CHANGELOG.md +2 -0
- package/packages/omo-codex/plugin/components/ultrawork/README.md +3 -3
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +51 -2
- package/packages/omo-codex/plugin/components/ultrawork/package.json +2 -1
- package/packages/omo-codex/plugin/components/ultrawork/scripts/sync-directive.mjs +14 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +380 -0
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +5 -2
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +4 -4
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/src/codex-hook.ts +5 -3
- package/packages/omo-codex/plugin/components/ultrawork/src/skill-pointer.ts +56 -0
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +4 -4
- package/packages/omo-codex/plugin/components/ultrawork/test/directive-source.test.ts +12 -0
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +1 -0
- package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +82 -0
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +56 -5
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.js +5 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/ultrawork-directive.d.ts +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/ultrawork-directive.js +5 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/ultrawork-skill-pointer.d.ts +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/ultrawork-skill-pointer.js +46 -0
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +5 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/ultrawork-directive.ts +9 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/ultrawork-skill-pointer.ts +55 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +49 -0
- package/packages/omo-codex/plugin/package-lock.json +13 -13
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +147 -2
- package/packages/omo-codex/plugin/scripts/auto-update-release-notes.mjs +33 -0
- package/packages/omo-codex/plugin/scripts/auto-update.mjs +48 -10
- package/packages/omo-codex/plugin/scripts/build-components.mjs +63 -17
- package/packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs +10 -3
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +19 -0
- package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +18 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/06-fix.md +6 -0
- package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +13 -3
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +8 -3
- package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/lazyweb.md +77 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/stitch-design-example.md +121 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/EVIDENCE.md +10 -2
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/UPSTREAM.md +1 -1
- package/packages/omo-codex/plugin/skills/programming/SKILL.md +10 -1
- package/packages/omo-codex/plugin/skills/programming/references/logging.md +91 -0
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +380 -0
- package/packages/omo-codex/plugin/skills/ultrawork/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +5 -2
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +4 -4
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/ATTRIBUTION.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +31 -10
- package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +32 -0
- package/packages/omo-codex/plugin/test/auto-update.test.mjs +153 -3
- package/packages/omo-codex/plugin/test/install-time-build-runtime.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +20 -1
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +39 -10
- package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +56 -0
- package/packages/omo-codex/plugin/test/ulw-research-epistemic-contract.test.mjs +98 -0
- package/packages/omo-codex/plugin/test/ulw-research-skill-contract.test.mjs +25 -7
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +612 -4193
- package/packages/shared-skills/skills/debugging/references/methodology/06-fix.md +6 -0
- package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +13 -3
- package/packages/shared-skills/skills/frontend/SKILL.md +8 -3
- package/packages/shared-skills/skills/frontend/references/design/README.md +1 -1
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -1
- package/packages/shared-skills/skills/frontend/references/design/lazyweb.md +77 -0
- package/packages/shared-skills/skills/frontend/references/design/stitch-design-example.md +121 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/EVIDENCE.md +10 -2
- package/packages/shared-skills/skills/frontend/references/designpowers/UPSTREAM.md +1 -1
- package/packages/shared-skills/skills/programming/SKILL.md +10 -1
- package/packages/shared-skills/skills/programming/references/logging.md +91 -0
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +5 -5
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +7 -7
- package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/packages/shared-skills/skills/ulw-research/ATTRIBUTION.md +2 -2
- package/packages/shared-skills/skills/ulw-research/SKILL.md +28 -7
- package/packages/omo-codex/plugin/skills/ultraresearch/SKILL.md +0 -10
- package/packages/omo-codex/plugin/skills/ultraresearch/agents/openai.yaml +0 -2
- /package/dist/skills/frontend/references/designpowers/vendor/skills/accessible-content/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/adaptive-interfaces/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/cognitive-accessibility/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/design-debate/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/design-debt-tracker/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/design-handoff/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/design-md/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/design-retrospective/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/design-review/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/design-system-alignment/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/designpowers-critique/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/heuristic-evaluation/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/inclusive-personas/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/inspiration-scouting/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/interaction-design/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/motion-choreography/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/research-planning/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/responsive-patterns/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/synthetic-user-testing/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/taste-feedback/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/taste-report/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/token-architecture/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/ui-composition/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/usability-testing/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/verification-before-shipping/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/voice-and-tone/{SKILL.md → reference.md} +0 -0
- /package/dist/skills/frontend/references/designpowers/vendor/skills/writing-design-plans/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/accessible-content/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/adaptive-interfaces/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/cognitive-accessibility/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-debate/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-debt-tracker/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-handoff/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-md/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-retrospective/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-review/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-system-alignment/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/designpowers-critique/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/heuristic-evaluation/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/inclusive-personas/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/inspiration-scouting/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/interaction-design/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/motion-choreography/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/research-planning/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/responsive-patterns/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/synthetic-user-testing/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/taste-feedback/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/taste-report/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/token-architecture/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/ui-composition/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/usability-testing/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/verification-before-shipping/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/voice-and-tone/{SKILL.md → reference.md} +0 -0
- /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/writing-design-plans/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/accessible-content/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/adaptive-interfaces/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/cognitive-accessibility/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-debate/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-debt-tracker/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-handoff/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-md/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-retrospective/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-review/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-system-alignment/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/designpowers-critique/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/heuristic-evaluation/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/inclusive-personas/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/inspiration-scouting/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/interaction-design/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/motion-choreography/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/research-planning/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/responsive-patterns/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/synthetic-user-testing/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/taste-feedback/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/taste-report/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/token-architecture/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/ui-composition/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/usability-testing/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/verification-before-shipping/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/voice-and-tone/{SKILL.md → reference.md} +0 -0
- /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/writing-design-plans/{SKILL.md → reference.md} +0 -0
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// components/codegraph/src/cli.ts
|
|
4
|
-
import { realpathSync as
|
|
5
|
-
import { basename as basename5, resolve as
|
|
6
|
-
import { stderr as
|
|
7
|
-
import { fileURLToPath as
|
|
4
|
+
import { realpathSync as realpathSync6 } from "node:fs";
|
|
5
|
+
import { basename as basename5, resolve as resolve6 } from "node:path";
|
|
6
|
+
import { stderr as processStderr4 } from "node:process";
|
|
7
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
8
8
|
|
|
9
9
|
// components/codegraph/src/hook.ts
|
|
10
|
-
import { execFile as
|
|
11
|
-
import { homedir as
|
|
12
|
-
import { join as
|
|
13
|
-
import {
|
|
14
|
-
|
|
10
|
+
import { execFile as execFile4, spawn } from "node:child_process";
|
|
11
|
+
import { homedir as homedir13 } from "node:os";
|
|
12
|
+
import { join as join13 } from "node:path";
|
|
13
|
+
import {
|
|
14
|
+
cwd as processCwd2,
|
|
15
|
+
env as processEnv2,
|
|
16
|
+
stderr as processStderr2,
|
|
17
|
+
stdin as processStdin,
|
|
18
|
+
stdout as processStdout
|
|
19
|
+
} from "node:process";
|
|
20
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
15
21
|
|
|
16
22
|
// ../../utils/src/codegraph/env.ts
|
|
17
23
|
import { homedir } from "node:os";
|
|
18
24
|
import { join } from "node:path";
|
|
19
25
|
var CODEGRAPH_INSTALL_DIR_ENV = "CODEGRAPH_INSTALL_DIR";
|
|
26
|
+
var CODEGRAPH_NO_DAEMON_ENV = "CODEGRAPH_NO_DAEMON";
|
|
20
27
|
var CODEGRAPH_NO_DOWNLOAD_ENV = "CODEGRAPH_NO_DOWNLOAD";
|
|
21
28
|
var CODEGRAPH_TELEMETRY_ENV = "CODEGRAPH_TELEMETRY";
|
|
22
29
|
var DO_NOT_TRACK_ENV = "DO_NOT_TRACK";
|
|
@@ -50,6 +57,7 @@ var SAFE_CODEGRAPH_RUNTIME_ENV_KEYS = new Set([
|
|
|
50
57
|
"CODEGRAPH_ALLOW_UNSAFE_NODE",
|
|
51
58
|
"CODEGRAPH_BIN",
|
|
52
59
|
"CODEGRAPH_FAKE_LOG",
|
|
60
|
+
"CODEGRAPH_NO_DAEMON",
|
|
53
61
|
"CODEGRAPH_NODE_BIN",
|
|
54
62
|
"OMO_CODEGRAPH_BIN",
|
|
55
63
|
"OMO_CODEGRAPH_PROJECT_CWD",
|
|
@@ -59,6 +67,7 @@ function buildCodegraphEnv(options = {}) {
|
|
|
59
67
|
const homeDir = options.homeDir ?? homedir();
|
|
60
68
|
return {
|
|
61
69
|
[CODEGRAPH_INSTALL_DIR_ENV]: join(homeDir, ".omo", "codegraph"),
|
|
70
|
+
[CODEGRAPH_NO_DAEMON_ENV]: "1",
|
|
62
71
|
[CODEGRAPH_NO_DOWNLOAD_ENV]: "1",
|
|
63
72
|
[CODEGRAPH_TELEMETRY_ENV]: "0",
|
|
64
73
|
[DO_NOT_TRACK_ENV]: "1"
|
|
@@ -86,22 +95,15 @@ function buildCodegraphChildEnv(options = {}) {
|
|
|
86
95
|
}
|
|
87
96
|
|
|
88
97
|
// ../../utils/src/codegraph/guidance.ts
|
|
89
|
-
import { homedir as
|
|
98
|
+
import { homedir as homedir5 } from "node:os";
|
|
90
99
|
|
|
91
100
|
// ../../utils/src/codegraph/workspace.ts
|
|
101
|
+
import { appendFileSync, existsSync as existsSync2, lstatSync as lstatSync2, mkdirSync, realpathSync as realpathSync3, readFileSync as readFileSync2, statSync, symlinkSync } from "node:fs";
|
|
102
|
+
import { join as join5 } from "node:path";
|
|
103
|
+
|
|
104
|
+
// ../../utils/src/codegraph/paths.ts
|
|
92
105
|
import { createHash } from "node:crypto";
|
|
93
|
-
import {
|
|
94
|
-
appendFileSync,
|
|
95
|
-
existsSync,
|
|
96
|
-
lstatSync,
|
|
97
|
-
mkdirSync,
|
|
98
|
-
readFileSync,
|
|
99
|
-
readdirSync,
|
|
100
|
-
realpathSync,
|
|
101
|
-
rmSync,
|
|
102
|
-
statSync,
|
|
103
|
-
symlinkSync
|
|
104
|
-
} from "node:fs";
|
|
106
|
+
import { realpathSync } from "node:fs";
|
|
105
107
|
import { homedir as homedir2 } from "node:os";
|
|
106
108
|
import { basename, join as join2, resolve } from "node:path";
|
|
107
109
|
function sanitizeBase(value) {
|
|
@@ -111,13 +113,23 @@ function sanitizeBase(value) {
|
|
|
111
113
|
function codegraphDataRoot(homeDir) {
|
|
112
114
|
return join2(homeDir, ".omo", "codegraph");
|
|
113
115
|
}
|
|
116
|
+
function canonicalizeCodegraphPath(path) {
|
|
117
|
+
const resolved = resolve(path);
|
|
118
|
+
try {
|
|
119
|
+
return realpathSync(resolved);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
if (error instanceof Error)
|
|
122
|
+
return resolved;
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
114
126
|
function workspaceStorageName(workspace) {
|
|
115
|
-
const resolved =
|
|
127
|
+
const resolved = canonicalizeCodegraphPath(workspace);
|
|
116
128
|
const hash = createHash("sha256").update(resolved).digest("hex").slice(0, 16);
|
|
117
129
|
return `${sanitizeBase(basename(resolved))}-${hash}`;
|
|
118
130
|
}
|
|
119
131
|
function resolveCodegraphWorkspacePaths(workspace, options = {}) {
|
|
120
|
-
const resolvedWorkspace =
|
|
132
|
+
const resolvedWorkspace = canonicalizeCodegraphPath(workspace);
|
|
121
133
|
const dataRoot = codegraphDataRoot(options.homeDir ?? homedir2());
|
|
122
134
|
return {
|
|
123
135
|
dataDir: join2(dataRoot, "projects", workspaceStorageName(resolvedWorkspace)),
|
|
@@ -125,6 +137,127 @@ function resolveCodegraphWorkspacePaths(workspace, options = {}) {
|
|
|
125
137
|
projectLink: join2(resolvedWorkspace, ".codegraph")
|
|
126
138
|
};
|
|
127
139
|
}
|
|
140
|
+
|
|
141
|
+
// ../../utils/src/codegraph/store.ts
|
|
142
|
+
import { existsSync, lstatSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
143
|
+
import { homedir as homedir3 } from "node:os";
|
|
144
|
+
import { join as join3 } from "node:path";
|
|
145
|
+
var CODEGRAPH_PROJECT_SOURCE_METADATA_FILE = "source.json";
|
|
146
|
+
var CODEGRAPH_PROJECT_SOURCE_METADATA_VERSION = 1;
|
|
147
|
+
function writeCodegraphSourceMetadata(dataDir, sourceDir) {
|
|
148
|
+
writeFileSync(join3(dataDir, CODEGRAPH_PROJECT_SOURCE_METADATA_FILE), `${JSON.stringify({ sourceDir, version: CODEGRAPH_PROJECT_SOURCE_METADATA_VERSION }, null, 2)}
|
|
149
|
+
`);
|
|
150
|
+
}
|
|
151
|
+
function readRecordedSourceDir(projectDir) {
|
|
152
|
+
const metadataPath = join3(projectDir, CODEGRAPH_PROJECT_SOURCE_METADATA_FILE);
|
|
153
|
+
if (!existsSync(metadataPath))
|
|
154
|
+
return null;
|
|
155
|
+
try {
|
|
156
|
+
const parsed = JSON.parse(readFileSync(metadataPath, "utf8"));
|
|
157
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
158
|
+
return null;
|
|
159
|
+
const sourceDir = parsed.sourceDir;
|
|
160
|
+
return typeof sourceDir === "string" && sourceDir.trim().length > 0 ? sourceDir : null;
|
|
161
|
+
} catch (error) {
|
|
162
|
+
if (isNonFatalSourceMetadataError(error))
|
|
163
|
+
return null;
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function isNonFatalSourceMetadataError(error) {
|
|
168
|
+
if (error instanceof SyntaxError)
|
|
169
|
+
return true;
|
|
170
|
+
const code = typeof error === "object" && error !== null && "code" in error ? error.code : undefined;
|
|
171
|
+
return typeof code === "string" && ["EACCES", "ENOENT", "ENOTDIR", "EPERM"].includes(code);
|
|
172
|
+
}
|
|
173
|
+
function recordedSourceIsMissing(projectDir) {
|
|
174
|
+
const sourceDir = readRecordedSourceDir(projectDir);
|
|
175
|
+
return sourceDir !== null && !existsSync(sourceDir);
|
|
176
|
+
}
|
|
177
|
+
function pruneDeadCodegraphProjectStores(options = {}) {
|
|
178
|
+
const projectsDir = join3(codegraphDataRoot(options.homeDir ?? homedir3()), "projects");
|
|
179
|
+
const removed = [];
|
|
180
|
+
if (!existsSync(projectsDir))
|
|
181
|
+
return { remainingBytes: 0, removed };
|
|
182
|
+
for (const entry of readdirSync(projectsDir, { withFileTypes: true })) {
|
|
183
|
+
if (!entry.isDirectory())
|
|
184
|
+
continue;
|
|
185
|
+
const projectDir = join3(projectsDir, entry.name);
|
|
186
|
+
if (!recordedSourceIsMissing(projectDir))
|
|
187
|
+
continue;
|
|
188
|
+
rmSync(projectDir, { force: true, recursive: true });
|
|
189
|
+
removed.push(projectDir);
|
|
190
|
+
}
|
|
191
|
+
return { remainingBytes: 0, removed };
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ../../utils/src/codegraph/exclusion.ts
|
|
195
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
196
|
+
import { homedir as homedir4, tmpdir as osTmpdir } from "node:os";
|
|
197
|
+
import { isAbsolute, join as join4, resolve as resolve2 } from "node:path";
|
|
198
|
+
var POSIX_DEFAULT_EXCLUDED_ROOTS = ["/tmp", "/private/tmp"];
|
|
199
|
+
function expandHome(path, homeDir) {
|
|
200
|
+
if (path === "~")
|
|
201
|
+
return homeDir;
|
|
202
|
+
if (path.startsWith("~/") || path.startsWith("~\\"))
|
|
203
|
+
return join4(homeDir, path.slice(2));
|
|
204
|
+
return path;
|
|
205
|
+
}
|
|
206
|
+
function realpathIfPossible(path) {
|
|
207
|
+
try {
|
|
208
|
+
return realpathSync2(path);
|
|
209
|
+
} catch (error) {
|
|
210
|
+
if (error instanceof Error)
|
|
211
|
+
return resolve2(path);
|
|
212
|
+
throw error;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function resolveConfiguredRoot(path, homeDir) {
|
|
216
|
+
const expanded = expandHome(path, homeDir);
|
|
217
|
+
return realpathIfPossible(isAbsolute(expanded) ? expanded : join4(homeDir, expanded));
|
|
218
|
+
}
|
|
219
|
+
function normalizeForComparison(path, platform) {
|
|
220
|
+
const normalized = path.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
221
|
+
return platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
222
|
+
}
|
|
223
|
+
function pathIsWithin(path, root, platform) {
|
|
224
|
+
const candidate = normalizeForComparison(path, platform);
|
|
225
|
+
const normalizedRoot = normalizeForComparison(root, platform);
|
|
226
|
+
return candidate === normalizedRoot || candidate.startsWith(`${normalizedRoot}/`);
|
|
227
|
+
}
|
|
228
|
+
function hasOmoPathSegment(path) {
|
|
229
|
+
return path.split(/[\\/]+/).includes(".omo");
|
|
230
|
+
}
|
|
231
|
+
function defaultExcludedRoots(platform, tmpdir) {
|
|
232
|
+
return platform === "win32" ? [tmpdir] : [...POSIX_DEFAULT_EXCLUDED_ROOTS, tmpdir];
|
|
233
|
+
}
|
|
234
|
+
function shouldExcludeCodegraphProject(workspace, options = {}) {
|
|
235
|
+
const platform = options.platform ?? process.platform;
|
|
236
|
+
const homeDir = options.homeDir ?? homedir4();
|
|
237
|
+
const tmpdir = options.tmpdir ?? osTmpdir();
|
|
238
|
+
const resolvedWorkspace = realpathIfPossible(resolve2(workspace));
|
|
239
|
+
if (hasOmoPathSegment(resolvedWorkspace)) {
|
|
240
|
+
return { excluded: true, matchedRoot: ".omo", reason: "omo-state" };
|
|
241
|
+
}
|
|
242
|
+
for (const root of defaultExcludedRoots(platform, tmpdir)) {
|
|
243
|
+
const resolvedRoot = realpathIfPossible(resolve2(root));
|
|
244
|
+
if (pathIsWithin(resolvedWorkspace, resolvedRoot, platform)) {
|
|
245
|
+
return { excluded: true, matchedRoot: root, reason: "tmp-root" };
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
for (const root of options.excludedRoots ?? []) {
|
|
249
|
+
const trimmedRoot = root.trim();
|
|
250
|
+
if (trimmedRoot.length === 0)
|
|
251
|
+
continue;
|
|
252
|
+
const resolvedRoot = resolveConfiguredRoot(trimmedRoot, homeDir);
|
|
253
|
+
if (pathIsWithin(resolvedWorkspace, resolvedRoot, platform)) {
|
|
254
|
+
return { excluded: true, matchedRoot: root, reason: "custom-root" };
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return { excluded: false };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// ../../utils/src/codegraph/workspace.ts
|
|
128
261
|
function fallbackResult(dataRoot, projectLink, reason) {
|
|
129
262
|
return { dataDir: projectLink, dataRoot, linked: false, mode: "in-place-fallback", projectLink, reason };
|
|
130
263
|
}
|
|
@@ -134,20 +267,21 @@ function isSameFilesystem(workspace, dataRoot, override) {
|
|
|
134
267
|
return statSync(workspace).dev === statSync(dataRoot).dev;
|
|
135
268
|
}
|
|
136
269
|
function ensureInPlaceFallback(projectLink) {
|
|
137
|
-
if (!
|
|
270
|
+
if (!existsSync2(projectLink))
|
|
138
271
|
mkdirSync(projectLink, { recursive: true });
|
|
139
272
|
}
|
|
140
273
|
function prepareCodegraphWorkspace(workspace, options = {}) {
|
|
141
|
-
const resolvedWorkspace =
|
|
274
|
+
const resolvedWorkspace = canonicalizeCodegraphPath(workspace);
|
|
142
275
|
const { dataDir, dataRoot, projectLink } = resolveCodegraphWorkspacePaths(resolvedWorkspace, options);
|
|
143
276
|
try {
|
|
144
277
|
mkdirSync(dataDir, { recursive: true });
|
|
145
|
-
|
|
146
|
-
|
|
278
|
+
writeCodegraphSourceMetadata(dataDir, resolvedWorkspace);
|
|
279
|
+
if (existsSync2(projectLink)) {
|
|
280
|
+
const linkStat = lstatSync2(projectLink);
|
|
147
281
|
if (!linkStat.isSymbolicLink()) {
|
|
148
282
|
return { dataDir: projectLink, dataRoot, linked: false, mode: "in-project", projectLink };
|
|
149
283
|
}
|
|
150
|
-
if (
|
|
284
|
+
if (realpathSync3(projectLink) === realpathSync3(dataDir)) {
|
|
151
285
|
return { dataDir, dataRoot, linked: true, mode: "global-linked", projectLink };
|
|
152
286
|
}
|
|
153
287
|
return fallbackResult(dataRoot, projectLink, "existing .codegraph symlink points outside OMO store");
|
|
@@ -164,19 +298,20 @@ function prepareCodegraphWorkspace(workspace, options = {}) {
|
|
|
164
298
|
try {
|
|
165
299
|
ensureInPlaceFallback(projectLink);
|
|
166
300
|
} catch (fallbackError) {
|
|
167
|
-
|
|
301
|
+
const fallbackReason = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
|
|
302
|
+
return fallbackResult(dataRoot, projectLink, `${reason}; fallback failed: ${fallbackReason}`);
|
|
168
303
|
}
|
|
169
304
|
return fallbackResult(dataRoot, projectLink, reason);
|
|
170
305
|
}
|
|
171
306
|
}
|
|
172
307
|
function ensureCodegraphGitignored(workspace) {
|
|
173
|
-
const gitDir =
|
|
174
|
-
if (!
|
|
308
|
+
const gitDir = join5(workspace, ".git");
|
|
309
|
+
if (!existsSync2(gitDir))
|
|
175
310
|
return false;
|
|
176
|
-
const excludePath =
|
|
311
|
+
const excludePath = join5(gitDir, "info", "exclude");
|
|
177
312
|
try {
|
|
178
|
-
mkdirSync(
|
|
179
|
-
const existing =
|
|
313
|
+
mkdirSync(join5(gitDir, "info"), { recursive: true });
|
|
314
|
+
const existing = existsSync2(excludePath) ? readFileSync2(excludePath, "utf8") : "";
|
|
180
315
|
if (existing.split(/\r?\n/).includes(".codegraph"))
|
|
181
316
|
return true;
|
|
182
317
|
appendFileSync(excludePath, `${existing.endsWith(`
|
|
@@ -210,7 +345,7 @@ function getCodegraphUninitializedProject(input) {
|
|
|
210
345
|
}
|
|
211
346
|
function buildCodegraphInitGuidance(projectPath, options = {}) {
|
|
212
347
|
const { dataDir, dataRoot, projectLink } = resolveCodegraphWorkspacePaths(projectPath, {
|
|
213
|
-
homeDir: options.homeDir ??
|
|
348
|
+
homeDir: options.homeDir ?? homedir5()
|
|
214
349
|
});
|
|
215
350
|
const displayProjectPath = formatDisplayPath(projectPath);
|
|
216
351
|
const displayProjectLink = formatDisplayPath(projectLink);
|
|
@@ -278,15 +413,15 @@ function isRecord(value) {
|
|
|
278
413
|
}
|
|
279
414
|
|
|
280
415
|
// ../../utils/src/codegraph/resolve.ts
|
|
281
|
-
import { existsSync as
|
|
282
|
-
import { homedir as
|
|
416
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
417
|
+
import { homedir as homedir6 } from "node:os";
|
|
283
418
|
import { spawnSync } from "node:child_process";
|
|
284
|
-
import { basename as basename2, dirname, join as
|
|
419
|
+
import { basename as basename2, dirname, join as join7 } from "node:path";
|
|
285
420
|
import { createRequire } from "node:module";
|
|
286
421
|
|
|
287
422
|
// ../../utils/src/runtime/which.ts
|
|
288
423
|
import { accessSync, constants } from "node:fs";
|
|
289
|
-
import { delimiter, join as
|
|
424
|
+
import { delimiter, join as join6 } from "node:path";
|
|
290
425
|
var runtime = globalThis;
|
|
291
426
|
function isUnsafeCommandName(commandName) {
|
|
292
427
|
if (commandName.includes("/") || commandName.includes("\\"))
|
|
@@ -341,7 +476,7 @@ function bunWhich(commandName) {
|
|
|
341
476
|
return null;
|
|
342
477
|
for (const pathEntry of pathEntries) {
|
|
343
478
|
for (const candidateName of candidateNames) {
|
|
344
|
-
const candidatePath =
|
|
479
|
+
const candidatePath = join6(pathEntry, candidateName);
|
|
345
480
|
if (isExecutable(candidatePath))
|
|
346
481
|
return candidatePath;
|
|
347
482
|
}
|
|
@@ -460,8 +595,8 @@ function defaultNodeRuntime(env, fileExists, which, nodeVersion) {
|
|
|
460
595
|
function defaultProvisionedBin(homeDir, fileExists) {
|
|
461
596
|
const binaryName = process.platform === "win32" ? "codegraph.cmd" : "codegraph";
|
|
462
597
|
const candidates = [
|
|
463
|
-
|
|
464
|
-
|
|
598
|
+
join7(homeDir, ".omo", "codegraph", "bin", binaryName),
|
|
599
|
+
join7(homeDir, ".omo", "codegraph", "node-servers", "node_modules", ".bin", binaryName)
|
|
465
600
|
];
|
|
466
601
|
return candidates.find((candidate) => fileExists(candidate)) ?? null;
|
|
467
602
|
}
|
|
@@ -469,7 +604,7 @@ function resolveBundledShim(requireResolve, fileExists) {
|
|
|
469
604
|
try {
|
|
470
605
|
const packageJson = requireResolve(`${CODEGRAPH_PACKAGE}/package.json`);
|
|
471
606
|
const packageRoot = dirname(packageJson);
|
|
472
|
-
const candidates = [
|
|
607
|
+
const candidates = [join7(packageRoot, "bin", "codegraph.js"), join7(packageRoot, "npm-shim.js")];
|
|
473
608
|
return candidates.find((candidate) => fileExists(candidate)) ?? null;
|
|
474
609
|
} catch (error) {
|
|
475
610
|
if (error instanceof Error)
|
|
@@ -485,7 +620,7 @@ function resolveBundledShim(requireResolve, fileExists) {
|
|
|
485
620
|
}
|
|
486
621
|
function resolveCodegraphCommand(options = {}) {
|
|
487
622
|
const env = options.env ?? process.env;
|
|
488
|
-
const fileExists = options.fileExists ??
|
|
623
|
+
const fileExists = options.fileExists ?? existsSync3;
|
|
489
624
|
const configuredBin = env[CODEGRAPH_ENV_BIN]?.trim() || env[CODEGRAPH_LEGACY_ENV_BIN]?.trim();
|
|
490
625
|
if (configuredBin !== undefined && configuredBin.length > 0) {
|
|
491
626
|
return { argsPrefix: [], command: configuredBin, exists: fileExists(configuredBin), source: "env" };
|
|
@@ -497,7 +632,7 @@ function resolveCodegraphCommand(options = {}) {
|
|
|
497
632
|
if (bundled !== null && runtime2 !== null) {
|
|
498
633
|
return { argsPrefix: [bundled], command: runtime2, exists: true, source: "bundled" };
|
|
499
634
|
}
|
|
500
|
-
const provisioned = options.provisioned?.() ?? defaultProvisionedBin(options.homeDir ??
|
|
635
|
+
const provisioned = options.provisioned?.() ?? defaultProvisionedBin(options.homeDir ?? homedir6(), fileExists);
|
|
501
636
|
if (provisioned !== null && fileExists(provisioned)) {
|
|
502
637
|
return { argsPrefix: [], command: provisioned, exists: true, source: "provisioned" };
|
|
503
638
|
}
|
|
@@ -511,11 +646,14 @@ function resolveCodegraphCommand(options = {}) {
|
|
|
511
646
|
}
|
|
512
647
|
|
|
513
648
|
// shared/src/config-loader.ts
|
|
514
|
-
import { homedir as
|
|
649
|
+
import { homedir as homedir8 } from "node:os";
|
|
515
650
|
|
|
516
651
|
// ../../utils/src/omo-config/loader.ts
|
|
517
|
-
import { existsSync as
|
|
518
|
-
import { homedir as
|
|
652
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
653
|
+
import { homedir as homedir7 } from "node:os";
|
|
654
|
+
|
|
655
|
+
// ../../utils/src/omo-config/body.ts
|
|
656
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
519
657
|
|
|
520
658
|
// ../../utils/src/deep-merge.ts
|
|
521
659
|
var DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
@@ -1393,127 +1531,13 @@ var HARNESS_IDS = ["codex", "opencode", "omo"];
|
|
|
1393
1531
|
var SETTING_HARNESS_SUPPORT = {
|
|
1394
1532
|
"codegraph.auto_provision": HARNESS_IDS,
|
|
1395
1533
|
"codegraph.enabled": HARNESS_IDS,
|
|
1534
|
+
"codegraph.excluded_roots": ["codex"],
|
|
1396
1535
|
"codegraph.install_dir": HARNESS_IDS,
|
|
1397
1536
|
"codegraph.telemetry": HARNESS_IDS,
|
|
1398
1537
|
"codegraph.watch_debounce_ms": ["opencode", "omo"]
|
|
1399
1538
|
};
|
|
1400
1539
|
|
|
1401
|
-
// ../../utils/src/omo-config/
|
|
1402
|
-
var CODEGRAPH_ENV_KEYS = [
|
|
1403
|
-
["auto_provision", "AUTO_PROVISION", "boolean"],
|
|
1404
|
-
["enabled", "ENABLED", "boolean"],
|
|
1405
|
-
["install_dir", "INSTALL_DIR", "string"],
|
|
1406
|
-
["telemetry", "TELEMETRY", "boolean"],
|
|
1407
|
-
["watch_debounce_ms", "WATCH_DEBOUNCE_MS", "number"]
|
|
1408
|
-
];
|
|
1409
|
-
function parseBooleanEnv(value) {
|
|
1410
|
-
const normalized = value.trim().toLowerCase();
|
|
1411
|
-
if (["1", "true", "yes", "on"].includes(normalized))
|
|
1412
|
-
return true;
|
|
1413
|
-
if (["0", "false", "no", "off"].includes(normalized))
|
|
1414
|
-
return false;
|
|
1415
|
-
return null;
|
|
1416
|
-
}
|
|
1417
|
-
function parseEnvValue(value, kind) {
|
|
1418
|
-
if (kind === "boolean")
|
|
1419
|
-
return parseBooleanEnv(value);
|
|
1420
|
-
if (kind === "number") {
|
|
1421
|
-
const parsed = Number(value);
|
|
1422
|
-
return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;
|
|
1423
|
-
}
|
|
1424
|
-
return value;
|
|
1425
|
-
}
|
|
1426
|
-
function setCodegraphSetting(config, key, value) {
|
|
1427
|
-
switch (key) {
|
|
1428
|
-
case "auto_provision":
|
|
1429
|
-
if (typeof value === "boolean")
|
|
1430
|
-
config.auto_provision = value;
|
|
1431
|
-
return;
|
|
1432
|
-
case "enabled":
|
|
1433
|
-
if (typeof value === "boolean")
|
|
1434
|
-
config.enabled = value;
|
|
1435
|
-
return;
|
|
1436
|
-
case "install_dir":
|
|
1437
|
-
if (typeof value === "string")
|
|
1438
|
-
config.install_dir = value;
|
|
1439
|
-
return;
|
|
1440
|
-
case "telemetry":
|
|
1441
|
-
if (typeof value === "boolean")
|
|
1442
|
-
config.telemetry = value;
|
|
1443
|
-
return;
|
|
1444
|
-
case "watch_debounce_ms":
|
|
1445
|
-
if (typeof value === "number")
|
|
1446
|
-
config.watch_debounce_ms = value;
|
|
1447
|
-
return;
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
function buildEnvOverrides(harness, env, warnings, merge) {
|
|
1451
|
-
let config = {};
|
|
1452
|
-
for (const prefix of ["OMO", harness.toUpperCase()]) {
|
|
1453
|
-
const codegraph = {};
|
|
1454
|
-
for (const [settingKey, envSuffix, kind] of CODEGRAPH_ENV_KEYS) {
|
|
1455
|
-
const envKey = `${prefix}_CODEGRAPH_${envSuffix}`;
|
|
1456
|
-
const rawValue = env[envKey];
|
|
1457
|
-
if (rawValue === undefined)
|
|
1458
|
-
continue;
|
|
1459
|
-
const parsed = parseEnvValue(rawValue, kind);
|
|
1460
|
-
if (parsed === null) {
|
|
1461
|
-
warnings.push(`${envKey} has invalid ${kind} value "${rawValue}"`);
|
|
1462
|
-
continue;
|
|
1463
|
-
}
|
|
1464
|
-
setCodegraphSetting(codegraph, settingKey, parsed);
|
|
1465
|
-
}
|
|
1466
|
-
if (Object.keys(codegraph).length > 0) {
|
|
1467
|
-
config = merge(config, { codegraph });
|
|
1468
|
-
}
|
|
1469
|
-
}
|
|
1470
|
-
return config;
|
|
1471
|
-
}
|
|
1472
|
-
|
|
1473
|
-
// ../../utils/src/omo-config/resolve.ts
|
|
1474
|
-
import { existsSync as existsSync3 } from "node:fs";
|
|
1475
|
-
import { dirname as dirname2, isAbsolute, join as join5, relative, resolve as resolve2 } from "node:path";
|
|
1476
|
-
function containsPath(parent, child) {
|
|
1477
|
-
const pathToChild = relative(parent, child);
|
|
1478
|
-
return pathToChild === "" || !pathToChild.startsWith("..") && !isAbsolute(pathToChild);
|
|
1479
|
-
}
|
|
1480
|
-
function findProjectConfigPathsNearestFirst(cwd, homeDir) {
|
|
1481
|
-
const startDir = resolve2(cwd);
|
|
1482
|
-
const stopBeforeDir = containsPath(resolve2(homeDir), startDir) ? resolve2(homeDir) : null;
|
|
1483
|
-
const paths = [];
|
|
1484
|
-
let currentDir = startDir;
|
|
1485
|
-
while (true) {
|
|
1486
|
-
if (stopBeforeDir !== null && currentDir === stopBeforeDir)
|
|
1487
|
-
break;
|
|
1488
|
-
const configPath = join5(currentDir, ".omo", "config.jsonc");
|
|
1489
|
-
if (existsSync3(configPath)) {
|
|
1490
|
-
paths.push(configPath);
|
|
1491
|
-
}
|
|
1492
|
-
const parentDir = dirname2(currentDir);
|
|
1493
|
-
if (parentDir === currentDir)
|
|
1494
|
-
break;
|
|
1495
|
-
currentDir = parentDir;
|
|
1496
|
-
}
|
|
1497
|
-
return paths;
|
|
1498
|
-
}
|
|
1499
|
-
function resolveOmoConfigPaths(options) {
|
|
1500
|
-
const globalPath = join5(resolve2(options.homeDir), ".omo", "config.jsonc");
|
|
1501
|
-
const projectPathsFarthestFirst = findProjectConfigPathsNearestFirst(options.cwd, options.homeDir).reverse();
|
|
1502
|
-
return [
|
|
1503
|
-
{ path: globalPath, scope: "global" },
|
|
1504
|
-
...projectPathsFarthestFirst.map((path) => ({ path, scope: "project" }))
|
|
1505
|
-
];
|
|
1506
|
-
}
|
|
1507
|
-
function toMissingSource(candidate) {
|
|
1508
|
-
return {
|
|
1509
|
-
exists: false,
|
|
1510
|
-
loaded: false,
|
|
1511
|
-
path: candidate.path,
|
|
1512
|
-
scope: candidate.scope
|
|
1513
|
-
};
|
|
1514
|
-
}
|
|
1515
|
-
|
|
1516
|
-
// ../../utils/src/omo-config/loader.ts
|
|
1540
|
+
// ../../utils/src/omo-config/body.ts
|
|
1517
1541
|
var BUILT_IN_DEFAULTS = {
|
|
1518
1542
|
codegraph: {
|
|
1519
1543
|
auto_provision: true,
|
|
@@ -1525,6 +1549,7 @@ var HARNESS_BLOCK_KEYS = HARNESS_IDS.map((harness) => `[${harness}]`);
|
|
|
1525
1549
|
var CODEGRAPH_SETTING_KEYS = [
|
|
1526
1550
|
"auto_provision",
|
|
1527
1551
|
"enabled",
|
|
1552
|
+
"excluded_roots",
|
|
1528
1553
|
"install_dir",
|
|
1529
1554
|
"telemetry",
|
|
1530
1555
|
"watch_debounce_ms"
|
|
@@ -1563,7 +1588,7 @@ function mergeCodegraphConfig(base, override) {
|
|
|
1563
1588
|
for (const key of CODEGRAPH_SETTING_KEYS) {
|
|
1564
1589
|
if (!hasOwn(merged, key))
|
|
1565
1590
|
continue;
|
|
1566
|
-
|
|
1591
|
+
setCodegraphSetting(codegraph, key, merged[key]);
|
|
1567
1592
|
}
|
|
1568
1593
|
return Object.keys(codegraph).length > 0 ? codegraph : undefined;
|
|
1569
1594
|
}
|
|
@@ -1580,6 +1605,9 @@ function isKnownHarnessBlockKey(key) {
|
|
|
1580
1605
|
return HARNESS_BLOCK_KEYS.includes(key);
|
|
1581
1606
|
}
|
|
1582
1607
|
function validateCodegraphValue(key, value) {
|
|
1608
|
+
if (key === "excluded_roots") {
|
|
1609
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? null : "must be an array of strings";
|
|
1610
|
+
}
|
|
1583
1611
|
if (key === "install_dir")
|
|
1584
1612
|
return typeof value === "string" ? null : "must be a string";
|
|
1585
1613
|
if (key === "watch_debounce_ms") {
|
|
@@ -1587,7 +1615,7 @@ function validateCodegraphValue(key, value) {
|
|
|
1587
1615
|
}
|
|
1588
1616
|
return typeof value === "boolean" ? null : "must be a boolean";
|
|
1589
1617
|
}
|
|
1590
|
-
function
|
|
1618
|
+
function setCodegraphSetting(config, key, value) {
|
|
1591
1619
|
switch (key) {
|
|
1592
1620
|
case "auto_provision":
|
|
1593
1621
|
if (typeof value === "boolean")
|
|
@@ -1597,6 +1625,11 @@ function setCodegraphSetting2(config, key, value) {
|
|
|
1597
1625
|
if (typeof value === "boolean")
|
|
1598
1626
|
config.enabled = value;
|
|
1599
1627
|
return;
|
|
1628
|
+
case "excluded_roots":
|
|
1629
|
+
if (Array.isArray(value) && value.every((entry) => typeof entry === "string")) {
|
|
1630
|
+
config.excluded_roots = value;
|
|
1631
|
+
}
|
|
1632
|
+
return;
|
|
1600
1633
|
case "install_dir":
|
|
1601
1634
|
if (typeof value === "string")
|
|
1602
1635
|
config.install_dir = value;
|
|
@@ -1627,7 +1660,7 @@ function normalizeCodegraphSection(section, pathPrefix, warnings) {
|
|
|
1627
1660
|
warnings.push(`${pathPrefix}.${key} ${error}`);
|
|
1628
1661
|
continue;
|
|
1629
1662
|
}
|
|
1630
|
-
|
|
1663
|
+
setCodegraphSetting(codegraph, key, value);
|
|
1631
1664
|
}
|
|
1632
1665
|
return codegraph;
|
|
1633
1666
|
}
|
|
@@ -1662,7 +1695,7 @@ function normalizeActiveHarnessBlock(value, harness, pathPrefix, warnings) {
|
|
|
1662
1695
|
}
|
|
1663
1696
|
function loadConfigFile(path, harness) {
|
|
1664
1697
|
try {
|
|
1665
|
-
const content =
|
|
1698
|
+
const content = readFileSync3(path, "utf-8");
|
|
1666
1699
|
const parsed = parseJsoncSafe(content);
|
|
1667
1700
|
if (parsed.errors.length > 0) {
|
|
1668
1701
|
return {
|
|
@@ -1706,15 +1739,137 @@ function validateHarnessApplicability(config, harness) {
|
|
|
1706
1739
|
}
|
|
1707
1740
|
return warnings;
|
|
1708
1741
|
}
|
|
1742
|
+
|
|
1743
|
+
// ../../utils/src/omo-config/env-overrides.ts
|
|
1744
|
+
var CODEGRAPH_ENV_KEYS = [
|
|
1745
|
+
["auto_provision", "AUTO_PROVISION", "boolean"],
|
|
1746
|
+
["enabled", "ENABLED", "boolean"],
|
|
1747
|
+
["install_dir", "INSTALL_DIR", "string"],
|
|
1748
|
+
["telemetry", "TELEMETRY", "boolean"],
|
|
1749
|
+
["watch_debounce_ms", "WATCH_DEBOUNCE_MS", "number"]
|
|
1750
|
+
];
|
|
1751
|
+
function parseBooleanEnv(value) {
|
|
1752
|
+
const normalized = value.trim().toLowerCase();
|
|
1753
|
+
if (["1", "true", "yes", "on"].includes(normalized))
|
|
1754
|
+
return true;
|
|
1755
|
+
if (["0", "false", "no", "off"].includes(normalized))
|
|
1756
|
+
return false;
|
|
1757
|
+
return null;
|
|
1758
|
+
}
|
|
1759
|
+
function parseEnvValue(value, kind) {
|
|
1760
|
+
if (kind === "boolean")
|
|
1761
|
+
return parseBooleanEnv(value);
|
|
1762
|
+
if (kind === "number") {
|
|
1763
|
+
const parsed = Number(value);
|
|
1764
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;
|
|
1765
|
+
}
|
|
1766
|
+
return value;
|
|
1767
|
+
}
|
|
1768
|
+
function setCodegraphSetting2(config, key, value) {
|
|
1769
|
+
switch (key) {
|
|
1770
|
+
case "auto_provision":
|
|
1771
|
+
if (typeof value === "boolean")
|
|
1772
|
+
config.auto_provision = value;
|
|
1773
|
+
return;
|
|
1774
|
+
case "enabled":
|
|
1775
|
+
if (typeof value === "boolean")
|
|
1776
|
+
config.enabled = value;
|
|
1777
|
+
return;
|
|
1778
|
+
case "excluded_roots":
|
|
1779
|
+
if (Array.isArray(value) && value.every((entry) => typeof entry === "string")) {
|
|
1780
|
+
config.excluded_roots = value;
|
|
1781
|
+
}
|
|
1782
|
+
return;
|
|
1783
|
+
case "install_dir":
|
|
1784
|
+
if (typeof value === "string")
|
|
1785
|
+
config.install_dir = value;
|
|
1786
|
+
return;
|
|
1787
|
+
case "telemetry":
|
|
1788
|
+
if (typeof value === "boolean")
|
|
1789
|
+
config.telemetry = value;
|
|
1790
|
+
return;
|
|
1791
|
+
case "watch_debounce_ms":
|
|
1792
|
+
if (typeof value === "number")
|
|
1793
|
+
config.watch_debounce_ms = value;
|
|
1794
|
+
return;
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
function buildEnvOverrides(harness, env, warnings, merge) {
|
|
1798
|
+
let config = {};
|
|
1799
|
+
for (const prefix of ["OMO", harness.toUpperCase()]) {
|
|
1800
|
+
const codegraph = {};
|
|
1801
|
+
for (const [settingKey, envSuffix, kind] of CODEGRAPH_ENV_KEYS) {
|
|
1802
|
+
const envKey = `${prefix}_CODEGRAPH_${envSuffix}`;
|
|
1803
|
+
const rawValue = env[envKey];
|
|
1804
|
+
if (rawValue === undefined)
|
|
1805
|
+
continue;
|
|
1806
|
+
const parsed = parseEnvValue(rawValue, kind);
|
|
1807
|
+
if (parsed === null) {
|
|
1808
|
+
warnings.push(`${envKey} has invalid ${kind} value "${rawValue}"`);
|
|
1809
|
+
continue;
|
|
1810
|
+
}
|
|
1811
|
+
setCodegraphSetting2(codegraph, settingKey, parsed);
|
|
1812
|
+
}
|
|
1813
|
+
if (Object.keys(codegraph).length > 0) {
|
|
1814
|
+
config = merge(config, { codegraph });
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
return config;
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
// ../../utils/src/omo-config/resolve.ts
|
|
1821
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
1822
|
+
import { dirname as dirname2, isAbsolute as isAbsolute2, join as join8, relative, resolve as resolve3 } from "node:path";
|
|
1823
|
+
function containsPath(parent, child) {
|
|
1824
|
+
const pathToChild = relative(parent, child);
|
|
1825
|
+
return pathToChild === "" || !pathToChild.startsWith("..") && !isAbsolute2(pathToChild);
|
|
1826
|
+
}
|
|
1827
|
+
function findProjectConfigPathsNearestFirst(cwd, homeDir) {
|
|
1828
|
+
const startDir = resolve3(cwd);
|
|
1829
|
+
const stopBeforeDir = containsPath(resolve3(homeDir), startDir) ? resolve3(homeDir) : null;
|
|
1830
|
+
const paths = [];
|
|
1831
|
+
let currentDir = startDir;
|
|
1832
|
+
while (true) {
|
|
1833
|
+
if (stopBeforeDir !== null && currentDir === stopBeforeDir)
|
|
1834
|
+
break;
|
|
1835
|
+
const configPath = join8(currentDir, ".omo", "config.jsonc");
|
|
1836
|
+
if (existsSync4(configPath)) {
|
|
1837
|
+
paths.push(configPath);
|
|
1838
|
+
}
|
|
1839
|
+
const parentDir = dirname2(currentDir);
|
|
1840
|
+
if (parentDir === currentDir)
|
|
1841
|
+
break;
|
|
1842
|
+
currentDir = parentDir;
|
|
1843
|
+
}
|
|
1844
|
+
return paths;
|
|
1845
|
+
}
|
|
1846
|
+
function resolveOmoConfigPaths(options) {
|
|
1847
|
+
const globalPath = join8(resolve3(options.homeDir), ".omo", "config.jsonc");
|
|
1848
|
+
const projectPathsFarthestFirst = findProjectConfigPathsNearestFirst(options.cwd, options.homeDir).reverse();
|
|
1849
|
+
return [
|
|
1850
|
+
{ path: globalPath, scope: "global" },
|
|
1851
|
+
...projectPathsFarthestFirst.map((path) => ({ path, scope: "project" }))
|
|
1852
|
+
];
|
|
1853
|
+
}
|
|
1854
|
+
function toMissingSource(candidate) {
|
|
1855
|
+
return {
|
|
1856
|
+
exists: false,
|
|
1857
|
+
loaded: false,
|
|
1858
|
+
path: candidate.path,
|
|
1859
|
+
scope: candidate.scope
|
|
1860
|
+
};
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
// ../../utils/src/omo-config/loader.ts
|
|
1709
1864
|
function loadOmoConfig(options) {
|
|
1710
1865
|
const cwd = options.cwd ?? process.cwd();
|
|
1711
|
-
const homeDir = options.homeDir ?? process.env["HOME"] ?? process.env["USERPROFILE"] ??
|
|
1866
|
+
const homeDir = options.homeDir ?? process.env["HOME"] ?? process.env["USERPROFILE"] ?? homedir7();
|
|
1712
1867
|
const env = options.env ?? process.env;
|
|
1713
1868
|
let config = BUILT_IN_DEFAULTS;
|
|
1714
1869
|
const sources = [];
|
|
1715
1870
|
const warnings = [];
|
|
1716
1871
|
for (const candidate of resolveOmoConfigPaths({ cwd, homeDir })) {
|
|
1717
|
-
if (!
|
|
1872
|
+
if (!existsSync5(candidate.path)) {
|
|
1718
1873
|
if (candidate.scope === "global") {
|
|
1719
1874
|
sources.push(toMissingSource(candidate));
|
|
1720
1875
|
}
|
|
@@ -1762,23 +1917,460 @@ function getCodexOmoConfig(options = {}) {
|
|
|
1762
1917
|
}
|
|
1763
1918
|
function resolveHomeDir(options) {
|
|
1764
1919
|
const env = options.env ?? process.env;
|
|
1765
|
-
return options.homeDir ?? env["HOME"] ?? env["USERPROFILE"] ??
|
|
1920
|
+
return options.homeDir ?? env["HOME"] ?? env["USERPROFILE"] ?? homedir8();
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
// components/codegraph/src/cache-gc.ts
|
|
1924
|
+
var NON_FATAL_GC_ERROR_CODES = new Set(["EACCES", "EBUSY", "ENOENT", "ENOTEMPTY", "ENOTDIR", "EPERM"]);
|
|
1925
|
+
function pruneCodegraphProjectStoresBestEffort(homeDir, options = {}) {
|
|
1926
|
+
try {
|
|
1927
|
+
(options.prune ?? pruneDeadCodegraphProjectStores)({ homeDir });
|
|
1928
|
+
} catch (error) {
|
|
1929
|
+
if (!isNonFatalCodegraphGcError(error))
|
|
1930
|
+
throw error;
|
|
1931
|
+
options.debugLog?.(`CodeGraph cache GC skipped: ${error.message}`);
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
function isNonFatalCodegraphGcError(error) {
|
|
1935
|
+
if (!(error instanceof Error))
|
|
1936
|
+
return false;
|
|
1937
|
+
const code = typeof error === "object" && error !== null && "code" in error ? error.code : undefined;
|
|
1938
|
+
return typeof code === "string" && NON_FATAL_GC_ERROR_CODES.has(code);
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
// components/codegraph/src/hook-sweep.ts
|
|
1942
|
+
import { fileURLToPath } from "node:url";
|
|
1943
|
+
// ../../utils/src/codegraph/process-sweeper.ts
|
|
1944
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, statSync as statSync2, utimesSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1945
|
+
import { homedir as homedir10 } from "node:os";
|
|
1946
|
+
import { dirname as dirname3, join as join10 } from "node:path";
|
|
1947
|
+
|
|
1948
|
+
// ../../utils/src/codegraph/process-exec.ts
|
|
1949
|
+
import { execFile } from "node:child_process";
|
|
1950
|
+
|
|
1951
|
+
// ../../utils/src/codegraph/process-match.ts
|
|
1952
|
+
import { posix, win32 } from "node:path";
|
|
1953
|
+
var SERVE_WRAPPER_SUFFIX = "/components/codegraph/dist/serve.js";
|
|
1954
|
+
var UPSTREAM_PACKAGE_SEGMENT = "/@colbymchenry/codegraph/";
|
|
1955
|
+
function parsePosixProcessTable(output) {
|
|
1956
|
+
const processes = [];
|
|
1957
|
+
for (const line of output.split(/\r?\n/)) {
|
|
1958
|
+
const match = /^\s*(\d+)\s+(\d+)\s+(.+?)\s*$/.exec(line);
|
|
1959
|
+
if (match === null)
|
|
1960
|
+
continue;
|
|
1961
|
+
const pid = Number(match[1]);
|
|
1962
|
+
const ppid = Number(match[2]);
|
|
1963
|
+
const command = match[3];
|
|
1964
|
+
if (!isValidProcessId(pid) || !Number.isInteger(ppid) || ppid < 0 || command === undefined)
|
|
1965
|
+
continue;
|
|
1966
|
+
processes.push({ command, pid, ppid });
|
|
1967
|
+
}
|
|
1968
|
+
return processes;
|
|
1969
|
+
}
|
|
1970
|
+
function parseWindowsProcessTable(output) {
|
|
1971
|
+
const parsed = parseJson(output);
|
|
1972
|
+
const entries = Array.isArray(parsed) ? parsed : parsed === undefined ? [] : [parsed];
|
|
1973
|
+
const processes = [];
|
|
1974
|
+
for (const entry of entries) {
|
|
1975
|
+
if (!isRecord3(entry))
|
|
1976
|
+
continue;
|
|
1977
|
+
const pid = numberField(entry, "ProcessId");
|
|
1978
|
+
const ppid = numberField(entry, "ParentProcessId");
|
|
1979
|
+
const command = stringField(entry, "CommandLine");
|
|
1980
|
+
if (pid === undefined || ppid === undefined || command === undefined || command.trim().length === 0)
|
|
1981
|
+
continue;
|
|
1982
|
+
processes.push({ command, pid, ppid });
|
|
1983
|
+
}
|
|
1984
|
+
return processes;
|
|
1985
|
+
}
|
|
1986
|
+
function selectZombieCodegraphProcesses(processes, options) {
|
|
1987
|
+
const platform = options.platform ?? process.platform;
|
|
1988
|
+
const livePids = new Set(processes.map((processInfo) => processInfo.pid));
|
|
1989
|
+
const roots = normalizeRoots(options.ownedRoots, platform);
|
|
1990
|
+
const zombies = [];
|
|
1991
|
+
for (const processInfo of processes) {
|
|
1992
|
+
const match = matchOwnedCodegraphCommand(processInfo.command, roots, platform);
|
|
1993
|
+
if (match === null)
|
|
1994
|
+
continue;
|
|
1995
|
+
if (!isOrphaned(processInfo, livePids))
|
|
1996
|
+
continue;
|
|
1997
|
+
zombies.push({ ...processInfo, matchedRoot: match.root, matchKind: match.kind });
|
|
1998
|
+
}
|
|
1999
|
+
return zombies;
|
|
2000
|
+
}
|
|
2001
|
+
function matchOwnedCodegraphCommand(command, roots, platform) {
|
|
2002
|
+
const normalizedCommand = normalizeForComparison2(command, platform);
|
|
2003
|
+
for (const root of roots) {
|
|
2004
|
+
if (root.length === 0)
|
|
2005
|
+
continue;
|
|
2006
|
+
const serveWrapper = `${root}${SERVE_WRAPPER_SUFFIX}`;
|
|
2007
|
+
if (hasExecutableToken(normalizedCommand, serveWrapper))
|
|
2008
|
+
return { kind: "serve-wrapper", root };
|
|
2009
|
+
if (upstreamPackagePathIsUnderRoot(normalizedCommand, root)) {
|
|
2010
|
+
return { kind: "upstream-codegraph", root };
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
return null;
|
|
2014
|
+
}
|
|
2015
|
+
function hasExecutableToken(command, expectedPath) {
|
|
2016
|
+
let searchFrom = 0;
|
|
2017
|
+
for (;; ) {
|
|
2018
|
+
const pathIndex = command.indexOf(expectedPath, searchFrom);
|
|
2019
|
+
if (pathIndex < 0)
|
|
2020
|
+
return false;
|
|
2021
|
+
const tokenStart = findTokenStart(command, pathIndex);
|
|
2022
|
+
const tokenEnd = findTokenEnd(command, pathIndex + expectedPath.length);
|
|
2023
|
+
if (command.slice(tokenStart, tokenEnd) === expectedPath && tokenLooksExecutable(command, tokenStart))
|
|
2024
|
+
return true;
|
|
2025
|
+
searchFrom = pathIndex + expectedPath.length;
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
function tokenLooksExecutable(command, tokenStart) {
|
|
2029
|
+
const prefix = command.slice(0, tokenStart).trimEnd();
|
|
2030
|
+
if (prefix.length === 0)
|
|
2031
|
+
return true;
|
|
2032
|
+
const previousTokenStart = findTokenStart(prefix, prefix.length - 1);
|
|
2033
|
+
const previousToken = prefix.slice(previousTokenStart);
|
|
2034
|
+
const executableName = previousToken.split("/").at(-1) ?? previousToken;
|
|
2035
|
+
return /^node\d*(\.exe)?$/.test(executableName) || /^bun(\.exe)?$/.test(executableName);
|
|
2036
|
+
}
|
|
2037
|
+
function upstreamPackagePathIsUnderRoot(command, root) {
|
|
2038
|
+
let searchFrom = 0;
|
|
2039
|
+
for (;; ) {
|
|
2040
|
+
const packageIndex = command.indexOf(UPSTREAM_PACKAGE_SEGMENT, searchFrom);
|
|
2041
|
+
if (packageIndex < 0)
|
|
2042
|
+
return false;
|
|
2043
|
+
const tokenStart = findTokenStart(command, packageIndex);
|
|
2044
|
+
if (command.slice(tokenStart).startsWith(`${root}/`) && tokenLooksExecutable(command, tokenStart))
|
|
2045
|
+
return true;
|
|
2046
|
+
searchFrom = packageIndex + UPSTREAM_PACKAGE_SEGMENT.length;
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
function findTokenStart(command, index) {
|
|
2050
|
+
for (let cursor = index - 1;cursor >= 0; cursor -= 1) {
|
|
2051
|
+
if (/\s|["']/.test(command[cursor] ?? ""))
|
|
2052
|
+
return cursor + 1;
|
|
2053
|
+
}
|
|
2054
|
+
return 0;
|
|
2055
|
+
}
|
|
2056
|
+
function findTokenEnd(command, index) {
|
|
2057
|
+
for (let cursor = index;cursor < command.length; cursor += 1) {
|
|
2058
|
+
if (/\s|["']/.test(command[cursor] ?? ""))
|
|
2059
|
+
return cursor;
|
|
2060
|
+
}
|
|
2061
|
+
return command.length;
|
|
2062
|
+
}
|
|
2063
|
+
function normalizeRoots(roots, platform) {
|
|
2064
|
+
const normalized = new Set;
|
|
2065
|
+
for (const root of roots) {
|
|
2066
|
+
const trimmed = root.trim();
|
|
2067
|
+
if (trimmed.length === 0)
|
|
2068
|
+
continue;
|
|
2069
|
+
normalized.add(normalizeForComparison2(resolvePathForPlatform(trimmed, platform), platform));
|
|
2070
|
+
}
|
|
2071
|
+
return [...normalized].sort((left, right) => right.length - left.length || left.localeCompare(right));
|
|
2072
|
+
}
|
|
2073
|
+
function resolvePathForPlatform(value, platform) {
|
|
2074
|
+
return platform === "win32" ? win32.resolve(value) : posix.resolve(value);
|
|
2075
|
+
}
|
|
2076
|
+
function normalizeForComparison2(value, platform) {
|
|
2077
|
+
const normalized = value.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
2078
|
+
return platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
2079
|
+
}
|
|
2080
|
+
function isOrphaned(processInfo, livePids) {
|
|
2081
|
+
return processInfo.ppid === 1 || !livePids.has(processInfo.ppid);
|
|
2082
|
+
}
|
|
2083
|
+
function isValidProcessId(value) {
|
|
2084
|
+
return Number.isSafeInteger(value) && value > 0;
|
|
2085
|
+
}
|
|
2086
|
+
function parseJson(text) {
|
|
2087
|
+
try {
|
|
2088
|
+
return JSON.parse(text);
|
|
2089
|
+
} catch (error) {
|
|
2090
|
+
if (error instanceof SyntaxError)
|
|
2091
|
+
return;
|
|
2092
|
+
throw error;
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
function numberField(record, key) {
|
|
2096
|
+
const value = record[key];
|
|
2097
|
+
return typeof value === "number" && isValidProcessId(value) ? value : undefined;
|
|
2098
|
+
}
|
|
2099
|
+
function stringField(record, key) {
|
|
2100
|
+
const value = record[key];
|
|
2101
|
+
return typeof value === "string" ? value : undefined;
|
|
2102
|
+
}
|
|
2103
|
+
function isRecord3(value) {
|
|
2104
|
+
return typeof value === "object" && value !== null;
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
// ../../utils/src/codegraph/process-exec.ts
|
|
2108
|
+
function enumerateCodegraphProcesses(platform = process.platform) {
|
|
2109
|
+
return platform === "win32" ? enumerateWindowsProcesses() : enumeratePosixProcesses();
|
|
2110
|
+
}
|
|
2111
|
+
function createDefaultCodegraphProcessKiller(platform = process.platform) {
|
|
2112
|
+
return platform === "win32" ? createWindowsKiller() : createPosixKiller();
|
|
2113
|
+
}
|
|
2114
|
+
function enumeratePosixProcesses() {
|
|
2115
|
+
return execFileText("ps", ["-eo", "pid=,ppid=,command="]).then(parsePosixProcessTable);
|
|
2116
|
+
}
|
|
2117
|
+
function enumerateWindowsProcesses() {
|
|
2118
|
+
const command = [
|
|
2119
|
+
"Get-CimInstance Win32_Process",
|
|
2120
|
+
"Select-Object ProcessId,ParentProcessId,CommandLine",
|
|
2121
|
+
"ConvertTo-Json -Compress -Depth 2"
|
|
2122
|
+
].join(" | ");
|
|
2123
|
+
return execFileText("powershell.exe", ["-NoProfile", "-Command", command]).then(parseWindowsProcessTable);
|
|
2124
|
+
}
|
|
2125
|
+
function createPosixKiller() {
|
|
2126
|
+
return {
|
|
2127
|
+
isAlive: (pid) => {
|
|
2128
|
+
try {
|
|
2129
|
+
process.kill(pid, 0);
|
|
2130
|
+
return true;
|
|
2131
|
+
} catch (error) {
|
|
2132
|
+
if (!(error instanceof Error))
|
|
2133
|
+
throw error;
|
|
2134
|
+
return processKillErrorMeansAlive(error);
|
|
2135
|
+
}
|
|
2136
|
+
},
|
|
2137
|
+
kill: (pid) => {
|
|
2138
|
+
process.kill(pid, "SIGKILL");
|
|
2139
|
+
return Promise.resolve();
|
|
2140
|
+
},
|
|
2141
|
+
terminate: (pid) => {
|
|
2142
|
+
process.kill(pid, "SIGTERM");
|
|
2143
|
+
return Promise.resolve();
|
|
2144
|
+
}
|
|
2145
|
+
};
|
|
2146
|
+
}
|
|
2147
|
+
function createWindowsKiller() {
|
|
2148
|
+
return {
|
|
2149
|
+
isAlive: (pid) => {
|
|
2150
|
+
try {
|
|
2151
|
+
process.kill(pid, 0);
|
|
2152
|
+
return true;
|
|
2153
|
+
} catch (error) {
|
|
2154
|
+
if (!(error instanceof Error))
|
|
2155
|
+
throw error;
|
|
2156
|
+
return processKillErrorMeansAlive(error);
|
|
2157
|
+
}
|
|
2158
|
+
},
|
|
2159
|
+
kill: (pid) => execFileVoid("taskkill.exe", ["/PID", String(pid), "/T", "/F"]),
|
|
2160
|
+
terminate: (pid) => execFileVoid("taskkill.exe", ["/PID", String(pid), "/T"])
|
|
2161
|
+
};
|
|
2162
|
+
}
|
|
2163
|
+
function execFileText(command, args) {
|
|
2164
|
+
return new Promise((resolvePromise, reject) => {
|
|
2165
|
+
execFile(command, [...args], { encoding: "utf8", maxBuffer: 16 * 1024 * 1024, windowsHide: true }, (error, stdout) => {
|
|
2166
|
+
if (error !== null) {
|
|
2167
|
+
reject(error);
|
|
2168
|
+
return;
|
|
2169
|
+
}
|
|
2170
|
+
resolvePromise(stdout);
|
|
2171
|
+
});
|
|
2172
|
+
});
|
|
2173
|
+
}
|
|
2174
|
+
function execFileVoid(command, args) {
|
|
2175
|
+
return execFileText(command, args).then(() => {
|
|
2176
|
+
return;
|
|
2177
|
+
});
|
|
2178
|
+
}
|
|
2179
|
+
function processKillErrorMeansAlive(error) {
|
|
2180
|
+
const code = typeof error === "object" && error !== null && "code" in error ? error.code : undefined;
|
|
2181
|
+
if (code === "ESRCH")
|
|
2182
|
+
return false;
|
|
2183
|
+
if (code === "EPERM")
|
|
2184
|
+
return true;
|
|
2185
|
+
return false;
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
// ../../utils/src/codegraph/process-roots.ts
|
|
2189
|
+
import { existsSync as existsSync6, readdirSync as readdirSync2, realpathSync as realpathSync4 } from "node:fs";
|
|
2190
|
+
import { homedir as homedir9 } from "node:os";
|
|
2191
|
+
import { join as join9, resolve as resolve4 } from "node:path";
|
|
2192
|
+
function discoverCodegraphOwnedRoots(options = {}) {
|
|
2193
|
+
const env = options.env ?? process.env;
|
|
2194
|
+
const homeDir = options.homeDir ?? env["HOME"] ?? env["USERPROFILE"] ?? homedir9();
|
|
2195
|
+
const roots = new Set;
|
|
2196
|
+
addRoot(roots, options.trustedCodegraphInstallDir);
|
|
2197
|
+
addRoot(roots, buildCodegraphEnv({ homeDir })[CODEGRAPH_INSTALL_DIR_ENV]);
|
|
2198
|
+
addRoot(roots, options.pluginRoot);
|
|
2199
|
+
for (const root of options.extraRoots ?? [])
|
|
2200
|
+
addRoot(roots, root);
|
|
2201
|
+
for (const root of readCodexPluginCacheRoots(options.codexHome ?? env["CODEX_HOME"] ?? join9(homeDir, ".codex"))) {
|
|
2202
|
+
addRoot(roots, root);
|
|
2203
|
+
}
|
|
2204
|
+
return [...roots];
|
|
2205
|
+
}
|
|
2206
|
+
function readCodexPluginCacheRoots(codexHome) {
|
|
2207
|
+
const cacheRoot = join9(codexHome, "plugins", "cache");
|
|
2208
|
+
if (!existsSync6(cacheRoot))
|
|
2209
|
+
return [];
|
|
2210
|
+
const roots = [];
|
|
2211
|
+
for (const publisher of safeReadDir(cacheRoot)) {
|
|
2212
|
+
if (!OMO_CODEX_PLUGIN_CACHE_PUBLISHERS.has(publisher))
|
|
2213
|
+
continue;
|
|
2214
|
+
const omoRoot = join9(cacheRoot, publisher, "omo");
|
|
2215
|
+
if (!existsSync6(omoRoot))
|
|
2216
|
+
continue;
|
|
2217
|
+
for (const version of safeReadDir(omoRoot))
|
|
2218
|
+
roots.push(join9(omoRoot, version));
|
|
2219
|
+
}
|
|
2220
|
+
return roots;
|
|
2221
|
+
}
|
|
2222
|
+
function addRoot(roots, root) {
|
|
2223
|
+
if (root === undefined || root.trim().length === 0)
|
|
2224
|
+
return;
|
|
2225
|
+
const resolved = resolve4(root);
|
|
2226
|
+
roots.add(resolved);
|
|
2227
|
+
roots.add(realpathIfPossible2(resolved));
|
|
2228
|
+
}
|
|
2229
|
+
function safeReadDir(path) {
|
|
2230
|
+
try {
|
|
2231
|
+
return readdirSync2(path, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
2232
|
+
} catch (error) {
|
|
2233
|
+
if (isNonFatalFsError(error))
|
|
2234
|
+
return [];
|
|
2235
|
+
throw error;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
function realpathIfPossible2(path) {
|
|
2239
|
+
try {
|
|
2240
|
+
return realpathSync4(path);
|
|
2241
|
+
} catch (error) {
|
|
2242
|
+
if (error instanceof Error)
|
|
2243
|
+
return resolve4(path);
|
|
2244
|
+
throw error;
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
function isNonFatalFsError(error) {
|
|
2248
|
+
if (!(error instanceof Error))
|
|
2249
|
+
return false;
|
|
2250
|
+
const code = typeof error === "object" && error !== null && "code" in error ? error.code : undefined;
|
|
2251
|
+
return typeof code === "string" && ["EACCES", "ENOENT", "ENOTDIR", "EPERM"].includes(code);
|
|
2252
|
+
}
|
|
2253
|
+
var OMO_CODEX_PLUGIN_CACHE_PUBLISHERS = new Set(["sisyphuslabs"]);
|
|
2254
|
+
|
|
2255
|
+
// ../../utils/src/codegraph/process-sweeper.ts
|
|
2256
|
+
var DEFAULT_GRACE_MS = 2000;
|
|
2257
|
+
var DEFAULT_THROTTLE_MS = 60 * 60 * 1000;
|
|
2258
|
+
var SWEEP_STAMP_FILE = "zombie-sweep.stamp";
|
|
2259
|
+
async function sweepCodegraphZombies(options = {}) {
|
|
2260
|
+
const homeDir = options.homeDir ?? options.env?.["HOME"] ?? options.env?.["USERPROFILE"] ?? homedir10();
|
|
2261
|
+
const stampFile = join10(codegraphDataRoot(homeDir), SWEEP_STAMP_FILE);
|
|
2262
|
+
const nowMs = options.nowMs ?? Date.now();
|
|
2263
|
+
const dryRun = options.dryRun === true;
|
|
2264
|
+
const ownedRoots = options.ownedRoots ?? discoverCodegraphOwnedRoots(options);
|
|
2265
|
+
if (options.force !== true && isSweepThrottled(stampFile, nowMs, options.throttleMs ?? DEFAULT_THROTTLE_MS)) {
|
|
2266
|
+
return emptyResult("throttled", dryRun, ownedRoots, stampFile);
|
|
2267
|
+
}
|
|
2268
|
+
try {
|
|
2269
|
+
const provider = options.processProvider ?? (() => enumerateCodegraphProcesses(options.platform));
|
|
2270
|
+
const candidates = selectZombieCodegraphProcesses(await provider(), {
|
|
2271
|
+
ownedRoots,
|
|
2272
|
+
...options.platform === undefined ? {} : { platform: options.platform }
|
|
2273
|
+
});
|
|
2274
|
+
const result = dryRun ? { failed: [], killed: [] } : await killCandidates(candidates, options.killer ?? createDefaultCodegraphProcessKiller(options.platform), options);
|
|
2275
|
+
if (!dryRun)
|
|
2276
|
+
writeSweepStamp(stampFile, nowMs);
|
|
2277
|
+
return { action: "swept", candidates, dryRun, failed: result.failed, killed: result.killed, ownedRoots, stampFile };
|
|
2278
|
+
} catch (error) {
|
|
2279
|
+
options.log?.(`CodeGraph zombie sweep skipped: ${error instanceof Error ? error.message : String(error)}`);
|
|
2280
|
+
return emptyResult("failed", dryRun, ownedRoots, stampFile);
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
async function killCandidates(candidates, killer, options) {
|
|
2284
|
+
const failed = [];
|
|
2285
|
+
const killed = [];
|
|
2286
|
+
for (const candidate of candidates) {
|
|
2287
|
+
const terminated = await safelyTerminate(candidate.pid, killer, failed, options.log);
|
|
2288
|
+
if (!terminated)
|
|
2289
|
+
continue;
|
|
2290
|
+
await delay(options.graceMs ?? DEFAULT_GRACE_MS);
|
|
2291
|
+
if (!await killer.isAlive(candidate.pid)) {
|
|
2292
|
+
killed.push(candidate);
|
|
2293
|
+
continue;
|
|
2294
|
+
}
|
|
2295
|
+
if (await safelyKill(candidate.pid, killer, failed, options.log))
|
|
2296
|
+
killed.push(candidate);
|
|
2297
|
+
}
|
|
2298
|
+
return { failed, killed };
|
|
2299
|
+
}
|
|
2300
|
+
async function safelyTerminate(pid, killer, failed, log) {
|
|
2301
|
+
try {
|
|
2302
|
+
await killer.terminate(pid);
|
|
2303
|
+
return true;
|
|
2304
|
+
} catch (error) {
|
|
2305
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2306
|
+
failed.push({ error: message, pid, stage: "terminate" });
|
|
2307
|
+
log?.(`CodeGraph zombie sweep failed to terminate pid ${pid}: ${message}`);
|
|
2308
|
+
return false;
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
async function safelyKill(pid, killer, failed, log) {
|
|
2312
|
+
try {
|
|
2313
|
+
await killer.kill(pid);
|
|
2314
|
+
return true;
|
|
2315
|
+
} catch (error) {
|
|
2316
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2317
|
+
failed.push({ error: message, pid, stage: "kill" });
|
|
2318
|
+
log?.(`CodeGraph zombie sweep failed to kill pid ${pid}: ${message}`);
|
|
2319
|
+
return false;
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
function isSweepThrottled(stampFile, nowMs, throttleMs) {
|
|
2323
|
+
if (!existsSync7(stampFile))
|
|
2324
|
+
return false;
|
|
2325
|
+
return nowMs - statSync2(stampFile).mtimeMs < throttleMs;
|
|
2326
|
+
}
|
|
2327
|
+
function writeSweepStamp(stampFile, nowMs) {
|
|
2328
|
+
mkdirSync2(dirname3(stampFile), { recursive: true });
|
|
2329
|
+
writeFileSync2(stampFile, `${new Date(nowMs).toISOString()}
|
|
2330
|
+
`);
|
|
2331
|
+
const stampDate = new Date(nowMs);
|
|
2332
|
+
utimesSync(stampFile, stampDate, stampDate);
|
|
2333
|
+
}
|
|
2334
|
+
function emptyResult(action, dryRun, ownedRoots, stampFile) {
|
|
2335
|
+
return { action, candidates: [], dryRun, failed: [], killed: [], ownedRoots, stampFile };
|
|
2336
|
+
}
|
|
2337
|
+
function delay(ms) {
|
|
2338
|
+
if (ms <= 0)
|
|
2339
|
+
return Promise.resolve();
|
|
2340
|
+
return new Promise((resolvePromise) => {
|
|
2341
|
+
setTimeout(resolvePromise, ms);
|
|
2342
|
+
});
|
|
2343
|
+
}
|
|
2344
|
+
// components/codegraph/src/hook-sweep.ts
|
|
2345
|
+
async function sweepCodegraphZombiesBestEffort(options, sweep = sweepCodegraphZombies) {
|
|
2346
|
+
try {
|
|
2347
|
+
await sweep({
|
|
2348
|
+
...options,
|
|
2349
|
+
pluginRoot: defaultPluginRoot(),
|
|
2350
|
+
...options.log === undefined ? {} : { log: options.log }
|
|
2351
|
+
});
|
|
2352
|
+
} catch (error) {
|
|
2353
|
+
options.log?.(`CodeGraph zombie sweep skipped: ${error instanceof Error ? error.message : String(error)}`);
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
function defaultPluginRoot() {
|
|
2357
|
+
return fileURLToPath(new URL("../../..", import.meta.url));
|
|
1766
2358
|
}
|
|
1767
2359
|
|
|
1768
2360
|
// components/codegraph/src/session-start-worker.ts
|
|
1769
|
-
import { execFile as
|
|
1770
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
1771
|
-
import { homedir as
|
|
1772
|
-
import { extname, join as
|
|
2361
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
2362
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync9, mkdirSync as mkdirSync3 } from "node:fs";
|
|
2363
|
+
import { homedir as homedir12 } from "node:os";
|
|
2364
|
+
import { extname, join as join12 } from "node:path";
|
|
1773
2365
|
import { cwd as processCwd, env as processEnv, execPath as processExecPath, stderr as processStderr } from "node:process";
|
|
1774
2366
|
|
|
1775
2367
|
// ../../utils/src/codegraph/provision.ts
|
|
1776
2368
|
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
1777
|
-
import { execFile } from "node:child_process";
|
|
2369
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
1778
2370
|
import { chmod, mkdir, readdir, readFile, rename, rm, rmdir, stat, writeFile } from "node:fs/promises";
|
|
1779
|
-
import { existsSync as
|
|
1780
|
-
import { homedir as
|
|
1781
|
-
import { basename as basename3, join as
|
|
2371
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
2372
|
+
import { homedir as homedir11, hostname } from "node:os";
|
|
2373
|
+
import { basename as basename3, join as join11 } from "node:path";
|
|
1782
2374
|
import { promisify } from "node:util";
|
|
1783
2375
|
|
|
1784
2376
|
// ../../utils/src/codegraph/manifest.ts
|
|
@@ -1822,15 +2414,15 @@ var CODEGRAPH_PROVISION_MANIFEST = {
|
|
|
1822
2414
|
var DEFAULT_LOCK_WAIT_MS = 5000;
|
|
1823
2415
|
var DEFAULT_LOCK_STALE_MS = 120000;
|
|
1824
2416
|
var DEFAULT_DOWNLOAD_TIMEOUT_MS = 60000;
|
|
1825
|
-
var execFileAsync = promisify(
|
|
2417
|
+
var execFileAsync = promisify(execFile2);
|
|
1826
2418
|
function platformKey() {
|
|
1827
2419
|
return `${process.platform}-${process.arch}`;
|
|
1828
2420
|
}
|
|
1829
2421
|
function markerPath(installDir, version) {
|
|
1830
|
-
return
|
|
2422
|
+
return join11(installDir, ".provisioned", `codegraph-${version}.json`);
|
|
1831
2423
|
}
|
|
1832
2424
|
function defaultInstallDir() {
|
|
1833
|
-
return
|
|
2425
|
+
return join11(homedir11(), ".omo", "codegraph");
|
|
1834
2426
|
}
|
|
1835
2427
|
function sha256(bytes) {
|
|
1836
2428
|
return createHash2("sha256").update(bytes).digest("hex");
|
|
@@ -1850,7 +2442,7 @@ async function removeEmptyDirectory(path) {
|
|
|
1850
2442
|
}
|
|
1851
2443
|
}
|
|
1852
2444
|
function sleep(ms) {
|
|
1853
|
-
return new Promise((
|
|
2445
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
1854
2446
|
}
|
|
1855
2447
|
async function defaultDownloader(asset, timeoutMs = DEFAULT_DOWNLOAD_TIMEOUT_MS) {
|
|
1856
2448
|
const response = await fetch(asset.url, { signal: AbortSignal.timeout(timeoutMs) });
|
|
@@ -1864,7 +2456,7 @@ function forcedBadChecksumOptions(options) {
|
|
|
1864
2456
|
const key = options.platformKey ?? platformKey();
|
|
1865
2457
|
return {
|
|
1866
2458
|
downloader: async () => new TextEncoder().encode("checksum mismatch"),
|
|
1867
|
-
installDir: options.installDir ??
|
|
2459
|
+
installDir: options.installDir ?? join11(options.lockDir, "codegraph-force-bad-checksum"),
|
|
1868
2460
|
manifest: {
|
|
1869
2461
|
assets: {
|
|
1870
2462
|
[key]: { executableName: process.platform === "win32" ? "codegraph.cmd" : "codegraph", sha256: "0000", url: "memory://bad" }
|
|
@@ -1875,13 +2467,13 @@ function forcedBadChecksumOptions(options) {
|
|
|
1875
2467
|
};
|
|
1876
2468
|
}
|
|
1877
2469
|
async function readMarker(path) {
|
|
1878
|
-
if (!
|
|
2470
|
+
if (!existsSync8(path))
|
|
1879
2471
|
return null;
|
|
1880
2472
|
try {
|
|
1881
2473
|
const raw = JSON.parse(await readFile(path, "utf8"));
|
|
1882
2474
|
if (typeof raw === "object" && raw !== null && "binPath" in raw) {
|
|
1883
2475
|
const value = raw.binPath;
|
|
1884
|
-
return typeof value === "string" &&
|
|
2476
|
+
return typeof value === "string" && existsSync8(value) ? value : null;
|
|
1885
2477
|
}
|
|
1886
2478
|
return null;
|
|
1887
2479
|
} catch (error) {
|
|
@@ -1892,7 +2484,7 @@ async function readMarker(path) {
|
|
|
1892
2484
|
}
|
|
1893
2485
|
async function acquireLock(lockPath, waitMs, staleMs) {
|
|
1894
2486
|
const startedAt = Date.now();
|
|
1895
|
-
await mkdir(
|
|
2487
|
+
await mkdir(join11(lockPath, ".."), { recursive: true });
|
|
1896
2488
|
while (Date.now() - startedAt <= waitMs) {
|
|
1897
2489
|
try {
|
|
1898
2490
|
await mkdir(lockPath);
|
|
@@ -1917,24 +2509,24 @@ async function installExtractedBundle(extractDir, installDir, executableName) {
|
|
|
1917
2509
|
const roots = await readdir(extractDir);
|
|
1918
2510
|
if (roots.length !== 1)
|
|
1919
2511
|
throw new Error(`CodeGraph archive should contain one root directory, found ${roots.length}`);
|
|
1920
|
-
const bundleDir =
|
|
2512
|
+
const bundleDir = join11(extractDir, roots[0] ?? "");
|
|
1921
2513
|
const bundleEntries = await readdir(bundleDir);
|
|
1922
2514
|
await mkdir(installDir, { recursive: true });
|
|
1923
2515
|
for (const entry of bundleEntries) {
|
|
1924
|
-
await rm(
|
|
1925
|
-
await rename(
|
|
2516
|
+
await rm(join11(installDir, entry), { force: true, recursive: true });
|
|
2517
|
+
await rename(join11(bundleDir, entry), join11(installDir, entry));
|
|
1926
2518
|
}
|
|
1927
|
-
const destination =
|
|
1928
|
-
if (!
|
|
2519
|
+
const destination = join11(installDir, "bin", executableName);
|
|
2520
|
+
if (!existsSync8(destination))
|
|
1929
2521
|
throw new Error(`CodeGraph archive did not contain bin/${executableName}`);
|
|
1930
2522
|
await chmod(destination, 493);
|
|
1931
2523
|
return destination;
|
|
1932
2524
|
}
|
|
1933
2525
|
async function installAsset(layout) {
|
|
1934
2526
|
const { asset, downloader, installDir, version } = layout;
|
|
1935
|
-
const stagingDir =
|
|
1936
|
-
const archivePath =
|
|
1937
|
-
const extractDir =
|
|
2527
|
+
const stagingDir = join11(installDir, ".staging", randomUUID());
|
|
2528
|
+
const archivePath = join11(stagingDir, basename3(asset.url));
|
|
2529
|
+
const extractDir = join11(stagingDir, "extract");
|
|
1938
2530
|
try {
|
|
1939
2531
|
await mkdir(extractDir, { recursive: true });
|
|
1940
2532
|
const bytes = await downloader(asset);
|
|
@@ -1948,13 +2540,13 @@ async function installAsset(layout) {
|
|
|
1948
2540
|
await writeFile(archivePath, bytes);
|
|
1949
2541
|
await extractTarGz(archivePath, extractDir);
|
|
1950
2542
|
const destination = await installExtractedBundle(extractDir, installDir, asset.executableName);
|
|
1951
|
-
await mkdir(
|
|
2543
|
+
await mkdir(join11(installDir, ".provisioned"), { recursive: true });
|
|
1952
2544
|
await writeFile(markerPath(installDir, version), `${JSON.stringify({ binPath: destination, version })}
|
|
1953
2545
|
`);
|
|
1954
2546
|
return destination;
|
|
1955
2547
|
} finally {
|
|
1956
2548
|
await rm(stagingDir, { force: true, recursive: true });
|
|
1957
|
-
await removeEmptyDirectory(
|
|
2549
|
+
await removeEmptyDirectory(join11(installDir, ".staging"));
|
|
1958
2550
|
}
|
|
1959
2551
|
}
|
|
1960
2552
|
async function ensureCodegraphProvisioned(options) {
|
|
@@ -1967,7 +2559,7 @@ async function ensureCodegraphProvisioned(options) {
|
|
|
1967
2559
|
const existing = await readMarker(marker);
|
|
1968
2560
|
if (existing !== null)
|
|
1969
2561
|
return { binPath: existing, provisioned: true };
|
|
1970
|
-
const lockPath =
|
|
2562
|
+
const lockPath = join11(options.lockDir, `codegraph-${hostname()}.lock`);
|
|
1971
2563
|
const release = await acquireLock(lockPath, options.lockWaitMs ?? DEFAULT_LOCK_WAIT_MS, options.lockStaleMs ?? DEFAULT_LOCK_STALE_MS);
|
|
1972
2564
|
if (release === null)
|
|
1973
2565
|
return { error: "timed out waiting for codegraph provisioning lock", provisioned: false };
|
|
@@ -2057,8 +2649,8 @@ async function resolveOrProvisionCommand(deps, config, env, homeDir, nodeSupport
|
|
|
2057
2649
|
return { kind: "unsupported-node" };
|
|
2058
2650
|
if (config.auto_provision === false)
|
|
2059
2651
|
return { error: "codegraph binary unavailable and auto_provision is disabled", kind: "unavailable", source: resolved.source };
|
|
2060
|
-
const installDir = trustedInstallDir ??
|
|
2061
|
-
const provisioned = await deps.ensureProvisioned({ installDir, lockDir:
|
|
2652
|
+
const installDir = trustedInstallDir ?? join12(homeDir, ".omo", "codegraph");
|
|
2653
|
+
const provisioned = await deps.ensureProvisioned({ installDir, lockDir: join12(installDir, ".locks"), version: CODEGRAPH_VERSION });
|
|
2062
2654
|
if (!provisioned.provisioned || provisioned.binPath === undefined) {
|
|
2063
2655
|
return { error: provisioned.error ?? "provisioning did not produce a binary", kind: "unavailable", source: resolved.source };
|
|
2064
2656
|
}
|
|
@@ -2078,7 +2670,7 @@ function decideStartupAction(status) {
|
|
|
2078
2670
|
${status.stderr ?? ""}`.toLowerCase();
|
|
2079
2671
|
if (text.includes("not initialized") || text.includes("uninitialized"))
|
|
2080
2672
|
return { kind: "init" };
|
|
2081
|
-
const initialized = jsonSaysInitialized(
|
|
2673
|
+
const initialized = jsonSaysInitialized(parseJson2(status.stdout));
|
|
2082
2674
|
if (initialized === false)
|
|
2083
2675
|
return { kind: "init" };
|
|
2084
2676
|
if (initialized === true)
|
|
@@ -2088,7 +2680,7 @@ ${status.stderr ?? ""}`.toLowerCase();
|
|
|
2088
2680
|
return { kind: "sync" };
|
|
2089
2681
|
}
|
|
2090
2682
|
function jsonSaysInitialized(value) {
|
|
2091
|
-
if (!
|
|
2683
|
+
if (!isRecord4(value))
|
|
2092
2684
|
return;
|
|
2093
2685
|
const initialized = value["initialized"] ?? value["isInitialized"] ?? value["ready"];
|
|
2094
2686
|
if (typeof initialized === "boolean")
|
|
@@ -2106,7 +2698,7 @@ function jsonSaysInitialized(value) {
|
|
|
2106
2698
|
async function runCodegraphCommand(projectRoot, command, args, options) {
|
|
2107
2699
|
const invocation = resolveCodegraphCommandInvocation(command, args);
|
|
2108
2700
|
return new Promise((resolvePromise) => {
|
|
2109
|
-
|
|
2701
|
+
execFile3(invocation.command, [...invocation.args], { cwd: projectRoot, encoding: "utf8", env: buildCodegraphChildEnv({ ambientEnv: processEnv, codegraphEnv: options.env }), maxBuffer: 1024 * 1024, timeout: options.timeoutMs, windowsHide: true }, (error, stdout, stderr) => {
|
|
2110
2702
|
if (error === null) {
|
|
2111
2703
|
resolvePromise({ exitCode: 0, stderr: toOutputText(stderr), stdout: toOutputText(stdout), timedOut: false });
|
|
2112
2704
|
return;
|
|
@@ -2126,9 +2718,9 @@ function resolveCodegraphCommandInvocation(command, args, platform = process.pla
|
|
|
2126
2718
|
return { args: ["/d", "/s", "/c", command, ...args], command: "cmd.exe" };
|
|
2127
2719
|
}
|
|
2128
2720
|
function appendOutcome(homeDir, outcome) {
|
|
2129
|
-
const logDir =
|
|
2130
|
-
|
|
2131
|
-
appendFileSync2(
|
|
2721
|
+
const logDir = join12(homeDir, ".omo", "codegraph");
|
|
2722
|
+
mkdirSync3(logDir, { recursive: true });
|
|
2723
|
+
appendFileSync2(join12(logDir, "session-start.jsonl"), `${JSON.stringify({ ...outcome, timestamp: new Date().toISOString() })}
|
|
2132
2724
|
`);
|
|
2133
2725
|
}
|
|
2134
2726
|
function safeLogOutcome(logOutcome, outcome) {
|
|
@@ -2145,8 +2737,8 @@ function safeLogOutcome(logOutcome, outcome) {
|
|
|
2145
2737
|
function provisionedBinFromInstallDir(installDir) {
|
|
2146
2738
|
if (installDir === undefined)
|
|
2147
2739
|
return null;
|
|
2148
|
-
const candidate =
|
|
2149
|
-
return
|
|
2740
|
+
const candidate = join12(installDir, "bin", process.platform === "win32" ? "codegraph.cmd" : "codegraph");
|
|
2741
|
+
return existsSync9(candidate) ? candidate : null;
|
|
2150
2742
|
}
|
|
2151
2743
|
function resolveExitCode(error) {
|
|
2152
2744
|
if ("code" in error && typeof error.code === "number")
|
|
@@ -2157,9 +2749,9 @@ function toOutputText(value) {
|
|
|
2157
2749
|
return Buffer.isBuffer(value) ? value.toString("utf8") : value;
|
|
2158
2750
|
}
|
|
2159
2751
|
function resolveHomeDir2(env) {
|
|
2160
|
-
return env["HOME"] ?? env["USERPROFILE"] ??
|
|
2752
|
+
return env["HOME"] ?? env["USERPROFILE"] ?? homedir12();
|
|
2161
2753
|
}
|
|
2162
|
-
function
|
|
2754
|
+
function parseJson2(text) {
|
|
2163
2755
|
try {
|
|
2164
2756
|
return JSON.parse(text);
|
|
2165
2757
|
} catch (error) {
|
|
@@ -2168,7 +2760,7 @@ function parseJson(text) {
|
|
|
2168
2760
|
throw error;
|
|
2169
2761
|
}
|
|
2170
2762
|
}
|
|
2171
|
-
function
|
|
2763
|
+
function isRecord4(value) {
|
|
2172
2764
|
return typeof value === "object" && value !== null;
|
|
2173
2765
|
}
|
|
2174
2766
|
|
|
@@ -2187,9 +2779,24 @@ async function executeCodegraphSessionStartHook(options = {}) {
|
|
|
2187
2779
|
const projectRoot = resolveProjectRoot(input, options.cwd ?? processCwd2());
|
|
2188
2780
|
const homeDir = resolveHomeDir3(env);
|
|
2189
2781
|
const config = options.config ?? getCodexOmoConfig({ cwd: projectRoot, env, homeDir });
|
|
2782
|
+
pruneCodegraphProjectStoresBestEffort(homeDir, { debugLog: writeDebugLog });
|
|
2783
|
+
await sweepCodegraphZombiesBestEffort({
|
|
2784
|
+
env,
|
|
2785
|
+
homeDir,
|
|
2786
|
+
...config.trustedCodegraphInstallDir === undefined ? {} : { trustedCodegraphInstallDir: config.trustedCodegraphInstallDir },
|
|
2787
|
+
log: writeDebugLog
|
|
2788
|
+
}, options.sweepZombies);
|
|
2190
2789
|
if (config.codegraph?.enabled === false) {
|
|
2191
2790
|
return { action: "skipped-disabled", exitCode: 0 };
|
|
2192
2791
|
}
|
|
2792
|
+
const excludedRoots = config.codegraph?.excluded_roots;
|
|
2793
|
+
const exclusion = shouldExcludeCodegraphProject(projectRoot, {
|
|
2794
|
+
homeDir,
|
|
2795
|
+
...excludedRoots === undefined ? {} : { excludedRoots }
|
|
2796
|
+
});
|
|
2797
|
+
if (exclusion.excluded) {
|
|
2798
|
+
return { action: "skipped-excluded", exitCode: 0 };
|
|
2799
|
+
}
|
|
2193
2800
|
const isInitialized = await (options.statusProbe ?? isCodegraphProjectInitialized)({
|
|
2194
2801
|
env,
|
|
2195
2802
|
homeDir,
|
|
@@ -2231,7 +2838,7 @@ async function isCodegraphProjectInitialized(options) {
|
|
|
2231
2838
|
}
|
|
2232
2839
|
function runStatusProbe(projectRoot, command, args, env) {
|
|
2233
2840
|
return new Promise((resolveProbe) => {
|
|
2234
|
-
|
|
2841
|
+
execFile4(command, [...args], {
|
|
2235
2842
|
cwd: projectRoot,
|
|
2236
2843
|
encoding: "utf8",
|
|
2237
2844
|
env,
|
|
@@ -2248,8 +2855,8 @@ function runStatusProbe(projectRoot, command, args, env) {
|
|
|
2248
2855
|
});
|
|
2249
2856
|
}
|
|
2250
2857
|
function codegraphStatusSaysInitialized(stdout) {
|
|
2251
|
-
const parsed =
|
|
2252
|
-
if (!
|
|
2858
|
+
const parsed = parseJson3(stdout);
|
|
2859
|
+
if (!isRecord5(parsed))
|
|
2253
2860
|
return false;
|
|
2254
2861
|
const initialized = parsed["initialized"] ?? parsed["isInitialized"] ?? parsed["ready"];
|
|
2255
2862
|
if (typeof initialized === "boolean")
|
|
@@ -2263,7 +2870,7 @@ function codegraphStatusSaysInitialized(stdout) {
|
|
|
2263
2870
|
function provisionedBinFromInstallDir2(installDir) {
|
|
2264
2871
|
if (installDir === undefined)
|
|
2265
2872
|
return null;
|
|
2266
|
-
return
|
|
2873
|
+
return join13(installDir, "bin", process.platform === "win32" ? "codegraph.cmd" : "codegraph");
|
|
2267
2874
|
}
|
|
2268
2875
|
async function executeCodegraphPostToolUseHook(options = {}) {
|
|
2269
2876
|
const env = options.env ?? processEnv2;
|
|
@@ -2275,9 +2882,9 @@ async function executeCodegraphPostToolUseHook(options = {}) {
|
|
|
2275
2882
|
return { action: "emitted-guidance", exitCode: 0 };
|
|
2276
2883
|
}
|
|
2277
2884
|
function runCodegraphPostToolUseHook(input, options = {}) {
|
|
2278
|
-
const toolName =
|
|
2279
|
-
const cwd =
|
|
2280
|
-
const toolOutput =
|
|
2885
|
+
const toolName = isRecord5(input) ? input["tool_name"] : undefined;
|
|
2886
|
+
const cwd = isRecord5(input) ? input["cwd"] : undefined;
|
|
2887
|
+
const toolOutput = isRecord5(input) ? input["tool_response"] ?? input["tool_output"] ?? input["response"] : input;
|
|
2281
2888
|
const guidance = buildCodegraphInitGuidanceForToolResult({ cwd, toolName, toolOutput }, options);
|
|
2282
2889
|
if (guidance === null)
|
|
2283
2890
|
return "";
|
|
@@ -2299,12 +2906,18 @@ function writeHookJson(stdout) {
|
|
|
2299
2906
|
stdout.write(`${JSON.stringify(output)}
|
|
2300
2907
|
`);
|
|
2301
2908
|
}
|
|
2909
|
+
function writeDebugLog(message) {
|
|
2910
|
+
if (processEnv2["OMO_CODEGRAPH_DEBUG"] !== "1")
|
|
2911
|
+
return;
|
|
2912
|
+
processStderr2.write(`${message}
|
|
2913
|
+
`);
|
|
2914
|
+
}
|
|
2302
2915
|
function spawnDetachedWorker(invocation) {
|
|
2303
2916
|
const child = spawn(invocation.command, [...invocation.args], { detached: true, env: invocation.env, stdio: "ignore" });
|
|
2304
2917
|
child.unref();
|
|
2305
2918
|
}
|
|
2306
2919
|
function resolveHomeDir3(env) {
|
|
2307
|
-
return env["HOME"] ?? env["USERPROFILE"] ??
|
|
2920
|
+
return env["HOME"] ?? env["USERPROFILE"] ?? homedir13();
|
|
2308
2921
|
}
|
|
2309
2922
|
function resolveExitCode2(error) {
|
|
2310
2923
|
if ("code" in error && typeof error.code === "number")
|
|
@@ -2315,7 +2928,7 @@ function toOutputText2(value) {
|
|
|
2315
2928
|
return Buffer.isBuffer(value) ? value.toString("utf8") : value;
|
|
2316
2929
|
}
|
|
2317
2930
|
function resolveProjectRoot(input, fallback) {
|
|
2318
|
-
if (!
|
|
2931
|
+
if (!isRecord5(input))
|
|
2319
2932
|
return fallback;
|
|
2320
2933
|
const cwd = input["cwd"];
|
|
2321
2934
|
return typeof cwd === "string" && cwd.trim().length > 0 ? cwd : fallback;
|
|
@@ -2328,9 +2941,9 @@ async function readHookInput(stdin) {
|
|
|
2328
2941
|
text += typeof chunk === "string" ? chunk : String(chunk);
|
|
2329
2942
|
if (text.trim().length === 0)
|
|
2330
2943
|
return;
|
|
2331
|
-
return
|
|
2944
|
+
return parseJson3(text);
|
|
2332
2945
|
}
|
|
2333
|
-
function
|
|
2946
|
+
function parseJson3(text) {
|
|
2334
2947
|
try {
|
|
2335
2948
|
return JSON.parse(text);
|
|
2336
2949
|
} catch (error) {
|
|
@@ -2339,25 +2952,25 @@ function parseJson2(text) {
|
|
|
2339
2952
|
throw error;
|
|
2340
2953
|
}
|
|
2341
2954
|
}
|
|
2342
|
-
function
|
|
2955
|
+
function isRecord5(value) {
|
|
2343
2956
|
return typeof value === "object" && value !== null;
|
|
2344
2957
|
}
|
|
2345
2958
|
function defaultWorkerCliPath() {
|
|
2346
|
-
return
|
|
2959
|
+
return fileURLToPath2(import.meta.url);
|
|
2347
2960
|
}
|
|
2348
2961
|
|
|
2349
2962
|
// components/codegraph/src/serve.ts
|
|
2350
|
-
import { existsSync as
|
|
2351
|
-
import { homedir as
|
|
2352
|
-
import { basename as basename4, join as
|
|
2963
|
+
import { existsSync as existsSync10, realpathSync as realpathSync5 } from "node:fs";
|
|
2964
|
+
import { homedir as homedir14 } from "node:os";
|
|
2965
|
+
import { basename as basename4, join as join14, resolve as resolve5 } from "node:path";
|
|
2353
2966
|
import {
|
|
2354
2967
|
cwd as processCwd3,
|
|
2355
2968
|
env as processEnv3,
|
|
2356
2969
|
stdin as processStdin2,
|
|
2357
|
-
stderr as
|
|
2970
|
+
stderr as processStderr3,
|
|
2358
2971
|
stdout as processStdout2
|
|
2359
2972
|
} from "node:process";
|
|
2360
|
-
import { fileURLToPath as
|
|
2973
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
2361
2974
|
|
|
2362
2975
|
// components/codegraph/src/mcp-bridge.ts
|
|
2363
2976
|
import { spawn as spawn2 } from "node:child_process";
|
|
@@ -2834,11 +3447,13 @@ var CODEGRAPH_SKIP_HINT = `CodeGraph MCP skipped: codegraph binary not found. In
|
|
|
2834
3447
|
`;
|
|
2835
3448
|
var CODEGRAPH_DISABLED_HINT = `CodeGraph MCP skipped: disabled by OMO SOT config. Set [codex].codegraph.enabled=true to enable it.
|
|
2836
3449
|
`;
|
|
3450
|
+
var CODEGRAPH_EXCLUDED_HINT = `CodeGraph MCP skipped: project excluded by OMO CodeGraph policy.
|
|
3451
|
+
`;
|
|
2837
3452
|
var CODEGRAPH_VERSION2 = "1.0.1";
|
|
2838
3453
|
var PROJECT_CWD_ENV_KEYS = ["OMO_CODEGRAPH_PROJECT_CWD", SESSION_START_CWD_ENV, "PWD"];
|
|
2839
3454
|
async function runCodegraphServe(options = {}) {
|
|
2840
3455
|
const env = options.env ?? processEnv3;
|
|
2841
|
-
const homeDir = options.homeDir ??
|
|
3456
|
+
const homeDir = options.homeDir ?? homedir14();
|
|
2842
3457
|
const wrapperCwd = options.cwd ?? processCwd3();
|
|
2843
3458
|
const projectCwd = resolveProjectCwd(env, wrapperCwd);
|
|
2844
3459
|
const config = options.config ?? getCodexOmoConfig({ cwd: projectCwd, env, homeDir });
|
|
@@ -2846,6 +3461,14 @@ async function runCodegraphServe(options = {}) {
|
|
|
2846
3461
|
if (codegraphConfig.enabled === false) {
|
|
2847
3462
|
return runUnavailableMcp(CODEGRAPH_DISABLED_HINT, options);
|
|
2848
3463
|
}
|
|
3464
|
+
const excludedRoots = codegraphConfig.excluded_roots;
|
|
3465
|
+
const exclusion = shouldExcludeCodegraphProject(projectCwd, {
|
|
3466
|
+
homeDir,
|
|
3467
|
+
...excludedRoots === undefined ? {} : { excludedRoots }
|
|
3468
|
+
});
|
|
3469
|
+
if (exclusion.excluded) {
|
|
3470
|
+
return runUnavailableMcp(CODEGRAPH_EXCLUDED_HINT, options);
|
|
3471
|
+
}
|
|
2849
3472
|
const trustedInstallDir = config.trustedCodegraphInstallDir;
|
|
2850
3473
|
const resolutionOptions = {
|
|
2851
3474
|
env,
|
|
@@ -2854,7 +3477,7 @@ async function runCodegraphServe(options = {}) {
|
|
|
2854
3477
|
};
|
|
2855
3478
|
let resolution = options.resolve?.(resolutionOptions) ?? resolveCodegraphCommand(resolutionOptions);
|
|
2856
3479
|
const nodeSupport = evaluateCodegraphNodeSupport({ env, nodeVersion: options.nodeVersion });
|
|
2857
|
-
if (!resolution.exists || shouldSkipResolvedCommand(resolution, options.commandExists ??
|
|
3480
|
+
if (!resolution.exists || shouldSkipResolvedCommand(resolution, options.commandExists ?? existsSync10)) {
|
|
2858
3481
|
if (resolution.source === "path" && !nodeSupport.supported) {
|
|
2859
3482
|
return runUnavailableMcp(buildCodegraphNodeSkipHint(nodeSupport), options);
|
|
2860
3483
|
}
|
|
@@ -2881,12 +3504,12 @@ async function runCodegraphServe(options = {}) {
|
|
|
2881
3504
|
env: mergedEnv,
|
|
2882
3505
|
input: options.stdin ?? processStdin2,
|
|
2883
3506
|
output: options.stdout ?? processStdout2,
|
|
2884
|
-
stderr: options.stderr ??
|
|
3507
|
+
stderr: options.stderr ?? processStderr3,
|
|
2885
3508
|
stdio: "pipe"
|
|
2886
3509
|
});
|
|
2887
3510
|
}
|
|
2888
3511
|
async function runUnavailableMcp(reason, options) {
|
|
2889
|
-
(options.stderr ??
|
|
3512
|
+
(options.stderr ?? processStderr3).write(reason);
|
|
2890
3513
|
await runUnavailableCodegraphMcpServer({
|
|
2891
3514
|
input: options.stdin ?? processStdin2,
|
|
2892
3515
|
output: options.stdout ?? processStdout2,
|
|
@@ -2900,10 +3523,10 @@ async function provisionMissingCodegraph(options) {
|
|
|
2900
3523
|
return null;
|
|
2901
3524
|
if (options.config.auto_provision === false)
|
|
2902
3525
|
return null;
|
|
2903
|
-
const installDir = options.trustedInstallDir ??
|
|
3526
|
+
const installDir = options.trustedInstallDir ?? join14(options.homeDir, ".omo", "codegraph");
|
|
2904
3527
|
const result = await options.ensureProvisioned({
|
|
2905
3528
|
installDir,
|
|
2906
|
-
lockDir:
|
|
3529
|
+
lockDir: join14(installDir, ".locks"),
|
|
2907
3530
|
version: CODEGRAPH_VERSION2
|
|
2908
3531
|
});
|
|
2909
3532
|
if (!result.provisioned || result.binPath === undefined)
|
|
@@ -2921,7 +3544,7 @@ function looksLikePath2(command) {
|
|
|
2921
3544
|
return command.includes("/") || command.includes("\\");
|
|
2922
3545
|
}
|
|
2923
3546
|
function codegraphEnvForConfig2(trustedInstallDir, homeDir, buildEnv) {
|
|
2924
|
-
const env = buildEnv?.({ homeDir }) ?? buildCodegraphEnv({ homeDir });
|
|
3547
|
+
const env = { ...buildEnv?.({ homeDir }) ?? buildCodegraphEnv({ homeDir }), [CODEGRAPH_NO_DAEMON_ENV]: "1" };
|
|
2925
3548
|
return trustedInstallDir === undefined ? env : { ...env, CODEGRAPH_INSTALL_DIR: trustedInstallDir };
|
|
2926
3549
|
}
|
|
2927
3550
|
function resolveProjectCwd(env, fallback) {
|
|
@@ -2929,24 +3552,24 @@ function resolveProjectCwd(env, fallback) {
|
|
|
2929
3552
|
const candidate = env[key]?.trim();
|
|
2930
3553
|
if (candidate === undefined || candidate.length === 0)
|
|
2931
3554
|
continue;
|
|
2932
|
-
const resolved =
|
|
2933
|
-
if (
|
|
3555
|
+
const resolved = resolve5(candidate);
|
|
3556
|
+
if (existsSync10(resolved))
|
|
2934
3557
|
return resolved;
|
|
2935
3558
|
}
|
|
2936
|
-
return
|
|
3559
|
+
return resolve5(fallback);
|
|
2937
3560
|
}
|
|
2938
3561
|
function provisionedBinFromInstallDir3(installDir) {
|
|
2939
3562
|
if (installDir === undefined)
|
|
2940
3563
|
return null;
|
|
2941
|
-
const candidate =
|
|
2942
|
-
return
|
|
3564
|
+
const candidate = join14(installDir, "bin", process.platform === "win32" ? "codegraph.cmd" : "codegraph");
|
|
3565
|
+
return existsSync10(candidate) ? candidate : null;
|
|
2943
3566
|
}
|
|
2944
3567
|
async function runCodegraphServeCli() {
|
|
2945
3568
|
process.exitCode = await runCodegraphServe();
|
|
2946
3569
|
}
|
|
2947
3570
|
if (isDirectInvocation(process.argv[1])) {
|
|
2948
3571
|
runCodegraphServeCli().catch((error) => {
|
|
2949
|
-
|
|
3572
|
+
processStderr3.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}
|
|
2950
3573
|
`);
|
|
2951
3574
|
process.exitCode = 1;
|
|
2952
3575
|
});
|
|
@@ -2954,11 +3577,68 @@ if (isDirectInvocation(process.argv[1])) {
|
|
|
2954
3577
|
function isDirectInvocation(argvPath) {
|
|
2955
3578
|
if (argvPath === undefined)
|
|
2956
3579
|
return false;
|
|
2957
|
-
const modulePath =
|
|
3580
|
+
const modulePath = fileURLToPath3(import.meta.url);
|
|
2958
3581
|
const moduleName = basename4(modulePath);
|
|
2959
3582
|
if (moduleName !== "serve.js" && moduleName !== "serve.ts")
|
|
2960
3583
|
return false;
|
|
2961
|
-
return
|
|
3584
|
+
return realpathSync5(resolve5(argvPath)) === realpathSync5(modulePath);
|
|
3585
|
+
}
|
|
3586
|
+
|
|
3587
|
+
// components/codegraph/src/sweep-cli.ts
|
|
3588
|
+
async function runCodegraphSweepCli(options = {}) {
|
|
3589
|
+
const args = parseSweepCliArgs(options.argv ?? process.argv);
|
|
3590
|
+
const result = await sweepCodegraphZombies({
|
|
3591
|
+
...options,
|
|
3592
|
+
dryRun: args.dryRun,
|
|
3593
|
+
extraRoots: args.roots,
|
|
3594
|
+
force: args.force,
|
|
3595
|
+
...args.roots.length > 0 ? { ownedRoots: args.roots } : {}
|
|
3596
|
+
});
|
|
3597
|
+
writeSweepReport(options.stdout ?? process.stdout, result);
|
|
3598
|
+
return result.action === "failed" ? 1 : 0;
|
|
3599
|
+
}
|
|
3600
|
+
function parseSweepCliArgs(argv) {
|
|
3601
|
+
const roots = [];
|
|
3602
|
+
let dryRun = false;
|
|
3603
|
+
let force = false;
|
|
3604
|
+
for (let index = 3;index < argv.length; index += 1) {
|
|
3605
|
+
const arg = argv[index];
|
|
3606
|
+
if (arg === "--dry-run") {
|
|
3607
|
+
dryRun = true;
|
|
3608
|
+
continue;
|
|
3609
|
+
}
|
|
3610
|
+
if (arg === "--force") {
|
|
3611
|
+
force = true;
|
|
3612
|
+
continue;
|
|
3613
|
+
}
|
|
3614
|
+
if (arg === "--root") {
|
|
3615
|
+
const value = argv[index + 1];
|
|
3616
|
+
if (value !== undefined && value.trim().length > 0)
|
|
3617
|
+
roots.push(value);
|
|
3618
|
+
index += 1;
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
return { dryRun, force, roots };
|
|
3622
|
+
}
|
|
3623
|
+
function writeSweepReport(stdout, result) {
|
|
3624
|
+
stdout.write(`${JSON.stringify({
|
|
3625
|
+
action: result.action,
|
|
3626
|
+
candidates: result.candidates.map(formatProcess),
|
|
3627
|
+
dryRun: result.dryRun,
|
|
3628
|
+
failed: result.failed,
|
|
3629
|
+
killed: result.killed.map(formatProcess),
|
|
3630
|
+
ownedRoots: result.ownedRoots,
|
|
3631
|
+
stampFile: result.stampFile
|
|
3632
|
+
})}
|
|
3633
|
+
`);
|
|
3634
|
+
}
|
|
3635
|
+
function formatProcess(processInfo) {
|
|
3636
|
+
return {
|
|
3637
|
+
matchKind: processInfo.matchKind,
|
|
3638
|
+
matchedRoot: processInfo.matchedRoot,
|
|
3639
|
+
pid: processInfo.pid,
|
|
3640
|
+
ppid: processInfo.ppid
|
|
3641
|
+
};
|
|
2962
3642
|
}
|
|
2963
3643
|
|
|
2964
3644
|
// components/codegraph/src/cli.ts
|
|
@@ -2966,6 +3646,14 @@ async function runCodegraphCli(options = {}) {
|
|
|
2966
3646
|
const argv = options.argv ?? process.argv;
|
|
2967
3647
|
const command = argv[2];
|
|
2968
3648
|
const subcommand = argv[3];
|
|
3649
|
+
if (command === "sweep") {
|
|
3650
|
+
return runCodegraphSweepCli({
|
|
3651
|
+
...options.sweepOptions,
|
|
3652
|
+
argv,
|
|
3653
|
+
...options.env === undefined ? {} : { env: options.env },
|
|
3654
|
+
...options.stdout === undefined ? {} : { stdout: options.stdout }
|
|
3655
|
+
});
|
|
3656
|
+
}
|
|
2969
3657
|
if (command === "hook" && subcommand === "session-start") {
|
|
2970
3658
|
return runCodegraphSessionStartHook(options);
|
|
2971
3659
|
}
|
|
@@ -2991,7 +3679,7 @@ async function runCodegraphCli(options = {}) {
|
|
|
2991
3679
|
}
|
|
2992
3680
|
if (isDirectInvocation2(process.argv[1])) {
|
|
2993
3681
|
runCodegraphCli().catch((error) => {
|
|
2994
|
-
|
|
3682
|
+
processStderr4.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}
|
|
2995
3683
|
`);
|
|
2996
3684
|
process.exitCode = 1;
|
|
2997
3685
|
});
|
|
@@ -2999,11 +3687,11 @@ if (isDirectInvocation2(process.argv[1])) {
|
|
|
2999
3687
|
function isDirectInvocation2(argvPath) {
|
|
3000
3688
|
if (argvPath === undefined)
|
|
3001
3689
|
return false;
|
|
3002
|
-
const modulePath =
|
|
3690
|
+
const modulePath = fileURLToPath4(import.meta.url);
|
|
3003
3691
|
const moduleName = basename5(modulePath);
|
|
3004
3692
|
if (moduleName !== "cli.js" && moduleName !== "cli.ts")
|
|
3005
3693
|
return false;
|
|
3006
|
-
return
|
|
3694
|
+
return realpathSync6(resolve6(argvPath)) === realpathSync6(modulePath);
|
|
3007
3695
|
}
|
|
3008
3696
|
export {
|
|
3009
3697
|
runCodegraphCli
|