oh-my-opencode 4.18.2 → 4.19.1
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/.agents/command/omomomo.md +1 -1
- package/.agents/skills/omomomo/SKILL.md +1 -1
- package/.opencode/command/omomomo.md +1 -1
- package/README.ja.md +6 -6
- package/README.ko.md +6 -6
- package/README.md +8 -8
- package/README.ru.md +6 -6
- package/README.zh-cn.md +6 -6
- package/dist/agents/atlas/agent.d.ts +7 -6
- package/dist/agents/gpt-prompt-identity.d.ts +3 -0
- package/dist/agents/sisyphus/gpt-5-5.d.ts +1 -1
- package/dist/agents/sisyphus/gpt-task-system-guide.d.ts +1 -0
- package/dist/agents/sisyphus/index.d.ts +5 -0
- package/dist/agents/sisyphus/kimi-k3.d.ts +19 -0
- package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
- package/dist/agents/sisyphus-junior/agent.d.ts +8 -4
- package/dist/agents/sisyphus-junior/gpt-5-5.d.ts +2 -2
- package/dist/agents/sisyphus-junior/index.d.ts +2 -0
- package/dist/agents/sisyphus-junior/kimi-k3.d.ts +12 -0
- package/dist/agents/types.d.ts +2 -2
- package/dist/cli/index.js +781 -215
- package/dist/cli-node/index.js +781 -215
- package/dist/config/index.d.ts +1 -1
- package/dist/config/schema/agent-overrides.d.ts +48 -48
- package/dist/config/schema/browser-automation.d.ts +1 -0
- package/dist/config/schema/categories.d.ts +6 -6
- package/dist/config/schema/codegraph.d.ts +2 -0
- package/dist/config/schema/commands.d.ts +1 -3
- package/dist/config/schema/default-mode.d.ts +1 -1
- package/dist/config/schema/fallback-models.d.ts +5 -5
- package/dist/config/schema/goal.d.ts +7 -0
- package/dist/config/schema/hooks.d.ts +1 -1
- package/dist/config/schema/oh-my-opencode-config.d.ts +56 -58
- package/dist/config/schema/ralph-loop.d.ts +1 -1
- package/dist/config/schema.d.ts +1 -1
- package/dist/create-hooks.d.ts +1 -1
- package/dist/features/builtin-commands/templates/goal.d.ts +1 -0
- package/dist/features/builtin-commands/templates/stop-continuation.d.ts +1 -1
- package/dist/features/builtin-commands/types.d.ts +1 -1
- package/dist/hooks/auto-slash-command/executor.d.ts +1 -0
- package/dist/hooks/codegraph-bootstrap/hook.d.ts +3 -2
- package/dist/hooks/goal/command-arguments.d.ts +13 -0
- package/dist/hooks/goal/controller.d.ts +26 -0
- package/dist/hooks/goal/index.d.ts +23 -0
- package/dist/hooks/goal/prompt.d.ts +3 -0
- package/dist/hooks/goal/store.d.ts +8 -0
- package/dist/hooks/goal/tools.d.ts +10 -0
- package/dist/hooks/goal/types.d.ts +93 -0
- package/dist/hooks/goal/validation.d.ts +4 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/keyword-detector/hook.d.ts +1 -2
- package/dist/hooks/ralph-loop/types.d.ts +1 -1
- package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
- package/dist/hooks/start-work/notepad-scaffold.d.ts +10 -0
- package/dist/index.js +5398 -5109
- package/dist/oh-my-opencode.schema.json +34 -19
- package/dist/plugin/chat-message/loop-commands.d.ts +1 -1
- package/dist/plugin/chat-message/types.d.ts +23 -10
- package/dist/plugin/hooks/create-core-hooks.d.ts +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +3 -2
- package/dist/plugin/hooks/create-transform-hooks.d.ts +0 -2
- package/dist/plugin/stop-continuation.d.ts +2 -2
- package/dist/shared/omo-process-sweep.d.ts +18 -0
- package/dist/shared/system-directive.d.ts +0 -1
- package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
- package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
- package/dist/skills/ulw-plan/SKILL.md +31 -8
- package/dist/skills/ulw-plan/references/full-workflow.md +117 -6
- package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
- package/dist/skills/ulw-research/SKILL.md +3 -3
- package/dist/testing/create-plugin-module.d.ts +1 -0
- package/dist/tools/delegate-task/types.d.ts +0 -1
- package/dist/tui.js +138 -80
- package/package.json +14 -14
- package/packages/git-bash-mcp/dist/cli.js +54 -8
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +60 -0
- package/packages/lsp-core/src/lsp/client.ts +14 -1
- package/packages/lsp-core/src/lsp/fixtures/diagnostics-freshness-contract-probe.ts +2 -2
- package/packages/lsp-core/src/mcp.ts +9 -0
- package/packages/lsp-daemon/dist/cli.js +319 -51
- package/packages/lsp-daemon/dist/client.js +136 -48
- package/packages/lsp-daemon/dist/daemon-client.d.ts +0 -10
- package/packages/lsp-daemon/dist/daemon-client.js +4 -34
- package/packages/lsp-daemon/dist/daemon-failure-result.d.ts +3 -0
- package/packages/lsp-daemon/dist/daemon-failure-result.js +38 -0
- package/packages/lsp-daemon/dist/daemon-request-error.d.ts +14 -0
- package/packages/lsp-daemon/dist/daemon-request-error.js +26 -0
- package/packages/lsp-daemon/dist/daemon-server.js +5 -1
- package/packages/lsp-daemon/dist/index.js +137 -48
- package/packages/lsp-daemon/dist/proxy.d.ts +2 -0
- package/packages/lsp-daemon/dist/proxy.js +1 -0
- package/packages/lsp-daemon/dist/version-reap.d.ts +26 -0
- package/packages/lsp-daemon/dist/version-reap.js +182 -0
- package/packages/lsp-tools-mcp/dist/cli.js +61 -10
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +6 -1
- package/packages/lsp-tools-mcp/dist/mcp.js +61 -10
- package/packages/lsp-tools-mcp/dist/tools.js +6 -1
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +416 -25
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +22 -2
- package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +7 -6
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +638 -267
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +178 -89
- package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
- package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +3 -1
- package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +3 -1
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +98 -32
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +5 -0
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +15 -6
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +6 -2
- package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +1 -1
- package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +148 -0
- package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +31 -2
- package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +1 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +65 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +3 -7
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +1 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +57 -3
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +41 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +109 -8
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +2 -2
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +43 -0
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/AGENTS.md +1 -0
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +80 -40
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +11 -0
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +11 -0
- package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +60 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +8 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +147 -60
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/src/boulder-reader.ts +3 -71
- package/packages/omo-codex/plugin/components/start-work-continuation/src/plan-checklist.ts +171 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/boulder-reader.test.ts +198 -23
- package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +4 -3
- package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +6 -5
- package/packages/omo-codex/plugin/components/start-work-continuation/test/fixtures/plan-scaffold.md +15 -0
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +10 -10
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +3 -3
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +31 -8
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +117 -6
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
- package/packages/omo-codex/plugin/components/ultrawork/src/codex-hook.ts +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +42 -0
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +6 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.d.ts +21 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +64 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +15 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.d.ts +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +85 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +0 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +13 -33
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +998 -593
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.js +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +4 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +10 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.d.ts +15 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.js +84 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.d.ts +5 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.js +81 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +7 -59
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +12 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.d.ts +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.js +122 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- 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 +8 -6
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +84 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +13 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +49 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +13 -45
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/goal-status.ts +4 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +4 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +20 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-batch.ts +125 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-mutations.ts +59 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +6 -58
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +12 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/validation-batch.ts +122 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +76 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +111 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +67 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +57 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering-batch.test.ts +152 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +29 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch-checkpoint.test.ts +147 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch.test.ts +73 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +2 -2
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +2 -2
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +2 -2
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +41 -41
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +32 -28
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +17 -45
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/toml-section-editor.mjs +455 -0
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +3 -18
- package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +43 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +8 -6
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +31 -8
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +117 -6
- package/packages/omo-codex/plugin/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +11 -11
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +26 -0
- package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +41 -0
- package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +2 -2
- package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +6 -6
- package/packages/omo-codex/plugin/test/multi-agent-v2-regression.test.mjs +3 -3
- package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +62 -0
- package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +271 -14
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +3 -18
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +0 -5
- package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +293 -0
- package/packages/omo-codex/scripts/install-config.test.mjs +10 -10
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +401 -22
- package/packages/omo-codex/scripts/install-generated-bundle.test.mjs +39 -2
- package/packages/omo-codex/scripts/install-marketplace-cache.test.mjs +4 -1
- package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +31 -8
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +117 -6
- package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
- package/packages/shared-skills/skills/ulw-research/SKILL.md +3 -3
- package/dist/features/builtin-commands/templates/ralph-loop.d.ts +0 -3
- package/dist/skills/ultraresearch/SKILL.md +0 -10
- package/packages/shared-skills/skills/lcx-contribute-bug-fix/SKILL.md +0 -273
- package/packages/shared-skills/skills/lcx-contribute-bug-fix/agents/openai.yaml +0 -12
- package/packages/shared-skills/skills/lcx-contribute-bug-fix/scripts/create-pr-body.mjs +0 -107
- package/packages/shared-skills/skills/lcx-doctor/SKILL.md +0 -128
- package/packages/shared-skills/skills/lcx-doctor/agents/openai.yaml +0 -11
- package/packages/shared-skills/skills/lcx-report-bug/SKILL.md +0 -268
- package/packages/shared-skills/skills/lcx-report-bug/agents/openai.yaml +0 -11
- package/packages/shared-skills/skills/ultraresearch/SKILL.md +0 -10
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/SKILL.md +0 -0
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/agents/openai.yaml +0 -0
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/scripts/create-pr-body.mjs +0 -0
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-doctor/SKILL.md +0 -0
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-doctor/agents/openai.yaml +0 -0
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-report-bug/SKILL.md +0 -0
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-report-bug/agents/openai.yaml +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
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
|
|
4
|
+
import { realpathSync as realpathSync7 } from "node:fs";
|
|
5
|
+
import { basename as basename5, resolve as resolve8 } from "node:path";
|
|
6
6
|
import { stderr as processStderr4 } from "node:process";
|
|
7
7
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
8
8
|
|
|
9
9
|
// components/codegraph/src/hook.ts
|
|
10
10
|
import { execFile as execFile4, spawn } from "node:child_process";
|
|
11
11
|
import { homedir as homedir13 } from "node:os";
|
|
12
|
-
import { join as
|
|
12
|
+
import { join as join14 } from "node:path";
|
|
13
13
|
import {
|
|
14
14
|
cwd as processCwd2,
|
|
15
15
|
env as processEnv2,
|
|
@@ -56,6 +56,7 @@ var SAFE_AMBIENT_ENV_KEYS = new Set([
|
|
|
56
56
|
var SAFE_CODEGRAPH_RUNTIME_ENV_KEYS = new Set([
|
|
57
57
|
"CODEGRAPH_ALLOW_UNSAFE_NODE",
|
|
58
58
|
"CODEGRAPH_BIN",
|
|
59
|
+
"CODEGRAPH_DAEMON_IDLE_TIMEOUT_MS",
|
|
59
60
|
"CODEGRAPH_FAKE_LOG",
|
|
60
61
|
"CODEGRAPH_NO_DAEMON",
|
|
61
62
|
"CODEGRAPH_NODE_BIN",
|
|
@@ -67,7 +68,7 @@ function buildCodegraphEnv(options = {}) {
|
|
|
67
68
|
const homeDir = options.homeDir ?? homedir();
|
|
68
69
|
return {
|
|
69
70
|
[CODEGRAPH_INSTALL_DIR_ENV]: join(homeDir, ".omo", "codegraph"),
|
|
70
|
-
[CODEGRAPH_NO_DAEMON_ENV]: "1",
|
|
71
|
+
...options.daemon === true ? {} : { [CODEGRAPH_NO_DAEMON_ENV]: "1" },
|
|
71
72
|
[CODEGRAPH_NO_DOWNLOAD_ENV]: "1",
|
|
72
73
|
[CODEGRAPH_TELEMETRY_ENV]: "0",
|
|
73
74
|
[DO_NOT_TRACK_ENV]: "1"
|
|
@@ -98,8 +99,9 @@ function buildCodegraphChildEnv(options = {}) {
|
|
|
98
99
|
import { homedir as homedir5 } from "node:os";
|
|
99
100
|
|
|
100
101
|
// ../../utils/src/codegraph/workspace.ts
|
|
102
|
+
import { execFileSync } from "node:child_process";
|
|
101
103
|
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";
|
|
104
|
+
import { dirname, join as join5, resolve as resolve3 } from "node:path";
|
|
103
105
|
|
|
104
106
|
// ../../utils/src/codegraph/paths.ts
|
|
105
107
|
import { createHash } from "node:crypto";
|
|
@@ -305,12 +307,52 @@ function prepareCodegraphWorkspace(workspace, options = {}) {
|
|
|
305
307
|
}
|
|
306
308
|
}
|
|
307
309
|
function ensureCodegraphGitignored(workspace) {
|
|
308
|
-
const
|
|
309
|
-
if (!existsSync2(
|
|
310
|
+
const gitMarkerPath = join5(workspace, ".git");
|
|
311
|
+
if (!existsSync2(gitMarkerPath))
|
|
310
312
|
return false;
|
|
311
|
-
const excludePath = join5(gitDir, "info", "exclude");
|
|
312
313
|
try {
|
|
313
|
-
|
|
314
|
+
const isWorktree = execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
315
|
+
cwd: workspace,
|
|
316
|
+
encoding: "utf8",
|
|
317
|
+
shell: false,
|
|
318
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
319
|
+
timeout: 5000,
|
|
320
|
+
windowsHide: true
|
|
321
|
+
}).trim();
|
|
322
|
+
if (isWorktree !== "true")
|
|
323
|
+
return false;
|
|
324
|
+
const gitTopLevel = execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
325
|
+
cwd: workspace,
|
|
326
|
+
encoding: "utf8",
|
|
327
|
+
shell: false,
|
|
328
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
329
|
+
timeout: 5000,
|
|
330
|
+
windowsHide: true
|
|
331
|
+
}).trim();
|
|
332
|
+
if (gitTopLevel.length === 0 || realpathSync3.native(gitTopLevel) !== realpathSync3.native(workspace))
|
|
333
|
+
return false;
|
|
334
|
+
const gitDir = execFileSync("git", ["rev-parse", "--absolute-git-dir"], {
|
|
335
|
+
cwd: workspace,
|
|
336
|
+
encoding: "utf8",
|
|
337
|
+
shell: false,
|
|
338
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
339
|
+
timeout: 5000,
|
|
340
|
+
windowsHide: true
|
|
341
|
+
}).trim();
|
|
342
|
+
if (gitDir.length === 0 || !gitMarkerOwnsGitDir(gitMarkerPath, workspace, gitDir))
|
|
343
|
+
return false;
|
|
344
|
+
const gitExcludePath = execFileSync("git", ["rev-parse", "--git-path", "info/exclude"], {
|
|
345
|
+
cwd: workspace,
|
|
346
|
+
encoding: "utf8",
|
|
347
|
+
shell: false,
|
|
348
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
349
|
+
timeout: 5000,
|
|
350
|
+
windowsHide: true
|
|
351
|
+
}).trim();
|
|
352
|
+
if (gitExcludePath.length === 0)
|
|
353
|
+
return false;
|
|
354
|
+
const excludePath = resolve3(workspace, gitExcludePath);
|
|
355
|
+
mkdirSync(dirname(excludePath), { recursive: true });
|
|
314
356
|
const existing = existsSync2(excludePath) ? readFileSync2(excludePath, "utf8") : "";
|
|
315
357
|
if (existing.split(/\r?\n/).includes(".codegraph"))
|
|
316
358
|
return true;
|
|
@@ -319,12 +361,38 @@ function ensureCodegraphGitignored(workspace) {
|
|
|
319
361
|
`}.codegraph
|
|
320
362
|
`);
|
|
321
363
|
return true;
|
|
322
|
-
} catch
|
|
323
|
-
|
|
324
|
-
return false;
|
|
325
|
-
throw error;
|
|
364
|
+
} catch {
|
|
365
|
+
return false;
|
|
326
366
|
}
|
|
327
367
|
}
|
|
368
|
+
function gitMarkerOwnsGitDir(gitMarkerPath, workspace, gitDir) {
|
|
369
|
+
const markerStat = lstatSync2(gitMarkerPath);
|
|
370
|
+
if (markerStat.isSymbolicLink())
|
|
371
|
+
return false;
|
|
372
|
+
const resolvedGitDir = realpathSync3.native(gitDir);
|
|
373
|
+
if (markerStat.isDirectory())
|
|
374
|
+
return realpathSync3.native(gitMarkerPath) === resolvedGitDir;
|
|
375
|
+
if (!markerStat.isFile())
|
|
376
|
+
return false;
|
|
377
|
+
const markerMatch = /^gitdir:\s*(.+)\s*$/i.exec(readFileSync2(gitMarkerPath, "utf8").trim());
|
|
378
|
+
if (markerMatch?.[1] === undefined)
|
|
379
|
+
return false;
|
|
380
|
+
if (realpathSync3.native(resolve3(workspace, markerMatch[1])) !== resolvedGitDir)
|
|
381
|
+
return false;
|
|
382
|
+
const backlinkPath = join5(resolvedGitDir, "gitdir");
|
|
383
|
+
if (existsSync2(backlinkPath)) {
|
|
384
|
+
const backlink = readFileSync2(backlinkPath, "utf8").trim();
|
|
385
|
+
return backlink.length > 0 && realpathSync3.native(resolve3(resolvedGitDir, backlink)) === realpathSync3.native(gitMarkerPath);
|
|
386
|
+
}
|
|
387
|
+
const coreWorktree = execFileSync("git", ["config", "--file", join5(resolvedGitDir, "config"), "--get", "core.worktree"], {
|
|
388
|
+
encoding: "utf8",
|
|
389
|
+
shell: false,
|
|
390
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
391
|
+
timeout: 5000,
|
|
392
|
+
windowsHide: true
|
|
393
|
+
}).trim();
|
|
394
|
+
return coreWorktree.length > 0 && realpathSync3.native(resolve3(resolvedGitDir, coreWorktree)) === realpathSync3.native(workspace);
|
|
395
|
+
}
|
|
328
396
|
|
|
329
397
|
// ../../utils/src/codegraph/guidance.ts
|
|
330
398
|
var CODEGRAPH_UNINITIALIZED_PATTERN = /CodeGraph not initialized in ([\s\S]*?)\.\s*Run ['`]codegraph init['`] in that project first\./i;
|
|
@@ -332,6 +400,9 @@ var ANSI_ESCAPE_PATTERN = /\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g;
|
|
|
332
400
|
var CODEGRAPH_STATUS_PROJECT_PATTERN = /^.*?\bProject:\s*(.+?)\s*$/im;
|
|
333
401
|
var CODEGRAPH_STATUS_UNINITIALIZED_PATTERN = /^.*?\bNot initialized\s*$/im;
|
|
334
402
|
var CODEGRAPH_INIT_HINT_PATTERN = /Run\s+["'`]codegraph init["'`]\s+(?:in that project first|to initialize)\.?/i;
|
|
403
|
+
var CODEGRAPH_PROJECT_NOT_INDEXED_PATTERN = /The project at (.+?) isn't indexed with codegraph\b/i;
|
|
404
|
+
var CODEGRAPH_NO_PROJECT_LOADED_PATTERN = /No CodeGraph project is loaded for this session\./i;
|
|
405
|
+
var CODEGRAPH_NO_PROJECT_SEARCHED_FROM_PATTERN = /^Searched for a \.codegraph\/ directory starting from:\s*(.+?)\s*$/im;
|
|
335
406
|
function getCodegraphUninitializedProject(input) {
|
|
336
407
|
const output = textFromUnknown(input.toolOutput);
|
|
337
408
|
if (!isCodegraphTool(input.toolName))
|
|
@@ -372,6 +443,16 @@ function extractProjectPath(output) {
|
|
|
372
443
|
const uninitializedProject = uninitializedMatch?.[1]?.trim();
|
|
373
444
|
if (uninitializedProject && uninitializedProject.length > 0)
|
|
374
445
|
return uninitializedProject;
|
|
446
|
+
const notIndexedMatch = normalizedOutput.match(CODEGRAPH_PROJECT_NOT_INDEXED_PATTERN);
|
|
447
|
+
const notIndexedProject = notIndexedMatch?.[1]?.trim();
|
|
448
|
+
if (notIndexedProject && notIndexedProject.length > 0)
|
|
449
|
+
return notIndexedProject;
|
|
450
|
+
if (CODEGRAPH_NO_PROJECT_LOADED_PATTERN.test(normalizedOutput)) {
|
|
451
|
+
const searchedFromMatch = normalizedOutput.match(CODEGRAPH_NO_PROJECT_SEARCHED_FROM_PATTERN);
|
|
452
|
+
const searchedFromProject = searchedFromMatch?.[1]?.trim();
|
|
453
|
+
if (searchedFromProject && searchedFromProject.length > 0)
|
|
454
|
+
return searchedFromProject;
|
|
455
|
+
}
|
|
375
456
|
if (!looksLikeCodegraphUninitializedOutput(normalizedOutput))
|
|
376
457
|
return null;
|
|
377
458
|
const statusMatch = normalizedOutput.match(CODEGRAPH_STATUS_PROJECT_PATTERN);
|
|
@@ -416,7 +497,7 @@ function isRecord(value) {
|
|
|
416
497
|
import { existsSync as existsSync3 } from "node:fs";
|
|
417
498
|
import { homedir as homedir6 } from "node:os";
|
|
418
499
|
import { spawnSync } from "node:child_process";
|
|
419
|
-
import { basename as basename2, dirname, join as join7 } from "node:path";
|
|
500
|
+
import { basename as basename2, dirname as dirname2, join as join7 } from "node:path";
|
|
420
501
|
import { createRequire } from "node:module";
|
|
421
502
|
|
|
422
503
|
// ../../utils/src/runtime/which.ts
|
|
@@ -603,7 +684,7 @@ function defaultProvisionedBin(homeDir, fileExists) {
|
|
|
603
684
|
function resolveBundledShim(requireResolve, fileExists) {
|
|
604
685
|
try {
|
|
605
686
|
const packageJson = requireResolve(`${CODEGRAPH_PACKAGE}/package.json`);
|
|
606
|
-
const packageRoot =
|
|
687
|
+
const packageRoot = dirname2(packageJson);
|
|
607
688
|
const candidates = [join7(packageRoot, "bin", "codegraph.js"), join7(packageRoot, "npm-shim.js")];
|
|
608
689
|
return candidates.find((candidate) => fileExists(candidate)) ?? null;
|
|
609
690
|
} catch (error) {
|
|
@@ -1530,8 +1611,9 @@ function parseJsoncSafe(content) {
|
|
|
1530
1611
|
var HARNESS_IDS = ["codex", "opencode", "omo"];
|
|
1531
1612
|
var SETTING_HARNESS_SUPPORT = {
|
|
1532
1613
|
"codegraph.auto_provision": HARNESS_IDS,
|
|
1614
|
+
"codegraph.daemon": ["codex", "opencode"],
|
|
1533
1615
|
"codegraph.enabled": HARNESS_IDS,
|
|
1534
|
-
"codegraph.excluded_roots": ["codex"],
|
|
1616
|
+
"codegraph.excluded_roots": ["codex", "opencode"],
|
|
1535
1617
|
"codegraph.install_dir": HARNESS_IDS,
|
|
1536
1618
|
"codegraph.telemetry": HARNESS_IDS,
|
|
1537
1619
|
"codegraph.watch_debounce_ms": ["opencode", "omo"]
|
|
@@ -1548,6 +1630,7 @@ var BUILT_IN_DEFAULTS = {
|
|
|
1548
1630
|
var HARNESS_BLOCK_KEYS = HARNESS_IDS.map((harness) => `[${harness}]`);
|
|
1549
1631
|
var CODEGRAPH_SETTING_KEYS = [
|
|
1550
1632
|
"auto_provision",
|
|
1633
|
+
"daemon",
|
|
1551
1634
|
"enabled",
|
|
1552
1635
|
"excluded_roots",
|
|
1553
1636
|
"install_dir",
|
|
@@ -1621,6 +1704,10 @@ function setCodegraphSetting(config, key, value) {
|
|
|
1621
1704
|
if (typeof value === "boolean")
|
|
1622
1705
|
config.auto_provision = value;
|
|
1623
1706
|
return;
|
|
1707
|
+
case "daemon":
|
|
1708
|
+
if (typeof value === "boolean")
|
|
1709
|
+
config.daemon = value;
|
|
1710
|
+
return;
|
|
1624
1711
|
case "enabled":
|
|
1625
1712
|
if (typeof value === "boolean")
|
|
1626
1713
|
config.enabled = value;
|
|
@@ -1819,14 +1906,14 @@ function buildEnvOverrides(harness, env, warnings, merge) {
|
|
|
1819
1906
|
|
|
1820
1907
|
// ../../utils/src/omo-config/resolve.ts
|
|
1821
1908
|
import { existsSync as existsSync4 } from "node:fs";
|
|
1822
|
-
import { dirname as
|
|
1909
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join8, relative, resolve as resolve4 } from "node:path";
|
|
1823
1910
|
function containsPath(parent, child) {
|
|
1824
1911
|
const pathToChild = relative(parent, child);
|
|
1825
1912
|
return pathToChild === "" || !pathToChild.startsWith("..") && !isAbsolute2(pathToChild);
|
|
1826
1913
|
}
|
|
1827
1914
|
function findProjectConfigPathsNearestFirst(cwd, homeDir) {
|
|
1828
|
-
const startDir =
|
|
1829
|
-
const stopBeforeDir = containsPath(
|
|
1915
|
+
const startDir = resolve4(cwd);
|
|
1916
|
+
const stopBeforeDir = containsPath(resolve4(homeDir), startDir) ? resolve4(homeDir) : null;
|
|
1830
1917
|
const paths = [];
|
|
1831
1918
|
let currentDir = startDir;
|
|
1832
1919
|
while (true) {
|
|
@@ -1836,7 +1923,7 @@ function findProjectConfigPathsNearestFirst(cwd, homeDir) {
|
|
|
1836
1923
|
if (existsSync4(configPath)) {
|
|
1837
1924
|
paths.push(configPath);
|
|
1838
1925
|
}
|
|
1839
|
-
const parentDir =
|
|
1926
|
+
const parentDir = dirname3(currentDir);
|
|
1840
1927
|
if (parentDir === currentDir)
|
|
1841
1928
|
break;
|
|
1842
1929
|
currentDir = parentDir;
|
|
@@ -1844,7 +1931,7 @@ function findProjectConfigPathsNearestFirst(cwd, homeDir) {
|
|
|
1844
1931
|
return paths;
|
|
1845
1932
|
}
|
|
1846
1933
|
function resolveOmoConfigPaths(options) {
|
|
1847
|
-
const globalPath = join8(
|
|
1934
|
+
const globalPath = join8(resolve4(options.homeDir), ".omo", "config.jsonc");
|
|
1848
1935
|
const projectPathsFarthestFirst = findProjectConfigPathsNearestFirst(options.cwd, options.homeDir).reverse();
|
|
1849
1936
|
return [
|
|
1850
1937
|
{ path: globalPath, scope: "global" },
|
|
@@ -1940,77 +2027,131 @@ function isNonFatalCodegraphGcError(error) {
|
|
|
1940
2027
|
|
|
1941
2028
|
// components/codegraph/src/hook-sweep.ts
|
|
1942
2029
|
import { fileURLToPath } from "node:url";
|
|
1943
|
-
// ../../utils/src/
|
|
2030
|
+
// ../../utils/src/process-sweep/sweeper.ts
|
|
1944
2031
|
import { existsSync as existsSync7, mkdirSync as mkdirSync2, statSync as statSync2, utimesSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1945
2032
|
import { homedir as homedir10 } from "node:os";
|
|
1946
|
-
import { dirname as
|
|
2033
|
+
import { dirname as dirname5, join as join11 } from "node:path";
|
|
1947
2034
|
|
|
1948
|
-
// ../../utils/src/codegraph/
|
|
1949
|
-
import {
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
2035
|
+
// ../../utils/src/codegraph/daemon-lock.ts
|
|
2036
|
+
import { readFileSync as readFileSync4, realpathSync as realpathSync4 } from "node:fs";
|
|
2037
|
+
import { dirname as dirname4, join as join9, resolve as resolve5 } from "node:path";
|
|
2038
|
+
function parseDaemonLock(raw) {
|
|
2039
|
+
const trimmed = raw.trim();
|
|
2040
|
+
if (trimmed.length === 0)
|
|
2041
|
+
return null;
|
|
2042
|
+
try {
|
|
2043
|
+
const parsed = JSON.parse(trimmed);
|
|
2044
|
+
if (typeof parsed === "object" && parsed !== null && "pid" in parsed) {
|
|
2045
|
+
const pid = parsed.pid;
|
|
2046
|
+
if (typeof pid === "number" && Number.isSafeInteger(pid) && pid > 0) {
|
|
2047
|
+
const record = parsed;
|
|
2048
|
+
return {
|
|
2049
|
+
pid,
|
|
2050
|
+
...typeof record["socketPath"] === "string" ? { socketPath: record["socketPath"] } : {},
|
|
2051
|
+
...typeof record["startedAt"] === "number" ? { startedAt: record["startedAt"] } : {},
|
|
2052
|
+
...typeof record["version"] === "string" ? { version: record["version"] } : {}
|
|
2053
|
+
};
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
return null;
|
|
2057
|
+
} catch (error) {
|
|
2058
|
+
if (!(error instanceof SyntaxError))
|
|
2059
|
+
throw error;
|
|
1967
2060
|
}
|
|
1968
|
-
|
|
2061
|
+
const legacyPid = Number(trimmed);
|
|
2062
|
+
if (Number.isSafeInteger(legacyPid) && legacyPid > 0)
|
|
2063
|
+
return { pid: legacyPid };
|
|
2064
|
+
return null;
|
|
1969
2065
|
}
|
|
1970
|
-
function
|
|
1971
|
-
const
|
|
1972
|
-
const
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
2066
|
+
function daemonLockCandidates(projectRoot) {
|
|
2067
|
+
const dirs = new Set;
|
|
2068
|
+
const resolved = resolve5(projectRoot);
|
|
2069
|
+
collectAncestors(resolved, dirs);
|
|
2070
|
+
collectAncestors(realpathIfPossible2(resolved), dirs);
|
|
2071
|
+
return [...dirs].map((dir) => join9(dir, ".codegraph", "daemon.pid"));
|
|
2072
|
+
}
|
|
2073
|
+
function evaluateDaemonStaleness(pid, projectRoot) {
|
|
2074
|
+
let sawLock = false;
|
|
2075
|
+
for (const lockPath of daemonLockCandidates(projectRoot)) {
|
|
2076
|
+
const raw = readLockIfPresent(lockPath);
|
|
2077
|
+
if (raw === undefined)
|
|
1981
2078
|
continue;
|
|
1982
|
-
|
|
2079
|
+
if (raw === null)
|
|
2080
|
+
return { stale: false, reason: "lock-unreadable" };
|
|
2081
|
+
sawLock = true;
|
|
2082
|
+
const lock = parseDaemonLock(raw);
|
|
2083
|
+
if (lock === null)
|
|
2084
|
+
return { stale: false, reason: "lock-unparseable" };
|
|
2085
|
+
if (lock.pid === pid)
|
|
2086
|
+
return { stale: false, reason: "lock-pid-match" };
|
|
2087
|
+
}
|
|
2088
|
+
return sawLock ? { stale: true, reason: "lock-pid-mismatch" } : { stale: true, reason: "lock-absent" };
|
|
2089
|
+
}
|
|
2090
|
+
function readLockIfPresent(lockPath) {
|
|
2091
|
+
try {
|
|
2092
|
+
return readFileSync4(lockPath, "utf8");
|
|
2093
|
+
} catch (error) {
|
|
2094
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
2095
|
+
return;
|
|
2096
|
+
if (error instanceof Error && "code" in error && error.code === "ENOTDIR")
|
|
2097
|
+
return;
|
|
2098
|
+
return null;
|
|
1983
2099
|
}
|
|
1984
|
-
return processes;
|
|
1985
2100
|
}
|
|
1986
|
-
function
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
continue;
|
|
1995
|
-
if (!isOrphaned(processInfo, livePids))
|
|
1996
|
-
continue;
|
|
1997
|
-
zombies.push({ ...processInfo, matchedRoot: match.root, matchKind: match.kind });
|
|
2101
|
+
function collectAncestors(start, output) {
|
|
2102
|
+
let current = start;
|
|
2103
|
+
for (;; ) {
|
|
2104
|
+
output.add(current);
|
|
2105
|
+
const parent = dirname4(current);
|
|
2106
|
+
if (parent === current)
|
|
2107
|
+
return;
|
|
2108
|
+
current = parent;
|
|
1998
2109
|
}
|
|
1999
|
-
return zombies;
|
|
2000
2110
|
}
|
|
2001
|
-
function
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2111
|
+
function realpathIfPossible2(path) {
|
|
2112
|
+
try {
|
|
2113
|
+
return realpathSync4(path);
|
|
2114
|
+
} catch (error) {
|
|
2115
|
+
if (error instanceof Error)
|
|
2116
|
+
return path;
|
|
2117
|
+
throw error;
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
// ../../utils/src/process-sweep/command-match.ts
|
|
2122
|
+
import { posix, win32 } from "node:path";
|
|
2123
|
+
function splitCommandTokens(command) {
|
|
2124
|
+
const tokens = [];
|
|
2125
|
+
let current = "";
|
|
2126
|
+
let quote = null;
|
|
2127
|
+
let tokenStarted = false;
|
|
2128
|
+
for (const char of command) {
|
|
2129
|
+
if (quote !== null) {
|
|
2130
|
+
if (char === quote) {
|
|
2131
|
+
quote = null;
|
|
2132
|
+
} else {
|
|
2133
|
+
current += char;
|
|
2134
|
+
}
|
|
2135
|
+
continue;
|
|
2136
|
+
}
|
|
2137
|
+
if (char === '"' || char === "'") {
|
|
2138
|
+
quote = char;
|
|
2139
|
+
tokenStarted = true;
|
|
2140
|
+
continue;
|
|
2141
|
+
}
|
|
2142
|
+
if (/\s/.test(char)) {
|
|
2143
|
+
if (tokenStarted || current.length > 0) {
|
|
2144
|
+
tokens.push(current);
|
|
2145
|
+
current = "";
|
|
2146
|
+
tokenStarted = false;
|
|
2147
|
+
}
|
|
2005
2148
|
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
2149
|
}
|
|
2150
|
+
current += char;
|
|
2012
2151
|
}
|
|
2013
|
-
|
|
2152
|
+
if (tokenStarted || current.length > 0)
|
|
2153
|
+
tokens.push(current);
|
|
2154
|
+
return tokens;
|
|
2014
2155
|
}
|
|
2015
2156
|
function hasExecutableToken(command, expectedPath) {
|
|
2016
2157
|
let searchFrom = 0;
|
|
@@ -2026,24 +2167,19 @@ function hasExecutableToken(command, expectedPath) {
|
|
|
2026
2167
|
}
|
|
2027
2168
|
}
|
|
2028
2169
|
function tokenLooksExecutable(command, tokenStart) {
|
|
2029
|
-
|
|
2170
|
+
let prefix = command.slice(0, tokenStart).trimEnd();
|
|
2030
2171
|
if (prefix.length === 0)
|
|
2031
2172
|
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
2173
|
for (;; ) {
|
|
2040
|
-
const
|
|
2041
|
-
|
|
2174
|
+
const previousTokenStart = findTokenStart(prefix, prefix.length - 1);
|
|
2175
|
+
const previousToken = prefix.slice(previousTokenStart);
|
|
2176
|
+
if (!previousToken.startsWith("-")) {
|
|
2177
|
+
const executableName = previousToken.split("/").at(-1) ?? previousToken;
|
|
2178
|
+
return /^node\d*(\.exe)?$/i.test(executableName) || /^bun(\.exe)?$/i.test(executableName);
|
|
2179
|
+
}
|
|
2180
|
+
prefix = prefix.slice(0, previousTokenStart).trimEnd();
|
|
2181
|
+
if (prefix.length === 0)
|
|
2042
2182
|
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
2183
|
}
|
|
2048
2184
|
}
|
|
2049
2185
|
function findTokenStart(command, index) {
|
|
@@ -2077,6 +2213,39 @@ function normalizeForComparison2(value, platform) {
|
|
|
2077
2213
|
const normalized = value.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
2078
2214
|
return platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
2079
2215
|
}
|
|
2216
|
+
|
|
2217
|
+
// ../../utils/src/process-sweep/process-table.ts
|
|
2218
|
+
function parsePosixProcessTable(output) {
|
|
2219
|
+
const processes = [];
|
|
2220
|
+
for (const line of output.split(/\r?\n/)) {
|
|
2221
|
+
const match = /^\s*(\d+)\s+(\d+)\s+(.+?)\s*$/.exec(line);
|
|
2222
|
+
if (match === null)
|
|
2223
|
+
continue;
|
|
2224
|
+
const pid = Number(match[1]);
|
|
2225
|
+
const ppid = Number(match[2]);
|
|
2226
|
+
const command = match[3];
|
|
2227
|
+
if (!isValidProcessId(pid) || !Number.isInteger(ppid) || ppid < 0 || command === undefined)
|
|
2228
|
+
continue;
|
|
2229
|
+
processes.push({ command, pid, ppid });
|
|
2230
|
+
}
|
|
2231
|
+
return processes;
|
|
2232
|
+
}
|
|
2233
|
+
function parseWindowsProcessTable(output) {
|
|
2234
|
+
const parsed = parseJson(output);
|
|
2235
|
+
const entries = Array.isArray(parsed) ? parsed : parsed === undefined ? [] : [parsed];
|
|
2236
|
+
const processes = [];
|
|
2237
|
+
for (const entry of entries) {
|
|
2238
|
+
if (!isRecord3(entry))
|
|
2239
|
+
continue;
|
|
2240
|
+
const pid = numberField(entry, "ProcessId");
|
|
2241
|
+
const ppid = numberField(entry, "ParentProcessId");
|
|
2242
|
+
const command = stringField(entry, "CommandLine");
|
|
2243
|
+
if (pid === undefined || ppid === undefined || command === undefined || command.trim().length === 0)
|
|
2244
|
+
continue;
|
|
2245
|
+
processes.push({ command, pid, ppid });
|
|
2246
|
+
}
|
|
2247
|
+
return processes;
|
|
2248
|
+
}
|
|
2080
2249
|
function isOrphaned(processInfo, livePids) {
|
|
2081
2250
|
return processInfo.ppid === 1 || !livePids.has(processInfo.ppid);
|
|
2082
2251
|
}
|
|
@@ -2104,13 +2273,113 @@ function isRecord3(value) {
|
|
|
2104
2273
|
return typeof value === "object" && value !== null;
|
|
2105
2274
|
}
|
|
2106
2275
|
|
|
2107
|
-
// ../../utils/src/
|
|
2108
|
-
|
|
2276
|
+
// ../../utils/src/process-sweep/codegraph-family.ts
|
|
2277
|
+
var SERVE_WRAPPER_SUFFIX = "/components/codegraph/dist/serve.js";
|
|
2278
|
+
var UPSTREAM_PACKAGE_SEGMENT = "/@colbymchenry/codegraph/";
|
|
2279
|
+
function selectZombieCodegraphProcesses(processes, options) {
|
|
2280
|
+
const platform = options.platform ?? process.platform;
|
|
2281
|
+
const livePids = new Set(processes.map((processInfo) => processInfo.pid));
|
|
2282
|
+
const roots = normalizeRoots(options.ownedRoots, platform);
|
|
2283
|
+
const zombies = [];
|
|
2284
|
+
for (const processInfo of processes) {
|
|
2285
|
+
const daemon = matchDaemonCommand(processInfo.command, roots, platform);
|
|
2286
|
+
if (daemon !== null) {
|
|
2287
|
+
if (!isOrphaned(processInfo, livePids))
|
|
2288
|
+
continue;
|
|
2289
|
+
zombies.push({
|
|
2290
|
+
...processInfo,
|
|
2291
|
+
daemonProjectRoot: daemon.projectRoot,
|
|
2292
|
+
matchedRoot: daemon.root,
|
|
2293
|
+
matchKind: "upstream-daemon"
|
|
2294
|
+
});
|
|
2295
|
+
continue;
|
|
2296
|
+
}
|
|
2297
|
+
const match = matchOwnedCodegraphCommand(processInfo.command, roots, platform);
|
|
2298
|
+
if (match === null)
|
|
2299
|
+
continue;
|
|
2300
|
+
if (!isOrphaned(processInfo, livePids))
|
|
2301
|
+
continue;
|
|
2302
|
+
zombies.push({ ...processInfo, matchedRoot: match.root, matchKind: match.kind });
|
|
2303
|
+
}
|
|
2304
|
+
return zombies;
|
|
2305
|
+
}
|
|
2306
|
+
var STANDALONE_LAUNCHER_SUFFIXES = ["/bin/codegraph", "/bin/codegraph.exe"];
|
|
2307
|
+
var BUNDLE_SCRIPT_SUFFIX = "/lib/dist/bin/codegraph.js";
|
|
2308
|
+
function matchDaemonCommand(command, roots, platform) {
|
|
2309
|
+
const projectRoot = extractDaemonProjectRoot(splitCommandTokens(command));
|
|
2310
|
+
if (projectRoot === null)
|
|
2311
|
+
return null;
|
|
2312
|
+
const normalizedCommand = normalizeForComparison2(command, platform);
|
|
2313
|
+
for (const root of roots) {
|
|
2314
|
+
if (root.length === 0)
|
|
2315
|
+
continue;
|
|
2316
|
+
if (upstreamPackagePathIsUnderRoot(normalizedCommand, root))
|
|
2317
|
+
return { projectRoot, root };
|
|
2318
|
+
for (const suffix of STANDALONE_LAUNCHER_SUFFIXES) {
|
|
2319
|
+
if (hasExecutableToken(normalizedCommand, `${root}${suffix}`))
|
|
2320
|
+
return { projectRoot, root };
|
|
2321
|
+
}
|
|
2322
|
+
if (hasExecutableToken(normalizedCommand, `${root}${BUNDLE_SCRIPT_SUFFIX}`))
|
|
2323
|
+
return { projectRoot, root };
|
|
2324
|
+
}
|
|
2325
|
+
return null;
|
|
2326
|
+
}
|
|
2327
|
+
function extractDaemonProjectRoot(tokens) {
|
|
2328
|
+
if (!tokens.includes("serve") || !tokens.includes("--mcp"))
|
|
2329
|
+
return null;
|
|
2330
|
+
const pathIndex = tokens.indexOf("--path");
|
|
2331
|
+
if (pathIndex < 0)
|
|
2332
|
+
return null;
|
|
2333
|
+
const value = tokens[pathIndex + 1];
|
|
2334
|
+
if (value === undefined || value.length === 0 || value.startsWith("--"))
|
|
2335
|
+
return null;
|
|
2336
|
+
return value;
|
|
2337
|
+
}
|
|
2338
|
+
function matchOwnedCodegraphCommand(command, roots, platform) {
|
|
2339
|
+
const normalizedCommand = normalizeForComparison2(command, platform);
|
|
2340
|
+
for (const root of roots) {
|
|
2341
|
+
if (root.length === 0)
|
|
2342
|
+
continue;
|
|
2343
|
+
const serveWrapper = `${root}${SERVE_WRAPPER_SUFFIX}`;
|
|
2344
|
+
if (hasExecutableToken(normalizedCommand, serveWrapper))
|
|
2345
|
+
return { kind: "serve-wrapper", root };
|
|
2346
|
+
if (upstreamPackagePathIsUnderRoot(normalizedCommand, root)) {
|
|
2347
|
+
return { kind: "upstream-codegraph", root };
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
return null;
|
|
2351
|
+
}
|
|
2352
|
+
function upstreamPackagePathIsUnderRoot(command, root) {
|
|
2353
|
+
let searchFrom = 0;
|
|
2354
|
+
for (;; ) {
|
|
2355
|
+
const packageIndex = command.indexOf(UPSTREAM_PACKAGE_SEGMENT, searchFrom);
|
|
2356
|
+
if (packageIndex < 0)
|
|
2357
|
+
return false;
|
|
2358
|
+
const tokenStart = findTokenStart(command, packageIndex);
|
|
2359
|
+
if (command.slice(tokenStart).startsWith(`${root}/`) && tokenLooksExecutable(command, tokenStart))
|
|
2360
|
+
return true;
|
|
2361
|
+
searchFrom = packageIndex + UPSTREAM_PACKAGE_SEGMENT.length;
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
|
|
2365
|
+
// ../../utils/src/process-sweep/exec.ts
|
|
2366
|
+
import { execFile } from "node:child_process";
|
|
2367
|
+
function enumerateProcesses(platform = process.platform) {
|
|
2109
2368
|
return platform === "win32" ? enumerateWindowsProcesses() : enumeratePosixProcesses();
|
|
2110
2369
|
}
|
|
2111
|
-
function
|
|
2370
|
+
function createDefaultProcessKiller(platform = process.platform) {
|
|
2112
2371
|
return platform === "win32" ? createWindowsKiller() : createPosixKiller();
|
|
2113
2372
|
}
|
|
2373
|
+
function defaultIsProcessAlive(pid) {
|
|
2374
|
+
try {
|
|
2375
|
+
process.kill(pid, 0);
|
|
2376
|
+
return true;
|
|
2377
|
+
} catch (error) {
|
|
2378
|
+
if (!(error instanceof Error))
|
|
2379
|
+
throw error;
|
|
2380
|
+
return processKillErrorMeansAlive(error);
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2114
2383
|
function enumeratePosixProcesses() {
|
|
2115
2384
|
return execFileText("ps", ["-eo", "pid=,ppid=,command="]).then(parsePosixProcessTable);
|
|
2116
2385
|
}
|
|
@@ -2124,16 +2393,7 @@ function enumerateWindowsProcesses() {
|
|
|
2124
2393
|
}
|
|
2125
2394
|
function createPosixKiller() {
|
|
2126
2395
|
return {
|
|
2127
|
-
isAlive:
|
|
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
|
-
},
|
|
2396
|
+
isAlive: defaultIsProcessAlive,
|
|
2137
2397
|
kill: (pid) => {
|
|
2138
2398
|
process.kill(pid, "SIGKILL");
|
|
2139
2399
|
return Promise.resolve();
|
|
@@ -2146,16 +2406,7 @@ function createPosixKiller() {
|
|
|
2146
2406
|
}
|
|
2147
2407
|
function createWindowsKiller() {
|
|
2148
2408
|
return {
|
|
2149
|
-
isAlive:
|
|
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
|
-
},
|
|
2409
|
+
isAlive: defaultIsProcessAlive,
|
|
2159
2410
|
kill: (pid) => execFileVoid("taskkill.exe", ["/PID", String(pid), "/T", "/F"]),
|
|
2160
2411
|
terminate: (pid) => execFileVoid("taskkill.exe", ["/PID", String(pid), "/T"])
|
|
2161
2412
|
};
|
|
@@ -2185,10 +2436,10 @@ function processKillErrorMeansAlive(error) {
|
|
|
2185
2436
|
return false;
|
|
2186
2437
|
}
|
|
2187
2438
|
|
|
2188
|
-
// ../../utils/src/
|
|
2189
|
-
import { existsSync as existsSync6, readdirSync as readdirSync2, realpathSync as
|
|
2439
|
+
// ../../utils/src/process-sweep/roots.ts
|
|
2440
|
+
import { existsSync as existsSync6, readdirSync as readdirSync2, realpathSync as realpathSync5 } from "node:fs";
|
|
2190
2441
|
import { homedir as homedir9 } from "node:os";
|
|
2191
|
-
import { join as
|
|
2442
|
+
import { join as join10, resolve as resolve6 } from "node:path";
|
|
2192
2443
|
function discoverCodegraphOwnedRoots(options = {}) {
|
|
2193
2444
|
const env = options.env ?? process.env;
|
|
2194
2445
|
const homeDir = options.homeDir ?? env["HOME"] ?? env["USERPROFILE"] ?? homedir9();
|
|
@@ -2198,33 +2449,33 @@ function discoverCodegraphOwnedRoots(options = {}) {
|
|
|
2198
2449
|
addRoot(roots, options.pluginRoot);
|
|
2199
2450
|
for (const root of options.extraRoots ?? [])
|
|
2200
2451
|
addRoot(roots, root);
|
|
2201
|
-
for (const root of readCodexPluginCacheRoots(options.codexHome ?? env["CODEX_HOME"] ??
|
|
2452
|
+
for (const root of readCodexPluginCacheRoots(options.codexHome ?? env["CODEX_HOME"] ?? join10(homeDir, ".codex"))) {
|
|
2202
2453
|
addRoot(roots, root);
|
|
2203
2454
|
}
|
|
2204
2455
|
return [...roots];
|
|
2205
2456
|
}
|
|
2206
2457
|
function readCodexPluginCacheRoots(codexHome) {
|
|
2207
|
-
const cacheRoot =
|
|
2458
|
+
const cacheRoot = join10(codexHome, "plugins", "cache");
|
|
2208
2459
|
if (!existsSync6(cacheRoot))
|
|
2209
2460
|
return [];
|
|
2210
2461
|
const roots = [];
|
|
2211
2462
|
for (const publisher of safeReadDir(cacheRoot)) {
|
|
2212
2463
|
if (!OMO_CODEX_PLUGIN_CACHE_PUBLISHERS.has(publisher))
|
|
2213
2464
|
continue;
|
|
2214
|
-
const omoRoot =
|
|
2465
|
+
const omoRoot = join10(cacheRoot, publisher, "omo");
|
|
2215
2466
|
if (!existsSync6(omoRoot))
|
|
2216
2467
|
continue;
|
|
2217
2468
|
for (const version of safeReadDir(omoRoot))
|
|
2218
|
-
roots.push(
|
|
2469
|
+
roots.push(join10(omoRoot, version));
|
|
2219
2470
|
}
|
|
2220
2471
|
return roots;
|
|
2221
2472
|
}
|
|
2222
2473
|
function addRoot(roots, root) {
|
|
2223
2474
|
if (root === undefined || root.trim().length === 0)
|
|
2224
2475
|
return;
|
|
2225
|
-
const resolved =
|
|
2476
|
+
const resolved = resolve6(root);
|
|
2226
2477
|
roots.add(resolved);
|
|
2227
|
-
roots.add(
|
|
2478
|
+
roots.add(realpathIfPossible3(resolved));
|
|
2228
2479
|
}
|
|
2229
2480
|
function safeReadDir(path) {
|
|
2230
2481
|
try {
|
|
@@ -2235,12 +2486,12 @@ function safeReadDir(path) {
|
|
|
2235
2486
|
throw error;
|
|
2236
2487
|
}
|
|
2237
2488
|
}
|
|
2238
|
-
function
|
|
2489
|
+
function realpathIfPossible3(path) {
|
|
2239
2490
|
try {
|
|
2240
|
-
return
|
|
2491
|
+
return realpathSync5(path);
|
|
2241
2492
|
} catch (error) {
|
|
2242
2493
|
if (error instanceof Error)
|
|
2243
|
-
return
|
|
2494
|
+
return resolve6(path);
|
|
2244
2495
|
throw error;
|
|
2245
2496
|
}
|
|
2246
2497
|
}
|
|
@@ -2252,70 +2503,109 @@ function isNonFatalFsError(error) {
|
|
|
2252
2503
|
}
|
|
2253
2504
|
var OMO_CODEX_PLUGIN_CACHE_PUBLISHERS = new Set(["sisyphuslabs"]);
|
|
2254
2505
|
|
|
2255
|
-
// ../../utils/src/
|
|
2506
|
+
// ../../utils/src/process-sweep/sweeper.ts
|
|
2256
2507
|
var DEFAULT_GRACE_MS = 2000;
|
|
2257
2508
|
var DEFAULT_THROTTLE_MS = 60 * 60 * 1000;
|
|
2258
|
-
|
|
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);
|
|
2509
|
+
async function runProcessFamilySweep(config, options) {
|
|
2262
2510
|
const nowMs = options.nowMs ?? Date.now();
|
|
2263
2511
|
const dryRun = options.dryRun === true;
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
return emptyResult("throttled", dryRun, ownedRoots, stampFile);
|
|
2512
|
+
if (options.force !== true && isSweepThrottled(config.stampFile, nowMs, options.throttleMs ?? DEFAULT_THROTTLE_MS)) {
|
|
2513
|
+
return { action: "throttled", candidates: [], dryRun, failed: [], killed: [], spared: [], stampFile: config.stampFile };
|
|
2267
2514
|
}
|
|
2268
2515
|
try {
|
|
2269
|
-
const
|
|
2270
|
-
const
|
|
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);
|
|
2516
|
+
const plan = await config.collect();
|
|
2517
|
+
const { failed, killed } = dryRun ? { failed: [], killed: [] } : await killTargets(plan.killList, options.killer ?? createDefaultProcessKiller(options.platform), options, config.familyLabel);
|
|
2275
2518
|
if (!dryRun)
|
|
2276
|
-
writeSweepStamp(stampFile, nowMs);
|
|
2277
|
-
return {
|
|
2519
|
+
writeSweepStamp(config.stampFile, nowMs);
|
|
2520
|
+
return {
|
|
2521
|
+
action: "swept",
|
|
2522
|
+
candidates: plan.candidates,
|
|
2523
|
+
dryRun,
|
|
2524
|
+
failed,
|
|
2525
|
+
killed,
|
|
2526
|
+
spared: plan.spared,
|
|
2527
|
+
stampFile: config.stampFile
|
|
2528
|
+
};
|
|
2278
2529
|
} catch (error) {
|
|
2279
|
-
options.log?.(
|
|
2280
|
-
return
|
|
2530
|
+
options.log?.(`${config.familyLabel} skipped: ${error instanceof Error ? error.message : String(error)}`);
|
|
2531
|
+
return { action: "failed", candidates: [], dryRun, failed: [], killed: [], spared: [], stampFile: config.stampFile };
|
|
2281
2532
|
}
|
|
2282
2533
|
}
|
|
2283
|
-
|
|
2534
|
+
var CODEGRAPH_SWEEP_STAMP_FILE = "zombie-sweep.stamp";
|
|
2535
|
+
async function sweepCodegraphZombies(options = {}) {
|
|
2536
|
+
const homeDir = options.homeDir ?? options.env?.["HOME"] ?? options.env?.["USERPROFILE"] ?? homedir10();
|
|
2537
|
+
const stampFile = join11(codegraphDataRoot(homeDir), CODEGRAPH_SWEEP_STAMP_FILE);
|
|
2538
|
+
const ownedRoots = options.ownedRoots ?? discoverCodegraphOwnedRoots(options);
|
|
2539
|
+
const result = await runProcessFamilySweep({
|
|
2540
|
+
familyLabel: "CodeGraph zombie sweep",
|
|
2541
|
+
stampFile,
|
|
2542
|
+
collect: async () => {
|
|
2543
|
+
const provider = options.processProvider ?? (() => enumerateProcesses(options.platform));
|
|
2544
|
+
const candidates = selectZombieCodegraphProcesses(await provider(), {
|
|
2545
|
+
ownedRoots,
|
|
2546
|
+
...options.platform === undefined ? {} : { platform: options.platform }
|
|
2547
|
+
});
|
|
2548
|
+
const { killList, spared } = partitionByDaemonStaleness(candidates, options.log);
|
|
2549
|
+
return { candidates, killList, spared };
|
|
2550
|
+
}
|
|
2551
|
+
}, options);
|
|
2552
|
+
return { ...result, ownedRoots };
|
|
2553
|
+
}
|
|
2554
|
+
function partitionByDaemonStaleness(candidates, log) {
|
|
2555
|
+
const killList = [];
|
|
2556
|
+
const spared = [];
|
|
2557
|
+
for (const candidate of candidates) {
|
|
2558
|
+
if (candidate.matchKind !== "upstream-daemon") {
|
|
2559
|
+
killList.push(candidate);
|
|
2560
|
+
continue;
|
|
2561
|
+
}
|
|
2562
|
+
const staleness = evaluateDaemonStaleness(candidate.pid, candidate.daemonProjectRoot ?? candidate.matchedRoot);
|
|
2563
|
+
if (staleness.stale) {
|
|
2564
|
+
log?.(`CodeGraph zombie sweep sweeping stale daemon pid ${candidate.pid} (${staleness.reason})`);
|
|
2565
|
+
killList.push(candidate);
|
|
2566
|
+
continue;
|
|
2567
|
+
}
|
|
2568
|
+
log?.(`CodeGraph zombie sweep spared live daemon pid ${candidate.pid} (${staleness.reason})`);
|
|
2569
|
+
spared.push(candidate);
|
|
2570
|
+
}
|
|
2571
|
+
return { killList, spared };
|
|
2572
|
+
}
|
|
2573
|
+
async function killTargets(targets, killer, options, familyLabel) {
|
|
2284
2574
|
const failed = [];
|
|
2285
2575
|
const killed = [];
|
|
2286
|
-
for (const
|
|
2287
|
-
const terminated = await safelyTerminate(
|
|
2576
|
+
for (const target of targets) {
|
|
2577
|
+
const terminated = await safelyTerminate(target.pid, killer, failed, options.log, familyLabel);
|
|
2288
2578
|
if (!terminated)
|
|
2289
2579
|
continue;
|
|
2290
2580
|
await delay(options.graceMs ?? DEFAULT_GRACE_MS);
|
|
2291
|
-
if (!await killer.isAlive(
|
|
2292
|
-
killed.push(
|
|
2581
|
+
if (!await killer.isAlive(target.pid)) {
|
|
2582
|
+
killed.push(target);
|
|
2293
2583
|
continue;
|
|
2294
2584
|
}
|
|
2295
|
-
if (await safelyKill(
|
|
2296
|
-
killed.push(
|
|
2585
|
+
if (await safelyKill(target.pid, killer, failed, options.log, familyLabel))
|
|
2586
|
+
killed.push(target);
|
|
2297
2587
|
}
|
|
2298
2588
|
return { failed, killed };
|
|
2299
2589
|
}
|
|
2300
|
-
async function safelyTerminate(pid, killer, failed, log) {
|
|
2590
|
+
async function safelyTerminate(pid, killer, failed, log, familyLabel) {
|
|
2301
2591
|
try {
|
|
2302
2592
|
await killer.terminate(pid);
|
|
2303
2593
|
return true;
|
|
2304
2594
|
} catch (error) {
|
|
2305
2595
|
const message = error instanceof Error ? error.message : String(error);
|
|
2306
2596
|
failed.push({ error: message, pid, stage: "terminate" });
|
|
2307
|
-
log?.(
|
|
2597
|
+
log?.(`${familyLabel} failed to terminate pid ${pid}: ${message}`);
|
|
2308
2598
|
return false;
|
|
2309
2599
|
}
|
|
2310
2600
|
}
|
|
2311
|
-
async function safelyKill(pid, killer, failed, log) {
|
|
2601
|
+
async function safelyKill(pid, killer, failed, log, familyLabel) {
|
|
2312
2602
|
try {
|
|
2313
2603
|
await killer.kill(pid);
|
|
2314
2604
|
return true;
|
|
2315
2605
|
} catch (error) {
|
|
2316
2606
|
const message = error instanceof Error ? error.message : String(error);
|
|
2317
2607
|
failed.push({ error: message, pid, stage: "kill" });
|
|
2318
|
-
log?.(
|
|
2608
|
+
log?.(`${familyLabel} failed to kill pid ${pid}: ${message}`);
|
|
2319
2609
|
return false;
|
|
2320
2610
|
}
|
|
2321
2611
|
}
|
|
@@ -2325,15 +2615,12 @@ function isSweepThrottled(stampFile, nowMs, throttleMs) {
|
|
|
2325
2615
|
return nowMs - statSync2(stampFile).mtimeMs < throttleMs;
|
|
2326
2616
|
}
|
|
2327
2617
|
function writeSweepStamp(stampFile, nowMs) {
|
|
2328
|
-
mkdirSync2(
|
|
2618
|
+
mkdirSync2(dirname5(stampFile), { recursive: true });
|
|
2329
2619
|
writeFileSync2(stampFile, `${new Date(nowMs).toISOString()}
|
|
2330
2620
|
`);
|
|
2331
2621
|
const stampDate = new Date(nowMs);
|
|
2332
2622
|
utimesSync(stampFile, stampDate, stampDate);
|
|
2333
2623
|
}
|
|
2334
|
-
function emptyResult(action, dryRun, ownedRoots, stampFile) {
|
|
2335
|
-
return { action, candidates: [], dryRun, failed: [], killed: [], ownedRoots, stampFile };
|
|
2336
|
-
}
|
|
2337
2624
|
function delay(ms) {
|
|
2338
2625
|
if (ms <= 0)
|
|
2339
2626
|
return Promise.resolve();
|
|
@@ -2361,56 +2648,55 @@ function defaultPluginRoot() {
|
|
|
2361
2648
|
import { execFile as execFile3 } from "node:child_process";
|
|
2362
2649
|
import { appendFileSync as appendFileSync2, existsSync as existsSync9, mkdirSync as mkdirSync3 } from "node:fs";
|
|
2363
2650
|
import { homedir as homedir12 } from "node:os";
|
|
2364
|
-
import { extname, join as
|
|
2651
|
+
import { extname, join as join13 } from "node:path";
|
|
2365
2652
|
import { cwd as processCwd, env as processEnv, execPath as processExecPath, stderr as processStderr } from "node:process";
|
|
2366
2653
|
|
|
2367
|
-
// ../../utils/src/codegraph/provision.ts
|
|
2368
|
-
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
2369
|
-
import { execFile as execFile2 } from "node:child_process";
|
|
2370
|
-
import { chmod, mkdir, readdir, readFile, rename, rm, rmdir, stat, writeFile } from "node:fs/promises";
|
|
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";
|
|
2374
|
-
import { promisify } from "node:util";
|
|
2375
|
-
|
|
2376
2654
|
// ../../utils/src/codegraph/manifest.ts
|
|
2655
|
+
var CODEGRAPH_PINNED_VERSION = "1.4.1";
|
|
2377
2656
|
var CODEGRAPH_PROVISION_MANIFEST = {
|
|
2378
2657
|
assets: {
|
|
2379
2658
|
"darwin-arm64": {
|
|
2380
2659
|
executableName: "codegraph",
|
|
2381
|
-
sha256: "
|
|
2382
|
-
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.
|
|
2660
|
+
sha256: "4a679ae5a5cb9fff900dd59bb786da6a581b7f68f4cf713bdedd137e347d34dc",
|
|
2661
|
+
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.4.1/codegraph-darwin-arm64.tar.gz"
|
|
2383
2662
|
},
|
|
2384
2663
|
"darwin-x64": {
|
|
2385
2664
|
executableName: "codegraph",
|
|
2386
|
-
sha256: "
|
|
2387
|
-
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.
|
|
2665
|
+
sha256: "436f96943cfd926ea6d0a8454f18833d21254d5fd9b3d224317b1426132def95",
|
|
2666
|
+
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.4.1/codegraph-darwin-x64.tar.gz"
|
|
2388
2667
|
},
|
|
2389
2668
|
"linux-arm64": {
|
|
2390
2669
|
executableName: "codegraph",
|
|
2391
|
-
sha256: "
|
|
2392
|
-
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.
|
|
2670
|
+
sha256: "0d62c5eb2722f8d19d20f7a1bd974445e18d5294cb59be116a0c3d55ce87591f",
|
|
2671
|
+
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.4.1/codegraph-linux-arm64.tar.gz"
|
|
2393
2672
|
},
|
|
2394
2673
|
"linux-x64": {
|
|
2395
2674
|
executableName: "codegraph",
|
|
2396
|
-
sha256: "
|
|
2397
|
-
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.
|
|
2675
|
+
sha256: "fb585ff5018d6faaa46d282b61f4f689bc7967ed8a1b467a5c556dd7ced9b542",
|
|
2676
|
+
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.4.1/codegraph-linux-x64.tar.gz"
|
|
2398
2677
|
},
|
|
2399
2678
|
"win32-arm64": {
|
|
2400
2679
|
executableName: "codegraph.cmd",
|
|
2401
|
-
sha256: "
|
|
2402
|
-
url: "https://registry.npmjs.org/@colbymchenry/codegraph-win32-arm64/-/codegraph-win32-arm64-1.
|
|
2680
|
+
sha256: "e2a2a28c802a79804c7df203afa50bd461309c6c180ce3f76079fdc7cddc7697",
|
|
2681
|
+
url: "https://registry.npmjs.org/@colbymchenry/codegraph-win32-arm64/-/codegraph-win32-arm64-1.4.1.tgz"
|
|
2403
2682
|
},
|
|
2404
2683
|
"win32-x64": {
|
|
2405
2684
|
executableName: "codegraph.cmd",
|
|
2406
|
-
sha256: "
|
|
2407
|
-
url: "https://registry.npmjs.org/@colbymchenry/codegraph-win32-x64/-/codegraph-win32-x64-1.
|
|
2685
|
+
sha256: "4f08700fda5f4a03ad5b2956135c5788d739a351b3433db2b5820e5d5224c30d",
|
|
2686
|
+
url: "https://registry.npmjs.org/@colbymchenry/codegraph-win32-x64/-/codegraph-win32-x64-1.4.1.tgz"
|
|
2408
2687
|
}
|
|
2409
2688
|
},
|
|
2410
|
-
version:
|
|
2689
|
+
version: CODEGRAPH_PINNED_VERSION
|
|
2411
2690
|
};
|
|
2412
2691
|
|
|
2413
2692
|
// ../../utils/src/codegraph/provision.ts
|
|
2693
|
+
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
2694
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
2695
|
+
import { chmod, mkdir, readdir, readFile, rename, rm, rmdir, stat, writeFile } from "node:fs/promises";
|
|
2696
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
2697
|
+
import { homedir as homedir11, hostname } from "node:os";
|
|
2698
|
+
import { basename as basename3, join as join12 } from "node:path";
|
|
2699
|
+
import { promisify } from "node:util";
|
|
2414
2700
|
var DEFAULT_LOCK_WAIT_MS = 5000;
|
|
2415
2701
|
var DEFAULT_LOCK_STALE_MS = 120000;
|
|
2416
2702
|
var DEFAULT_DOWNLOAD_TIMEOUT_MS = 60000;
|
|
@@ -2419,10 +2705,10 @@ function platformKey() {
|
|
|
2419
2705
|
return `${process.platform}-${process.arch}`;
|
|
2420
2706
|
}
|
|
2421
2707
|
function markerPath(installDir, version) {
|
|
2422
|
-
return
|
|
2708
|
+
return join12(installDir, ".provisioned", `codegraph-${version}.json`);
|
|
2423
2709
|
}
|
|
2424
2710
|
function defaultInstallDir() {
|
|
2425
|
-
return
|
|
2711
|
+
return join12(homedir11(), ".omo", "codegraph");
|
|
2426
2712
|
}
|
|
2427
2713
|
function sha256(bytes) {
|
|
2428
2714
|
return createHash2("sha256").update(bytes).digest("hex");
|
|
@@ -2442,7 +2728,7 @@ async function removeEmptyDirectory(path) {
|
|
|
2442
2728
|
}
|
|
2443
2729
|
}
|
|
2444
2730
|
function sleep(ms) {
|
|
2445
|
-
return new Promise((
|
|
2731
|
+
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
2446
2732
|
}
|
|
2447
2733
|
async function defaultDownloader(asset, timeoutMs = DEFAULT_DOWNLOAD_TIMEOUT_MS) {
|
|
2448
2734
|
const response = await fetch(asset.url, { signal: AbortSignal.timeout(timeoutMs) });
|
|
@@ -2456,7 +2742,7 @@ function forcedBadChecksumOptions(options) {
|
|
|
2456
2742
|
const key = options.platformKey ?? platformKey();
|
|
2457
2743
|
return {
|
|
2458
2744
|
downloader: async () => new TextEncoder().encode("checksum mismatch"),
|
|
2459
|
-
installDir: options.installDir ??
|
|
2745
|
+
installDir: options.installDir ?? join12(options.lockDir, "codegraph-force-bad-checksum"),
|
|
2460
2746
|
manifest: {
|
|
2461
2747
|
assets: {
|
|
2462
2748
|
[key]: { executableName: process.platform === "win32" ? "codegraph.cmd" : "codegraph", sha256: "0000", url: "memory://bad" }
|
|
@@ -2484,7 +2770,7 @@ async function readMarker(path) {
|
|
|
2484
2770
|
}
|
|
2485
2771
|
async function acquireLock(lockPath, waitMs, staleMs) {
|
|
2486
2772
|
const startedAt = Date.now();
|
|
2487
|
-
await mkdir(
|
|
2773
|
+
await mkdir(join12(lockPath, ".."), { recursive: true });
|
|
2488
2774
|
while (Date.now() - startedAt <= waitMs) {
|
|
2489
2775
|
try {
|
|
2490
2776
|
await mkdir(lockPath);
|
|
@@ -2509,14 +2795,14 @@ async function installExtractedBundle(extractDir, installDir, executableName) {
|
|
|
2509
2795
|
const roots = await readdir(extractDir);
|
|
2510
2796
|
if (roots.length !== 1)
|
|
2511
2797
|
throw new Error(`CodeGraph archive should contain one root directory, found ${roots.length}`);
|
|
2512
|
-
const bundleDir =
|
|
2798
|
+
const bundleDir = join12(extractDir, roots[0] ?? "");
|
|
2513
2799
|
const bundleEntries = await readdir(bundleDir);
|
|
2514
2800
|
await mkdir(installDir, { recursive: true });
|
|
2515
2801
|
for (const entry of bundleEntries) {
|
|
2516
|
-
await rm(
|
|
2517
|
-
await rename(
|
|
2802
|
+
await rm(join12(installDir, entry), { force: true, recursive: true });
|
|
2803
|
+
await rename(join12(bundleDir, entry), join12(installDir, entry));
|
|
2518
2804
|
}
|
|
2519
|
-
const destination =
|
|
2805
|
+
const destination = join12(installDir, "bin", executableName);
|
|
2520
2806
|
if (!existsSync8(destination))
|
|
2521
2807
|
throw new Error(`CodeGraph archive did not contain bin/${executableName}`);
|
|
2522
2808
|
await chmod(destination, 493);
|
|
@@ -2524,9 +2810,9 @@ async function installExtractedBundle(extractDir, installDir, executableName) {
|
|
|
2524
2810
|
}
|
|
2525
2811
|
async function installAsset(layout) {
|
|
2526
2812
|
const { asset, downloader, installDir, version } = layout;
|
|
2527
|
-
const stagingDir =
|
|
2528
|
-
const archivePath =
|
|
2529
|
-
const extractDir =
|
|
2813
|
+
const stagingDir = join12(installDir, ".staging", randomUUID());
|
|
2814
|
+
const archivePath = join12(stagingDir, basename3(asset.url));
|
|
2815
|
+
const extractDir = join12(stagingDir, "extract");
|
|
2530
2816
|
try {
|
|
2531
2817
|
await mkdir(extractDir, { recursive: true });
|
|
2532
2818
|
const bytes = await downloader(asset);
|
|
@@ -2540,13 +2826,13 @@ async function installAsset(layout) {
|
|
|
2540
2826
|
await writeFile(archivePath, bytes);
|
|
2541
2827
|
await extractTarGz(archivePath, extractDir);
|
|
2542
2828
|
const destination = await installExtractedBundle(extractDir, installDir, asset.executableName);
|
|
2543
|
-
await mkdir(
|
|
2829
|
+
await mkdir(join12(installDir, ".provisioned"), { recursive: true });
|
|
2544
2830
|
await writeFile(markerPath(installDir, version), `${JSON.stringify({ binPath: destination, version })}
|
|
2545
2831
|
`);
|
|
2546
2832
|
return destination;
|
|
2547
2833
|
} finally {
|
|
2548
2834
|
await rm(stagingDir, { force: true, recursive: true });
|
|
2549
|
-
await removeEmptyDirectory(
|
|
2835
|
+
await removeEmptyDirectory(join12(installDir, ".staging"));
|
|
2550
2836
|
}
|
|
2551
2837
|
}
|
|
2552
2838
|
async function ensureCodegraphProvisioned(options) {
|
|
@@ -2559,7 +2845,7 @@ async function ensureCodegraphProvisioned(options) {
|
|
|
2559
2845
|
const existing = await readMarker(marker);
|
|
2560
2846
|
if (existing !== null)
|
|
2561
2847
|
return { binPath: existing, provisioned: true };
|
|
2562
|
-
const lockPath =
|
|
2848
|
+
const lockPath = join12(options.lockDir, `codegraph-${hostname()}.lock`);
|
|
2563
2849
|
const release = await acquireLock(lockPath, options.lockWaitMs ?? DEFAULT_LOCK_WAIT_MS, options.lockStaleMs ?? DEFAULT_LOCK_STALE_MS);
|
|
2564
2850
|
if (release === null)
|
|
2565
2851
|
return { error: "timed out waiting for codegraph provisioning lock", provisioned: false };
|
|
@@ -2585,7 +2871,7 @@ async function ensureCodegraphProvisioned(options) {
|
|
|
2585
2871
|
|
|
2586
2872
|
// components/codegraph/src/session-start-worker.ts
|
|
2587
2873
|
var SESSION_START_CWD_ENV = "OMO_CODEGRAPH_SESSION_START_CWD";
|
|
2588
|
-
var CODEGRAPH_VERSION =
|
|
2874
|
+
var CODEGRAPH_VERSION = CODEGRAPH_PINNED_VERSION;
|
|
2589
2875
|
var COMMAND_TIMEOUT_MS = 60000;
|
|
2590
2876
|
var WINDOWS_CMD_EXTENSIONS = new Set([".bat", ".cmd"]);
|
|
2591
2877
|
var WINDOWS_NODE_SCRIPT_EXTENSIONS = new Set([".cjs", ".js", ".mjs"]);
|
|
@@ -2649,15 +2935,15 @@ async function resolveOrProvisionCommand(deps, config, env, homeDir, nodeSupport
|
|
|
2649
2935
|
return { kind: "unsupported-node" };
|
|
2650
2936
|
if (config.auto_provision === false)
|
|
2651
2937
|
return { error: "codegraph binary unavailable and auto_provision is disabled", kind: "unavailable", source: resolved.source };
|
|
2652
|
-
const installDir = trustedInstallDir ??
|
|
2653
|
-
const provisioned = await deps.ensureProvisioned({ installDir, lockDir:
|
|
2938
|
+
const installDir = trustedInstallDir ?? join13(homeDir, ".omo", "codegraph");
|
|
2939
|
+
const provisioned = await deps.ensureProvisioned({ installDir, lockDir: join13(installDir, ".locks"), version: CODEGRAPH_VERSION });
|
|
2654
2940
|
if (!provisioned.provisioned || provisioned.binPath === undefined) {
|
|
2655
2941
|
return { error: provisioned.error ?? "provisioning did not produce a binary", kind: "unavailable", source: resolved.source };
|
|
2656
2942
|
}
|
|
2657
2943
|
return { kind: "resolved", resolution: { argsPrefix: [], command: provisioned.binPath, exists: true, source: "provisioned" } };
|
|
2658
2944
|
}
|
|
2659
2945
|
function codegraphEnvForConfig(config, homeDir) {
|
|
2660
|
-
const env = buildCodegraphEnv({ homeDir });
|
|
2946
|
+
const env = buildCodegraphEnv({ daemon: false, homeDir });
|
|
2661
2947
|
return config.trustedCodegraphInstallDir === undefined ? env : { ...env, CODEGRAPH_INSTALL_DIR: config.trustedCodegraphInstallDir };
|
|
2662
2948
|
}
|
|
2663
2949
|
function canUseResolvedCommand(resolved, nodeSupport) {
|
|
@@ -2718,9 +3004,9 @@ function resolveCodegraphCommandInvocation(command, args, platform = process.pla
|
|
|
2718
3004
|
return { args: ["/d", "/s", "/c", command, ...args], command: "cmd.exe" };
|
|
2719
3005
|
}
|
|
2720
3006
|
function appendOutcome(homeDir, outcome) {
|
|
2721
|
-
const logDir =
|
|
3007
|
+
const logDir = join13(homeDir, ".omo", "codegraph");
|
|
2722
3008
|
mkdirSync3(logDir, { recursive: true });
|
|
2723
|
-
appendFileSync2(
|
|
3009
|
+
appendFileSync2(join13(logDir, "session-start.jsonl"), `${JSON.stringify({ ...outcome, timestamp: new Date().toISOString() })}
|
|
2724
3010
|
`);
|
|
2725
3011
|
}
|
|
2726
3012
|
function safeLogOutcome(logOutcome, outcome) {
|
|
@@ -2737,7 +3023,7 @@ function safeLogOutcome(logOutcome, outcome) {
|
|
|
2737
3023
|
function provisionedBinFromInstallDir(installDir) {
|
|
2738
3024
|
if (installDir === undefined)
|
|
2739
3025
|
return null;
|
|
2740
|
-
const candidate =
|
|
3026
|
+
const candidate = join13(installDir, "bin", process.platform === "win32" ? "codegraph.cmd" : "codegraph");
|
|
2741
3027
|
return existsSync9(candidate) ? candidate : null;
|
|
2742
3028
|
}
|
|
2743
3029
|
function resolveExitCode(error) {
|
|
@@ -2798,6 +3084,7 @@ async function executeCodegraphSessionStartHook(options = {}) {
|
|
|
2798
3084
|
return { action: "skipped-excluded", exitCode: 0 };
|
|
2799
3085
|
}
|
|
2800
3086
|
const isInitialized = await (options.statusProbe ?? isCodegraphProjectInitialized)({
|
|
3087
|
+
daemon: config.codegraph?.daemon === true,
|
|
2801
3088
|
env,
|
|
2802
3089
|
homeDir,
|
|
2803
3090
|
projectRoot,
|
|
@@ -2828,7 +3115,7 @@ async function isCodegraphProjectInitialized(options) {
|
|
|
2828
3115
|
return false;
|
|
2829
3116
|
const invocation = resolveCodegraphCommandInvocation(resolved.command, [...resolved.argsPrefix, "status", "--json"]);
|
|
2830
3117
|
const codegraphEnv = {
|
|
2831
|
-
...buildCodegraphEnv({ homeDir: options.homeDir }),
|
|
3118
|
+
...buildCodegraphEnv({ daemon: options.daemon, homeDir: options.homeDir }),
|
|
2832
3119
|
...options.trustedCodegraphInstallDir === undefined ? {} : { CODEGRAPH_INSTALL_DIR: options.trustedCodegraphInstallDir }
|
|
2833
3120
|
};
|
|
2834
3121
|
const status = await runStatusProbe(options.projectRoot, invocation.command, invocation.args, buildCodegraphChildEnv({ ambientEnv: options.env, codegraphEnv, runtimeEnv: options.env }));
|
|
@@ -2870,7 +3157,7 @@ function codegraphStatusSaysInitialized(stdout) {
|
|
|
2870
3157
|
function provisionedBinFromInstallDir2(installDir) {
|
|
2871
3158
|
if (installDir === undefined)
|
|
2872
3159
|
return null;
|
|
2873
|
-
return
|
|
3160
|
+
return join14(installDir, "bin", process.platform === "win32" ? "codegraph.cmd" : "codegraph");
|
|
2874
3161
|
}
|
|
2875
3162
|
async function executeCodegraphPostToolUseHook(options = {}) {
|
|
2876
3163
|
const env = options.env ?? processEnv2;
|
|
@@ -2960,9 +3247,9 @@ function defaultWorkerCliPath() {
|
|
|
2960
3247
|
}
|
|
2961
3248
|
|
|
2962
3249
|
// components/codegraph/src/serve.ts
|
|
2963
|
-
import { existsSync as existsSync10, realpathSync as
|
|
3250
|
+
import { existsSync as existsSync10, realpathSync as realpathSync6 } from "node:fs";
|
|
2964
3251
|
import { homedir as homedir14 } from "node:os";
|
|
2965
|
-
import { basename as basename4, join as
|
|
3252
|
+
import { basename as basename4, join as join15, resolve as resolve7 } from "node:path";
|
|
2966
3253
|
import {
|
|
2967
3254
|
cwd as processCwd3,
|
|
2968
3255
|
env as processEnv3,
|
|
@@ -3023,7 +3310,7 @@ ${body}` : `${body}
|
|
|
3023
3310
|
await writeChunk(output, payload);
|
|
3024
3311
|
}
|
|
3025
3312
|
function writeChunk(output, chunk) {
|
|
3026
|
-
return new Promise((
|
|
3313
|
+
return new Promise((resolve7, reject) => {
|
|
3027
3314
|
let settled = false;
|
|
3028
3315
|
const onError = (error) => {
|
|
3029
3316
|
if (settled)
|
|
@@ -3043,7 +3330,7 @@ function writeChunk(output, chunk) {
|
|
|
3043
3330
|
return;
|
|
3044
3331
|
}
|
|
3045
3332
|
output.removeListener("error", onError);
|
|
3046
|
-
|
|
3333
|
+
resolve7();
|
|
3047
3334
|
});
|
|
3048
3335
|
} catch (error) {
|
|
3049
3336
|
output.removeListener("error", onError);
|
|
@@ -3135,16 +3422,35 @@ function bufferFromChunk(chunk) {
|
|
|
3135
3422
|
|
|
3136
3423
|
// ../../mcp-stdio-core/src/server.ts
|
|
3137
3424
|
var DEFAULT_IDLE_TIMEOUT_MS = 10 * 60000;
|
|
3425
|
+
var DEFAULT_PARENT_POLL_INTERVAL_MS = 30000;
|
|
3138
3426
|
var noopLog = () => {};
|
|
3427
|
+
function isProcessAlive(pid) {
|
|
3428
|
+
try {
|
|
3429
|
+
process.kill(pid, 0);
|
|
3430
|
+
return true;
|
|
3431
|
+
} catch (error) {
|
|
3432
|
+
return !hasErrorCode(error, "ESRCH");
|
|
3433
|
+
}
|
|
3434
|
+
}
|
|
3139
3435
|
async function runJsonRpcStdioServer(config) {
|
|
3140
3436
|
const log = config.log ?? noopLog;
|
|
3141
3437
|
const idleTimeoutMs = config.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
3142
|
-
|
|
3438
|
+
let isClosed = false;
|
|
3439
|
+
const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
|
|
3440
|
+
isClosed = true;
|
|
3441
|
+
config.onIdleTimeout?.();
|
|
3442
|
+
});
|
|
3443
|
+
const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
|
|
3444
|
+
isClosed = true;
|
|
3445
|
+
log("parent_exit", { parent_pid: parentPid, poll_interval_ms: pollIntervalMs });
|
|
3446
|
+
config.onParentExit?.();
|
|
3447
|
+
config.input.destroy();
|
|
3448
|
+
});
|
|
3143
3449
|
log("stdio_started", { cwd: process.cwd(), idle_timeout_ms: idleTimeoutMs });
|
|
3144
3450
|
idleTimer.arm();
|
|
3145
3451
|
try {
|
|
3146
3452
|
for await (const message of readStdioJsonRpcMessages(config.input)) {
|
|
3147
|
-
if (
|
|
3453
|
+
if (isClosed)
|
|
3148
3454
|
break;
|
|
3149
3455
|
idleTimer.arm();
|
|
3150
3456
|
if (message.kind === "parse_error") {
|
|
@@ -3155,8 +3461,12 @@ async function runJsonRpcStdioServer(config) {
|
|
|
3155
3461
|
if (!await handleRequest(message, config, log))
|
|
3156
3462
|
break;
|
|
3157
3463
|
}
|
|
3464
|
+
} catch (error) {
|
|
3465
|
+
if (!(isClosed && hasErrorCode(error, "ERR_STREAM_PREMATURE_CLOSE")))
|
|
3466
|
+
throw error;
|
|
3158
3467
|
} finally {
|
|
3159
3468
|
idleTimer.clear();
|
|
3469
|
+
watchdog.clear();
|
|
3160
3470
|
log("stdio_stopped");
|
|
3161
3471
|
}
|
|
3162
3472
|
}
|
|
@@ -3212,9 +3522,33 @@ function isTerminalOutputError(error) {
|
|
|
3212
3522
|
return false;
|
|
3213
3523
|
return error.code === "EPIPE" || error.code === "ERR_STREAM_DESTROYED" || error.code === "ERR_STREAM_WRITE_AFTER_END";
|
|
3214
3524
|
}
|
|
3215
|
-
function
|
|
3525
|
+
function hasErrorCode(error, code) {
|
|
3526
|
+
return error instanceof Error && "code" in error && error.code === code;
|
|
3527
|
+
}
|
|
3528
|
+
function createParentWatchdog(config, onDeadParent) {
|
|
3529
|
+
if (config === undefined)
|
|
3530
|
+
return { clear: () => {} };
|
|
3531
|
+
const pollIntervalMs = config.pollIntervalMs ?? DEFAULT_PARENT_POLL_INTERVAL_MS;
|
|
3532
|
+
if (pollIntervalMs <= 0)
|
|
3533
|
+
return { clear: () => {} };
|
|
3534
|
+
const parentPid = config.parentPid ?? process.ppid;
|
|
3535
|
+
const probeAlive = config.probeAlive ?? isProcessAlive;
|
|
3536
|
+
let fired = false;
|
|
3537
|
+
const timer = setInterval(() => {
|
|
3538
|
+
if (fired || probeAlive(parentPid))
|
|
3539
|
+
return;
|
|
3540
|
+
fired = true;
|
|
3541
|
+
onDeadParent(parentPid, pollIntervalMs);
|
|
3542
|
+
}, pollIntervalMs);
|
|
3543
|
+
timer.unref();
|
|
3544
|
+
return {
|
|
3545
|
+
clear: () => {
|
|
3546
|
+
clearInterval(timer);
|
|
3547
|
+
}
|
|
3548
|
+
};
|
|
3549
|
+
}
|
|
3550
|
+
function createIdleTimer(idleTimeoutMs, log, onTimeout) {
|
|
3216
3551
|
let timer = null;
|
|
3217
|
-
let isClosed = false;
|
|
3218
3552
|
return {
|
|
3219
3553
|
arm: () => {
|
|
3220
3554
|
if (timer !== null)
|
|
@@ -3222,9 +3556,8 @@ function createIdleTimer(idleTimeoutMs, log, onIdleTimeout) {
|
|
|
3222
3556
|
if (idleTimeoutMs <= 0)
|
|
3223
3557
|
return;
|
|
3224
3558
|
timer = setTimeout(() => {
|
|
3225
|
-
isClosed = true;
|
|
3226
3559
|
log("idle_timeout", { idle_timeout_ms: idleTimeoutMs });
|
|
3227
|
-
|
|
3560
|
+
onTimeout();
|
|
3228
3561
|
}, idleTimeoutMs);
|
|
3229
3562
|
timer.unref();
|
|
3230
3563
|
},
|
|
@@ -3233,8 +3566,7 @@ function createIdleTimer(idleTimeoutMs, log, onIdleTimeout) {
|
|
|
3233
3566
|
return;
|
|
3234
3567
|
clearTimeout(timer);
|
|
3235
3568
|
timer = null;
|
|
3236
|
-
}
|
|
3237
|
-
closed: () => isClosed
|
|
3569
|
+
}
|
|
3238
3570
|
};
|
|
3239
3571
|
}
|
|
3240
3572
|
// components/codegraph/src/serve-invocation.ts
|
|
@@ -3267,6 +3599,7 @@ class CodegraphBridgeStdioError extends Error {
|
|
|
3267
3599
|
var CODEGRAPH_NODE_DESCRIPTION = "Inspect one named symbol or file. In symbol mode, includeCode=true includes leaf-symbol source when available. Container symbols such as classes, interfaces, structs, enums, modules, and namespaces return structural outlines with member lists by design. For container source, request a specific member symbol or use file mode with symbolsOnly=false plus offset/limit.";
|
|
3268
3600
|
var CODEGRAPH_NODE_INCLUDE_CODE_DESCRIPTION = "Symbol mode: include leaf-symbol source when available. Container symbols such as classes, interfaces, structs, enums, modules, and namespaces intentionally return structural outlines with members; request a specific member symbol or use file mode with symbolsOnly=false plus offset/limit for source.";
|
|
3269
3601
|
var CODEGRAPH_CONTAINER_OUTLINE_GUIDANCE = "Container symbols intentionally return structural outlines with members. For source, request a specific member symbol or call codegraph_node in file mode with symbolsOnly=false plus offset/limit around the symbol location.";
|
|
3602
|
+
var SIGKILL_ESCALATION_MS = 2000;
|
|
3270
3603
|
async function runBridgedCodegraphProcess(command, args, options) {
|
|
3271
3604
|
const invocation = resolveServeProcessInvocation(command, args);
|
|
3272
3605
|
const child = spawn2(invocation.command, invocation.args, {
|
|
@@ -3292,17 +3625,24 @@ async function runBridgedCodegraphProcess(command, args, options) {
|
|
|
3292
3625
|
resolveExit(signal === null ? 0 : 1);
|
|
3293
3626
|
});
|
|
3294
3627
|
});
|
|
3295
|
-
const clientForwardingDone = forwardClientToCodegraph(options.input, childInput, pendingResponses, (mode) => {
|
|
3296
|
-
defaultResponseMode = mode;
|
|
3297
|
-
});
|
|
3298
|
-
const responseForwardingDone = forwardCodegraphToClient(childOutput, options.output, pendingResponses, () => defaultResponseMode);
|
|
3299
|
-
const bridgeDone = Promise.all([clientForwardingDone, responseForwardingDone]);
|
|
3300
|
-
const childAndResponsesDone = Promise.all([childExit, responseForwardingDone]).then(([exitCode]) => exitCode);
|
|
3301
3628
|
const destroyChildPipes = () => {
|
|
3302
3629
|
childInput.destroy();
|
|
3303
3630
|
childOutput.destroy();
|
|
3304
3631
|
};
|
|
3305
3632
|
childExit.then(destroyChildPipes, destroyChildPipes);
|
|
3633
|
+
let parentWatchdogFired = false;
|
|
3634
|
+
const parentWatchdog = createParentWatchdog(options.parentWatchdog, () => {
|
|
3635
|
+
parentWatchdogFired = true;
|
|
3636
|
+
options.input.destroy();
|
|
3637
|
+
destroyChildPipes();
|
|
3638
|
+
terminateCodegraphChild(child);
|
|
3639
|
+
});
|
|
3640
|
+
const clientForwardingDone = forwardClientToCodegraph(options.input, childInput, pendingResponses, (mode) => {
|
|
3641
|
+
defaultResponseMode = mode;
|
|
3642
|
+
}, () => parentWatchdogFired);
|
|
3643
|
+
const responseForwardingDone = forwardCodegraphToClient(childOutput, options.output, pendingResponses, () => defaultResponseMode, () => parentWatchdogFired);
|
|
3644
|
+
const bridgeDone = Promise.all([clientForwardingDone, responseForwardingDone]);
|
|
3645
|
+
const childAndResponsesDone = Promise.all([childExit, responseForwardingDone]).then(([exitCode]) => exitCode);
|
|
3306
3646
|
try {
|
|
3307
3647
|
return await Promise.race([childAndResponsesDone, bridgeDone.then(() => childExit)]);
|
|
3308
3648
|
} catch (error) {
|
|
@@ -3313,39 +3653,66 @@ async function runBridgedCodegraphProcess(command, args, options) {
|
|
|
3313
3653
|
return;
|
|
3314
3654
|
});
|
|
3315
3655
|
throw error;
|
|
3656
|
+
} finally {
|
|
3657
|
+
parentWatchdog.clear();
|
|
3316
3658
|
}
|
|
3317
3659
|
}
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3660
|
+
function terminateCodegraphChild(child) {
|
|
3661
|
+
if (child.exitCode !== null || child.signalCode !== null)
|
|
3662
|
+
return;
|
|
3663
|
+
child.kill("SIGTERM");
|
|
3664
|
+
const escalation = setTimeout(() => {
|
|
3665
|
+
if (child.exitCode === null && child.signalCode === null)
|
|
3666
|
+
child.kill("SIGKILL");
|
|
3667
|
+
}, SIGKILL_ESCALATION_MS);
|
|
3668
|
+
escalation.unref();
|
|
3669
|
+
}
|
|
3670
|
+
function isWatchdogTeardownError(error) {
|
|
3671
|
+
if (!(error instanceof Error) || !("code" in error))
|
|
3672
|
+
return false;
|
|
3673
|
+
return error.code === "ERR_STREAM_PREMATURE_CLOSE" || error.code === "ERR_STREAM_DESTROYED" || error.code === "ERR_STREAM_WRITE_AFTER_END" || error.code === "EPIPE";
|
|
3674
|
+
}
|
|
3675
|
+
async function forwardClientToCodegraph(input, childInput, pendingResponses, setDefaultResponseMode, tolerateWatchdogClose) {
|
|
3676
|
+
try {
|
|
3677
|
+
for await (const message of readStdioJsonRpcMessages(input)) {
|
|
3678
|
+
if (message.kind === "parse_error") {
|
|
3679
|
+
continue;
|
|
3680
|
+
}
|
|
3681
|
+
const responseMode = message.responseMode;
|
|
3682
|
+
setDefaultResponseMode(responseMode);
|
|
3683
|
+
const key = responseModeKey(message.payload);
|
|
3684
|
+
if (key !== null) {
|
|
3685
|
+
pendingResponses.set(key, {
|
|
3686
|
+
method: jsonRpcMethod(message.payload),
|
|
3687
|
+
responseMode,
|
|
3688
|
+
toolName: jsonRpcToolName(message.payload)
|
|
3689
|
+
});
|
|
3690
|
+
}
|
|
3691
|
+
await writeLine(childInput, JSON.stringify(message.payload));
|
|
3332
3692
|
}
|
|
3333
|
-
|
|
3693
|
+
childInput.end();
|
|
3694
|
+
} catch (error) {
|
|
3695
|
+
if (!(tolerateWatchdogClose() && isWatchdogTeardownError(error)))
|
|
3696
|
+
throw error;
|
|
3334
3697
|
}
|
|
3335
|
-
childInput.end();
|
|
3336
3698
|
}
|
|
3337
|
-
async function forwardCodegraphToClient(childOutput, output, pendingResponses, defaultResponseMode) {
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3699
|
+
async function forwardCodegraphToClient(childOutput, output, pendingResponses, defaultResponseMode, tolerateWatchdogClose) {
|
|
3700
|
+
try {
|
|
3701
|
+
for await (const message of readStdioJsonRpcMessages(childOutput)) {
|
|
3702
|
+
if (message.kind === "parse_error") {
|
|
3703
|
+
await writeStdioJsonRpcResponse(output, errorResponse(null, -32700, "Parse error", message.message), defaultResponseMode());
|
|
3704
|
+
continue;
|
|
3705
|
+
}
|
|
3706
|
+
const key = responseModeKey(message.payload);
|
|
3707
|
+
const pendingResponse = key === null ? undefined : pendingResponses.get(key);
|
|
3708
|
+
const responseMode = pendingResponse?.responseMode ?? defaultResponseMode();
|
|
3709
|
+
if (key !== null)
|
|
3710
|
+
pendingResponses.delete(key);
|
|
3711
|
+
await writeStdioJsonRpcResponse(output, clarifyCodegraphResponse(message.payload, pendingResponse), responseMode);
|
|
3342
3712
|
}
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
if (key !== null)
|
|
3347
|
-
pendingResponses.delete(key);
|
|
3348
|
-
await writeStdioJsonRpcResponse(output, clarifyCodegraphResponse(message.payload, pendingResponse), responseMode);
|
|
3713
|
+
} catch (error) {
|
|
3714
|
+
if (!(tolerateWatchdogClose() && isWatchdogTeardownError(error)))
|
|
3715
|
+
throw error;
|
|
3349
3716
|
}
|
|
3350
3717
|
}
|
|
3351
3718
|
function responseModeKey(payload) {
|
|
@@ -3477,7 +3844,8 @@ async function runUnavailableCodegraphMcpServer(options) {
|
|
|
3477
3844
|
serverVersion: options.serverVersion
|
|
3478
3845
|
},
|
|
3479
3846
|
input: options.input,
|
|
3480
|
-
output: options.output
|
|
3847
|
+
output: options.output,
|
|
3848
|
+
parentWatchdog: options.parentWatchdog ?? {}
|
|
3481
3849
|
});
|
|
3482
3850
|
}
|
|
3483
3851
|
async function handleUnavailableCodegraphMcpRequest(input, options) {
|
|
@@ -3521,7 +3889,7 @@ var CODEGRAPH_DISABLED_HINT = `CodeGraph MCP skipped: disabled by OMO SOT config
|
|
|
3521
3889
|
`;
|
|
3522
3890
|
var CODEGRAPH_EXCLUDED_HINT = `CodeGraph MCP skipped: project excluded by OMO CodeGraph policy.
|
|
3523
3891
|
`;
|
|
3524
|
-
var CODEGRAPH_VERSION2 =
|
|
3892
|
+
var CODEGRAPH_VERSION2 = CODEGRAPH_PINNED_VERSION;
|
|
3525
3893
|
var PROJECT_CWD_ENV_KEYS = ["OMO_CODEGRAPH_PROJECT_CWD", SESSION_START_CWD_ENV, "PWD"];
|
|
3526
3894
|
async function runCodegraphServe(options = {}) {
|
|
3527
3895
|
const env = options.env ?? processEnv3;
|
|
@@ -3569,7 +3937,7 @@ async function runCodegraphServe(options = {}) {
|
|
|
3569
3937
|
return runUnavailableMcp(buildCodegraphNodeSkipHint(nodeSupport), options);
|
|
3570
3938
|
}
|
|
3571
3939
|
const runProcess = options.runProcess ?? runBridgedCodegraphProcess;
|
|
3572
|
-
const codegraphEnv = codegraphEnvForConfig2(trustedInstallDir, homeDir, options.buildEnv);
|
|
3940
|
+
const codegraphEnv = codegraphEnvForConfig2(trustedInstallDir, homeDir, codegraphConfig.daemon === true, options.buildEnv);
|
|
3573
3941
|
const mergedEnv = buildCodegraphChildEnv({ ambientEnv: env, codegraphEnv, runtimeEnv: env });
|
|
3574
3942
|
return runProcess(resolution.command, [...resolution.argsPrefix, "serve", "--mcp"], {
|
|
3575
3943
|
cwd: projectCwd,
|
|
@@ -3577,7 +3945,8 @@ async function runCodegraphServe(options = {}) {
|
|
|
3577
3945
|
input: options.stdin ?? processStdin2,
|
|
3578
3946
|
output: options.stdout ?? processStdout2,
|
|
3579
3947
|
stderr: options.stderr ?? processStderr3,
|
|
3580
|
-
stdio: "pipe"
|
|
3948
|
+
stdio: "pipe",
|
|
3949
|
+
parentWatchdog: options.parentWatchdog ?? {}
|
|
3581
3950
|
});
|
|
3582
3951
|
}
|
|
3583
3952
|
async function runUnavailableMcp(reason, options) {
|
|
@@ -3586,7 +3955,8 @@ async function runUnavailableMcp(reason, options) {
|
|
|
3586
3955
|
input: options.stdin ?? processStdin2,
|
|
3587
3956
|
output: options.stdout ?? processStdout2,
|
|
3588
3957
|
reason,
|
|
3589
|
-
serverVersion: CODEGRAPH_VERSION2
|
|
3958
|
+
serverVersion: CODEGRAPH_VERSION2,
|
|
3959
|
+
parentWatchdog: options.parentWatchdog ?? {}
|
|
3590
3960
|
});
|
|
3591
3961
|
return 0;
|
|
3592
3962
|
}
|
|
@@ -3595,10 +3965,10 @@ async function provisionMissingCodegraph(options) {
|
|
|
3595
3965
|
return null;
|
|
3596
3966
|
if (options.config.auto_provision === false)
|
|
3597
3967
|
return null;
|
|
3598
|
-
const installDir = options.trustedInstallDir ??
|
|
3968
|
+
const installDir = options.trustedInstallDir ?? join15(options.homeDir, ".omo", "codegraph");
|
|
3599
3969
|
const result = await options.ensureProvisioned({
|
|
3600
3970
|
installDir,
|
|
3601
|
-
lockDir:
|
|
3971
|
+
lockDir: join15(installDir, ".locks"),
|
|
3602
3972
|
version: CODEGRAPH_VERSION2
|
|
3603
3973
|
});
|
|
3604
3974
|
if (!result.provisioned || result.binPath === undefined)
|
|
@@ -3615,8 +3985,8 @@ function shouldSkipResolvedCommand(resolution, commandExists) {
|
|
|
3615
3985
|
function looksLikePath2(command) {
|
|
3616
3986
|
return command.includes("/") || command.includes("\\");
|
|
3617
3987
|
}
|
|
3618
|
-
function codegraphEnvForConfig2(trustedInstallDir, homeDir, buildEnv) {
|
|
3619
|
-
const env =
|
|
3988
|
+
function codegraphEnvForConfig2(trustedInstallDir, homeDir, daemon, buildEnv) {
|
|
3989
|
+
const env = buildEnv?.({ daemon, homeDir }) ?? buildCodegraphEnv({ daemon, homeDir });
|
|
3620
3990
|
return trustedInstallDir === undefined ? env : { ...env, CODEGRAPH_INSTALL_DIR: trustedInstallDir };
|
|
3621
3991
|
}
|
|
3622
3992
|
function resolveProjectCwd(env, fallback) {
|
|
@@ -3624,16 +3994,16 @@ function resolveProjectCwd(env, fallback) {
|
|
|
3624
3994
|
const candidate = env[key]?.trim();
|
|
3625
3995
|
if (candidate === undefined || candidate.length === 0)
|
|
3626
3996
|
continue;
|
|
3627
|
-
const resolved =
|
|
3997
|
+
const resolved = resolve7(candidate);
|
|
3628
3998
|
if (existsSync10(resolved))
|
|
3629
3999
|
return resolved;
|
|
3630
4000
|
}
|
|
3631
|
-
return
|
|
4001
|
+
return resolve7(fallback);
|
|
3632
4002
|
}
|
|
3633
4003
|
function provisionedBinFromInstallDir3(installDir) {
|
|
3634
4004
|
if (installDir === undefined)
|
|
3635
4005
|
return null;
|
|
3636
|
-
const candidate =
|
|
4006
|
+
const candidate = join15(installDir, "bin", process.platform === "win32" ? "codegraph.cmd" : "codegraph");
|
|
3637
4007
|
return existsSync10(candidate) ? candidate : null;
|
|
3638
4008
|
}
|
|
3639
4009
|
async function runCodegraphServeCli() {
|
|
@@ -3653,7 +4023,7 @@ function isDirectInvocation(argvPath) {
|
|
|
3653
4023
|
const moduleName = basename4(modulePath);
|
|
3654
4024
|
if (moduleName !== "serve.js" && moduleName !== "serve.ts")
|
|
3655
4025
|
return false;
|
|
3656
|
-
return
|
|
4026
|
+
return realpathSync6(resolve7(argvPath)) === realpathSync6(modulePath);
|
|
3657
4027
|
}
|
|
3658
4028
|
|
|
3659
4029
|
// components/codegraph/src/sweep-cli.ts
|
|
@@ -3700,6 +4070,7 @@ function writeSweepReport(stdout, result) {
|
|
|
3700
4070
|
failed: result.failed,
|
|
3701
4071
|
killed: result.killed.map(formatProcess),
|
|
3702
4072
|
ownedRoots: result.ownedRoots,
|
|
4073
|
+
spared: result.spared.map(formatProcess),
|
|
3703
4074
|
stampFile: result.stampFile
|
|
3704
4075
|
})}
|
|
3705
4076
|
`);
|
|
@@ -3763,7 +4134,7 @@ function isDirectInvocation2(argvPath) {
|
|
|
3763
4134
|
const moduleName = basename5(modulePath);
|
|
3764
4135
|
if (moduleName !== "cli.js" && moduleName !== "cli.ts")
|
|
3765
4136
|
return false;
|
|
3766
|
-
return
|
|
4137
|
+
return realpathSync7(resolve8(argvPath)) === realpathSync7(modulePath);
|
|
3767
4138
|
}
|
|
3768
4139
|
export {
|
|
3769
4140
|
runCodegraphCli
|