lazycodex-ai 5.1.48 → 5.1.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1194 -752
- package/dist/cli/service-auth/accounts-gate.d.ts +11 -0
- package/dist/cli/service-auth/commands.d.ts +2 -4
- package/dist/cli/service-auth/index.d.ts +1 -1
- package/dist/cli/service-auth/keystore.d.ts +26 -2
- package/dist/cli/service-auth/protocol.d.ts +7 -1
- package/dist/cli/service-auth/session.d.ts +6 -0
- package/dist/cli/service-auth/signed-out-marker.d.ts +11 -0
- package/dist/cli-node/index.js +1194 -752
- package/package.json +3 -1
- package/packages/lsp-core/package.json +45 -0
- package/packages/lsp-core/src/index.ts +30 -0
- package/packages/lsp-core/src/lsp/bun-command-output.ts +82 -0
- package/packages/lsp-core/src/lsp/bun-project-checks.test.ts +170 -0
- package/packages/lsp-core/src/lsp/bun-project-checks.ts +223 -0
- package/packages/lsp-core/src/lsp/cleanup-errors.test.ts +18 -0
- package/packages/lsp-core/src/lsp/cleanup-errors.ts +14 -0
- package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +52 -0
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +471 -0
- package/packages/lsp-core/src/lsp/client-diagnostics-pull-timeout.test.ts +64 -0
- package/packages/lsp-core/src/lsp/client-wrapper-outside-cwd.test.ts +78 -0
- package/packages/lsp-core/src/lsp/client-wrapper.test.ts +213 -0
- package/packages/lsp-core/src/lsp/client-wrapper.ts +290 -0
- package/packages/lsp-core/src/lsp/client.ts +398 -0
- package/packages/lsp-core/src/lsp/config-loader.ts +254 -0
- package/packages/lsp-core/src/lsp/connection.ts +95 -0
- package/packages/lsp-core/src/lsp/constants.ts +17 -0
- package/packages/lsp-core/src/lsp/controlled-clock-test-support.ts +90 -0
- package/packages/lsp-core/src/lsp/directory-diagnostics.test.ts +221 -0
- package/packages/lsp-core/src/lsp/directory-diagnostics.ts +187 -0
- package/packages/lsp-core/src/lsp/effective-extension.ts +10 -0
- package/packages/lsp-core/src/lsp/errors.ts +89 -0
- package/packages/lsp-core/src/lsp/fake-bun-test-support.ts +102 -0
- package/packages/lsp-core/src/lsp/fixtures/diagnostics-freshness-contract-probe.ts +283 -0
- package/packages/lsp-core/src/lsp/fixtures/disposed-stdin-epipe-probe.ts +28 -0
- package/packages/lsp-core/src/lsp/fixtures/workspace-edit-contract-probe.ts +196 -0
- package/packages/lsp-core/src/lsp/fixtures/workspace-edit-server.mjs +234 -0
- package/packages/lsp-core/src/lsp/format-document.test.ts +143 -0
- package/packages/lsp-core/src/lsp/format-document.ts +90 -0
- package/packages/lsp-core/src/lsp/formatters.ts +144 -0
- package/packages/lsp-core/src/lsp/infer-extension.ts +66 -0
- package/packages/lsp-core/src/lsp/json-rpc-connection-cancellation.test.ts +97 -0
- package/packages/lsp-core/src/lsp/json-rpc-connection.ts +369 -0
- package/packages/lsp-core/src/lsp/language-mappings.ts +173 -0
- package/packages/lsp-core/src/lsp/manager-lifecycle.test.ts +262 -0
- package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +151 -0
- package/packages/lsp-core/src/lsp/manager.ts +495 -0
- package/packages/lsp-core/src/lsp/outside-context-workspace.ts +33 -0
- package/packages/lsp-core/src/lsp/process-pipe-errors.test.ts +21 -0
- package/packages/lsp-core/src/lsp/process-signal-cleanup.ts +21 -0
- package/packages/lsp-core/src/lsp/process.ts +221 -0
- package/packages/lsp-core/src/lsp/server-definitions.ts +205 -0
- package/packages/lsp-core/src/lsp/server-install-state.ts +67 -0
- package/packages/lsp-core/src/lsp/server-installation.test.ts +376 -0
- package/packages/lsp-core/src/lsp/server-installation.ts +218 -0
- package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +170 -0
- package/packages/lsp-core/src/lsp/server-resolution.ts +117 -0
- package/packages/lsp-core/src/lsp/startup-failure.ts +1 -0
- package/packages/lsp-core/src/lsp/timer-provider.ts +13 -0
- package/packages/lsp-core/src/lsp/transport-protocol.ts +52 -0
- package/packages/lsp-core/src/lsp/transport-request-timeout.test.ts +73 -0
- package/packages/lsp-core/src/lsp/transport.ts +339 -0
- package/packages/lsp-core/src/lsp/types.ts +134 -0
- package/packages/lsp-core/src/lsp/utils.test.ts +72 -0
- package/packages/lsp-core/src/lsp/utils.ts +40 -0
- package/packages/lsp-core/src/lsp/workspace-apply-edit-failure.ts +19 -0
- package/packages/lsp-core/src/lsp/workspace-apply-edit-lease.integration.test.ts +218 -0
- package/packages/lsp-core/src/lsp/workspace-apply-edit-sync.integration.test.ts +113 -0
- package/packages/lsp-core/src/lsp/workspace-apply-edit-test-support.ts +194 -0
- package/packages/lsp-core/src/lsp/workspace-apply-edit.integration.test.ts +163 -0
- package/packages/lsp-core/src/lsp/workspace-document-state.test.ts +150 -0
- package/packages/lsp-core/src/lsp/workspace-document-state.ts +392 -0
- package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +132 -0
- package/packages/lsp-core/src/lsp/workspace-edit-commit.test.ts +140 -0
- package/packages/lsp-core/src/lsp/workspace-edit-commit.ts +220 -0
- package/packages/lsp-core/src/lsp/workspace-edit-contract-evidence.test.ts +56 -0
- package/packages/lsp-core/src/lsp/workspace-edit-contract-evidence.ts +30 -0
- package/packages/lsp-core/src/lsp/workspace-edit-fingerprint.ts +44 -0
- package/packages/lsp-core/src/lsp/workspace-edit-options.test.ts +147 -0
- package/packages/lsp-core/src/lsp/workspace-edit-parse-helpers.ts +59 -0
- package/packages/lsp-core/src/lsp/workspace-edit-parser.ts +130 -0
- package/packages/lsp-core/src/lsp/workspace-edit-path.ts +98 -0
- package/packages/lsp-core/src/lsp/workspace-edit-plan-types.ts +60 -0
- package/packages/lsp-core/src/lsp/workspace-edit-plan.ts +73 -0
- package/packages/lsp-core/src/lsp/workspace-edit-prevalidation.test.ts +174 -0
- package/packages/lsp-core/src/lsp/workspace-edit-resource-parser.ts +89 -0
- package/packages/lsp-core/src/lsp/workspace-edit-simulation.ts +183 -0
- package/packages/lsp-core/src/lsp/workspace-edit-snapshot.ts +53 -0
- package/packages/lsp-core/src/lsp/workspace-edit-text.ts +125 -0
- package/packages/lsp-core/src/lsp/workspace-edit-types.ts +121 -0
- package/packages/lsp-core/src/lsp/workspace-edit.characterization.test.ts +95 -0
- package/packages/lsp-core/src/lsp/workspace-edit.ts +55 -0
- package/packages/lsp-core/src/lsp/workspace-markers.ts +18 -0
- package/packages/lsp-core/src/lsp/workspace-mutation-controller.ts +182 -0
- package/packages/lsp-core/src/mcp-protocol-pin.test.ts +97 -0
- package/packages/lsp-core/src/mcp.ts +122 -0
- package/packages/lsp-core/src/missing-dependency-result.test.ts +135 -0
- package/packages/lsp-core/src/missing-dependency-result.ts +79 -0
- package/packages/lsp-core/src/post-edit/file-location.ts +55 -0
- package/packages/lsp-core/src/post-edit/index.ts +3 -0
- package/packages/lsp-core/src/post-edit/not-installed-guidance.ts +36 -0
- package/packages/lsp-core/src/post-edit/not-installed.test.ts +224 -0
- package/packages/lsp-core/src/post-edit/orchestration.test.ts +157 -0
- package/packages/lsp-core/src/post-edit/orchestration.ts +205 -0
- package/packages/lsp-core/src/request-context.test.ts +200 -0
- package/packages/lsp-core/src/request-context.ts +235 -0
- package/packages/lsp-core/src/tool-surface.test.ts +173 -0
- package/packages/lsp-core/src/tools/bun-directory-diagnostics.test.ts +113 -0
- package/packages/lsp-core/src/tools/bun-directory-diagnostics.ts +75 -0
- package/packages/lsp-core/src/tools/definitions.ts +156 -0
- package/packages/lsp-core/src/tools/diagnostics.ts +133 -0
- package/packages/lsp-core/src/tools/format.test.ts +56 -0
- package/packages/lsp-core/src/tools/format.ts +56 -0
- package/packages/lsp-core/src/tools/index.ts +11 -0
- package/packages/lsp-core/src/tools/install-decision.ts +39 -0
- package/packages/lsp-core/src/tools/navigation.ts +88 -0
- package/packages/lsp-core/src/tools/parameters.test.ts +51 -0
- package/packages/lsp-core/src/tools/parameters.ts +49 -0
- package/packages/lsp-core/src/tools/rename.ts +69 -0
- package/packages/lsp-core/src/tools/result.ts +5 -0
- package/packages/lsp-core/src/tools/runtime.ts +21 -0
- package/packages/lsp-core/src/tools/schema.ts +9 -0
- package/packages/lsp-core/src/tools/status.ts +28 -0
- package/packages/lsp-core/src/tools/symbols.ts +99 -0
- package/packages/lsp-core/src/tools/types.ts +116 -0
- package/packages/lsp-core/src/tools.ts +1 -0
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/README.md +1 -1
- 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/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/lcx/skills/lcx-contribute-bug-fix/SKILL.md +51 -55
- package/packages/omo-codex/plugin/components/lcx/skills/lcx-contribute-bug-fix/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/components/lcx/skills/lcx-report-bug/SKILL.md +7 -7
- package/packages/omo-codex/plugin/components/lcx/skills/lcx-report-bug/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
- 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/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/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 +2 -2
- package/packages/omo-codex/plugin/components/telemetry/README.md +2 -2
- package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +52 -15
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +52 -19
- 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/telemetry/src/codex-hook.ts +2 -9
- package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -13
- package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +0 -2
- package/packages/omo-codex/plugin/components/telemetry/test/codex-hook-diagnostics.test.ts +0 -3
- package/packages/omo-codex/plugin/components/telemetry/test/codex-hook.test.ts +3 -8
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +3 -0
- 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/src/directive-content.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- 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-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/post-tool-use-recording-spawn-admission.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 +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- 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 +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-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-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 +16 -16
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/shared/package.json +1 -1
- package/packages/omo-codex/plugin/skills/ast-grep/README.md +1 -1
- package/packages/omo-codex/plugin/skills/ast-grep/install.ps1 +5 -3
- package/packages/omo-codex/plugin/skills/ast-grep/install.sh +4 -5
- package/packages/omo-codex/plugin/skills/ast-grep/references/install.md +2 -2
- package/packages/omo-codex/plugin/skills/ast-grep/scripts/ast_grep_helper.py +13 -3
- package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +5 -4
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +11 -11
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +2 -2
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/codex.md +4 -4
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/cli.py +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/find-agent-sessions.py +6 -3
- package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +34 -12
- package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +2 -2
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +2 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/component-catalogs.md +14 -10
- package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +19 -6
- package/packages/omo-codex/plugin/skills/frontend/references/design/grounding.md +29 -0
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/scripts/design_system.py +2 -0
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/scripts/search.py +2 -0
- package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/SKILL.md +51 -55
- package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/lcx-report-bug/SKILL.md +7 -7
- package/packages/omo-codex/plugin/skills/lcx-report-bug/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +5 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +2 -2
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/__main__.py +9 -6
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/summary.py +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +4 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/extract_cookies.py +4 -2
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +3 -0
- package/packages/omo-codex/plugin/skills/ulw-research/AGENTS.md +8 -4
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +7 -316
- package/packages/omo-codex/plugin/skills/ulw-research/references/deliverable-phase.md +23 -21
- package/packages/omo-codex/plugin/skills/ulw-research/references/fact-ledger-grammar.md +7 -3
- package/packages/omo-codex/plugin/skills/ulw-research/references/fact-ledger.md +42 -8
- package/packages/omo-codex/plugin/skills/ulw-research/references/fidelity-claim-kinds.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/references/markdown-blocks.md +12 -0
- package/packages/omo-codex/plugin/skills/ulw-research/references/report-gates.md +12 -5
- package/packages/omo-codex/plugin/skills/ulw-research/references/research-collection.md +195 -0
- package/packages/omo-codex/plugin/skills/ulw-research/references/research-delivery.md +123 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/claim-kinds.mjs +33 -5
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/contracts.mjs +13 -4
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/conversion-probe.mjs +229 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/css-hiding.mjs +158 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/css-lite.mjs +4 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/entities.mjs +13 -4
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-fill.mjs +11 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-meaning.mjs +13 -9
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-polish.mjs +40 -18
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-verify.mjs +25 -8
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands.mjs +35 -16
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-derive.mjs +7 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-fill.mjs +6 -4
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-ledger-kinds.mjs +6 -7
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-locate.mjs +15 -9
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-claims.mjs +4 -3
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-csv.mjs +32 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-lexicon.mjs +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-originals.mjs +161 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-policy.mjs +4 -4
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-records.mjs +81 -14
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-snapshot-readability.mjs +49 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-sources.mjs +76 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-trace.mjs +25 -11
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-value-unit.mjs +202 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-values.mjs +40 -39
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-fidelity.mjs +8 -6
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-static.mjs +10 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-lite.mjs +6 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-markup.mjs +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-text-map.mjs +140 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/markdown-closers.mjs +126 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/md-lite.mjs +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/number-grammar.mjs +33 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/numerals.mjs +18 -7
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/outcome-start.mjs +66 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/outcome.mjs +11 -22
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/placeholder.mjs +18 -6
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/polish-apply.mjs +3 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/raw-decode.mjs +110 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/raw-locator.mjs +47 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/report-tools-commands.mjs +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/report-tools.mjs +7 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-commands.mjs +79 -26
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-refresh.mjs +82 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-snapshot.mjs +73 -69
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-view.mjs +89 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/sources-citation.mjs +203 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/units.mjs +14 -3
- package/packages/omo-codex/plugin/test/payload-equivalence.test.mjs +6 -4
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +4 -3
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +338 -237
- package/packages/prompts-core/prompts/ultrawork/codex.md +3 -0
- package/packages/shared-skills/skill-source-filter.mjs +6 -2
- package/packages/shared-skills/skills/ast-grep/README.md +1 -1
- package/packages/shared-skills/skills/ast-grep/install.ps1 +5 -3
- package/packages/shared-skills/skills/ast-grep/install.sh +4 -5
- package/packages/shared-skills/skills/ast-grep/references/install.md +2 -2
- package/packages/shared-skills/skills/ast-grep/scripts/ast_grep_helper.py +13 -3
- package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +5 -4
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +11 -11
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +2 -2
- package/packages/shared-skills/skills/coding-agent-sessions/references/codex.md +4 -4
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/cli.py +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/find-agent-sessions.py +6 -3
- package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +1 -1
- package/packages/shared-skills/skills/frontend/SKILL.md +34 -12
- package/packages/shared-skills/skills/frontend/references/design/README.md +2 -2
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +2 -1
- package/packages/shared-skills/skills/frontend/references/design/component-catalogs.md +14 -10
- package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +19 -6
- package/packages/shared-skills/skills/frontend/references/design/grounding.md +29 -0
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/scripts/design_system.py +2 -0
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/scripts/search.py +2 -0
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +5 -4
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +2 -2
- package/packages/shared-skills/skills/ultimate-browsing/engine/__main__.py +9 -6
- package/packages/shared-skills/skills/ultimate-browsing/engine/summary.py +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +4 -4
- package/packages/shared-skills/skills/ultimate-browsing/scripts/extract_cookies.py +4 -2
- package/packages/shared-skills/skills/ulw-research/AGENTS.md +8 -4
- package/packages/shared-skills/skills/ulw-research/SKILL.md +7 -316
- package/packages/shared-skills/skills/ulw-research/references/deliverable-phase.md +23 -21
- package/packages/shared-skills/skills/ulw-research/references/fact-ledger-grammar.md +7 -3
- package/packages/shared-skills/skills/ulw-research/references/fact-ledger.md +42 -8
- package/packages/shared-skills/skills/ulw-research/references/fidelity-claim-kinds.md +1 -1
- package/packages/shared-skills/skills/ulw-research/references/markdown-blocks.md +12 -0
- package/packages/shared-skills/skills/ulw-research/references/report-gates.md +12 -5
- package/packages/shared-skills/skills/ulw-research/references/research-collection.md +195 -0
- package/packages/shared-skills/skills/ulw-research/references/research-delivery.md +123 -0
- package/packages/shared-skills/skills/ulw-research/scripts/claim-kinds.mjs +33 -5
- package/packages/shared-skills/skills/ulw-research/scripts/claim-kinds.test.ts +37 -2
- package/packages/shared-skills/skills/ulw-research/scripts/claim-prefix.test.ts +76 -0
- package/packages/shared-skills/skills/ulw-research/scripts/contracts-validation.test.ts +83 -0
- package/packages/shared-skills/skills/ulw-research/scripts/contracts.mjs +13 -4
- package/packages/shared-skills/skills/ulw-research/scripts/contracts.test.ts +6 -110
- package/packages/shared-skills/skills/ulw-research/scripts/conversion-altered.test.ts +154 -0
- package/packages/shared-skills/skills/ulw-research/scripts/conversion-originals.test.ts +297 -0
- package/packages/shared-skills/skills/ulw-research/scripts/conversion-probe-classes.test.ts +361 -0
- package/packages/shared-skills/skills/ulw-research/scripts/conversion-probe.mjs +229 -0
- package/packages/shared-skills/skills/ulw-research/scripts/conversion-probe.test.ts +218 -0
- package/packages/shared-skills/skills/ulw-research/scripts/copy-returns-polish.test.ts +4 -3
- package/packages/shared-skills/skills/ulw-research/scripts/css-hiding.mjs +158 -0
- package/packages/shared-skills/skills/ulw-research/scripts/css-lite.mjs +4 -2
- package/packages/shared-skills/skills/ulw-research/scripts/delivery-barrier-meaning.test.ts +186 -0
- package/packages/shared-skills/skills/ulw-research/scripts/delivery-barrier.test.ts +40 -87
- package/packages/shared-skills/skills/ulw-research/scripts/entities.mjs +13 -4
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-fill.mjs +11 -1
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-meaning.mjs +13 -9
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-polish.mjs +40 -18
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-verify.mjs +25 -8
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands.mjs +35 -16
- package/packages/shared-skills/skills/ulw-research/scripts/fact-derive-2.test.ts +149 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-derive.mjs +7 -2
- package/packages/shared-skills/skills/ulw-research/scripts/fact-derive.test.ts +7 -192
- package/packages/shared-skills/skills/ulw-research/scripts/fact-fill.mjs +6 -4
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-kinds.mjs +6 -7
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-kinds.test.ts +2 -1
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-legacy.test.ts +2 -1
- package/packages/shared-skills/skills/ulw-research/scripts/fact-locate.mjs +15 -9
- package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-dimensions-2.test.ts +149 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-dimensions.test.ts +4 -168
- package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-rules.test.ts +3 -229
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-claims.mjs +4 -3
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-csv.mjs +32 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-lexicon.mjs +1 -1
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-originals.mjs +161 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-policy.mjs +4 -4
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-records.mjs +81 -14
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-snapshot-readability.mjs +49 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-sources.mjs +76 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-trace.mjs +25 -11
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-value-unit.mjs +202 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-values.mjs +40 -39
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-values.test.ts +8 -29
- package/packages/shared-skills/skills/ulw-research/scripts/gates-fidelity.mjs +8 -6
- package/packages/shared-skills/skills/ulw-research/scripts/gates-static-headings.test.ts +17 -0
- package/packages/shared-skills/skills/ulw-research/scripts/gates-static.mjs +10 -1
- package/packages/shared-skills/skills/ulw-research/scripts/html-lite.mjs +6 -2
- package/packages/shared-skills/skills/ulw-research/scripts/html-markup.mjs +2 -2
- package/packages/shared-skills/skills/ulw-research/scripts/html-text-map.mjs +140 -0
- package/packages/shared-skills/skills/ulw-research/scripts/html-text-map.test.ts +148 -0
- package/packages/shared-skills/skills/ulw-research/scripts/markdown-closers.mjs +126 -0
- package/packages/shared-skills/skills/ulw-research/scripts/md-lite-boundaries.test.ts +46 -0
- package/packages/shared-skills/skills/ulw-research/scripts/md-lite.mjs +1 -1
- package/packages/shared-skills/skills/ulw-research/scripts/number-grammar.mjs +33 -0
- package/packages/shared-skills/skills/ulw-research/scripts/number-grammar.test.ts +36 -0
- package/packages/shared-skills/skills/ulw-research/scripts/numerals.mjs +18 -7
- package/packages/shared-skills/skills/ulw-research/scripts/numerals.test.ts +3 -0
- package/packages/shared-skills/skills/ulw-research/scripts/outcome-start.mjs +66 -0
- package/packages/shared-skills/skills/ulw-research/scripts/outcome-start.test.ts +109 -0
- package/packages/shared-skills/skills/ulw-research/scripts/outcome.mjs +11 -22
- package/packages/shared-skills/skills/ulw-research/scripts/page-source-locator.test.ts +187 -0
- package/packages/shared-skills/skills/ulw-research/scripts/placeholder.mjs +18 -6
- package/packages/shared-skills/skills/ulw-research/scripts/polish-apply.mjs +3 -2
- package/packages/shared-skills/skills/ulw-research/scripts/polish-markup.test.ts +15 -1
- package/packages/shared-skills/skills/ulw-research/scripts/polish-partial.test.ts +42 -0
- package/packages/shared-skills/skills/ulw-research/scripts/raw-decode.mjs +110 -0
- package/packages/shared-skills/skills/ulw-research/scripts/raw-locator.mjs +47 -0
- package/packages/shared-skills/skills/ulw-research/scripts/raw-snapshot.test.ts +139 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools-2.test.ts +233 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools-3.test.ts +141 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools-4.test.ts +135 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools-5.test.ts +231 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools-commands.mjs +1 -1
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools.mjs +7 -1
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools.test.ts +5 -800
- package/packages/shared-skills/skills/ulw-research/scripts/snapshot-readability.test.ts +116 -0
- package/packages/shared-skills/skills/ulw-research/scripts/source-commands.mjs +79 -26
- package/packages/shared-skills/skills/ulw-research/scripts/source-integrity.test.ts +243 -0
- package/packages/shared-skills/skills/ulw-research/scripts/source-refresh.mjs +82 -0
- package/packages/shared-skills/skills/ulw-research/scripts/source-snapshot.mjs +73 -69
- package/packages/shared-skills/skills/ulw-research/scripts/source-snapshot.test.ts +7 -4
- package/packages/shared-skills/skills/ulw-research/scripts/source-view.mjs +89 -0
- package/packages/shared-skills/skills/ulw-research/scripts/sources-citation.mjs +203 -0
- package/packages/shared-skills/skills/ulw-research/scripts/sources-citation.test.ts +236 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/contracts-support.ts +147 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/delivery-barrier-session.ts +59 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/derive-clock.ts +4 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fact-derive-support.ts +65 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fact-unit-dimensions-support.ts +41 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fact-unit-rules-support.ts +241 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fidelity-values-support.ts +30 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/conversion-probe.html +14 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/sources-shapes.html +20 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/numeral-classes.ts +196 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/report-tools-support.ts +182 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/value-mode-support.ts +48 -0
- package/packages/shared-skills/skills/ulw-research/scripts/units.mjs +14 -3
- package/packages/shared-skills/skills/ulw-research/scripts/units.test.ts +10 -0
- package/packages/shared-skills/skills/ulw-research/scripts/value-mode-unit-classes.test.ts +255 -0
- package/packages/shared-skills/skills/ulw-research/scripts/value-mode-unit.test.ts +179 -0
- package/packages/shared-skills/skills/ulw-research/scripts/value-rules-cli.test.ts +157 -0
- package/packages/shared-skills/skills/ulw-research/scripts/value-rules-followups.test.ts +72 -0
- package/packages/shared-skills/skills/ulw-research/scripts/value-rules-priority.test.ts +80 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +0 -7
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +0 -19
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +0 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +0 -1128
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_fetch_chain.py +0 -77
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_stealth.py +0 -86
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +0 -279
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate.py +0 -252
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +0 -78
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lazycodex-ai",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.51",
|
|
4
4
|
"description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -75,6 +75,8 @@
|
|
|
75
75
|
"packages/omo-codex/plugin/.codex-plugin",
|
|
76
76
|
"packages/omo-codex/marketplace.json",
|
|
77
77
|
"packages/omo-codex/lazycodex-repository",
|
|
78
|
+
"packages/lsp-core/package.json",
|
|
79
|
+
"packages/lsp-core/src",
|
|
78
80
|
"packages/lsp-tools-mcp/package.json",
|
|
79
81
|
"packages/lsp-tools-mcp/dist",
|
|
80
82
|
"packages/lsp-daemon/package.json",
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@oh-my-opencode/lsp-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": true,
|
|
6
|
+
"description": "Harness-neutral Language Server Protocol engine and tool definitions for oh-my-opencode.",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./src/index.ts",
|
|
10
|
+
"import": "./src/index.ts"
|
|
11
|
+
},
|
|
12
|
+
"./tools": {
|
|
13
|
+
"types": "./src/tools.ts",
|
|
14
|
+
"import": "./src/tools.ts"
|
|
15
|
+
},
|
|
16
|
+
"./request-context": {
|
|
17
|
+
"types": "./src/request-context.ts",
|
|
18
|
+
"import": "./src/request-context.ts"
|
|
19
|
+
},
|
|
20
|
+
"./missing-dependency-result": {
|
|
21
|
+
"types": "./src/missing-dependency-result.ts",
|
|
22
|
+
"import": "./src/missing-dependency-result.ts"
|
|
23
|
+
},
|
|
24
|
+
"./mcp": {
|
|
25
|
+
"types": "./src/mcp.ts",
|
|
26
|
+
"import": "./src/mcp.ts"
|
|
27
|
+
},
|
|
28
|
+
"./post-edit": {
|
|
29
|
+
"types": "./src/post-edit/index.ts",
|
|
30
|
+
"import": "./src/post-edit/index.ts"
|
|
31
|
+
},
|
|
32
|
+
"./lsp/*": {
|
|
33
|
+
"types": "./src/lsp/*.ts",
|
|
34
|
+
"import": "./src/lsp/*.ts"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"types": "./src/index.ts",
|
|
38
|
+
"scripts": {
|
|
39
|
+
"typecheck": "tsgo --noEmit -p tsconfig.json",
|
|
40
|
+
"test": "bun test src/*.test.ts src/**/*.test.ts"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@oh-my-opencode/mcp-stdio-core": "workspace:*"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export * from "./lsp/cleanup-errors.js";
|
|
2
|
+
export * from "./lsp/client-wrapper.js";
|
|
3
|
+
export * from "./lsp/client.js";
|
|
4
|
+
export * from "./lsp/config-loader.js";
|
|
5
|
+
export * from "./lsp/connection.js";
|
|
6
|
+
export * from "./lsp/constants.js";
|
|
7
|
+
export * from "./lsp/directory-diagnostics.js";
|
|
8
|
+
export * from "./lsp/effective-extension.js";
|
|
9
|
+
export * from "./lsp/errors.js";
|
|
10
|
+
export * from "./lsp/format-document.js";
|
|
11
|
+
export * from "./lsp/formatters.js";
|
|
12
|
+
export * from "./lsp/infer-extension.js";
|
|
13
|
+
export * from "./lsp/json-rpc-connection.js";
|
|
14
|
+
export * from "./lsp/language-mappings.js";
|
|
15
|
+
export * from "./lsp/manager.js";
|
|
16
|
+
export * from "./lsp/process-signal-cleanup.js";
|
|
17
|
+
export * from "./lsp/process.js";
|
|
18
|
+
export * from "./lsp/server-definitions.js";
|
|
19
|
+
export * from "./lsp/server-install-state.js";
|
|
20
|
+
export * from "./lsp/server-installation.js";
|
|
21
|
+
export * from "./lsp/server-resolution.js";
|
|
22
|
+
export * from "./lsp/transport.js";
|
|
23
|
+
export * from "./lsp/types.js";
|
|
24
|
+
export * from "./lsp/utils.js";
|
|
25
|
+
export * from "./lsp/workspace-edit.js";
|
|
26
|
+
export * from "./mcp.js";
|
|
27
|
+
export * from "./missing-dependency-result.js";
|
|
28
|
+
export * from "./post-edit/index.js";
|
|
29
|
+
export * from "./request-context.js";
|
|
30
|
+
export * from "./tools.js";
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import type { Diagnostic } from "./types.js";
|
|
3
|
+
|
|
4
|
+
export interface FileDiagnostic {
|
|
5
|
+
readonly file: string;
|
|
6
|
+
readonly diagnostic: Diagnostic;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const TSC_LINE = /^(.+?)\((\d+),(\d+)\): (error|warning|message) (TS\d+): (.*)$/;
|
|
10
|
+
const TSC_SEVERITY: Record<string, number> = { error: 1, warning: 2, message: 3 };
|
|
11
|
+
|
|
12
|
+
export function parseBunCheckOutput(stdout: string, cwd: string): FileDiagnostic[] {
|
|
13
|
+
const results: Array<{ file: string; diagnostic: Diagnostic }> = [];
|
|
14
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
15
|
+
const match = TSC_LINE.exec(line);
|
|
16
|
+
if (match) {
|
|
17
|
+
const [, path, lineNumber, column, severity, code, message] = match;
|
|
18
|
+
const start = { line: Number(lineNumber) - 1, character: Number(column) - 1 };
|
|
19
|
+
results.push({
|
|
20
|
+
file: resolve(cwd, path ?? ""),
|
|
21
|
+
diagnostic: {
|
|
22
|
+
range: { start, end: start },
|
|
23
|
+
severity: TSC_SEVERITY[severity ?? "error"] ?? 1,
|
|
24
|
+
code: code ?? "",
|
|
25
|
+
source: "bun check",
|
|
26
|
+
message: message ?? "",
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const previous = results[results.length - 1];
|
|
32
|
+
if (previous !== undefined && /^\s+\S/.test(line)) {
|
|
33
|
+
previous.diagnostic.message = `${previous.diagnostic.message}\n${line.trim()}`;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return results;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface EslintJsonMessage {
|
|
40
|
+
readonly ruleId?: string | null;
|
|
41
|
+
readonly severity?: number;
|
|
42
|
+
readonly message?: string;
|
|
43
|
+
readonly line?: number;
|
|
44
|
+
readonly column?: number;
|
|
45
|
+
readonly endLine?: number;
|
|
46
|
+
readonly endColumn?: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function parseBunLintJson(stdout: string): FileDiagnostic[] | undefined {
|
|
50
|
+
let parsed: unknown;
|
|
51
|
+
try {
|
|
52
|
+
parsed = JSON.parse(stdout);
|
|
53
|
+
} catch {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
if (!Array.isArray(parsed)) return undefined;
|
|
57
|
+
const results: FileDiagnostic[] = [];
|
|
58
|
+
for (const entry of parsed) {
|
|
59
|
+
if (entry === null || typeof entry !== "object") continue;
|
|
60
|
+
const filePath = (entry as { filePath?: unknown }).filePath;
|
|
61
|
+
const messages = (entry as { messages?: unknown }).messages;
|
|
62
|
+
if (typeof filePath !== "string" || !Array.isArray(messages)) continue;
|
|
63
|
+
for (const raw of messages as EslintJsonMessage[]) {
|
|
64
|
+
const start = { line: Math.max(0, (raw.line ?? 1) - 1), character: Math.max(0, (raw.column ?? 1) - 1) };
|
|
65
|
+
const end = {
|
|
66
|
+
line: raw.endLine === undefined ? start.line : Math.max(0, raw.endLine - 1),
|
|
67
|
+
character: raw.endColumn === undefined ? start.character : Math.max(0, raw.endColumn - 1),
|
|
68
|
+
};
|
|
69
|
+
results.push({
|
|
70
|
+
file: filePath,
|
|
71
|
+
diagnostic: {
|
|
72
|
+
range: { start, end },
|
|
73
|
+
severity: raw.severity === 2 ? 1 : 2,
|
|
74
|
+
...(raw.ruleId ? { code: raw.ruleId } : {}),
|
|
75
|
+
source: "bun lint",
|
|
76
|
+
message: raw.message ?? "",
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return results;
|
|
82
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from "bun:test";
|
|
2
|
+
import { writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
import { parseBunCheckOutput, parseBunLintJson } from "./bun-command-output.js";
|
|
6
|
+
import {
|
|
7
|
+
__resetBunCommandProbeCacheForTests,
|
|
8
|
+
bunHasCommand,
|
|
9
|
+
findBunProjectRoot,
|
|
10
|
+
projectShadowsBunCommand,
|
|
11
|
+
resolveBunProjectCommand,
|
|
12
|
+
} from "./bun-project-checks.js";
|
|
13
|
+
import { createFakeBun, createProject, removeFakeBunFixtures } from "./fake-bun-test-support.js";
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
__resetBunCommandProbeCacheForTests();
|
|
17
|
+
removeFakeBunFixtures();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("findBunProjectRoot", () => {
|
|
21
|
+
it("#given a bun.lock, a bunfig.toml or a bun packageManager #when looked up from a nested directory #then that project root is found", () => {
|
|
22
|
+
for (const marker of [{ "bun.lock": "" }, { "bunfig.toml": "" }, { "package.json": '{"packageManager":"bun@1.4.3"}' }]) {
|
|
23
|
+
const root = createProject({ ...marker, "src/deep/a.ts": "" });
|
|
24
|
+
expect(findBunProjectRoot(join(root, "src", "deep"))).toBe(root);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("#given an npm project inside a repository #when looked up #then the walk stops at the repository boundary", () => {
|
|
29
|
+
const root = createProject({ "package.json": '{"packageManager":"npm@11.0.0"}', "package-lock.json": "{}", "src/a.ts": "" });
|
|
30
|
+
expect(findBunProjectRoot(join(root, "src"))).toBeUndefined();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("#given a bunfig.toml in the home directory and no repository #when looked up below home #then it is not a Bun project", () => {
|
|
34
|
+
const home = createProject({ "bunfig.toml": "", "work/src/a.ts": "" }, { git: false });
|
|
35
|
+
expect(findBunProjectRoot(join(home, "work", "src"), home)).toBeUndefined();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe("projectShadowsBunCommand", () => {
|
|
40
|
+
it("#given a package.json script named like the command #when checked #then the built-in command is shadowed", () => {
|
|
41
|
+
const root = createProject({ "bun.lock": "", "package.json": '{"scripts":{"check":"tsc","lint":"eslint ."}}' });
|
|
42
|
+
expect(projectShadowsBunCommand("check", root)).toBe(true);
|
|
43
|
+
expect(projectShadowsBunCommand("lint", root)).toBe(true);
|
|
44
|
+
expect(projectShadowsBunCommand("format", root)).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("#given a lint.ts file #when checked #then lint is shadowed but check is not", () => {
|
|
48
|
+
const root = createProject({ "bun.lock": "", "lint.ts": "", "check.ts": "" });
|
|
49
|
+
expect(projectShadowsBunCommand("lint", root)).toBe(true);
|
|
50
|
+
expect(projectShadowsBunCommand("check", root)).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("#given a plain lint/ or format/ folder #when checked #then it does not shadow, but one with an index file does", () => {
|
|
54
|
+
const plain = createProject({ "bun.lock": "", "lint/rules.md": "", "format/notes.txt": "" });
|
|
55
|
+
expect(projectShadowsBunCommand("lint", plain)).toBe(false);
|
|
56
|
+
expect(projectShadowsBunCommand("format", plain)).toBe(false);
|
|
57
|
+
const runnable = createProject({ "bun.lock": "", "lint/index.ts": "" });
|
|
58
|
+
expect(projectShadowsBunCommand("lint", runnable)).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe("bunHasCommand", () => {
|
|
63
|
+
it("#given a bun without lint #when probed #then only the commands whose --help exits 0 are available", async () => {
|
|
64
|
+
const bun = createFakeBun({ commands: ["check"] });
|
|
65
|
+
expect(await bunHasCommand(bun.path, "check")).toBe(true);
|
|
66
|
+
expect(await bunHasCommand(bun.path, "lint")).toBe(false);
|
|
67
|
+
expect(await bunHasCommand(bun.path, "format")).toBe(false);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("#given concurrent and repeated probes #when probed #then each command runs --help once, in an empty directory", async () => {
|
|
71
|
+
const bun = createFakeBun({ commands: ["check", "lint"] });
|
|
72
|
+
await Promise.all([bunHasCommand(bun.path, "lint"), bunHasCommand(bun.path, "lint")]);
|
|
73
|
+
await bunHasCommand(bun.path, "lint");
|
|
74
|
+
const calls = bun.calls();
|
|
75
|
+
expect(calls.map((call) => call.args)).toEqual([["lint", "--help"]]);
|
|
76
|
+
expect(calls[0]?.cwdEntries).toEqual([]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("#given a bun whose format answers --help #when its format --write leaves the file unchanged #then format counts as unavailable", async () => {
|
|
80
|
+
const silent = createFakeBun({ commands: ["check", "format"], formatWrites: false });
|
|
81
|
+
const writing = createFakeBun({ commands: ["check", "format"], formatWrites: true });
|
|
82
|
+
expect(await bunHasCommand(silent.path, "format")).toBe(false);
|
|
83
|
+
expect(await bunHasCommand(writing.path, "format")).toBe(true);
|
|
84
|
+
expect(writing.calls().map((call) => call.args)).toEqual([
|
|
85
|
+
["format", "--help"],
|
|
86
|
+
["format", "--write", "probe.ts"],
|
|
87
|
+
]);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("#given a probe that times out #when probed again #then the timeout is not cached as absent and the retry answers", async () => {
|
|
91
|
+
const release = join(createProject({}), "release");
|
|
92
|
+
const bun = createFakeBun({ commands: ["check", "lint"], hangHelpUntil: release });
|
|
93
|
+
expect(await bunHasCommand(bun.path, "lint", 500)).toBe(false);
|
|
94
|
+
writeFileSync(release, "");
|
|
95
|
+
expect(await bunHasCommand(bun.path, "lint")).toBe(true);
|
|
96
|
+
}, 30_000);
|
|
97
|
+
|
|
98
|
+
it("#given a bun wrapper that starts bun as a child #when the probe times out #then the probe settles near its deadline", async () => {
|
|
99
|
+
const release = join(createProject({}), "release");
|
|
100
|
+
const bun = createFakeBun({ commands: ["check", "lint"], hangHelpUntil: release, wrapperForks: true });
|
|
101
|
+
const started = performance.now();
|
|
102
|
+
expect(await bunHasCommand(bun.path, "lint", 500)).toBe(false);
|
|
103
|
+
expect(performance.now() - started).toBeLessThan(5_000);
|
|
104
|
+
writeFileSync(release, "");
|
|
105
|
+
}, 30_000);
|
|
106
|
+
|
|
107
|
+
it("#given the bun binary is replaced in place #when probed again #then the new binary is probed", async () => {
|
|
108
|
+
const bun = createFakeBun({ commands: ["check"] });
|
|
109
|
+
expect(await bunHasCommand(bun.path, "lint")).toBe(false);
|
|
110
|
+
bun.upgrade({ commands: ["check", "lint"] });
|
|
111
|
+
expect(await bunHasCommand(bun.path, "lint")).toBe(true);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe("resolveBunProjectCommand", () => {
|
|
116
|
+
it("#given a non-Bun project #when resolved #then bun is never looked up", async () => {
|
|
117
|
+
const root = createProject({ "package.json": "{}", "src/a.ts": "" });
|
|
118
|
+
let lookups = 0;
|
|
119
|
+
expect(await resolveBunProjectCommand("check", root, { resolveBun: () => (lookups++, "/unused/bun") })).toBeUndefined();
|
|
120
|
+
expect(lookups).toBe(0);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("#given a Bun project and a bun with check #when resolved #then that bun is returned", async () => {
|
|
124
|
+
const root = createProject({ "bun.lock": "" });
|
|
125
|
+
const bun = createFakeBun({ commands: ["check"] });
|
|
126
|
+
expect(await resolveBunProjectCommand("check", root, { resolveBun: () => bun.path })).toBe(bun.path);
|
|
127
|
+
expect(await resolveBunProjectCommand("lint", root, { resolveBun: () => bun.path })).toBeUndefined();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe("bun command output", () => {
|
|
132
|
+
it("#given tsc-style bun check output #when parsed #then diagnostics carry file, 0-based position, code and continuation lines", () => {
|
|
133
|
+
const cwd = createProject({});
|
|
134
|
+
const parsed = parseBunCheckOutput(
|
|
135
|
+
"src/x.ts(3,7): error TS2322: Type 'string' is not assignable to type 'number'.\n The expected type comes from here.\n",
|
|
136
|
+
cwd,
|
|
137
|
+
);
|
|
138
|
+
expect(parsed).toEqual([
|
|
139
|
+
{
|
|
140
|
+
file: join(cwd, "src", "x.ts"),
|
|
141
|
+
diagnostic: {
|
|
142
|
+
range: { start: { line: 2, character: 6 }, end: { line: 2, character: 6 } },
|
|
143
|
+
severity: 1,
|
|
144
|
+
code: "TS2322",
|
|
145
|
+
source: "bun check",
|
|
146
|
+
message: "Type 'string' is not assignable to type 'number'.\nThe expected type comes from here.",
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
]);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("#given ESLint JSON from bun lint #when parsed #then errors and warnings map to LSP severities", () => {
|
|
153
|
+
const parsed = parseBunLintJson(
|
|
154
|
+
JSON.stringify([
|
|
155
|
+
{
|
|
156
|
+
filePath: "/p/a.ts",
|
|
157
|
+
messages: [
|
|
158
|
+
{ ruleId: "prefer-const", severity: 2, message: "Use const", line: 3, column: 7, endLine: 3, endColumn: 12 },
|
|
159
|
+
{ ruleId: null, severity: 1, message: "Unused directive", line: 1, column: 1 },
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
]),
|
|
163
|
+
);
|
|
164
|
+
expect(parsed?.map(({ file, diagnostic }) => [file, diagnostic.severity, diagnostic.code, diagnostic.range.start])).toEqual([
|
|
165
|
+
["/p/a.ts", 1, "prefer-const", { line: 2, character: 6 }],
|
|
166
|
+
["/p/a.ts", 2, undefined, { line: 0, character: 0 }],
|
|
167
|
+
]);
|
|
168
|
+
expect(parseBunLintJson("not json")).toBeUndefined();
|
|
169
|
+
});
|
|
170
|
+
});
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir, tmpdir } from "node:os";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
|
+
import { createSpawnCommand, killProcessTree } from "./process.js";
|
|
6
|
+
import { resolveServerBinary } from "./server-installation.js";
|
|
7
|
+
|
|
8
|
+
export type BunProjectCommand = "check" | "lint" | "format";
|
|
9
|
+
|
|
10
|
+
export interface BunProjectChecksOptions {
|
|
11
|
+
readonly resolveBun?: (cwd: string) => string | null;
|
|
12
|
+
readonly homeDir?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface BunCommandRun {
|
|
16
|
+
readonly exitCode: number | null;
|
|
17
|
+
readonly stdout: string;
|
|
18
|
+
readonly stderr: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const BUN_LOCKFILES = ["bun.lock", "bun.lockb", "bunfig.toml"];
|
|
22
|
+
const RUNNABLE_EXTENSIONS = [".tsx", ".ts", ".jsx", ".cts", ".cjs", ".js", ".mjs", ".mts"];
|
|
23
|
+
const BIN_SUFFIXES = process.platform === "win32" ? [".exe", ".bunx", ".cmd", ""] : [""];
|
|
24
|
+
const PROBE_TIMEOUT_MS = 10_000;
|
|
25
|
+
const UNFORMATTED_PROBE = "const a=1\n";
|
|
26
|
+
|
|
27
|
+
const probeCache = new Map<string, Promise<boolean>>();
|
|
28
|
+
|
|
29
|
+
export function __resetBunCommandProbeCacheForTests(): void {
|
|
30
|
+
probeCache.clear();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// The walk stops at the repository boundary, and never reads the home directory or anything above
|
|
34
|
+
// it, so a stray file there does not turn every directory outside a repository into a Bun project.
|
|
35
|
+
export function findBunProjectRoot(start: string, home: string = homedir()): string | undefined {
|
|
36
|
+
const stopAt = resolve(home);
|
|
37
|
+
let dir = resolve(start);
|
|
38
|
+
for (;;) {
|
|
39
|
+
if (dir === stopAt) return undefined;
|
|
40
|
+
if (BUN_LOCKFILES.some((name) => existsSync(join(dir, name)))) return dir;
|
|
41
|
+
if (packageManagerIsBun(join(dir, "package.json"))) return dir;
|
|
42
|
+
if (existsSync(join(dir, ".git"))) return undefined;
|
|
43
|
+
const parent = dirname(dir);
|
|
44
|
+
if (parent === dir) return undefined;
|
|
45
|
+
dir = parent;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function packageManagerIsBun(packageJsonPath: string): boolean {
|
|
50
|
+
const manifest = readJsonObject(packageJsonPath);
|
|
51
|
+
const packageManager = manifest?.["packageManager"];
|
|
52
|
+
return typeof packageManager === "string" && packageManager.startsWith("bun@");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function readJsonObject(path: string): Record<string, unknown> | undefined {
|
|
56
|
+
if (!existsSync(path)) return undefined;
|
|
57
|
+
try {
|
|
58
|
+
const parsed: unknown = JSON.parse(readFileSync(path, "utf8"));
|
|
59
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)
|
|
60
|
+
? (parsed as Record<string, unknown>)
|
|
61
|
+
: undefined;
|
|
62
|
+
} catch {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function isFile(path: string): boolean {
|
|
68
|
+
try {
|
|
69
|
+
return statSync(path).isFile();
|
|
70
|
+
} catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function isDirectory(path: string): boolean {
|
|
76
|
+
try {
|
|
77
|
+
return statSync(path).isDirectory();
|
|
78
|
+
} catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Bun still runs a project's own script (nearest package.json) named check/lint/format, and for
|
|
84
|
+
// lint/format also what `bun <name>` would run as a file: `name` or `name.<ext>`, a `name/` directory
|
|
85
|
+
// with a package.json or an index file, or an executable a package installed in node_modules/.bin.
|
|
86
|
+
export function projectShadowsBunCommand(command: BunProjectCommand, cwd: string): boolean {
|
|
87
|
+
const packageJsonDir = nearestPackageJsonDir(cwd);
|
|
88
|
+
if (packageJsonDir !== undefined) {
|
|
89
|
+
const scripts = readJsonObject(join(packageJsonDir, "package.json"))?.["scripts"];
|
|
90
|
+
if (scripts !== null && typeof scripts === "object" && typeof (scripts as Record<string, unknown>)[command] === "string") {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (command === "check") return false;
|
|
95
|
+
const base = join(cwd, command);
|
|
96
|
+
if (isFile(base) || RUNNABLE_EXTENSIONS.some((extension) => isFile(`${base}${extension}`))) return true;
|
|
97
|
+
if (isDirectory(base) && (isFile(join(base, "package.json")) || RUNNABLE_EXTENSIONS.some((extension) => isFile(join(base, `index${extension}`))))) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
let dir = resolve(cwd);
|
|
101
|
+
for (;;) {
|
|
102
|
+
if (BIN_SUFFIXES.some((suffix) => existsSync(join(dir, "node_modules", ".bin", `${command}${suffix}`)))) return true;
|
|
103
|
+
const parent = dirname(dir);
|
|
104
|
+
if (parent === dir) return false;
|
|
105
|
+
dir = parent;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function nearestPackageJsonDir(start: string): string | undefined {
|
|
110
|
+
let dir = resolve(start);
|
|
111
|
+
for (;;) {
|
|
112
|
+
if (existsSync(join(dir, "package.json"))) return dir;
|
|
113
|
+
const parent = dirname(dir);
|
|
114
|
+
if (parent === dir) return undefined;
|
|
115
|
+
dir = parent;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function binaryIdentity(bunPath: string): string {
|
|
120
|
+
try {
|
|
121
|
+
const stats = statSync(bunPath);
|
|
122
|
+
return `${stats.mtimeMs}:${stats.size}`;
|
|
123
|
+
} catch {
|
|
124
|
+
return "missing";
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Feature detection by exit code, in an empty directory: next to a same-named project script an
|
|
129
|
+
// older Bun runs that script for `--help` and exits 0. Asynchronous, so a probe never blocks the
|
|
130
|
+
// event loop; cached per binary and command, and re-probed when the binary file changes. Only a
|
|
131
|
+
// definite answer is kept: a probe that timed out or could not spawn is retried on the next call.
|
|
132
|
+
export function bunHasCommand(
|
|
133
|
+
bunPath: string,
|
|
134
|
+
command: BunProjectCommand,
|
|
135
|
+
timeoutMs: number = PROBE_TIMEOUT_MS,
|
|
136
|
+
): Promise<boolean> {
|
|
137
|
+
const key = `${bunPath}\0${binaryIdentity(bunPath)}\0${command}`;
|
|
138
|
+
const cached = probeCache.get(key);
|
|
139
|
+
if (cached !== undefined) return cached;
|
|
140
|
+
const probe = probeOnce(bunPath, command, timeoutMs).then((answer) => {
|
|
141
|
+
if (answer === undefined) probeCache.delete(key);
|
|
142
|
+
return answer === true;
|
|
143
|
+
});
|
|
144
|
+
probeCache.set(key, probe);
|
|
145
|
+
return probe;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// `format` must also prove it rewrites a file in place: a bun whose `format --write` printed to stdout
|
|
149
|
+
// instead, or ignored the flag, would leave every file unchanged and silently stop formatting.
|
|
150
|
+
async function probeOnce(bunPath: string, command: BunProjectCommand, timeoutMs: number): Promise<boolean | undefined> {
|
|
151
|
+
const emptyDir = mkdtempSync(join(tmpdir(), "omo-bun-probe-"));
|
|
152
|
+
const timeout = AbortSignal.timeout(timeoutMs);
|
|
153
|
+
try {
|
|
154
|
+
const help = await runBunCommand(bunPath, [command, "--help"], emptyDir, timeout);
|
|
155
|
+
if (help.exitCode === null) return undefined;
|
|
156
|
+
if (help.exitCode !== 0) return false;
|
|
157
|
+
if (command !== "format") return true;
|
|
158
|
+
const probeFile = join(emptyDir, "probe.ts");
|
|
159
|
+
writeFileSync(probeFile, UNFORMATTED_PROBE);
|
|
160
|
+
const write = await runBunCommand(bunPath, ["format", "--write", "probe.ts"], emptyDir, timeout);
|
|
161
|
+
if (write.exitCode === null) return undefined;
|
|
162
|
+
return write.exitCode === 0 && readFileSync(probeFile, "utf8") !== UNFORMATTED_PROBE;
|
|
163
|
+
} catch {
|
|
164
|
+
return undefined;
|
|
165
|
+
} finally {
|
|
166
|
+
rmSync(emptyDir, { recursive: true, force: true });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export async function resolveBunProjectCommand(
|
|
171
|
+
command: BunProjectCommand,
|
|
172
|
+
cwd: string,
|
|
173
|
+
options: BunProjectChecksOptions = {},
|
|
174
|
+
): Promise<string | undefined> {
|
|
175
|
+
if (findBunProjectRoot(cwd, options.homeDir) === undefined) return undefined;
|
|
176
|
+
if (projectShadowsBunCommand(command, cwd)) return undefined;
|
|
177
|
+
const bunPath = (options.resolveBun ?? defaultResolveBun)(cwd);
|
|
178
|
+
if (!bunPath) return undefined;
|
|
179
|
+
return (await bunHasCommand(bunPath, command)) ? bunPath : undefined;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function defaultResolveBun(cwd: string): string | null {
|
|
183
|
+
return resolveServerBinary(["bun"], cwd);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function runBunCommand(bunPath: string, args: readonly string[], cwd: string, signal?: AbortSignal): Promise<BunCommandRun> {
|
|
187
|
+
signal?.throwIfAborted();
|
|
188
|
+
const prepared = createSpawnCommand([bunPath, ...args]);
|
|
189
|
+
return new Promise((resolvePromise, reject) => {
|
|
190
|
+
const child = spawn(prepared.command, prepared.args, {
|
|
191
|
+
cwd,
|
|
192
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
193
|
+
shell: prepared.shell,
|
|
194
|
+
windowsHide: true,
|
|
195
|
+
detached: process.platform !== "win32",
|
|
196
|
+
});
|
|
197
|
+
const stdout: Buffer[] = [];
|
|
198
|
+
const stderr: Buffer[] = [];
|
|
199
|
+
// A wrapper (a .cmd shim through cmd.exe on Windows, a non-exec sh script elsewhere) leaves bun holding
|
|
200
|
+
// the pipes when only the direct child dies, so an aborted probe would outlive its timeout. Kill the
|
|
201
|
+
// whole tree: taskkill /T on Windows, the process group (hence `detached`) elsewhere.
|
|
202
|
+
const onAbort = () => killProcessTree(child, "SIGKILL");
|
|
203
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
204
|
+
child.stdout?.on("data", (chunk: Buffer) => stdout.push(chunk));
|
|
205
|
+
child.stderr?.on("data", (chunk: Buffer) => stderr.push(chunk));
|
|
206
|
+
child.once("error", (error) => {
|
|
207
|
+
signal?.removeEventListener("abort", onAbort);
|
|
208
|
+
reject(error);
|
|
209
|
+
});
|
|
210
|
+
child.once("close", (exitCode) => {
|
|
211
|
+
signal?.removeEventListener("abort", onAbort);
|
|
212
|
+
if (signal?.aborted) {
|
|
213
|
+
reject(signal.reason);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
resolvePromise({
|
|
217
|
+
exitCode,
|
|
218
|
+
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
219
|
+
stderr: Buffer.concat(stderr).toString("utf8"),
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { reportBestEffortCleanupError } from "./cleanup-errors.js";
|
|
4
|
+
|
|
5
|
+
describe("reportBestEffortCleanupError", () => {
|
|
6
|
+
test("#given an injected cleanup logger #when cleanup fails #then the normal diagnostic is emitted without an environment gate", () => {
|
|
7
|
+
// given
|
|
8
|
+
const messages: string[] = [];
|
|
9
|
+
|
|
10
|
+
// when
|
|
11
|
+
reportBestEffortCleanupError("client stop", new Error("connection closed"), (message) => {
|
|
12
|
+
messages.push(message);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// then
|
|
16
|
+
expect(messages).toEqual(["[lsp] ignored client stop failure during cleanup: connection closed"]);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type CleanupErrorLogger = (message: string) => void;
|
|
2
|
+
|
|
3
|
+
function writeCleanupError(message: string): void {
|
|
4
|
+
process.stderr.write(`${message}\n`);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function reportBestEffortCleanupError(
|
|
8
|
+
operation: string,
|
|
9
|
+
error: unknown,
|
|
10
|
+
logger: CleanupErrorLogger = writeCleanupError,
|
|
11
|
+
): void {
|
|
12
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
13
|
+
logger(`[lsp] ignored ${operation} failure during cleanup: ${message}`);
|
|
14
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { ControlledClock } from "./controlled-clock-test-support.js";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
createWorkspaceEditTestHarness,
|
|
7
|
+
diagnostic,
|
|
8
|
+
readEvents,
|
|
9
|
+
} from "./workspace-apply-edit-test-support.js";
|
|
10
|
+
|
|
11
|
+
const harness = createWorkspaceEditTestHarness();
|
|
12
|
+
|
|
13
|
+
afterEach(async () => {
|
|
14
|
+
await harness.cleanup();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe("LspClient diagnostics concurrency", () => {
|
|
18
|
+
it("#given concurrent diagnostics on a cold file and an exact didOpen publish #when pull is not advertised #then one didOpen opens the file and both requests receive the current diagnostics", async () => {
|
|
19
|
+
// The freshness window runs on a controlled clock: this case asserts that the exact-version
|
|
20
|
+
// didOpen publish satisfies BOTH requests, and the publish is what wakes them. On a real clock
|
|
21
|
+
// the 500ms window is a second, competing deadline against a real fixture server over a real
|
|
22
|
+
// pipe, so a starved Windows shard resolved the requests clean before the publish landed and
|
|
23
|
+
// the case failed with [] (#8323). Frozen, only the publish can settle it.
|
|
24
|
+
const clock = new ControlledClock();
|
|
25
|
+
const context = await harness.makeClient(
|
|
26
|
+
{
|
|
27
|
+
publishDiagnostics: [
|
|
28
|
+
{
|
|
29
|
+
trigger: "didOpen",
|
|
30
|
+
version: 1,
|
|
31
|
+
diagnostics: [diagnostic("exact-current")],
|
|
32
|
+
awaitClientDelivery: true,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{ diagnosticsFreshnessTimeoutMs: 500, versionlessPublishQuiescenceMs: 5, timerProvider: clock },
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const [first, second] = await Promise.all([
|
|
40
|
+
context.client.diagnostics(context.source),
|
|
41
|
+
context.client.diagnostics(context.source),
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
expect(first.items).toEqual([diagnostic("exact-current")]);
|
|
45
|
+
expect(second.items).toEqual([diagnostic("exact-current")]);
|
|
46
|
+
expect(
|
|
47
|
+
readEvents(context.events).filter(
|
|
48
|
+
(event) => event.type === "clientNotification" && event.method === "textDocument/didOpen",
|
|
49
|
+
),
|
|
50
|
+
).toHaveLength(1);
|
|
51
|
+
});
|
|
52
|
+
});
|