oh-my-opencode 4.19.4 → 5.0.0-beta.10
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/publish.md +44 -16
- package/.agents/skills/publish/SKILL.md +44 -16
- package/.agents/skills/work-with-pr/SKILL.md +37 -23
- package/.opencode/command/publish.md +44 -16
- package/.opencode/skills/work-with-pr/SKILL.md +37 -23
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +18 -6
- package/README.ru.md +1 -1
- package/README.zh-cn.md +1 -1
- package/bin/oh-my-opencode.js +14 -1
- package/bin/oh-my-opencode.test.ts +21 -0
- package/dist/agents/atlas/agent.d.ts +0 -1
- package/dist/agents/sisyphus/grok-4.d.ts +20 -0
- package/dist/agents/sisyphus/index.d.ts +2 -0
- package/dist/agents/sisyphus-agent-config.d.ts +6 -0
- package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
- package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +15 -4
- package/dist/agents/types.d.ts +2 -2
- package/dist/cli/index.js +1888 -807
- package/dist/cli/run/on-complete-hook.d.ts +2 -0
- package/dist/cli-node/index.js +1888 -807
- package/dist/config/schema/agent-overrides.d.ts +528 -0
- package/dist/config/schema/oh-my-opencode-config.d.ts +495 -0
- package/dist/features/monitor/batcher.d.ts +3 -1
- package/dist/features/monitor/manager-internals.d.ts +1 -0
- package/dist/features/monitor/output-injector-types.d.ts +2 -0
- package/dist/features/monitor/output-injector.d.ts +6 -0
- package/dist/hooks/atlas/final-wave-approval-gate.test-support.d.ts +50 -0
- package/dist/hooks/atlas/system-reminder-templates.d.ts +0 -1
- package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
- package/dist/hooks/todo-continuation-enforcer/unrecoverable-request-error.d.ts +9 -0
- package/dist/hooks/tool-pair-validator/hook.test-support.d.ts +29 -0
- package/dist/hooks/tool-pair-validator/tool-part-ids.d.ts +14 -5
- package/dist/hooks/tool-pair-validator/tool-result-repair.d.ts +4 -3
- package/dist/hooks/tool-pair-validator/types.d.ts +5 -22
- package/dist/index.js +3139 -2232
- package/dist/mcp/lsp.d.ts +1 -0
- package/dist/oh-my-opencode.schema.json +1466 -131
- package/dist/shared/normalize-sdk-response.d.ts +1 -0
- package/dist/shared/shell-env.d.ts +1 -1
- package/dist/shared/tmux/constants.d.ts +1 -1
- package/dist/skills/ast-grep/SOURCE +1 -1
- package/dist/skills/ast-grep/install.ps1 +2 -2
- package/dist/skills/ast-grep/install.sh +1 -1
- package/dist/skills/ast-grep/references/install.md +2 -2
- package/dist/skills/ast-grep/tests/smoke.sh +1 -1
- package/dist/skills/coding-agent-sessions/SKILL.md +3 -2
- package/dist/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/dist/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/dist/skills/frontend/SKILL.md +10 -7
- package/dist/skills/frontend/references/design/_INDEX.md +1 -0
- package/dist/skills/frontend/references/design/stylegallery.md +80 -0
- package/dist/skills/start-work/SKILL.md +54 -9
- package/dist/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/dist/skills/ultimate-browsing/SKILL.md +2 -2
- package/dist/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/dist/skills/ultimate-browsing/engine/__main__.py +8 -1
- package/dist/skills/ultimate-browsing/engine/bias_check.py +11 -0
- package/dist/skills/ultimate-browsing/engine/fetch_chain.py +90 -52
- package/dist/skills/ultimate-browsing/engine/result_schema.py +10 -1
- package/dist/skills/ultimate-browsing/engine/surrogate.py +214 -0
- package/dist/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
- package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/dist/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
- package/dist/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
- package/dist/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
- package/dist/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
- package/dist/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
- package/dist/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
- package/dist/skills/ultimate-browsing/engine/validators.py +46 -0
- package/dist/skills/ultimate-browsing/engine/waf_detector.py +1 -1
- package/dist/skills/ultimate-browsing/engine/waf_profiles.yaml +10 -5
- package/dist/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
- package/dist/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/dist/skills/ultimate-browsing/references/insane-search/README.md +4 -4
- package/dist/skills/ultimate-browsing/references/insane-search/cache-archive.md +51 -50
- package/dist/skills/ultimate-browsing/references/insane-search/fallback.md +1 -1
- package/dist/skills/ultimate-browsing/references/insane-search/jina.md +8 -2
- package/dist/skills/ultimate-browsing/references/insane-search/naver.md +1 -1
- package/dist/skills/ultimate-browsing/references/insane-search/twitter.md +3 -3
- package/dist/skills/ulw-plan/SKILL.md +3 -3
- package/dist/skills/ulw-plan/references/full-workflow.md +30 -6
- package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
- package/dist/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
- package/dist/skills/ulw-research/SKILL.md +15 -10
- package/dist/tui.js +477 -36
- package/docs/reference/web-terminal-visual-qa.md +1 -1
- package/package.json +34 -24
- package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +44 -0
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +0 -28
- package/packages/lsp-core/src/lsp/client-wrapper.test.ts +60 -7
- package/packages/lsp-core/src/lsp/client-wrapper.ts +69 -16
- package/packages/lsp-core/src/lsp/connection.ts +1 -1
- package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +20 -1
- package/packages/lsp-core/src/tools/diagnostics.ts +3 -3
- package/packages/lsp-core/src/tools/navigation.ts +4 -2
- package/packages/lsp-core/src/tools/rename.ts +4 -2
- package/packages/lsp-core/src/tools/symbols.ts +1 -1
- package/packages/lsp-daemon/dist/cli.js +108 -40
- package/packages/lsp-daemon/dist/client.js +123 -55
- package/packages/lsp-daemon/dist/ensure-daemon.d.ts +1 -0
- package/packages/lsp-daemon/dist/ensure-daemon.js +18 -5
- package/packages/lsp-daemon/dist/index.js +111 -43
- package/packages/lsp-tools-mcp/dist/cli.js +77 -23
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +1 -1
- package/packages/lsp-tools-mcp/dist/mcp.js +77 -23
- package/packages/lsp-tools-mcp/dist/tools.js +77 -23
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +268 -92
- 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 +7 -7
- package/packages/omo-codex/plugin/components/bootstrap/src/worker.ts +3 -0
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +220 -10
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +220 -10
- package/packages/omo-codex/plugin/components/codegraph/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/lazycodex-executor-verify/test/codex-hook.test.ts +3 -17
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +135 -67
- 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/rules/test/bundled-rules-priority.test.ts +11 -16
- package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +16 -23
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
- package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
- package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +37 -69
- package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
- package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +1 -15
- package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +4 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/README.md +5 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +2 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +18 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/src/codex-hook.ts +21 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +0 -3
- package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +107 -16
- 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/teammode/test/thread-title-hook.test.ts +3 -9
- package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +24 -12
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +24 -12
- 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/CHANGELOG.md +2 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-qa-executor.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-low.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +9 -2
- 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 +9 -2
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +3 -3
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +30 -6
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
- package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
- package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +11 -11
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +9 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +1 -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 +9 -9
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +66 -66
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +2 -2
- 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 +5 -4
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +23 -25
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +9 -9
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-commands.test.ts +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-helpers.test.ts +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-kind-guidance.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +2 -5
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +7 -40
- package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +4 -5
- 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 +1 -1
- 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 +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-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 +20 -20
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +4 -4
- package/packages/omo-codex/plugin/skills/ast-grep/SOURCE +1 -1
- package/packages/omo-codex/plugin/skills/ast-grep/install.ps1 +2 -2
- package/packages/omo-codex/plugin/skills/ast-grep/install.sh +1 -1
- package/packages/omo-codex/plugin/skills/ast-grep/references/install.md +2 -2
- package/packages/omo-codex/plugin/skills/ast-grep/tests/smoke.sh +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +10 -7
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +54 -9
- package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/__main__.py +8 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/bias_check.py +11 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/fetch_chain.py +90 -52
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/result_schema.py +10 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/surrogate.py +214 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/validators.py +46 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/waf_detector.py +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/waf_profiles.yaml +10 -5
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +4 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/cache-archive.md +51 -50
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/fallback.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/jina.md +8 -2
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/naver.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/twitter.md +3 -3
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +9 -2
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +5 -4
- package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +23 -25
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +3 -3
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +30 -6
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/packages/omo-codex/plugin/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +15 -10
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +4 -24
- package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
- package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
- package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
- package/packages/omo-codex/plugin/test/bootstrap-binlinks.test.mjs +12 -12
- package/packages/omo-codex/plugin/test/bootstrap-orchestration.test.mjs +36 -4
- package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
- package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
- package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +4 -4
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +1 -119
- package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
- package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
- package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
- package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
- package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
- package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +0 -3
- package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
- package/packages/omo-codex/scripts/install-bin-links.test.mjs +56 -2
- package/packages/omo-codex/scripts/install-delegated-command.test.mjs +6 -6
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +170 -78
- package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
- package/packages/omo-codex/scripts/install-local-entrypoint.test.mjs +4 -4
- package/packages/omo-codex/scripts/install-local.test.mjs +5 -2
- package/packages/shared-skills/index.mjs +19 -1
- package/packages/shared-skills/skills/ast-grep/SOURCE +1 -1
- package/packages/shared-skills/skills/ast-grep/install.ps1 +2 -2
- package/packages/shared-skills/skills/ast-grep/install.sh +1 -1
- package/packages/shared-skills/skills/ast-grep/references/install.md +2 -2
- package/packages/shared-skills/skills/ast-grep/tests/smoke.sh +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/shared-skills/skills/frontend/SKILL.md +10 -7
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/shared-skills/skills/start-work/SKILL.md +54 -9
- package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +2 -2
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/__main__.py +8 -1
- package/packages/shared-skills/skills/ultimate-browsing/engine/bias_check.py +11 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/fetch_chain.py +90 -52
- package/packages/shared-skills/skills/ultimate-browsing/engine/result_schema.py +10 -1
- package/packages/shared-skills/skills/ultimate-browsing/engine/surrogate.py +214 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/validators.py +46 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/waf_detector.py +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/engine/waf_profiles.yaml +10 -5
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +4 -4
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/cache-archive.md +51 -50
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/fallback.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/jina.md +8 -2
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/naver.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/twitter.md +3 -3
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +3 -3
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +30 -6
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
- package/packages/shared-skills/skills/ulw-research/SKILL.md +15 -10
- package/postinstall.mjs +6 -0
- package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
- package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
- package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
|
@@ -918,7 +918,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
918
918
|
initializationOptions: this.server.initialization
|
|
919
919
|
}, { timeoutMs: this.initializeTimeoutMs });
|
|
920
920
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
921
|
-
await this.sendNotification("initialized");
|
|
921
|
+
await this.sendNotification("initialized", {});
|
|
922
922
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
923
923
|
settings: { json: { validate: { enable: true } } }
|
|
924
924
|
});
|
|
@@ -3266,10 +3266,10 @@ function errorText(error) {
|
|
|
3266
3266
|
|
|
3267
3267
|
// src/ensure-daemon.ts
|
|
3268
3268
|
import { spawn as spawn2 } from "node:child_process";
|
|
3269
|
-
import { closeSync as closeSync2, mkdirSync as mkdirSync2, openSync as openSync2 } from "node:fs";
|
|
3269
|
+
import { closeSync as closeSync2, existsSync as existsSync6, mkdirSync as mkdirSync2, openSync as openSync2, writeSync as writeSync2 } from "node:fs";
|
|
3270
3270
|
import { Socket } from "node:net";
|
|
3271
|
-
import { dirname as dirname6 } from "node:path";
|
|
3272
|
-
import { execPath } from "node:process";
|
|
3271
|
+
import { dirname as dirname6, isAbsolute as isAbsolute4 } from "node:path";
|
|
3272
|
+
import { argv0, execPath } from "node:process";
|
|
3273
3273
|
|
|
3274
3274
|
// src/ipc-protocol.ts
|
|
3275
3275
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
@@ -3739,15 +3739,29 @@ function spawnDaemonProcess(paths) {
|
|
|
3739
3739
|
mkdirSync2(dirname6(paths.log), { recursive: true });
|
|
3740
3740
|
const logFd = openSync2(paths.log, "a");
|
|
3741
3741
|
try {
|
|
3742
|
-
const child = spawn2(
|
|
3742
|
+
const child = spawn2(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
|
|
3743
3743
|
detached: true,
|
|
3744
3744
|
stdio: ["ignore", logFd, logFd]
|
|
3745
3745
|
});
|
|
3746
|
+
child.once("spawn", () => closeSync2(logFd));
|
|
3747
|
+
child.once("error", (error) => {
|
|
3748
|
+
writeSync2(logFd, `[lsp-daemon] failed to spawn daemon: ${error.message}
|
|
3749
|
+
`);
|
|
3750
|
+
closeSync2(logFd);
|
|
3751
|
+
});
|
|
3746
3752
|
child.unref();
|
|
3747
|
-
}
|
|
3753
|
+
} catch (error) {
|
|
3748
3754
|
closeSync2(logFd);
|
|
3755
|
+
throw error;
|
|
3749
3756
|
}
|
|
3750
3757
|
}
|
|
3758
|
+
function resolveDaemonNodeExecutable(cachedExecPath = execPath, originalArgv0 = argv0, pathExists = existsSync6) {
|
|
3759
|
+
if (pathExists(cachedExecPath))
|
|
3760
|
+
return cachedExecPath;
|
|
3761
|
+
if (isAbsolute4(originalArgv0) && pathExists(originalArgv0))
|
|
3762
|
+
return originalArgv0;
|
|
3763
|
+
return "node";
|
|
3764
|
+
}
|
|
3751
3765
|
function defaultEnsureDaemonDeps() {
|
|
3752
3766
|
return {
|
|
3753
3767
|
probe: (paths, signal) => probeDaemon(paths, PROBE_TIMEOUT_MS, signal),
|
|
@@ -4139,18 +4153,18 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
|
|
|
4139
4153
|
};
|
|
4140
4154
|
}
|
|
4141
4155
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
4142
|
-
import { existsSync as
|
|
4143
|
-
import { dirname as dirname8, join as join4, resolve as resolve7 } from "node:path";
|
|
4156
|
+
import { existsSync as existsSync10, realpathSync as realpathSync4, statSync as statSync4 } from "node:fs";
|
|
4157
|
+
import { basename as basename3, dirname as dirname8, join as join4, resolve as resolve7 } from "node:path";
|
|
4144
4158
|
|
|
4145
4159
|
// ../lsp-core/src/lsp/server-install-state.ts
|
|
4146
|
-
import { existsSync as
|
|
4160
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
4147
4161
|
import { dirname as dirname7 } from "node:path";
|
|
4148
4162
|
function getInstallDecisionsPath() {
|
|
4149
4163
|
return lspRequestContext().installDecisionsPath;
|
|
4150
4164
|
}
|
|
4151
4165
|
function loadInstallDecisions() {
|
|
4152
4166
|
const path2 = getInstallDecisionsPath();
|
|
4153
|
-
if (!
|
|
4167
|
+
if (!existsSync7(path2))
|
|
4154
4168
|
return {};
|
|
4155
4169
|
try {
|
|
4156
4170
|
const parsed = JSON.parse(readFileSync4(path2, "utf8"));
|
|
@@ -4191,7 +4205,7 @@ function isRecord5(value) {
|
|
|
4191
4205
|
}
|
|
4192
4206
|
|
|
4193
4207
|
// ../lsp-core/src/lsp/config-loader.ts
|
|
4194
|
-
import { existsSync as
|
|
4208
|
+
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
|
|
4195
4209
|
|
|
4196
4210
|
// ../lsp-core/src/lsp/server-definitions.ts
|
|
4197
4211
|
var LSP_INSTALL_HINTS = {
|
|
@@ -4348,7 +4362,7 @@ function getUserConfigPath() {
|
|
|
4348
4362
|
return lspRequestContext().userConfigPath;
|
|
4349
4363
|
}
|
|
4350
4364
|
function loadJsonFile(path2) {
|
|
4351
|
-
if (!
|
|
4365
|
+
if (!existsSync8(path2))
|
|
4352
4366
|
return null;
|
|
4353
4367
|
try {
|
|
4354
4368
|
const parsed = JSON.parse(readFileSync5(path2, "utf-8"));
|
|
@@ -4536,7 +4550,7 @@ function getDisabledServerIds() {
|
|
|
4536
4550
|
}
|
|
4537
4551
|
|
|
4538
4552
|
// ../lsp-core/src/lsp/server-installation.ts
|
|
4539
|
-
import { existsSync as
|
|
4553
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
4540
4554
|
import { delimiter as delimiter3, join as join3 } from "node:path";
|
|
4541
4555
|
function isServerInstalled(command, _workingDirectory) {
|
|
4542
4556
|
if (command.length === 0)
|
|
@@ -4545,7 +4559,7 @@ function isServerInstalled(command, _workingDirectory) {
|
|
|
4545
4559
|
if (!cmd)
|
|
4546
4560
|
return false;
|
|
4547
4561
|
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
4548
|
-
if (
|
|
4562
|
+
if (existsSync9(cmd))
|
|
4549
4563
|
return true;
|
|
4550
4564
|
}
|
|
4551
4565
|
const isWindows = process.platform === "win32";
|
|
@@ -4566,7 +4580,7 @@ function isServerInstalled(command, _workingDirectory) {
|
|
|
4566
4580
|
const paths = pathEnv.split(delimiter3);
|
|
4567
4581
|
for (const p of paths) {
|
|
4568
4582
|
for (const suffix of exts) {
|
|
4569
|
-
if (
|
|
4583
|
+
if (existsSync9(join3(p, cmd + suffix))) {
|
|
4570
4584
|
return true;
|
|
4571
4585
|
}
|
|
4572
4586
|
}
|
|
@@ -4671,32 +4685,86 @@ function isDirectoryPath(filePath) {
|
|
|
4671
4685
|
}
|
|
4672
4686
|
}
|
|
4673
4687
|
function findWorkspaceRoot(filePath) {
|
|
4674
|
-
const
|
|
4688
|
+
const cwd = contextCwd();
|
|
4689
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4675
4690
|
let dir = abs;
|
|
4676
4691
|
if (!isDirectoryPath(dir)) {
|
|
4677
4692
|
dir = dirname8(dir);
|
|
4678
4693
|
}
|
|
4679
|
-
|
|
4680
|
-
while (dir
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4694
|
+
const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
|
|
4695
|
+
while (isPathInside(cwd, dir)) {
|
|
4696
|
+
const canonicalDir = existingDirectoryInsideContext(dir, cwd);
|
|
4697
|
+
if (canonicalDir !== undefined) {
|
|
4698
|
+
for (const marker of WORKSPACE_MARKERS) {
|
|
4699
|
+
if (existsSync10(join4(dir, marker))) {
|
|
4700
|
+
return canonicalDir;
|
|
4701
|
+
}
|
|
4684
4702
|
}
|
|
4685
4703
|
}
|
|
4686
|
-
|
|
4704
|
+
if (dir === cwd)
|
|
4705
|
+
break;
|
|
4687
4706
|
dir = dirname8(dir);
|
|
4688
4707
|
}
|
|
4689
|
-
return
|
|
4708
|
+
return fallbackRoot;
|
|
4690
4709
|
}
|
|
4691
|
-
function
|
|
4710
|
+
function resolveReadablePathInsideContext(filePath) {
|
|
4692
4711
|
const cwd = contextCwd();
|
|
4693
4712
|
const abs = resolve7(cwd, filePath);
|
|
4713
|
+
if (isPathInside(cwd, abs))
|
|
4714
|
+
return abs;
|
|
4715
|
+
const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
|
|
4716
|
+
if (rebased !== undefined)
|
|
4717
|
+
return rebased;
|
|
4718
|
+
const canonical = canonicalizeExistingOrNearestAncestor(abs);
|
|
4719
|
+
if (isPathInside(cwd, canonical))
|
|
4720
|
+
return canonical;
|
|
4721
|
+
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
4722
|
+
}
|
|
4723
|
+
function resolvePathInsideContext(filePath) {
|
|
4724
|
+
const cwd = contextCwd();
|
|
4725
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4694
4726
|
const canonical = canonicalizeExistingOrNearestAncestor(abs);
|
|
4695
4727
|
if (!isPathInside(cwd, canonical)) {
|
|
4696
4728
|
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
4697
4729
|
}
|
|
4698
4730
|
return canonical;
|
|
4699
4731
|
}
|
|
4732
|
+
function rebaseThroughCanonicalAncestor(path2, cwd) {
|
|
4733
|
+
let current = path2;
|
|
4734
|
+
const suffix = [];
|
|
4735
|
+
while (true) {
|
|
4736
|
+
if (existsSync10(current)) {
|
|
4737
|
+
const canonical = realpathSync4(current);
|
|
4738
|
+
if (isPathInside(cwd, canonical))
|
|
4739
|
+
return suffix.length === 0 ? canonical : join4(canonical, ...suffix);
|
|
4740
|
+
}
|
|
4741
|
+
const parent = dirname8(current);
|
|
4742
|
+
if (parent === current)
|
|
4743
|
+
return;
|
|
4744
|
+
suffix.unshift(basename3(current));
|
|
4745
|
+
current = parent;
|
|
4746
|
+
}
|
|
4747
|
+
}
|
|
4748
|
+
function existingDirectoryInsideContext(directory, cwd) {
|
|
4749
|
+
if (!existsSync10(directory))
|
|
4750
|
+
return;
|
|
4751
|
+
const canonical = realpathSync4(directory);
|
|
4752
|
+
if (!statSync4(canonical).isDirectory())
|
|
4753
|
+
return;
|
|
4754
|
+
return isPathInside(cwd, canonical) ? canonical : undefined;
|
|
4755
|
+
}
|
|
4756
|
+
function nearestExistingDirectoryInsideContext(directory, cwd) {
|
|
4757
|
+
let current = directory;
|
|
4758
|
+
while (isPathInside(cwd, current)) {
|
|
4759
|
+
const canonical = existingDirectoryInsideContext(current, cwd);
|
|
4760
|
+
if (canonical !== undefined)
|
|
4761
|
+
return canonical;
|
|
4762
|
+
if (current === cwd)
|
|
4763
|
+
return;
|
|
4764
|
+
current = dirname8(current);
|
|
4765
|
+
}
|
|
4766
|
+
return;
|
|
4767
|
+
}
|
|
4700
4768
|
function formatServerLookupError(result) {
|
|
4701
4769
|
if (result.status === "not_installed") {
|
|
4702
4770
|
return formatNotInstalled(result);
|
|
@@ -4767,7 +4835,7 @@ function formatNotInstalled(result) {
|
|
|
4767
4835
|
].join(`
|
|
4768
4836
|
`);
|
|
4769
4837
|
}
|
|
4770
|
-
var
|
|
4838
|
+
var READ_ONLY_TOOLS = new Set([
|
|
4771
4839
|
"diagnostics",
|
|
4772
4840
|
"definition",
|
|
4773
4841
|
"references",
|
|
@@ -4776,7 +4844,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
|
|
|
4776
4844
|
"prepareRename"
|
|
4777
4845
|
]);
|
|
4778
4846
|
async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
4779
|
-
const absPath = resolvePathInsideContext(filePath);
|
|
4847
|
+
const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
|
|
4780
4848
|
if (isDirectoryPath(absPath)) {
|
|
4781
4849
|
throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
|
|
4782
4850
|
}
|
|
@@ -4791,9 +4859,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4791
4859
|
const acquireAndCall = async (allowRetry) => {
|
|
4792
4860
|
const client = await manager.getClient(root, server2, options.signal);
|
|
4793
4861
|
try {
|
|
4794
|
-
return await fn(client, root);
|
|
4862
|
+
return await fn(client, root, absPath);
|
|
4795
4863
|
} catch (err) {
|
|
4796
|
-
if (allowRetry &&
|
|
4864
|
+
if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
|
|
4797
4865
|
manager.invalidateClient(root, server2.id, client);
|
|
4798
4866
|
return acquireAndCall(false);
|
|
4799
4867
|
}
|
|
@@ -4811,7 +4879,7 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4811
4879
|
}
|
|
4812
4880
|
|
|
4813
4881
|
// ../lsp-core/src/lsp/directory-diagnostics.ts
|
|
4814
|
-
import { existsSync as
|
|
4882
|
+
import { existsSync as existsSync11, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
|
|
4815
4883
|
import { join as join5, resolve as resolve8 } from "node:path";
|
|
4816
4884
|
|
|
4817
4885
|
// ../lsp-core/src/lsp/formatters.ts
|
|
@@ -4968,7 +5036,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4968
5036
|
throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
|
|
4969
5037
|
}
|
|
4970
5038
|
const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
|
|
4971
|
-
if (!
|
|
5039
|
+
if (!existsSync11(absDir)) {
|
|
4972
5040
|
throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
|
|
4973
5041
|
}
|
|
4974
5042
|
const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
|
|
@@ -5248,7 +5316,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
5248
5316
|
const filePath = requireString(params, "filePath");
|
|
5249
5317
|
const severity = severityFilter(params);
|
|
5250
5318
|
try {
|
|
5251
|
-
const absPath =
|
|
5319
|
+
const absPath = resolveReadablePathInsideContext(filePath);
|
|
5252
5320
|
if (isDirectoryPath(absPath)) {
|
|
5253
5321
|
const extension = inferExtensionFromDirectory(absPath);
|
|
5254
5322
|
if (!extension) {
|
|
@@ -5277,7 +5345,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
5277
5345
|
};
|
|
5278
5346
|
return text(output2.output, details2);
|
|
5279
5347
|
}
|
|
5280
|
-
const result = await withLspClient(filePath, async (client) => client.diagnostics(
|
|
5348
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
|
|
5281
5349
|
if (result.transientError) {
|
|
5282
5350
|
const message = result.transientError.message;
|
|
5283
5351
|
const details2 = {
|
|
@@ -5352,7 +5420,7 @@ async function executeLspGotoDefinition(params, signal) {
|
|
|
5352
5420
|
const line = requireNumber(params, "line");
|
|
5353
5421
|
const character = requireNumber(params, "character");
|
|
5354
5422
|
try {
|
|
5355
|
-
const result = await withLspClient(filePath, async (client) => client.definition(
|
|
5423
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
|
|
5356
5424
|
const locations = !result ? [] : Array.isArray(result) ? result : [result];
|
|
5357
5425
|
const details = { filePath, line, character, locations };
|
|
5358
5426
|
if (locations.length === 0)
|
|
@@ -5377,7 +5445,7 @@ async function executeLspFindReferences(params, signal) {
|
|
|
5377
5445
|
const character = requireNumber(params, "character");
|
|
5378
5446
|
const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
|
|
5379
5447
|
try {
|
|
5380
|
-
const result = await withLspClient(filePath, async (client) => client.references(
|
|
5448
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
|
|
5381
5449
|
const references = Array.isArray(result) ? result : [];
|
|
5382
5450
|
const total = references.length;
|
|
5383
5451
|
const truncated = total > DEFAULT_MAX_REFERENCES;
|
|
@@ -5419,7 +5487,7 @@ async function executeLspPrepareRename(params, signal) {
|
|
|
5419
5487
|
const line = requireNumber(params, "line");
|
|
5420
5488
|
const character = requireNumber(params, "character");
|
|
5421
5489
|
try {
|
|
5422
|
-
const result = await withLspClient(filePath, async (client) => client.prepareRename(
|
|
5490
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
|
|
5423
5491
|
const details = { filePath, line, character, result };
|
|
5424
5492
|
return text(formatPrepareRenameResult(result), details);
|
|
5425
5493
|
} catch (error) {
|
|
@@ -5440,7 +5508,7 @@ async function executeLspRename(params, signal) {
|
|
|
5440
5508
|
const character = requireNumber(params, "character");
|
|
5441
5509
|
const newName = requireString(params, "newName");
|
|
5442
5510
|
try {
|
|
5443
|
-
const result = await withLspClient(filePath, async (client) => client.rename(
|
|
5511
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
|
|
5444
5512
|
const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
|
|
5445
5513
|
return text(formatApplyResult(result.apply), details, !result.apply.success);
|
|
5446
5514
|
} catch (error) {
|
|
@@ -5520,7 +5588,7 @@ async function executeLspSymbols(params, signal) {
|
|
|
5520
5588
|
const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
|
|
5521
5589
|
return formatSymbolsResult(filePath, scope, symbols2, limit, query);
|
|
5522
5590
|
}
|
|
5523
|
-
const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(
|
|
5591
|
+
const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
|
|
5524
5592
|
return formatSymbolsResult(filePath, scope, symbols, limit);
|
|
5525
5593
|
} catch (error) {
|
|
5526
5594
|
const query = optionalString(params, "query");
|
|
@@ -6011,8 +6079,8 @@ function isRetryableTool(name) {
|
|
|
6011
6079
|
return name !== "rename" && name !== "lsp_rename";
|
|
6012
6080
|
}
|
|
6013
6081
|
// src/proxy.ts
|
|
6014
|
-
import { existsSync as
|
|
6015
|
-
import { basename as
|
|
6082
|
+
import { existsSync as existsSync12, realpathSync as realpathSync5 } from "node:fs";
|
|
6083
|
+
import { basename as basename4, delimiter as delimiter4, dirname as dirname9, isAbsolute as isAbsolute5 } from "node:path";
|
|
6016
6084
|
var DEFAULT_STARTUP_TIMEOUT_MS = 1e4;
|
|
6017
6085
|
async function runMcpStdioProxy(options = {}) {
|
|
6018
6086
|
const input = options.input ?? process.stdin;
|
|
@@ -6135,15 +6203,15 @@ function canonicalizePathList(value) {
|
|
|
6135
6203
|
return value.split(delimiter4).map((entry) => canonicalizePath(entry) ?? entry).join(delimiter4);
|
|
6136
6204
|
}
|
|
6137
6205
|
function canonicalizePath(value) {
|
|
6138
|
-
if (value === undefined || !
|
|
6206
|
+
if (value === undefined || !isAbsolute5(value) || !existsSync12(value))
|
|
6139
6207
|
return value;
|
|
6140
|
-
return
|
|
6208
|
+
return realpathSync5(value);
|
|
6141
6209
|
}
|
|
6142
6210
|
function projectRootFromOpenCodeConfigPath(path2) {
|
|
6143
|
-
if (
|
|
6211
|
+
if (basename4(path2) !== "lsp.json" && basename4(path2) !== "lsp-client.json")
|
|
6144
6212
|
return;
|
|
6145
6213
|
const configDir = dirname9(path2);
|
|
6146
|
-
const configDirName =
|
|
6214
|
+
const configDirName = basename4(configDir);
|
|
6147
6215
|
if (configDirName !== ".opencode" && configDirName !== ".omo")
|
|
6148
6216
|
return;
|
|
6149
6217
|
return dirname9(configDir);
|
|
@@ -920,7 +920,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
920
920
|
initializationOptions: this.server.initialization
|
|
921
921
|
}, { timeoutMs: this.initializeTimeoutMs });
|
|
922
922
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
923
|
-
await this.sendNotification("initialized");
|
|
923
|
+
await this.sendNotification("initialized", {});
|
|
924
924
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
925
925
|
settings: { json: { validate: { enable: true } } }
|
|
926
926
|
});
|
|
@@ -3320,8 +3320,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
|
|
|
3320
3320
|
};
|
|
3321
3321
|
}
|
|
3322
3322
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
3323
|
-
import { existsSync as existsSync9, statSync as statSync3 } from "node:fs";
|
|
3324
|
-
import { dirname as dirname6, join as join4, resolve as resolve7 } from "node:path";
|
|
3323
|
+
import { existsSync as existsSync9, realpathSync as realpathSync4, statSync as statSync3 } from "node:fs";
|
|
3324
|
+
import { basename as basename3, dirname as dirname6, join as join4, resolve as resolve7 } from "node:path";
|
|
3325
3325
|
|
|
3326
3326
|
// ../lsp-core/src/request-context.ts
|
|
3327
3327
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -4031,32 +4031,86 @@ function isDirectoryPath(filePath) {
|
|
|
4031
4031
|
}
|
|
4032
4032
|
}
|
|
4033
4033
|
function findWorkspaceRoot(filePath) {
|
|
4034
|
-
const
|
|
4034
|
+
const cwd = contextCwd();
|
|
4035
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4035
4036
|
let dir = abs;
|
|
4036
4037
|
if (!isDirectoryPath(dir)) {
|
|
4037
4038
|
dir = dirname6(dir);
|
|
4038
4039
|
}
|
|
4039
|
-
|
|
4040
|
-
while (dir
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4040
|
+
const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
|
|
4041
|
+
while (isPathInside(cwd, dir)) {
|
|
4042
|
+
const canonicalDir = existingDirectoryInsideContext(dir, cwd);
|
|
4043
|
+
if (canonicalDir !== undefined) {
|
|
4044
|
+
for (const marker of WORKSPACE_MARKERS) {
|
|
4045
|
+
if (existsSync9(join4(dir, marker))) {
|
|
4046
|
+
return canonicalDir;
|
|
4047
|
+
}
|
|
4044
4048
|
}
|
|
4045
4049
|
}
|
|
4046
|
-
|
|
4050
|
+
if (dir === cwd)
|
|
4051
|
+
break;
|
|
4047
4052
|
dir = dirname6(dir);
|
|
4048
4053
|
}
|
|
4049
|
-
return
|
|
4054
|
+
return fallbackRoot;
|
|
4050
4055
|
}
|
|
4051
|
-
function
|
|
4056
|
+
function resolveReadablePathInsideContext(filePath) {
|
|
4052
4057
|
const cwd = contextCwd();
|
|
4053
4058
|
const abs = resolve7(cwd, filePath);
|
|
4059
|
+
if (isPathInside(cwd, abs))
|
|
4060
|
+
return abs;
|
|
4061
|
+
const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
|
|
4062
|
+
if (rebased !== undefined)
|
|
4063
|
+
return rebased;
|
|
4064
|
+
const canonical = canonicalizeExistingOrNearestAncestor(abs);
|
|
4065
|
+
if (isPathInside(cwd, canonical))
|
|
4066
|
+
return canonical;
|
|
4067
|
+
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
4068
|
+
}
|
|
4069
|
+
function resolvePathInsideContext(filePath) {
|
|
4070
|
+
const cwd = contextCwd();
|
|
4071
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4054
4072
|
const canonical = canonicalizeExistingOrNearestAncestor(abs);
|
|
4055
4073
|
if (!isPathInside(cwd, canonical)) {
|
|
4056
4074
|
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
4057
4075
|
}
|
|
4058
4076
|
return canonical;
|
|
4059
4077
|
}
|
|
4078
|
+
function rebaseThroughCanonicalAncestor(path, cwd) {
|
|
4079
|
+
let current = path;
|
|
4080
|
+
const suffix = [];
|
|
4081
|
+
while (true) {
|
|
4082
|
+
if (existsSync9(current)) {
|
|
4083
|
+
const canonical = realpathSync4(current);
|
|
4084
|
+
if (isPathInside(cwd, canonical))
|
|
4085
|
+
return suffix.length === 0 ? canonical : join4(canonical, ...suffix);
|
|
4086
|
+
}
|
|
4087
|
+
const parent = dirname6(current);
|
|
4088
|
+
if (parent === current)
|
|
4089
|
+
return;
|
|
4090
|
+
suffix.unshift(basename3(current));
|
|
4091
|
+
current = parent;
|
|
4092
|
+
}
|
|
4093
|
+
}
|
|
4094
|
+
function existingDirectoryInsideContext(directory, cwd) {
|
|
4095
|
+
if (!existsSync9(directory))
|
|
4096
|
+
return;
|
|
4097
|
+
const canonical = realpathSync4(directory);
|
|
4098
|
+
if (!statSync3(canonical).isDirectory())
|
|
4099
|
+
return;
|
|
4100
|
+
return isPathInside(cwd, canonical) ? canonical : undefined;
|
|
4101
|
+
}
|
|
4102
|
+
function nearestExistingDirectoryInsideContext(directory, cwd) {
|
|
4103
|
+
let current = directory;
|
|
4104
|
+
while (isPathInside(cwd, current)) {
|
|
4105
|
+
const canonical = existingDirectoryInsideContext(current, cwd);
|
|
4106
|
+
if (canonical !== undefined)
|
|
4107
|
+
return canonical;
|
|
4108
|
+
if (current === cwd)
|
|
4109
|
+
return;
|
|
4110
|
+
current = dirname6(current);
|
|
4111
|
+
}
|
|
4112
|
+
return;
|
|
4113
|
+
}
|
|
4060
4114
|
function formatServerLookupError(result) {
|
|
4061
4115
|
if (result.status === "not_installed") {
|
|
4062
4116
|
return formatNotInstalled(result);
|
|
@@ -4127,7 +4181,7 @@ function formatNotInstalled(result) {
|
|
|
4127
4181
|
].join(`
|
|
4128
4182
|
`);
|
|
4129
4183
|
}
|
|
4130
|
-
var
|
|
4184
|
+
var READ_ONLY_TOOLS = new Set([
|
|
4131
4185
|
"diagnostics",
|
|
4132
4186
|
"definition",
|
|
4133
4187
|
"references",
|
|
@@ -4136,7 +4190,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
|
|
|
4136
4190
|
"prepareRename"
|
|
4137
4191
|
]);
|
|
4138
4192
|
async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
4139
|
-
const absPath = resolvePathInsideContext(filePath);
|
|
4193
|
+
const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
|
|
4140
4194
|
if (isDirectoryPath(absPath)) {
|
|
4141
4195
|
throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
|
|
4142
4196
|
}
|
|
@@ -4151,9 +4205,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4151
4205
|
const acquireAndCall = async (allowRetry) => {
|
|
4152
4206
|
const client = await manager2.getClient(root, server2, options.signal);
|
|
4153
4207
|
try {
|
|
4154
|
-
return await fn(client, root);
|
|
4208
|
+
return await fn(client, root, absPath);
|
|
4155
4209
|
} catch (err) {
|
|
4156
|
-
if (allowRetry &&
|
|
4210
|
+
if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
|
|
4157
4211
|
manager2.invalidateClient(root, server2.id, client);
|
|
4158
4212
|
return acquireAndCall(false);
|
|
4159
4213
|
}
|
|
@@ -4608,7 +4662,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4608
4662
|
const filePath = requireString(params, "filePath");
|
|
4609
4663
|
const severity = severityFilter(params);
|
|
4610
4664
|
try {
|
|
4611
|
-
const absPath =
|
|
4665
|
+
const absPath = resolveReadablePathInsideContext(filePath);
|
|
4612
4666
|
if (isDirectoryPath(absPath)) {
|
|
4613
4667
|
const extension = inferExtensionFromDirectory(absPath);
|
|
4614
4668
|
if (!extension) {
|
|
@@ -4637,7 +4691,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4637
4691
|
};
|
|
4638
4692
|
return text(output2.output, details2);
|
|
4639
4693
|
}
|
|
4640
|
-
const result = await withLspClient(filePath, async (client) => client.diagnostics(
|
|
4694
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
|
|
4641
4695
|
if (result.transientError) {
|
|
4642
4696
|
const message = result.transientError.message;
|
|
4643
4697
|
const details2 = {
|
|
@@ -4712,7 +4766,7 @@ async function executeLspGotoDefinition(params, signal) {
|
|
|
4712
4766
|
const line = requireNumber(params, "line");
|
|
4713
4767
|
const character = requireNumber(params, "character");
|
|
4714
4768
|
try {
|
|
4715
|
-
const result = await withLspClient(filePath, async (client) => client.definition(
|
|
4769
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
|
|
4716
4770
|
const locations = !result ? [] : Array.isArray(result) ? result : [result];
|
|
4717
4771
|
const details = { filePath, line, character, locations };
|
|
4718
4772
|
if (locations.length === 0)
|
|
@@ -4737,7 +4791,7 @@ async function executeLspFindReferences(params, signal) {
|
|
|
4737
4791
|
const character = requireNumber(params, "character");
|
|
4738
4792
|
const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
|
|
4739
4793
|
try {
|
|
4740
|
-
const result = await withLspClient(filePath, async (client) => client.references(
|
|
4794
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
|
|
4741
4795
|
const references = Array.isArray(result) ? result : [];
|
|
4742
4796
|
const total = references.length;
|
|
4743
4797
|
const truncated = total > DEFAULT_MAX_REFERENCES;
|
|
@@ -4779,7 +4833,7 @@ async function executeLspPrepareRename(params, signal) {
|
|
|
4779
4833
|
const line = requireNumber(params, "line");
|
|
4780
4834
|
const character = requireNumber(params, "character");
|
|
4781
4835
|
try {
|
|
4782
|
-
const result = await withLspClient(filePath, async (client) => client.prepareRename(
|
|
4836
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
|
|
4783
4837
|
const details = { filePath, line, character, result };
|
|
4784
4838
|
return text(formatPrepareRenameResult(result), details);
|
|
4785
4839
|
} catch (error) {
|
|
@@ -4800,7 +4854,7 @@ async function executeLspRename(params, signal) {
|
|
|
4800
4854
|
const character = requireNumber(params, "character");
|
|
4801
4855
|
const newName = requireString(params, "newName");
|
|
4802
4856
|
try {
|
|
4803
|
-
const result = await withLspClient(filePath, async (client) => client.rename(
|
|
4857
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
|
|
4804
4858
|
const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
|
|
4805
4859
|
return text(formatApplyResult(result.apply), details, !result.apply.success);
|
|
4806
4860
|
} catch (error) {
|
|
@@ -4880,7 +4934,7 @@ async function executeLspSymbols(params, signal) {
|
|
|
4880
4934
|
const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
|
|
4881
4935
|
return formatSymbolsResult(filePath, scope, symbols2, limit, query);
|
|
4882
4936
|
}
|
|
4883
|
-
const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(
|
|
4937
|
+
const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
|
|
4884
4938
|
return formatSymbolsResult(filePath, scope, symbols, limit);
|
|
4885
4939
|
} catch (error) {
|
|
4886
4940
|
const query = optionalString(params, "query");
|
|
@@ -918,7 +918,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
918
918
|
initializationOptions: this.server.initialization
|
|
919
919
|
}, { timeoutMs: this.initializeTimeoutMs });
|
|
920
920
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
921
|
-
await this.sendNotification("initialized");
|
|
921
|
+
await this.sendNotification("initialized", {});
|
|
922
922
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
923
923
|
settings: { json: { validate: { enable: true } } }
|
|
924
924
|
});
|