oh-my-opencode 4.19.0 → 4.19.2
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 +6 -6
- package/README.ru.md +6 -6
- package/README.zh-cn.md +6 -6
- package/dist/agents/atlas/agent.d.ts +5 -3
- package/dist/agents/explore.d.ts +4 -2
- package/dist/agents/gpt-prompt-identity.d.ts +3 -0
- package/dist/agents/hephaestus/agent.d.ts +4 -2
- package/dist/agents/librarian.d.ts +4 -2
- package/dist/agents/metis.d.ts +4 -2
- package/dist/agents/momus.d.ts +3 -2
- package/dist/agents/multimodal-looker.d.ts +4 -2
- package/dist/agents/oracle.d.ts +4 -2
- package/dist/agents/sisyphus/claude-opus-5.d.ts +33 -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 +2 -0
- package/dist/agents/sisyphus-agent-factory.d.ts +5 -2
- package/dist/agents/sisyphus-junior/agent.d.ts +4 -1
- package/dist/agents/sisyphus-junior/gpt-5-5.d.ts +2 -2
- package/dist/agents/types.d.ts +2 -2
- package/dist/cli/index.js +23577 -19269
- package/dist/cli-node/index.js +23577 -19269
- package/dist/config/schema/agent-names.d.ts +26 -26
- package/dist/config/schema/agent-overrides.d.ts +400 -400
- package/dist/config/schema/browser-automation.d.ts +2 -2
- package/dist/config/schema/categories.d.ts +36 -36
- package/dist/config/schema/codegraph.d.ts +2 -0
- package/dist/config/schema/commands.d.ts +2 -2
- package/dist/config/schema/dynamic-context-pruning.d.ts +1 -1
- package/dist/config/schema/experimental.d.ts +1 -1
- package/dist/config/schema/fallback-models.d.ts +25 -25
- package/dist/config/schema/hooks.d.ts +43 -43
- package/dist/config/schema/internal/permission.d.ts +9 -9
- package/dist/config/schema/keyword-detector.d.ts +6 -6
- package/dist/config/schema/oh-my-opencode-config.d.ts +404 -402
- package/dist/config/schema/tmux.d.ts +6 -6
- package/dist/create-hooks.d.ts +35 -35
- package/dist/features/background-agent/spawner/tmux-callback-invoker.d.ts +11 -0
- package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
- package/dist/features/claude-tasks/types.d.ts +4 -4
- package/dist/features/team-mode/team-runtime/shutdown-helpers.d.ts +1 -1
- package/dist/features/team-mode/team-runtime/shutdown-test-fixtures.d.ts +4 -4
- package/dist/features/team-mode/tools/lifecycle-test-fixture.d.ts +42 -42
- package/dist/features/tmux-subagent/environment-eligibility.d.ts +2 -0
- package/dist/features/tmux-subagent/index.d.ts +1 -0
- package/dist/features/tmux-subagent/tracked-session-state.d.ts +1 -0
- package/dist/features/tui-sidebar/snapshot-schema.d.ts +6 -6
- package/dist/help/schema/acp.d.ts +3 -3
- package/dist/help/schema/doctor.d.ts +4 -4
- package/dist/help/schema/status.d.ts +3 -3
- package/dist/hooks/codegraph-bootstrap/hook.d.ts +3 -2
- package/dist/hooks/goal/types.d.ts +5 -5
- package/dist/hooks/non-interactive-env/constants.d.ts +4 -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/hooks/start-work/parse-user-request.d.ts +2 -0
- package/dist/hooks/start-work/worktree-block.d.ts +5 -0
- package/dist/index.js +27370 -21301
- package/dist/mcp/types.d.ts +3 -3
- package/dist/oh-my-opencode.schema.json +11 -0
- package/dist/plugin/chat-message/loop-commands.d.ts +1 -0
- package/dist/plugin/command-execute-before.d.ts +3 -3
- package/dist/plugin/hooks/create-core-hooks.d.ts +25 -25
- package/dist/shared/omo-process-sweep.d.ts +18 -0
- package/dist/shared/tmux/tmux-utils/environment.d.ts +1 -1
- package/dist/shared/tmux/tmux-utils.d.ts +1 -1
- package/dist/shared/typescript-native-source-parser.d.ts +7 -0
- package/dist/skills/coding-agent-sessions/SKILL.md +5 -2
- package/dist/skills/coding-agent-sessions/references/all-platforms.md +3 -1
- package/dist/skills/coding-agent-sessions/references/senpi.md +15 -5
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
- package/dist/skills/debugging/SKILL.md +2 -1
- package/dist/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
- package/dist/skills/programming/SKILL.md +11 -1
- package/dist/skills/programming/references/logging.md +6 -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 +75 -11
- package/dist/skills/start-work/SKILL.md +12 -2
- package/dist/skills/ulw-plan/SKILL.md +21 -2
- package/dist/skills/ulw-plan/references/full-workflow.md +12 -1
- package/dist/skills/ulw-plan/references/intent-clear.md +1 -1
- package/dist/testing/create-plugin-module.d.ts +1 -0
- package/dist/tools/task/types.d.ts +10 -10
- package/dist/tui.js +23442 -19182
- 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 +62 -2
- 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 +72 -12
- 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/dist/cli.js +779 -385
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +302 -173
- 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 +23 -42
- 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 +17 -9
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +18 -25
- 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 +5 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +176 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +6 -1
- 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/provisioned-node-guard.test.ts +6 -0
- 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 +2 -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 +42 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +122 -10
- 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 +101 -64
- 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/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/directive.md +1 -1
- 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/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/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/plan.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +12 -7
- 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/ultrawork/SKILL.md +12 -7
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +21 -2
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +12 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +1 -1
- 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/directive.md +12 -7
- 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/SKILL.md +2 -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/shared/test/config-loader.test.ts +44 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +5 -2
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +3 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +15 -5
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
- package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -1
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
- package/packages/omo-codex/plugin/skills/programming/SKILL.md +11 -1
- package/packages/omo-codex/plugin/skills/programming/references/logging.md +6 -1
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +12 -2
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +12 -7
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +8 -6
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +21 -2
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +12 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +1 -1
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +9 -9
- 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/sync-skills-orchestration.test.mjs +22 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +49 -5
- package/packages/omo-codex/scripts/install-marketplace-cache.test.mjs +4 -1
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +5 -2
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +3 -1
- package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +15 -5
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
- package/packages/shared-skills/skills/debugging/SKILL.md +2 -1
- package/packages/shared-skills/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
- package/packages/shared-skills/skills/programming/SKILL.md +11 -1
- package/packages/shared-skills/skills/programming/references/logging.md +6 -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 +75 -11
- package/packages/shared-skills/skills/start-work/SKILL.md +12 -2
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +21 -2
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +12 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/serve.ts
|
|
4
|
-
import { existsSync as
|
|
4
|
+
import { existsSync as existsSync6, realpathSync as realpathSync2 } from "node:fs";
|
|
5
5
|
import { homedir as homedir7 } from "node:os";
|
|
6
|
-
import { basename as basename3, join as
|
|
6
|
+
import { basename as basename3, join as join8, resolve as resolve4 } from "node:path";
|
|
7
7
|
import {
|
|
8
8
|
cwd as processCwd,
|
|
9
9
|
env as processEnv,
|
|
@@ -50,6 +50,7 @@ var SAFE_AMBIENT_ENV_KEYS = new Set([
|
|
|
50
50
|
var SAFE_CODEGRAPH_RUNTIME_ENV_KEYS = new Set([
|
|
51
51
|
"CODEGRAPH_ALLOW_UNSAFE_NODE",
|
|
52
52
|
"CODEGRAPH_BIN",
|
|
53
|
+
"CODEGRAPH_DAEMON_IDLE_TIMEOUT_MS",
|
|
53
54
|
"CODEGRAPH_FAKE_LOG",
|
|
54
55
|
"CODEGRAPH_NO_DAEMON",
|
|
55
56
|
"CODEGRAPH_NODE_BIN",
|
|
@@ -61,7 +62,7 @@ function buildCodegraphEnv(options = {}) {
|
|
|
61
62
|
const homeDir = options.homeDir ?? homedir();
|
|
62
63
|
return {
|
|
63
64
|
[CODEGRAPH_INSTALL_DIR_ENV]: join(homeDir, ".omo", "codegraph"),
|
|
64
|
-
[CODEGRAPH_NO_DAEMON_ENV]: "1",
|
|
65
|
+
...options.daemon === false ? { [CODEGRAPH_NO_DAEMON_ENV]: "1" } : {},
|
|
65
66
|
[CODEGRAPH_NO_DOWNLOAD_ENV]: "1",
|
|
66
67
|
[CODEGRAPH_TELEMETRY_ENV]: "0",
|
|
67
68
|
[DO_NOT_TRACK_ENV]: "1"
|
|
@@ -88,6 +89,91 @@ function buildCodegraphChildEnv(options = {}) {
|
|
|
88
89
|
return env;
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
// ../../../../utils/src/codegraph/managed-runtime.ts
|
|
93
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
94
|
+
import { join as join2, resolve } from "node:path";
|
|
95
|
+
|
|
96
|
+
// ../../../../utils/src/record-type-guard.ts
|
|
97
|
+
function isPlainRecord(value) {
|
|
98
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ../../../../utils/src/codegraph/manifest.ts
|
|
102
|
+
var CODEGRAPH_PINNED_VERSION = "1.4.1";
|
|
103
|
+
var CODEGRAPH_PROVISION_MANIFEST = {
|
|
104
|
+
assets: {
|
|
105
|
+
"darwin-arm64": {
|
|
106
|
+
executableName: "codegraph",
|
|
107
|
+
sha256: "4a679ae5a5cb9fff900dd59bb786da6a581b7f68f4cf713bdedd137e347d34dc",
|
|
108
|
+
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.4.1/codegraph-darwin-arm64.tar.gz"
|
|
109
|
+
},
|
|
110
|
+
"darwin-x64": {
|
|
111
|
+
executableName: "codegraph",
|
|
112
|
+
sha256: "436f96943cfd926ea6d0a8454f18833d21254d5fd9b3d224317b1426132def95",
|
|
113
|
+
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.4.1/codegraph-darwin-x64.tar.gz"
|
|
114
|
+
},
|
|
115
|
+
"linux-arm64": {
|
|
116
|
+
executableName: "codegraph",
|
|
117
|
+
sha256: "0d62c5eb2722f8d19d20f7a1bd974445e18d5294cb59be116a0c3d55ce87591f",
|
|
118
|
+
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.4.1/codegraph-linux-arm64.tar.gz"
|
|
119
|
+
},
|
|
120
|
+
"linux-x64": {
|
|
121
|
+
executableName: "codegraph",
|
|
122
|
+
sha256: "fb585ff5018d6faaa46d282b61f4f689bc7967ed8a1b467a5c556dd7ced9b542",
|
|
123
|
+
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.4.1/codegraph-linux-x64.tar.gz"
|
|
124
|
+
},
|
|
125
|
+
"win32-arm64": {
|
|
126
|
+
executableName: "codegraph.cmd",
|
|
127
|
+
sha256: "e2a2a28c802a79804c7df203afa50bd461309c6c180ce3f76079fdc7cddc7697",
|
|
128
|
+
url: "https://registry.npmjs.org/@colbymchenry/codegraph-win32-arm64/-/codegraph-win32-arm64-1.4.1.tgz"
|
|
129
|
+
},
|
|
130
|
+
"win32-x64": {
|
|
131
|
+
executableName: "codegraph.cmd",
|
|
132
|
+
sha256: "4f08700fda5f4a03ad5b2956135c5788d739a351b3433db2b5820e5d5224c30d",
|
|
133
|
+
url: "https://registry.npmjs.org/@colbymchenry/codegraph-win32-x64/-/codegraph-win32-x64-1.4.1.tgz"
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
version: CODEGRAPH_PINNED_VERSION
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// ../../../../utils/src/codegraph/managed-runtime.ts
|
|
140
|
+
function resolvePinnedCodegraphBin(installDir, options = {}) {
|
|
141
|
+
if (installDir === undefined)
|
|
142
|
+
return null;
|
|
143
|
+
const fileExists = options.fileExists ?? existsSync;
|
|
144
|
+
const readText = options.readText ?? ((filePath) => readFileSync(filePath, "utf8"));
|
|
145
|
+
const expectedBin = join2(installDir, "bin", (options.platform ?? process.platform) === "win32" ? "codegraph.cmd" : "codegraph");
|
|
146
|
+
const markerPath = join2(installDir, ".provisioned", `codegraph-${CODEGRAPH_PINNED_VERSION}.json`);
|
|
147
|
+
if (!fileExists(expectedBin) || !fileExists(markerPath))
|
|
148
|
+
return null;
|
|
149
|
+
let markerText;
|
|
150
|
+
try {
|
|
151
|
+
markerText = readText(markerPath);
|
|
152
|
+
} catch {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
const marker = parseProvisionMarker(markerText);
|
|
156
|
+
if (marker === null || marker.version !== CODEGRAPH_PINNED_VERSION)
|
|
157
|
+
return null;
|
|
158
|
+
return resolve(marker.binPath) === resolve(expectedBin) ? expectedBin : null;
|
|
159
|
+
}
|
|
160
|
+
function parseProvisionMarker(text) {
|
|
161
|
+
try {
|
|
162
|
+
const value = JSON.parse(text);
|
|
163
|
+
if (!isPlainRecord(value))
|
|
164
|
+
return null;
|
|
165
|
+
const binPath = value["binPath"];
|
|
166
|
+
const version = value["version"];
|
|
167
|
+
if (typeof binPath !== "string" || typeof version !== "string")
|
|
168
|
+
return null;
|
|
169
|
+
return { binPath, version };
|
|
170
|
+
} catch (error) {
|
|
171
|
+
if (error instanceof SyntaxError)
|
|
172
|
+
return null;
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
91
177
|
// ../../../../utils/src/codegraph/node-support.ts
|
|
92
178
|
var CODEGRAPH_MIN_NODE_MAJOR = 20;
|
|
93
179
|
var CODEGRAPH_BLOCKED_NODE_MAJOR = 25;
|
|
@@ -121,49 +207,10 @@ function parseNodeMajor(version) {
|
|
|
121
207
|
import { createHash, randomUUID } from "node:crypto";
|
|
122
208
|
import { execFile } from "node:child_process";
|
|
123
209
|
import { chmod, mkdir, readdir, readFile, rename, rm, rmdir, stat, writeFile } from "node:fs/promises";
|
|
124
|
-
import { existsSync } from "node:fs";
|
|
210
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
125
211
|
import { homedir as homedir2, hostname } from "node:os";
|
|
126
|
-
import { basename, join as
|
|
212
|
+
import { basename, join as join3 } from "node:path";
|
|
127
213
|
import { promisify } from "node:util";
|
|
128
|
-
|
|
129
|
-
// ../../../../utils/src/codegraph/manifest.ts
|
|
130
|
-
var CODEGRAPH_PROVISION_MANIFEST = {
|
|
131
|
-
assets: {
|
|
132
|
-
"darwin-arm64": {
|
|
133
|
-
executableName: "codegraph",
|
|
134
|
-
sha256: "95bb27bf6382b69659e158e0c04d71cc394778951e1317d582be7807e7866908",
|
|
135
|
-
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.0.1/codegraph-darwin-arm64.tar.gz"
|
|
136
|
-
},
|
|
137
|
-
"darwin-x64": {
|
|
138
|
-
executableName: "codegraph",
|
|
139
|
-
sha256: "3311cc1d1f0f0ad742709b6a43d8a9187b1ef0af0dd30e0b58008dc673e29478",
|
|
140
|
-
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.0.1/codegraph-darwin-x64.tar.gz"
|
|
141
|
-
},
|
|
142
|
-
"linux-arm64": {
|
|
143
|
-
executableName: "codegraph",
|
|
144
|
-
sha256: "e16f612bc96c2ebccd04574cbed500c9939147c80666ad6bb024398dff7992ae",
|
|
145
|
-
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.0.1/codegraph-linux-arm64.tar.gz"
|
|
146
|
-
},
|
|
147
|
-
"linux-x64": {
|
|
148
|
-
executableName: "codegraph",
|
|
149
|
-
sha256: "d45a068f44596a85c7ba7d0ef924eaf7103fbbf3cafbeb668127daff60a52228",
|
|
150
|
-
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.0.1/codegraph-linux-x64.tar.gz"
|
|
151
|
-
},
|
|
152
|
-
"win32-arm64": {
|
|
153
|
-
executableName: "codegraph.cmd",
|
|
154
|
-
sha256: "8d57ced73b24d35f758f2ede2318e80e1d7241987f37a999e3d80edb6fddf961",
|
|
155
|
-
url: "https://registry.npmjs.org/@colbymchenry/codegraph-win32-arm64/-/codegraph-win32-arm64-1.0.1.tgz"
|
|
156
|
-
},
|
|
157
|
-
"win32-x64": {
|
|
158
|
-
executableName: "codegraph.cmd",
|
|
159
|
-
sha256: "52607fe73b05e741fd1087da2ceca9d3c8f565e36bf1a7070600bdbdf3931e32",
|
|
160
|
-
url: "https://registry.npmjs.org/@colbymchenry/codegraph-win32-x64/-/codegraph-win32-x64-1.0.1.tgz"
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
version: "1.0.1"
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
// ../../../../utils/src/codegraph/provision.ts
|
|
167
214
|
var DEFAULT_LOCK_WAIT_MS = 5000;
|
|
168
215
|
var DEFAULT_LOCK_STALE_MS = 120000;
|
|
169
216
|
var DEFAULT_DOWNLOAD_TIMEOUT_MS = 60000;
|
|
@@ -172,10 +219,10 @@ function platformKey() {
|
|
|
172
219
|
return `${process.platform}-${process.arch}`;
|
|
173
220
|
}
|
|
174
221
|
function markerPath(installDir, version) {
|
|
175
|
-
return
|
|
222
|
+
return join3(installDir, ".provisioned", `codegraph-${version}.json`);
|
|
176
223
|
}
|
|
177
224
|
function defaultInstallDir() {
|
|
178
|
-
return
|
|
225
|
+
return join3(homedir2(), ".omo", "codegraph");
|
|
179
226
|
}
|
|
180
227
|
function sha256(bytes) {
|
|
181
228
|
return createHash("sha256").update(bytes).digest("hex");
|
|
@@ -195,7 +242,7 @@ async function removeEmptyDirectory(path) {
|
|
|
195
242
|
}
|
|
196
243
|
}
|
|
197
244
|
function sleep(ms) {
|
|
198
|
-
return new Promise((
|
|
245
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
199
246
|
}
|
|
200
247
|
async function defaultDownloader(asset, timeoutMs = DEFAULT_DOWNLOAD_TIMEOUT_MS) {
|
|
201
248
|
const response = await fetch(asset.url, { signal: AbortSignal.timeout(timeoutMs) });
|
|
@@ -209,7 +256,7 @@ function forcedBadChecksumOptions(options) {
|
|
|
209
256
|
const key = options.platformKey ?? platformKey();
|
|
210
257
|
return {
|
|
211
258
|
downloader: async () => new TextEncoder().encode("checksum mismatch"),
|
|
212
|
-
installDir: options.installDir ??
|
|
259
|
+
installDir: options.installDir ?? join3(options.lockDir, "codegraph-force-bad-checksum"),
|
|
213
260
|
manifest: {
|
|
214
261
|
assets: {
|
|
215
262
|
[key]: { executableName: process.platform === "win32" ? "codegraph.cmd" : "codegraph", sha256: "0000", url: "memory://bad" }
|
|
@@ -220,13 +267,13 @@ function forcedBadChecksumOptions(options) {
|
|
|
220
267
|
};
|
|
221
268
|
}
|
|
222
269
|
async function readMarker(path) {
|
|
223
|
-
if (!
|
|
270
|
+
if (!existsSync2(path))
|
|
224
271
|
return null;
|
|
225
272
|
try {
|
|
226
273
|
const raw = JSON.parse(await readFile(path, "utf8"));
|
|
227
274
|
if (typeof raw === "object" && raw !== null && "binPath" in raw) {
|
|
228
275
|
const value = raw.binPath;
|
|
229
|
-
return typeof value === "string" &&
|
|
276
|
+
return typeof value === "string" && existsSync2(value) ? value : null;
|
|
230
277
|
}
|
|
231
278
|
return null;
|
|
232
279
|
} catch (error) {
|
|
@@ -237,7 +284,7 @@ async function readMarker(path) {
|
|
|
237
284
|
}
|
|
238
285
|
async function acquireLock(lockPath, waitMs, staleMs) {
|
|
239
286
|
const startedAt = Date.now();
|
|
240
|
-
await mkdir(
|
|
287
|
+
await mkdir(join3(lockPath, ".."), { recursive: true });
|
|
241
288
|
while (Date.now() - startedAt <= waitMs) {
|
|
242
289
|
try {
|
|
243
290
|
await mkdir(lockPath);
|
|
@@ -262,24 +309,24 @@ async function installExtractedBundle(extractDir, installDir, executableName) {
|
|
|
262
309
|
const roots = await readdir(extractDir);
|
|
263
310
|
if (roots.length !== 1)
|
|
264
311
|
throw new Error(`CodeGraph archive should contain one root directory, found ${roots.length}`);
|
|
265
|
-
const bundleDir =
|
|
312
|
+
const bundleDir = join3(extractDir, roots[0] ?? "");
|
|
266
313
|
const bundleEntries = await readdir(bundleDir);
|
|
267
314
|
await mkdir(installDir, { recursive: true });
|
|
268
315
|
for (const entry of bundleEntries) {
|
|
269
|
-
await rm(
|
|
270
|
-
await rename(
|
|
316
|
+
await rm(join3(installDir, entry), { force: true, recursive: true });
|
|
317
|
+
await rename(join3(bundleDir, entry), join3(installDir, entry));
|
|
271
318
|
}
|
|
272
|
-
const destination =
|
|
273
|
-
if (!
|
|
319
|
+
const destination = join3(installDir, "bin", executableName);
|
|
320
|
+
if (!existsSync2(destination))
|
|
274
321
|
throw new Error(`CodeGraph archive did not contain bin/${executableName}`);
|
|
275
322
|
await chmod(destination, 493);
|
|
276
323
|
return destination;
|
|
277
324
|
}
|
|
278
325
|
async function installAsset(layout) {
|
|
279
326
|
const { asset, downloader, installDir, version } = layout;
|
|
280
|
-
const stagingDir =
|
|
281
|
-
const archivePath =
|
|
282
|
-
const extractDir =
|
|
327
|
+
const stagingDir = join3(installDir, ".staging", randomUUID());
|
|
328
|
+
const archivePath = join3(stagingDir, basename(asset.url));
|
|
329
|
+
const extractDir = join3(stagingDir, "extract");
|
|
283
330
|
try {
|
|
284
331
|
await mkdir(extractDir, { recursive: true });
|
|
285
332
|
const bytes = await downloader(asset);
|
|
@@ -293,13 +340,13 @@ async function installAsset(layout) {
|
|
|
293
340
|
await writeFile(archivePath, bytes);
|
|
294
341
|
await extractTarGz(archivePath, extractDir);
|
|
295
342
|
const destination = await installExtractedBundle(extractDir, installDir, asset.executableName);
|
|
296
|
-
await mkdir(
|
|
343
|
+
await mkdir(join3(installDir, ".provisioned"), { recursive: true });
|
|
297
344
|
await writeFile(markerPath(installDir, version), `${JSON.stringify({ binPath: destination, version })}
|
|
298
345
|
`);
|
|
299
346
|
return destination;
|
|
300
347
|
} finally {
|
|
301
348
|
await rm(stagingDir, { force: true, recursive: true });
|
|
302
|
-
await removeEmptyDirectory(
|
|
349
|
+
await removeEmptyDirectory(join3(installDir, ".staging"));
|
|
303
350
|
}
|
|
304
351
|
}
|
|
305
352
|
async function ensureCodegraphProvisioned(options) {
|
|
@@ -312,7 +359,7 @@ async function ensureCodegraphProvisioned(options) {
|
|
|
312
359
|
const existing = await readMarker(marker);
|
|
313
360
|
if (existing !== null)
|
|
314
361
|
return { binPath: existing, provisioned: true };
|
|
315
|
-
const lockPath =
|
|
362
|
+
const lockPath = join3(options.lockDir, `codegraph-${hostname()}.lock`);
|
|
316
363
|
const release = await acquireLock(lockPath, options.lockWaitMs ?? DEFAULT_LOCK_WAIT_MS, options.lockStaleMs ?? DEFAULT_LOCK_STALE_MS);
|
|
317
364
|
if (release === null)
|
|
318
365
|
return { error: "timed out waiting for codegraph provisioning lock", provisioned: false };
|
|
@@ -337,15 +384,15 @@ async function ensureCodegraphProvisioned(options) {
|
|
|
337
384
|
}
|
|
338
385
|
|
|
339
386
|
// ../../../../utils/src/codegraph/resolve.ts
|
|
340
|
-
import { existsSync as
|
|
387
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
341
388
|
import { homedir as homedir3 } from "node:os";
|
|
342
389
|
import { spawnSync } from "node:child_process";
|
|
343
|
-
import { basename as basename2, dirname, join as
|
|
390
|
+
import { basename as basename2, dirname, join as join5 } from "node:path";
|
|
344
391
|
import { createRequire } from "node:module";
|
|
345
392
|
|
|
346
393
|
// ../../../../utils/src/runtime/which.ts
|
|
347
394
|
import { accessSync, constants } from "node:fs";
|
|
348
|
-
import { delimiter, join as
|
|
395
|
+
import { delimiter, join as join4 } from "node:path";
|
|
349
396
|
var runtime = globalThis;
|
|
350
397
|
function isUnsafeCommandName(commandName) {
|
|
351
398
|
if (commandName.includes("/") || commandName.includes("\\"))
|
|
@@ -400,7 +447,7 @@ function bunWhich(commandName) {
|
|
|
400
447
|
return null;
|
|
401
448
|
for (const pathEntry of pathEntries) {
|
|
402
449
|
for (const candidateName of candidateNames) {
|
|
403
|
-
const candidatePath =
|
|
450
|
+
const candidatePath = join4(pathEntry, candidateName);
|
|
404
451
|
if (isExecutable(candidatePath))
|
|
405
452
|
return candidatePath;
|
|
406
453
|
}
|
|
@@ -488,18 +535,13 @@ function defaultNodeRuntime(env, fileExists, which, nodeVersion) {
|
|
|
488
535
|
return null;
|
|
489
536
|
}
|
|
490
537
|
function defaultProvisionedBin(homeDir, fileExists) {
|
|
491
|
-
|
|
492
|
-
const candidates = [
|
|
493
|
-
join4(homeDir, ".omo", "codegraph", "bin", binaryName),
|
|
494
|
-
join4(homeDir, ".omo", "codegraph", "node-servers", "node_modules", ".bin", binaryName)
|
|
495
|
-
];
|
|
496
|
-
return candidates.find((candidate) => fileExists(candidate)) ?? null;
|
|
538
|
+
return resolvePinnedCodegraphBin(join5(homeDir, ".omo", "codegraph"), { fileExists });
|
|
497
539
|
}
|
|
498
540
|
function resolveBundledShim(requireResolve, fileExists) {
|
|
499
541
|
try {
|
|
500
542
|
const packageJson = requireResolve(`${CODEGRAPH_PACKAGE}/package.json`);
|
|
501
543
|
const packageRoot = dirname(packageJson);
|
|
502
|
-
const candidates = [
|
|
544
|
+
const candidates = [join5(packageRoot, "bin", "codegraph.js"), join5(packageRoot, "npm-shim.js")];
|
|
503
545
|
return candidates.find((candidate) => fileExists(candidate)) ?? null;
|
|
504
546
|
} catch (error) {
|
|
505
547
|
if (error instanceof Error)
|
|
@@ -515,7 +557,7 @@ function resolveBundledShim(requireResolve, fileExists) {
|
|
|
515
557
|
}
|
|
516
558
|
function resolveCodegraphCommand(options = {}) {
|
|
517
559
|
const env = options.env ?? process.env;
|
|
518
|
-
const fileExists = options.fileExists ??
|
|
560
|
+
const fileExists = options.fileExists ?? existsSync3;
|
|
519
561
|
const configuredBin = env[CODEGRAPH_ENV_BIN]?.trim() || env[CODEGRAPH_LEGACY_ENV_BIN]?.trim();
|
|
520
562
|
if (configuredBin !== undefined && configuredBin.length > 0) {
|
|
521
563
|
return { argsPrefix: [], command: configuredBin, exists: fileExists(configuredBin), source: "env" };
|
|
@@ -543,13 +585,13 @@ function resolveCodegraphCommand(options = {}) {
|
|
|
543
585
|
// ../../../../utils/src/codegraph/exclusion.ts
|
|
544
586
|
import { realpathSync } from "node:fs";
|
|
545
587
|
import { homedir as homedir4, tmpdir as osTmpdir } from "node:os";
|
|
546
|
-
import { isAbsolute, join as
|
|
588
|
+
import { isAbsolute, join as join6, resolve as resolve2 } from "node:path";
|
|
547
589
|
var POSIX_DEFAULT_EXCLUDED_ROOTS = ["/tmp", "/private/tmp"];
|
|
548
590
|
function expandHome(path, homeDir) {
|
|
549
591
|
if (path === "~")
|
|
550
592
|
return homeDir;
|
|
551
593
|
if (path.startsWith("~/") || path.startsWith("~\\"))
|
|
552
|
-
return
|
|
594
|
+
return join6(homeDir, path.slice(2));
|
|
553
595
|
return path;
|
|
554
596
|
}
|
|
555
597
|
function realpathIfPossible(path) {
|
|
@@ -557,13 +599,13 @@ function realpathIfPossible(path) {
|
|
|
557
599
|
return realpathSync(path);
|
|
558
600
|
} catch (error) {
|
|
559
601
|
if (error instanceof Error)
|
|
560
|
-
return
|
|
602
|
+
return resolve2(path);
|
|
561
603
|
throw error;
|
|
562
604
|
}
|
|
563
605
|
}
|
|
564
606
|
function resolveConfiguredRoot(path, homeDir) {
|
|
565
607
|
const expanded = expandHome(path, homeDir);
|
|
566
|
-
return realpathIfPossible(isAbsolute(expanded) ? expanded :
|
|
608
|
+
return realpathIfPossible(isAbsolute(expanded) ? expanded : join6(homeDir, expanded));
|
|
567
609
|
}
|
|
568
610
|
function normalizeForComparison(path, platform) {
|
|
569
611
|
const normalized = path.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
@@ -584,12 +626,12 @@ function shouldExcludeCodegraphProject(workspace, options = {}) {
|
|
|
584
626
|
const platform = options.platform ?? process.platform;
|
|
585
627
|
const homeDir = options.homeDir ?? homedir4();
|
|
586
628
|
const tmpdir = options.tmpdir ?? osTmpdir();
|
|
587
|
-
const resolvedWorkspace = realpathIfPossible(
|
|
629
|
+
const resolvedWorkspace = realpathIfPossible(resolve2(workspace));
|
|
588
630
|
if (hasOmoPathSegment(resolvedWorkspace)) {
|
|
589
631
|
return { excluded: true, matchedRoot: ".omo", reason: "omo-state" };
|
|
590
632
|
}
|
|
591
633
|
for (const root of defaultExcludedRoots(platform, tmpdir)) {
|
|
592
|
-
const resolvedRoot = realpathIfPossible(
|
|
634
|
+
const resolvedRoot = realpathIfPossible(resolve2(root));
|
|
593
635
|
if (pathIsWithin(resolvedWorkspace, resolvedRoot, platform)) {
|
|
594
636
|
return { excluded: true, matchedRoot: root, reason: "tmp-root" };
|
|
595
637
|
}
|
|
@@ -609,11 +651,11 @@ function shouldExcludeCodegraphProject(workspace, options = {}) {
|
|
|
609
651
|
import { homedir as homedir6 } from "node:os";
|
|
610
652
|
|
|
611
653
|
// ../../../../utils/src/omo-config/loader.ts
|
|
612
|
-
import { existsSync as
|
|
654
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
613
655
|
import { homedir as homedir5 } from "node:os";
|
|
614
656
|
|
|
615
657
|
// ../../../../utils/src/omo-config/body.ts
|
|
616
|
-
import { readFileSync } from "node:fs";
|
|
658
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
617
659
|
|
|
618
660
|
// ../../../../utils/src/deep-merge.ts
|
|
619
661
|
var DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
@@ -1490,8 +1532,9 @@ function parseJsoncSafe(content) {
|
|
|
1490
1532
|
var HARNESS_IDS = ["codex", "opencode", "omo"];
|
|
1491
1533
|
var SETTING_HARNESS_SUPPORT = {
|
|
1492
1534
|
"codegraph.auto_provision": HARNESS_IDS,
|
|
1535
|
+
"codegraph.daemon": ["codex", "opencode"],
|
|
1493
1536
|
"codegraph.enabled": HARNESS_IDS,
|
|
1494
|
-
"codegraph.excluded_roots": ["codex"],
|
|
1537
|
+
"codegraph.excluded_roots": ["codex", "opencode"],
|
|
1495
1538
|
"codegraph.install_dir": HARNESS_IDS,
|
|
1496
1539
|
"codegraph.telemetry": HARNESS_IDS,
|
|
1497
1540
|
"codegraph.watch_debounce_ms": ["opencode", "omo"]
|
|
@@ -1501,6 +1544,7 @@ var SETTING_HARNESS_SUPPORT = {
|
|
|
1501
1544
|
var BUILT_IN_DEFAULTS = {
|
|
1502
1545
|
codegraph: {
|
|
1503
1546
|
auto_provision: true,
|
|
1547
|
+
daemon: true,
|
|
1504
1548
|
enabled: true,
|
|
1505
1549
|
telemetry: false
|
|
1506
1550
|
}
|
|
@@ -1508,6 +1552,7 @@ var BUILT_IN_DEFAULTS = {
|
|
|
1508
1552
|
var HARNESS_BLOCK_KEYS = HARNESS_IDS.map((harness) => `[${harness}]`);
|
|
1509
1553
|
var CODEGRAPH_SETTING_KEYS = [
|
|
1510
1554
|
"auto_provision",
|
|
1555
|
+
"daemon",
|
|
1511
1556
|
"enabled",
|
|
1512
1557
|
"excluded_roots",
|
|
1513
1558
|
"install_dir",
|
|
@@ -1581,6 +1626,10 @@ function setCodegraphSetting(config, key, value) {
|
|
|
1581
1626
|
if (typeof value === "boolean")
|
|
1582
1627
|
config.auto_provision = value;
|
|
1583
1628
|
return;
|
|
1629
|
+
case "daemon":
|
|
1630
|
+
if (typeof value === "boolean")
|
|
1631
|
+
config.daemon = value;
|
|
1632
|
+
return;
|
|
1584
1633
|
case "enabled":
|
|
1585
1634
|
if (typeof value === "boolean")
|
|
1586
1635
|
config.enabled = value;
|
|
@@ -1655,7 +1704,7 @@ function normalizeActiveHarnessBlock(value, harness, pathPrefix, warnings) {
|
|
|
1655
1704
|
}
|
|
1656
1705
|
function loadConfigFile(path, harness) {
|
|
1657
1706
|
try {
|
|
1658
|
-
const content =
|
|
1707
|
+
const content = readFileSync2(path, "utf-8");
|
|
1659
1708
|
const parsed = parseJsoncSafe(content);
|
|
1660
1709
|
if (parsed.errors.length > 0) {
|
|
1661
1710
|
return {
|
|
@@ -1778,22 +1827,22 @@ function buildEnvOverrides(harness, env, warnings, merge) {
|
|
|
1778
1827
|
}
|
|
1779
1828
|
|
|
1780
1829
|
// ../../../../utils/src/omo-config/resolve.ts
|
|
1781
|
-
import { existsSync as
|
|
1782
|
-
import { dirname as dirname2, isAbsolute as isAbsolute2, join as
|
|
1830
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
1831
|
+
import { dirname as dirname2, isAbsolute as isAbsolute2, join as join7, relative, resolve as resolve3 } from "node:path";
|
|
1783
1832
|
function containsPath(parent, child) {
|
|
1784
1833
|
const pathToChild = relative(parent, child);
|
|
1785
1834
|
return pathToChild === "" || !pathToChild.startsWith("..") && !isAbsolute2(pathToChild);
|
|
1786
1835
|
}
|
|
1787
1836
|
function findProjectConfigPathsNearestFirst(cwd, homeDir) {
|
|
1788
|
-
const startDir =
|
|
1789
|
-
const stopBeforeDir = containsPath(
|
|
1837
|
+
const startDir = resolve3(cwd);
|
|
1838
|
+
const stopBeforeDir = containsPath(resolve3(homeDir), startDir) ? resolve3(homeDir) : null;
|
|
1790
1839
|
const paths = [];
|
|
1791
1840
|
let currentDir = startDir;
|
|
1792
1841
|
while (true) {
|
|
1793
1842
|
if (stopBeforeDir !== null && currentDir === stopBeforeDir)
|
|
1794
1843
|
break;
|
|
1795
|
-
const configPath =
|
|
1796
|
-
if (
|
|
1844
|
+
const configPath = join7(currentDir, ".omo", "config.jsonc");
|
|
1845
|
+
if (existsSync4(configPath)) {
|
|
1797
1846
|
paths.push(configPath);
|
|
1798
1847
|
}
|
|
1799
1848
|
const parentDir = dirname2(currentDir);
|
|
@@ -1804,7 +1853,7 @@ function findProjectConfigPathsNearestFirst(cwd, homeDir) {
|
|
|
1804
1853
|
return paths;
|
|
1805
1854
|
}
|
|
1806
1855
|
function resolveOmoConfigPaths(options) {
|
|
1807
|
-
const globalPath =
|
|
1856
|
+
const globalPath = join7(resolve3(options.homeDir), ".omo", "config.jsonc");
|
|
1808
1857
|
const projectPathsFarthestFirst = findProjectConfigPathsNearestFirst(options.cwd, options.homeDir).reverse();
|
|
1809
1858
|
return [
|
|
1810
1859
|
{ path: globalPath, scope: "global" },
|
|
@@ -1829,7 +1878,7 @@ function loadOmoConfig(options) {
|
|
|
1829
1878
|
const sources = [];
|
|
1830
1879
|
const warnings = [];
|
|
1831
1880
|
for (const candidate of resolveOmoConfigPaths({ cwd, homeDir })) {
|
|
1832
|
-
if (!
|
|
1881
|
+
if (!existsSync5(candidate.path)) {
|
|
1833
1882
|
if (candidate.scope === "global") {
|
|
1834
1883
|
sources.push(toMissingSource(candidate));
|
|
1835
1884
|
}
|
|
@@ -1884,7 +1933,7 @@ function resolveHomeDir(options) {
|
|
|
1884
1933
|
import { spawn } from "node:child_process";
|
|
1885
1934
|
|
|
1886
1935
|
// ../../../../mcp-stdio-core/src/record.ts
|
|
1887
|
-
function
|
|
1936
|
+
function isPlainRecord2(value) {
|
|
1888
1937
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1889
1938
|
}
|
|
1890
1939
|
// ../../../../mcp-stdio-core/src/responses.ts
|
|
@@ -1931,7 +1980,7 @@ ${body}` : `${body}
|
|
|
1931
1980
|
await writeChunk(output, payload);
|
|
1932
1981
|
}
|
|
1933
1982
|
function writeChunk(output, chunk) {
|
|
1934
|
-
return new Promise((
|
|
1983
|
+
return new Promise((resolve4, reject) => {
|
|
1935
1984
|
let settled = false;
|
|
1936
1985
|
const onError = (error) => {
|
|
1937
1986
|
if (settled)
|
|
@@ -1951,7 +2000,7 @@ function writeChunk(output, chunk) {
|
|
|
1951
2000
|
return;
|
|
1952
2001
|
}
|
|
1953
2002
|
output.removeListener("error", onError);
|
|
1954
|
-
|
|
2003
|
+
resolve4();
|
|
1955
2004
|
});
|
|
1956
2005
|
} catch (error) {
|
|
1957
2006
|
output.removeListener("error", onError);
|
|
@@ -2043,16 +2092,35 @@ function bufferFromChunk(chunk) {
|
|
|
2043
2092
|
|
|
2044
2093
|
// ../../../../mcp-stdio-core/src/server.ts
|
|
2045
2094
|
var DEFAULT_IDLE_TIMEOUT_MS = 10 * 60000;
|
|
2095
|
+
var DEFAULT_PARENT_POLL_INTERVAL_MS = 30000;
|
|
2046
2096
|
var noopLog = () => {};
|
|
2097
|
+
function isProcessAlive(pid) {
|
|
2098
|
+
try {
|
|
2099
|
+
process.kill(pid, 0);
|
|
2100
|
+
return true;
|
|
2101
|
+
} catch (error) {
|
|
2102
|
+
return !hasErrorCode(error, "ESRCH");
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2047
2105
|
async function runJsonRpcStdioServer(config) {
|
|
2048
2106
|
const log = config.log ?? noopLog;
|
|
2049
2107
|
const idleTimeoutMs = config.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
2050
|
-
|
|
2108
|
+
let isClosed = false;
|
|
2109
|
+
const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
|
|
2110
|
+
isClosed = true;
|
|
2111
|
+
config.onIdleTimeout?.();
|
|
2112
|
+
});
|
|
2113
|
+
const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
|
|
2114
|
+
isClosed = true;
|
|
2115
|
+
log("parent_exit", { parent_pid: parentPid, poll_interval_ms: pollIntervalMs });
|
|
2116
|
+
config.onParentExit?.();
|
|
2117
|
+
config.input.destroy();
|
|
2118
|
+
});
|
|
2051
2119
|
log("stdio_started", { cwd: process.cwd(), idle_timeout_ms: idleTimeoutMs });
|
|
2052
2120
|
idleTimer.arm();
|
|
2053
2121
|
try {
|
|
2054
2122
|
for await (const message of readStdioJsonRpcMessages(config.input)) {
|
|
2055
|
-
if (
|
|
2123
|
+
if (isClosed)
|
|
2056
2124
|
break;
|
|
2057
2125
|
idleTimer.arm();
|
|
2058
2126
|
if (message.kind === "parse_error") {
|
|
@@ -2063,8 +2131,12 @@ async function runJsonRpcStdioServer(config) {
|
|
|
2063
2131
|
if (!await handleRequest(message, config, log))
|
|
2064
2132
|
break;
|
|
2065
2133
|
}
|
|
2134
|
+
} catch (error) {
|
|
2135
|
+
if (!(isClosed && hasErrorCode(error, "ERR_STREAM_PREMATURE_CLOSE")))
|
|
2136
|
+
throw error;
|
|
2066
2137
|
} finally {
|
|
2067
2138
|
idleTimer.clear();
|
|
2139
|
+
watchdog.clear();
|
|
2068
2140
|
log("stdio_stopped");
|
|
2069
2141
|
}
|
|
2070
2142
|
}
|
|
@@ -2081,8 +2153,8 @@ async function handleParseError(message, config, log) {
|
|
|
2081
2153
|
}
|
|
2082
2154
|
async function handleRequest(message, config, log) {
|
|
2083
2155
|
const parsed = message.payload;
|
|
2084
|
-
const id =
|
|
2085
|
-
const method =
|
|
2156
|
+
const id = isPlainRecord2(parsed) ? jsonRpcId(parsed["id"]) : null;
|
|
2157
|
+
const method = isPlainRecord2(parsed) && typeof parsed["method"] === "string" ? parsed["method"] : null;
|
|
2086
2158
|
log("request", { id: id === null ? null : String(id), method });
|
|
2087
2159
|
let response;
|
|
2088
2160
|
try {
|
|
@@ -2120,9 +2192,33 @@ function isTerminalOutputError(error) {
|
|
|
2120
2192
|
return false;
|
|
2121
2193
|
return error.code === "EPIPE" || error.code === "ERR_STREAM_DESTROYED" || error.code === "ERR_STREAM_WRITE_AFTER_END";
|
|
2122
2194
|
}
|
|
2123
|
-
function
|
|
2195
|
+
function hasErrorCode(error, code) {
|
|
2196
|
+
return error instanceof Error && "code" in error && error.code === code;
|
|
2197
|
+
}
|
|
2198
|
+
function createParentWatchdog(config, onDeadParent) {
|
|
2199
|
+
if (config === undefined)
|
|
2200
|
+
return { clear: () => {} };
|
|
2201
|
+
const pollIntervalMs = config.pollIntervalMs ?? DEFAULT_PARENT_POLL_INTERVAL_MS;
|
|
2202
|
+
if (pollIntervalMs <= 0)
|
|
2203
|
+
return { clear: () => {} };
|
|
2204
|
+
const parentPid = config.parentPid ?? process.ppid;
|
|
2205
|
+
const probeAlive = config.probeAlive ?? isProcessAlive;
|
|
2206
|
+
let fired = false;
|
|
2207
|
+
const timer = setInterval(() => {
|
|
2208
|
+
if (fired || probeAlive(parentPid))
|
|
2209
|
+
return;
|
|
2210
|
+
fired = true;
|
|
2211
|
+
onDeadParent(parentPid, pollIntervalMs);
|
|
2212
|
+
}, pollIntervalMs);
|
|
2213
|
+
timer.unref();
|
|
2214
|
+
return {
|
|
2215
|
+
clear: () => {
|
|
2216
|
+
clearInterval(timer);
|
|
2217
|
+
}
|
|
2218
|
+
};
|
|
2219
|
+
}
|
|
2220
|
+
function createIdleTimer(idleTimeoutMs, log, onTimeout) {
|
|
2124
2221
|
let timer = null;
|
|
2125
|
-
let isClosed = false;
|
|
2126
2222
|
return {
|
|
2127
2223
|
arm: () => {
|
|
2128
2224
|
if (timer !== null)
|
|
@@ -2130,9 +2226,8 @@ function createIdleTimer(idleTimeoutMs, log, onIdleTimeout) {
|
|
|
2130
2226
|
if (idleTimeoutMs <= 0)
|
|
2131
2227
|
return;
|
|
2132
2228
|
timer = setTimeout(() => {
|
|
2133
|
-
isClosed = true;
|
|
2134
2229
|
log("idle_timeout", { idle_timeout_ms: idleTimeoutMs });
|
|
2135
|
-
|
|
2230
|
+
onTimeout();
|
|
2136
2231
|
}, idleTimeoutMs);
|
|
2137
2232
|
timer.unref();
|
|
2138
2233
|
},
|
|
@@ -2141,8 +2236,7 @@ function createIdleTimer(idleTimeoutMs, log, onIdleTimeout) {
|
|
|
2141
2236
|
return;
|
|
2142
2237
|
clearTimeout(timer);
|
|
2143
2238
|
timer = null;
|
|
2144
|
-
}
|
|
2145
|
-
closed: () => isClosed
|
|
2239
|
+
}
|
|
2146
2240
|
};
|
|
2147
2241
|
}
|
|
2148
2242
|
// src/serve-invocation.ts
|
|
@@ -2175,6 +2269,7 @@ class CodegraphBridgeStdioError extends Error {
|
|
|
2175
2269
|
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.";
|
|
2176
2270
|
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.";
|
|
2177
2271
|
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.";
|
|
2272
|
+
var SIGKILL_ESCALATION_MS = 2000;
|
|
2178
2273
|
async function runBridgedCodegraphProcess(command, args, options) {
|
|
2179
2274
|
const invocation = resolveServeProcessInvocation(command, args);
|
|
2180
2275
|
const child = spawn(invocation.command, invocation.args, {
|
|
@@ -2200,17 +2295,24 @@ async function runBridgedCodegraphProcess(command, args, options) {
|
|
|
2200
2295
|
resolveExit(signal === null ? 0 : 1);
|
|
2201
2296
|
});
|
|
2202
2297
|
});
|
|
2203
|
-
const clientForwardingDone = forwardClientToCodegraph(options.input, childInput, pendingResponses, (mode) => {
|
|
2204
|
-
defaultResponseMode = mode;
|
|
2205
|
-
});
|
|
2206
|
-
const responseForwardingDone = forwardCodegraphToClient(childOutput, options.output, pendingResponses, () => defaultResponseMode);
|
|
2207
|
-
const bridgeDone = Promise.all([clientForwardingDone, responseForwardingDone]);
|
|
2208
|
-
const childAndResponsesDone = Promise.all([childExit, responseForwardingDone]).then(([exitCode]) => exitCode);
|
|
2209
2298
|
const destroyChildPipes = () => {
|
|
2210
2299
|
childInput.destroy();
|
|
2211
2300
|
childOutput.destroy();
|
|
2212
2301
|
};
|
|
2213
2302
|
childExit.then(destroyChildPipes, destroyChildPipes);
|
|
2303
|
+
let parentWatchdogFired = false;
|
|
2304
|
+
const parentWatchdog = createParentWatchdog(options.parentWatchdog, () => {
|
|
2305
|
+
parentWatchdogFired = true;
|
|
2306
|
+
options.input.destroy();
|
|
2307
|
+
destroyChildPipes();
|
|
2308
|
+
terminateCodegraphChild(child);
|
|
2309
|
+
});
|
|
2310
|
+
const clientForwardingDone = forwardClientToCodegraph(options.input, childInput, pendingResponses, (mode) => {
|
|
2311
|
+
defaultResponseMode = mode;
|
|
2312
|
+
}, () => parentWatchdogFired);
|
|
2313
|
+
const responseForwardingDone = forwardCodegraphToClient(childOutput, options.output, pendingResponses, () => defaultResponseMode, () => parentWatchdogFired);
|
|
2314
|
+
const bridgeDone = Promise.all([clientForwardingDone, responseForwardingDone]);
|
|
2315
|
+
const childAndResponsesDone = Promise.all([childExit, responseForwardingDone]).then(([exitCode]) => exitCode);
|
|
2214
2316
|
try {
|
|
2215
2317
|
return await Promise.race([childAndResponsesDone, bridgeDone.then(() => childExit)]);
|
|
2216
2318
|
} catch (error) {
|
|
@@ -2221,58 +2323,85 @@ async function runBridgedCodegraphProcess(command, args, options) {
|
|
|
2221
2323
|
return;
|
|
2222
2324
|
});
|
|
2223
2325
|
throw error;
|
|
2326
|
+
} finally {
|
|
2327
|
+
parentWatchdog.clear();
|
|
2224
2328
|
}
|
|
2225
2329
|
}
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2330
|
+
function terminateCodegraphChild(child) {
|
|
2331
|
+
if (child.exitCode !== null || child.signalCode !== null)
|
|
2332
|
+
return;
|
|
2333
|
+
child.kill("SIGTERM");
|
|
2334
|
+
const escalation = setTimeout(() => {
|
|
2335
|
+
if (child.exitCode === null && child.signalCode === null)
|
|
2336
|
+
child.kill("SIGKILL");
|
|
2337
|
+
}, SIGKILL_ESCALATION_MS);
|
|
2338
|
+
escalation.unref();
|
|
2339
|
+
}
|
|
2340
|
+
function isWatchdogTeardownError(error) {
|
|
2341
|
+
if (!(error instanceof Error) || !("code" in error))
|
|
2342
|
+
return false;
|
|
2343
|
+
return error.code === "ERR_STREAM_PREMATURE_CLOSE" || error.code === "ERR_STREAM_DESTROYED" || error.code === "ERR_STREAM_WRITE_AFTER_END" || error.code === "EPIPE";
|
|
2344
|
+
}
|
|
2345
|
+
async function forwardClientToCodegraph(input, childInput, pendingResponses, setDefaultResponseMode, tolerateWatchdogClose) {
|
|
2346
|
+
try {
|
|
2347
|
+
for await (const message of readStdioJsonRpcMessages(input)) {
|
|
2348
|
+
if (message.kind === "parse_error") {
|
|
2349
|
+
continue;
|
|
2350
|
+
}
|
|
2351
|
+
const responseMode = message.responseMode;
|
|
2352
|
+
setDefaultResponseMode(responseMode);
|
|
2353
|
+
const key = responseModeKey(message.payload);
|
|
2354
|
+
if (key !== null) {
|
|
2355
|
+
pendingResponses.set(key, {
|
|
2356
|
+
method: jsonRpcMethod(message.payload),
|
|
2357
|
+
responseMode,
|
|
2358
|
+
toolName: jsonRpcToolName(message.payload)
|
|
2359
|
+
});
|
|
2360
|
+
}
|
|
2361
|
+
await writeLine(childInput, JSON.stringify(message.payload));
|
|
2240
2362
|
}
|
|
2241
|
-
|
|
2363
|
+
childInput.end();
|
|
2364
|
+
} catch (error) {
|
|
2365
|
+
if (!(tolerateWatchdogClose() && isWatchdogTeardownError(error)))
|
|
2366
|
+
throw error;
|
|
2242
2367
|
}
|
|
2243
|
-
childInput.end();
|
|
2244
2368
|
}
|
|
2245
|
-
async function forwardCodegraphToClient(childOutput, output, pendingResponses, defaultResponseMode) {
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2369
|
+
async function forwardCodegraphToClient(childOutput, output, pendingResponses, defaultResponseMode, tolerateWatchdogClose) {
|
|
2370
|
+
try {
|
|
2371
|
+
for await (const message of readStdioJsonRpcMessages(childOutput)) {
|
|
2372
|
+
if (message.kind === "parse_error") {
|
|
2373
|
+
await writeStdioJsonRpcResponse(output, errorResponse(null, -32700, "Parse error", message.message), defaultResponseMode());
|
|
2374
|
+
continue;
|
|
2375
|
+
}
|
|
2376
|
+
const key = responseModeKey(message.payload);
|
|
2377
|
+
const pendingResponse = key === null ? undefined : pendingResponses.get(key);
|
|
2378
|
+
const responseMode = pendingResponse?.responseMode ?? defaultResponseMode();
|
|
2379
|
+
if (key !== null)
|
|
2380
|
+
pendingResponses.delete(key);
|
|
2381
|
+
await writeStdioJsonRpcResponse(output, clarifyCodegraphResponse(message.payload, pendingResponse), responseMode);
|
|
2250
2382
|
}
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
if (key !== null)
|
|
2255
|
-
pendingResponses.delete(key);
|
|
2256
|
-
await writeStdioJsonRpcResponse(output, clarifyCodegraphResponse(message.payload, pendingResponse), responseMode);
|
|
2383
|
+
} catch (error) {
|
|
2384
|
+
if (!(tolerateWatchdogClose() && isWatchdogTeardownError(error)))
|
|
2385
|
+
throw error;
|
|
2257
2386
|
}
|
|
2258
2387
|
}
|
|
2259
2388
|
function responseModeKey(payload) {
|
|
2260
|
-
if (!
|
|
2389
|
+
if (!isPlainRecord2(payload) || !("id" in payload))
|
|
2261
2390
|
return null;
|
|
2262
2391
|
const id = jsonRpcId(payload["id"]);
|
|
2263
2392
|
return `${typeof id}:${String(id)}`;
|
|
2264
2393
|
}
|
|
2265
2394
|
function jsonRpcMethod(payload) {
|
|
2266
|
-
if (!
|
|
2395
|
+
if (!isPlainRecord2(payload))
|
|
2267
2396
|
return null;
|
|
2268
2397
|
const method = payload["method"];
|
|
2269
2398
|
return typeof method === "string" ? method : null;
|
|
2270
2399
|
}
|
|
2271
2400
|
function jsonRpcToolName(payload) {
|
|
2272
|
-
if (jsonRpcMethod(payload) !== "tools/call" || !
|
|
2401
|
+
if (jsonRpcMethod(payload) !== "tools/call" || !isPlainRecord2(payload))
|
|
2273
2402
|
return null;
|
|
2274
2403
|
const params = payload["params"];
|
|
2275
|
-
if (!
|
|
2404
|
+
if (!isPlainRecord2(params))
|
|
2276
2405
|
return null;
|
|
2277
2406
|
const name = params["name"];
|
|
2278
2407
|
return typeof name === "string" ? name : null;
|
|
@@ -2286,14 +2415,14 @@ function clarifyCodegraphResponse(payload, pendingResponse) {
|
|
|
2286
2415
|
return payload;
|
|
2287
2416
|
}
|
|
2288
2417
|
function clarifyCodegraphToolsList(payload) {
|
|
2289
|
-
if (!
|
|
2418
|
+
if (!isPlainRecord2(payload))
|
|
2290
2419
|
return payload;
|
|
2291
2420
|
const result = payload["result"];
|
|
2292
|
-
if (!
|
|
2421
|
+
if (!isPlainRecord2(result) || !Array.isArray(result["tools"]))
|
|
2293
2422
|
return payload;
|
|
2294
2423
|
let changed = false;
|
|
2295
2424
|
const tools = result["tools"].map((tool) => {
|
|
2296
|
-
if (!
|
|
2425
|
+
if (!isPlainRecord2(tool) || tool["name"] !== "codegraph_node")
|
|
2297
2426
|
return tool;
|
|
2298
2427
|
if (!hasCodegraphNodeContractMetadata(tool))
|
|
2299
2428
|
return tool;
|
|
@@ -2310,7 +2439,7 @@ function clarifyCodegraphNodeTool(tool) {
|
|
|
2310
2439
|
description: CODEGRAPH_NODE_DESCRIPTION
|
|
2311
2440
|
};
|
|
2312
2441
|
const inputSchema = tool["inputSchema"];
|
|
2313
|
-
if (
|
|
2442
|
+
if (isPlainRecord2(inputSchema))
|
|
2314
2443
|
clarified["inputSchema"] = clarifyCodegraphNodeInputSchema(inputSchema);
|
|
2315
2444
|
return clarified;
|
|
2316
2445
|
}
|
|
@@ -2318,17 +2447,17 @@ function hasCodegraphNodeContractMetadata(tool) {
|
|
|
2318
2447
|
if (typeof tool["description"] === "string")
|
|
2319
2448
|
return true;
|
|
2320
2449
|
const inputSchema = tool["inputSchema"];
|
|
2321
|
-
if (!
|
|
2450
|
+
if (!isPlainRecord2(inputSchema))
|
|
2322
2451
|
return false;
|
|
2323
2452
|
const properties = inputSchema["properties"];
|
|
2324
|
-
return
|
|
2453
|
+
return isPlainRecord2(properties) && isPlainRecord2(properties["includeCode"]);
|
|
2325
2454
|
}
|
|
2326
2455
|
function clarifyCodegraphNodeInputSchema(inputSchema) {
|
|
2327
2456
|
const properties = inputSchema["properties"];
|
|
2328
|
-
if (!
|
|
2457
|
+
if (!isPlainRecord2(properties))
|
|
2329
2458
|
return inputSchema;
|
|
2330
2459
|
const includeCode = properties["includeCode"];
|
|
2331
|
-
if (!
|
|
2460
|
+
if (!isPlainRecord2(includeCode))
|
|
2332
2461
|
return inputSchema;
|
|
2333
2462
|
return {
|
|
2334
2463
|
...inputSchema,
|
|
@@ -2342,14 +2471,14 @@ function clarifyCodegraphNodeInputSchema(inputSchema) {
|
|
|
2342
2471
|
};
|
|
2343
2472
|
}
|
|
2344
2473
|
function clarifyCodegraphNodeCallResult(payload) {
|
|
2345
|
-
if (!
|
|
2474
|
+
if (!isPlainRecord2(payload))
|
|
2346
2475
|
return payload;
|
|
2347
2476
|
const result = payload["result"];
|
|
2348
|
-
if (!
|
|
2477
|
+
if (!isPlainRecord2(result) || !Array.isArray(result["content"]))
|
|
2349
2478
|
return payload;
|
|
2350
2479
|
let changed = false;
|
|
2351
2480
|
const content = result["content"].map((item) => {
|
|
2352
|
-
if (!
|
|
2481
|
+
if (!isPlainRecord2(item) || item["type"] !== "text" || typeof item["text"] !== "string")
|
|
2353
2482
|
return item;
|
|
2354
2483
|
const text = clarifyContainerOutlineGuidance(item["text"]);
|
|
2355
2484
|
if (text === item["text"])
|
|
@@ -2385,11 +2514,12 @@ async function runUnavailableCodegraphMcpServer(options) {
|
|
|
2385
2514
|
serverVersion: options.serverVersion
|
|
2386
2515
|
},
|
|
2387
2516
|
input: options.input,
|
|
2388
|
-
output: options.output
|
|
2517
|
+
output: options.output,
|
|
2518
|
+
parentWatchdog: options.parentWatchdog ?? {}
|
|
2389
2519
|
});
|
|
2390
2520
|
}
|
|
2391
2521
|
async function handleUnavailableCodegraphMcpRequest(input, options) {
|
|
2392
|
-
if (!
|
|
2522
|
+
if (!isPlainRecord2(input)) {
|
|
2393
2523
|
return errorResponse(null, -32600, "Invalid Request");
|
|
2394
2524
|
}
|
|
2395
2525
|
const id = jsonRpcId(input["id"]);
|
|
@@ -2417,7 +2547,7 @@ async function handleUnavailableCodegraphMcpRequest(input, options) {
|
|
|
2417
2547
|
return errorResponse(id, -32601, `Method not found: ${String(method)}`);
|
|
2418
2548
|
}
|
|
2419
2549
|
function requestedProtocolVersion(params) {
|
|
2420
|
-
if (!
|
|
2550
|
+
if (!isPlainRecord2(params) || typeof params["protocolVersion"] !== "string")
|
|
2421
2551
|
return "2024-11-05";
|
|
2422
2552
|
return params["protocolVersion"];
|
|
2423
2553
|
}
|
|
@@ -2434,7 +2564,7 @@ var CODEGRAPH_DISABLED_HINT = `CodeGraph MCP skipped: disabled by OMO SOT config
|
|
|
2434
2564
|
`;
|
|
2435
2565
|
var CODEGRAPH_EXCLUDED_HINT = `CodeGraph MCP skipped: project excluded by OMO CodeGraph policy.
|
|
2436
2566
|
`;
|
|
2437
|
-
var CODEGRAPH_VERSION =
|
|
2567
|
+
var CODEGRAPH_VERSION = CODEGRAPH_PINNED_VERSION;
|
|
2438
2568
|
var PROJECT_CWD_ENV_KEYS = ["OMO_CODEGRAPH_PROJECT_CWD", SESSION_START_CWD_ENV, "PWD"];
|
|
2439
2569
|
async function runCodegraphServe(options = {}) {
|
|
2440
2570
|
const env = options.env ?? processEnv;
|
|
@@ -2462,7 +2592,7 @@ async function runCodegraphServe(options = {}) {
|
|
|
2462
2592
|
};
|
|
2463
2593
|
let resolution = options.resolve?.(resolutionOptions) ?? resolveCodegraphCommand(resolutionOptions);
|
|
2464
2594
|
const nodeSupport = evaluateCodegraphNodeSupport({ env, nodeVersion: options.nodeVersion });
|
|
2465
|
-
if (!resolution.exists || shouldSkipResolvedCommand(resolution, options.commandExists ??
|
|
2595
|
+
if (!resolution.exists || shouldSkipResolvedCommand(resolution, options.commandExists ?? existsSync6)) {
|
|
2466
2596
|
if (resolution.source === "path" && !nodeSupport.supported) {
|
|
2467
2597
|
return runUnavailableMcp(buildCodegraphNodeSkipHint(nodeSupport), options);
|
|
2468
2598
|
}
|
|
@@ -2482,7 +2612,7 @@ async function runCodegraphServe(options = {}) {
|
|
|
2482
2612
|
return runUnavailableMcp(buildCodegraphNodeSkipHint(nodeSupport), options);
|
|
2483
2613
|
}
|
|
2484
2614
|
const runProcess = options.runProcess ?? runBridgedCodegraphProcess;
|
|
2485
|
-
const codegraphEnv = codegraphEnvForConfig(trustedInstallDir, homeDir, options.buildEnv);
|
|
2615
|
+
const codegraphEnv = codegraphEnvForConfig(trustedInstallDir, homeDir, codegraphConfig.daemon !== false, options.buildEnv);
|
|
2486
2616
|
const mergedEnv = buildCodegraphChildEnv({ ambientEnv: env, codegraphEnv, runtimeEnv: env });
|
|
2487
2617
|
return runProcess(resolution.command, [...resolution.argsPrefix, "serve", "--mcp"], {
|
|
2488
2618
|
cwd: projectCwd,
|
|
@@ -2490,7 +2620,8 @@ async function runCodegraphServe(options = {}) {
|
|
|
2490
2620
|
input: options.stdin ?? processStdin,
|
|
2491
2621
|
output: options.stdout ?? processStdout,
|
|
2492
2622
|
stderr: options.stderr ?? processStderr,
|
|
2493
|
-
stdio: "pipe"
|
|
2623
|
+
stdio: "pipe",
|
|
2624
|
+
parentWatchdog: options.parentWatchdog ?? {}
|
|
2494
2625
|
});
|
|
2495
2626
|
}
|
|
2496
2627
|
async function runUnavailableMcp(reason, options) {
|
|
@@ -2499,7 +2630,8 @@ async function runUnavailableMcp(reason, options) {
|
|
|
2499
2630
|
input: options.stdin ?? processStdin,
|
|
2500
2631
|
output: options.stdout ?? processStdout,
|
|
2501
2632
|
reason,
|
|
2502
|
-
serverVersion: CODEGRAPH_VERSION
|
|
2633
|
+
serverVersion: CODEGRAPH_VERSION,
|
|
2634
|
+
parentWatchdog: options.parentWatchdog ?? {}
|
|
2503
2635
|
});
|
|
2504
2636
|
return 0;
|
|
2505
2637
|
}
|
|
@@ -2508,10 +2640,10 @@ async function provisionMissingCodegraph(options) {
|
|
|
2508
2640
|
return null;
|
|
2509
2641
|
if (options.config.auto_provision === false)
|
|
2510
2642
|
return null;
|
|
2511
|
-
const installDir = options.trustedInstallDir ??
|
|
2643
|
+
const installDir = options.trustedInstallDir ?? join8(options.homeDir, ".omo", "codegraph");
|
|
2512
2644
|
const result = await options.ensureProvisioned({
|
|
2513
2645
|
installDir,
|
|
2514
|
-
lockDir:
|
|
2646
|
+
lockDir: join8(installDir, ".locks"),
|
|
2515
2647
|
version: CODEGRAPH_VERSION
|
|
2516
2648
|
});
|
|
2517
2649
|
if (!result.provisioned || result.binPath === undefined)
|
|
@@ -2528,8 +2660,8 @@ function shouldSkipResolvedCommand(resolution, commandExists) {
|
|
|
2528
2660
|
function looksLikePath2(command) {
|
|
2529
2661
|
return command.includes("/") || command.includes("\\");
|
|
2530
2662
|
}
|
|
2531
|
-
function codegraphEnvForConfig(trustedInstallDir, homeDir, buildEnv) {
|
|
2532
|
-
const env =
|
|
2663
|
+
function codegraphEnvForConfig(trustedInstallDir, homeDir, daemon, buildEnv) {
|
|
2664
|
+
const env = buildEnv?.({ daemon, homeDir }) ?? buildCodegraphEnv({ daemon, homeDir });
|
|
2533
2665
|
return trustedInstallDir === undefined ? env : { ...env, CODEGRAPH_INSTALL_DIR: trustedInstallDir };
|
|
2534
2666
|
}
|
|
2535
2667
|
function resolveProjectCwd(env, fallback) {
|
|
@@ -2537,17 +2669,14 @@ function resolveProjectCwd(env, fallback) {
|
|
|
2537
2669
|
const candidate = env[key]?.trim();
|
|
2538
2670
|
if (candidate === undefined || candidate.length === 0)
|
|
2539
2671
|
continue;
|
|
2540
|
-
const resolved =
|
|
2541
|
-
if (
|
|
2672
|
+
const resolved = resolve4(candidate);
|
|
2673
|
+
if (existsSync6(resolved))
|
|
2542
2674
|
return resolved;
|
|
2543
2675
|
}
|
|
2544
|
-
return
|
|
2676
|
+
return resolve4(fallback);
|
|
2545
2677
|
}
|
|
2546
2678
|
function provisionedBinFromInstallDir(installDir) {
|
|
2547
|
-
|
|
2548
|
-
return null;
|
|
2549
|
-
const candidate = join7(installDir, "bin", process.platform === "win32" ? "codegraph.cmd" : "codegraph");
|
|
2550
|
-
return existsSync5(candidate) ? candidate : null;
|
|
2679
|
+
return resolvePinnedCodegraphBin(installDir);
|
|
2551
2680
|
}
|
|
2552
2681
|
async function runCodegraphServeCli() {
|
|
2553
2682
|
process.exitCode = await runCodegraphServe();
|
|
@@ -2566,7 +2695,7 @@ function isDirectInvocation(argvPath) {
|
|
|
2566
2695
|
const moduleName = basename3(modulePath);
|
|
2567
2696
|
if (moduleName !== "serve.js" && moduleName !== "serve.ts")
|
|
2568
2697
|
return false;
|
|
2569
|
-
return realpathSync2(
|
|
2698
|
+
return realpathSync2(resolve4(argvPath)) === realpathSync2(modulePath);
|
|
2570
2699
|
}
|
|
2571
2700
|
export {
|
|
2572
2701
|
runCodegraphServeCli,
|