oh-my-opencode 5.0.0-beta.1 → 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.
Files changed (196) hide show
  1. package/.agents/command/publish.md +44 -16
  2. package/.agents/skills/publish/SKILL.md +44 -16
  3. package/.agents/skills/work-with-pr/SKILL.md +37 -23
  4. package/.opencode/command/publish.md +44 -16
  5. package/.opencode/skills/work-with-pr/SKILL.md +37 -23
  6. package/README.md +12 -1
  7. package/dist/agents/atlas/agent.d.ts +0 -1
  8. package/dist/agents/sisyphus/grok-4.d.ts +20 -0
  9. package/dist/agents/sisyphus/index.d.ts +2 -0
  10. package/dist/agents/sisyphus-agent-config.d.ts +6 -0
  11. package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
  12. package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +15 -4
  13. package/dist/agents/types.d.ts +2 -2
  14. package/dist/cli/index.js +797 -465
  15. package/dist/cli/run/on-complete-hook.d.ts +2 -0
  16. package/dist/cli-node/index.js +797 -465
  17. package/dist/hooks/atlas/final-wave-approval-gate.test-support.d.ts +50 -0
  18. package/dist/hooks/atlas/system-reminder-templates.d.ts +0 -1
  19. package/dist/index.js +1511 -1140
  20. package/dist/shared/normalize-sdk-response.d.ts +1 -0
  21. package/dist/shared/shell-env.d.ts +1 -1
  22. package/dist/skills/coding-agent-sessions/SKILL.md +3 -2
  23. package/dist/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  24. package/dist/skills/coding-agent-sessions/references/senpi.md +4 -4
  25. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  26. package/dist/skills/frontend/SKILL.md +10 -7
  27. package/dist/skills/frontend/references/design/_INDEX.md +1 -0
  28. package/dist/skills/frontend/references/design/stylegallery.md +80 -0
  29. package/dist/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  30. package/dist/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  31. package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
  32. package/dist/skills/ultimate-browsing/references/chrome-stealth.md +11 -11
  33. package/dist/skills/ulw-plan/SKILL.md +2 -2
  34. package/dist/skills/ulw-plan/references/full-workflow.md +27 -3
  35. package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
  36. package/dist/skills/ulw-plan/references/intent-unclear.md +3 -3
  37. package/dist/tui.js +176 -14
  38. package/package.json +21 -19
  39. package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +44 -0
  40. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +0 -28
  41. package/packages/lsp-core/src/lsp/client-wrapper.test.ts +60 -7
  42. package/packages/lsp-core/src/lsp/client-wrapper.ts +69 -16
  43. package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +20 -1
  44. package/packages/lsp-core/src/tools/diagnostics.ts +3 -3
  45. package/packages/lsp-core/src/tools/navigation.ts +4 -2
  46. package/packages/lsp-core/src/tools/rename.ts +4 -2
  47. package/packages/lsp-core/src/tools/symbols.ts +1 -1
  48. package/packages/lsp-daemon/dist/cli.js +83 -29
  49. package/packages/lsp-daemon/dist/client.js +76 -22
  50. package/packages/lsp-daemon/dist/index.js +81 -27
  51. package/packages/lsp-tools-mcp/dist/cli.js +76 -22
  52. package/packages/lsp-tools-mcp/dist/mcp.js +76 -22
  53. package/packages/lsp-tools-mcp/dist/tools.js +76 -22
  54. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  55. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  56. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  57. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +118 -8
  58. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +118 -8
  59. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  60. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  61. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  62. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  63. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  64. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  65. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  66. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +3 -17
  67. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  68. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +83 -29
  69. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  70. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  71. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  72. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  73. package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +11 -16
  74. package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +16 -23
  75. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
  76. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
  77. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
  78. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
  79. package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
  80. package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +37 -69
  81. package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
  82. package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +1 -15
  83. package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +3 -2
  84. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  85. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  86. package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +0 -3
  87. package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +2 -16
  88. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  89. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  90. package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +3 -9
  91. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +24 -12
  92. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +24 -12
  93. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  94. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  95. package/packages/omo-codex/plugin/components/ultrawork/directive.md +6 -0
  96. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  97. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  98. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +6 -0
  99. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +2 -2
  100. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +27 -3
  101. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
  102. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +3 -3
  103. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
  104. package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
  105. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +6 -0
  106. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  107. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  108. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -2
  109. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
  110. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -0
  111. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
  112. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +2 -2
  113. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
  114. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +2 -35
  115. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +4 -5
  116. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  117. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  118. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  119. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  120. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  121. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  122. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  123. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  124. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  125. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  126. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  127. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  128. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  129. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  130. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  131. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  132. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  133. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  134. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  135. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  136. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  137. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  138. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  139. package/packages/omo-codex/plugin/package-lock.json +20 -20
  140. package/packages/omo-codex/plugin/package.json +1 -1
  141. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
  142. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  143. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
  144. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  145. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +10 -7
  146. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
  147. package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
  148. package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  149. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  150. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
  151. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +11 -11
  152. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +6 -0
  153. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -2
  154. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
  155. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -0
  156. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +2 -2
  157. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +27 -3
  158. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
  159. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +3 -3
  160. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
  161. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +4 -24
  162. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
  163. package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
  164. package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
  165. package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
  166. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
  167. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
  168. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +1 -119
  169. package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
  170. package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
  171. package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
  172. package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
  173. package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
  174. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +0 -3
  175. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
  176. package/packages/omo-codex/scripts/install-dist/install-local.mjs +57 -19
  177. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
  178. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
  179. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  180. package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
  181. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  182. package/packages/shared-skills/skills/frontend/SKILL.md +10 -7
  183. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
  184. package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
  185. package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  186. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  187. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
  188. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +11 -11
  189. package/packages/shared-skills/skills/ulw-plan/SKILL.md +2 -2
  190. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +27 -3
  191. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
  192. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +3 -3
  193. package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
  194. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
  195. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
  196. package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
@@ -1141,8 +1141,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
1141
1141
  };
1142
1142
  }
1143
1143
  // ../lsp-core/src/lsp/client-wrapper.ts
1144
- import { existsSync as existsSync10, statSync as statSync4 } from "node:fs";
1145
- import { dirname as dirname8, join as join4, resolve as resolve7 } from "node:path";
1144
+ import { existsSync as existsSync10, realpathSync as realpathSync4, statSync as statSync4 } from "node:fs";
1145
+ import { basename as basename3, dirname as dirname8, join as join4, resolve as resolve7 } from "node:path";
1146
1146
 
1147
1147
  // ../lsp-core/src/lsp/effective-extension.ts
1148
1148
  import { basename as basename2, extname } from "node:path";
@@ -4686,32 +4686,86 @@ function isDirectoryPath(filePath) {
4686
4686
  }
4687
4687
  }
4688
4688
  function findWorkspaceRoot(filePath) {
4689
- const abs = resolvePathInsideContext(filePath);
4689
+ const cwd = contextCwd();
4690
+ const abs = resolveReadablePathInsideContext(filePath);
4690
4691
  let dir = abs;
4691
4692
  if (!isDirectoryPath(dir)) {
4692
4693
  dir = dirname8(dir);
4693
4694
  }
4694
- let prevDir = "";
4695
- while (dir !== prevDir) {
4696
- for (const marker of WORKSPACE_MARKERS) {
4697
- if (existsSync10(join4(dir, marker))) {
4698
- return dir;
4695
+ const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4696
+ while (isPathInside(cwd, dir)) {
4697
+ const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4698
+ if (canonicalDir !== undefined) {
4699
+ for (const marker of WORKSPACE_MARKERS) {
4700
+ if (existsSync10(join4(dir, marker))) {
4701
+ return canonicalDir;
4702
+ }
4699
4703
  }
4700
4704
  }
4701
- prevDir = dir;
4705
+ if (dir === cwd)
4706
+ break;
4702
4707
  dir = dirname8(dir);
4703
4708
  }
4704
- return dirname8(abs);
4709
+ return fallbackRoot;
4705
4710
  }
4706
- function resolvePathInsideContext(filePath) {
4711
+ function resolveReadablePathInsideContext(filePath) {
4707
4712
  const cwd = contextCwd();
4708
4713
  const abs = resolve7(cwd, filePath);
4714
+ if (isPathInside(cwd, abs))
4715
+ return abs;
4716
+ const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
4717
+ if (rebased !== undefined)
4718
+ return rebased;
4719
+ const canonical = canonicalizeExistingOrNearestAncestor(abs);
4720
+ if (isPathInside(cwd, canonical))
4721
+ return canonical;
4722
+ throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
4723
+ }
4724
+ function resolvePathInsideContext(filePath) {
4725
+ const cwd = contextCwd();
4726
+ const abs = resolveReadablePathInsideContext(filePath);
4709
4727
  const canonical = canonicalizeExistingOrNearestAncestor(abs);
4710
4728
  if (!isPathInside(cwd, canonical)) {
4711
4729
  throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
4712
4730
  }
4713
4731
  return canonical;
4714
4732
  }
4733
+ function rebaseThroughCanonicalAncestor(path2, cwd) {
4734
+ let current = path2;
4735
+ const suffix = [];
4736
+ while (true) {
4737
+ if (existsSync10(current)) {
4738
+ const canonical = realpathSync4(current);
4739
+ if (isPathInside(cwd, canonical))
4740
+ return suffix.length === 0 ? canonical : join4(canonical, ...suffix);
4741
+ }
4742
+ const parent = dirname8(current);
4743
+ if (parent === current)
4744
+ return;
4745
+ suffix.unshift(basename3(current));
4746
+ current = parent;
4747
+ }
4748
+ }
4749
+ function existingDirectoryInsideContext(directory, cwd) {
4750
+ if (!existsSync10(directory))
4751
+ return;
4752
+ const canonical = realpathSync4(directory);
4753
+ if (!statSync4(canonical).isDirectory())
4754
+ return;
4755
+ return isPathInside(cwd, canonical) ? canonical : undefined;
4756
+ }
4757
+ function nearestExistingDirectoryInsideContext(directory, cwd) {
4758
+ let current = directory;
4759
+ while (isPathInside(cwd, current)) {
4760
+ const canonical = existingDirectoryInsideContext(current, cwd);
4761
+ if (canonical !== undefined)
4762
+ return canonical;
4763
+ if (current === cwd)
4764
+ return;
4765
+ current = dirname8(current);
4766
+ }
4767
+ return;
4768
+ }
4715
4769
  function formatServerLookupError(result) {
4716
4770
  if (result.status === "not_installed") {
4717
4771
  return formatNotInstalled(result);
@@ -4782,7 +4836,7 @@ function formatNotInstalled(result) {
4782
4836
  ].join(`
4783
4837
  `);
4784
4838
  }
4785
- var READ_ONLY_RETRY_TOOLS = new Set([
4839
+ var READ_ONLY_TOOLS = new Set([
4786
4840
  "diagnostics",
4787
4841
  "definition",
4788
4842
  "references",
@@ -4791,7 +4845,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
4791
4845
  "prepareRename"
4792
4846
  ]);
4793
4847
  async function withLspClient(filePath, fn, toolName, options = {}) {
4794
- const absPath = resolvePathInsideContext(filePath);
4848
+ const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
4795
4849
  if (isDirectoryPath(absPath)) {
4796
4850
  throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
4797
4851
  }
@@ -4806,9 +4860,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4806
4860
  const acquireAndCall = async (allowRetry) => {
4807
4861
  const client = await manager.getClient(root, server2, options.signal);
4808
4862
  try {
4809
- return await fn(client, root);
4863
+ return await fn(client, root, absPath);
4810
4864
  } catch (err) {
4811
- if (allowRetry && READ_ONLY_RETRY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4865
+ if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4812
4866
  manager.invalidateClient(root, server2.id, client);
4813
4867
  return acquireAndCall(false);
4814
4868
  }
@@ -5263,7 +5317,7 @@ async function executeLspDiagnostics(params, signal) {
5263
5317
  const filePath = requireString(params, "filePath");
5264
5318
  const severity = severityFilter(params);
5265
5319
  try {
5266
- const absPath = resolvePathInsideContext(filePath);
5320
+ const absPath = resolveReadablePathInsideContext(filePath);
5267
5321
  if (isDirectoryPath(absPath)) {
5268
5322
  const extension = inferExtensionFromDirectory(absPath);
5269
5323
  if (!extension) {
@@ -5292,7 +5346,7 @@ async function executeLspDiagnostics(params, signal) {
5292
5346
  };
5293
5347
  return text(output2.output, details2);
5294
5348
  }
5295
- const result = await withLspClient(filePath, async (client) => client.diagnostics(filePath, signal), "diagnostics", clientOptions(signal));
5349
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
5296
5350
  if (result.transientError) {
5297
5351
  const message = result.transientError.message;
5298
5352
  const details2 = {
@@ -5367,7 +5421,7 @@ async function executeLspGotoDefinition(params, signal) {
5367
5421
  const line = requireNumber(params, "line");
5368
5422
  const character = requireNumber(params, "character");
5369
5423
  try {
5370
- const result = await withLspClient(filePath, async (client) => client.definition(filePath, line, character, signal), "definition", clientOptions(signal));
5424
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
5371
5425
  const locations = !result ? [] : Array.isArray(result) ? result : [result];
5372
5426
  const details = { filePath, line, character, locations };
5373
5427
  if (locations.length === 0)
@@ -5392,7 +5446,7 @@ async function executeLspFindReferences(params, signal) {
5392
5446
  const character = requireNumber(params, "character");
5393
5447
  const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
5394
5448
  try {
5395
- const result = await withLspClient(filePath, async (client) => client.references(filePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5449
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5396
5450
  const references = Array.isArray(result) ? result : [];
5397
5451
  const total = references.length;
5398
5452
  const truncated = total > DEFAULT_MAX_REFERENCES;
@@ -5434,7 +5488,7 @@ async function executeLspPrepareRename(params, signal) {
5434
5488
  const line = requireNumber(params, "line");
5435
5489
  const character = requireNumber(params, "character");
5436
5490
  try {
5437
- const result = await withLspClient(filePath, async (client) => client.prepareRename(filePath, line, character, signal), "prepareRename", clientOptions(signal));
5491
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
5438
5492
  const details = { filePath, line, character, result };
5439
5493
  return text(formatPrepareRenameResult(result), details);
5440
5494
  } catch (error) {
@@ -5455,7 +5509,7 @@ async function executeLspRename(params, signal) {
5455
5509
  const character = requireNumber(params, "character");
5456
5510
  const newName = requireString(params, "newName");
5457
5511
  try {
5458
- const result = await withLspClient(filePath, async (client) => client.rename(filePath, line, character, newName, signal), "rename", clientOptions(signal));
5512
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
5459
5513
  const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
5460
5514
  return text(formatApplyResult(result.apply), details, !result.apply.success);
5461
5515
  } catch (error) {
@@ -5535,7 +5589,7 @@ async function executeLspSymbols(params, signal) {
5535
5589
  const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
5536
5590
  return formatSymbolsResult(filePath, scope, symbols2, limit, query);
5537
5591
  }
5538
- const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(filePath, signal), "documentSymbols", clientOptions(signal));
5592
+ const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
5539
5593
  return formatSymbolsResult(filePath, scope, symbols, limit);
5540
5594
  } catch (error) {
5541
5595
  const query = optionalString(params, "query");
@@ -4153,8 +4153,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
4153
4153
  };
4154
4154
  }
4155
4155
  // ../lsp-core/src/lsp/client-wrapper.ts
4156
- import { existsSync as existsSync10, statSync as statSync4 } from "node:fs";
4157
- 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";
4158
4158
 
4159
4159
  // ../lsp-core/src/lsp/server-install-state.ts
4160
4160
  import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
@@ -4685,32 +4685,86 @@ function isDirectoryPath(filePath) {
4685
4685
  }
4686
4686
  }
4687
4687
  function findWorkspaceRoot(filePath) {
4688
- const abs = resolvePathInsideContext(filePath);
4688
+ const cwd = contextCwd();
4689
+ const abs = resolveReadablePathInsideContext(filePath);
4689
4690
  let dir = abs;
4690
4691
  if (!isDirectoryPath(dir)) {
4691
4692
  dir = dirname8(dir);
4692
4693
  }
4693
- let prevDir = "";
4694
- while (dir !== prevDir) {
4695
- for (const marker of WORKSPACE_MARKERS) {
4696
- if (existsSync10(join4(dir, marker))) {
4697
- return dir;
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
+ }
4698
4702
  }
4699
4703
  }
4700
- prevDir = dir;
4704
+ if (dir === cwd)
4705
+ break;
4701
4706
  dir = dirname8(dir);
4702
4707
  }
4703
- return dirname8(abs);
4708
+ return fallbackRoot;
4704
4709
  }
4705
- function resolvePathInsideContext(filePath) {
4710
+ function resolveReadablePathInsideContext(filePath) {
4706
4711
  const cwd = contextCwd();
4707
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);
4708
4726
  const canonical = canonicalizeExistingOrNearestAncestor(abs);
4709
4727
  if (!isPathInside(cwd, canonical)) {
4710
4728
  throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
4711
4729
  }
4712
4730
  return canonical;
4713
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
+ }
4714
4768
  function formatServerLookupError(result) {
4715
4769
  if (result.status === "not_installed") {
4716
4770
  return formatNotInstalled(result);
@@ -4781,7 +4835,7 @@ function formatNotInstalled(result) {
4781
4835
  ].join(`
4782
4836
  `);
4783
4837
  }
4784
- var READ_ONLY_RETRY_TOOLS = new Set([
4838
+ var READ_ONLY_TOOLS = new Set([
4785
4839
  "diagnostics",
4786
4840
  "definition",
4787
4841
  "references",
@@ -4790,7 +4844,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
4790
4844
  "prepareRename"
4791
4845
  ]);
4792
4846
  async function withLspClient(filePath, fn, toolName, options = {}) {
4793
- const absPath = resolvePathInsideContext(filePath);
4847
+ const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
4794
4848
  if (isDirectoryPath(absPath)) {
4795
4849
  throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
4796
4850
  }
@@ -4805,9 +4859,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4805
4859
  const acquireAndCall = async (allowRetry) => {
4806
4860
  const client = await manager.getClient(root, server2, options.signal);
4807
4861
  try {
4808
- return await fn(client, root);
4862
+ return await fn(client, root, absPath);
4809
4863
  } catch (err) {
4810
- if (allowRetry && READ_ONLY_RETRY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4864
+ if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4811
4865
  manager.invalidateClient(root, server2.id, client);
4812
4866
  return acquireAndCall(false);
4813
4867
  }
@@ -5262,7 +5316,7 @@ async function executeLspDiagnostics(params, signal) {
5262
5316
  const filePath = requireString(params, "filePath");
5263
5317
  const severity = severityFilter(params);
5264
5318
  try {
5265
- const absPath = resolvePathInsideContext(filePath);
5319
+ const absPath = resolveReadablePathInsideContext(filePath);
5266
5320
  if (isDirectoryPath(absPath)) {
5267
5321
  const extension = inferExtensionFromDirectory(absPath);
5268
5322
  if (!extension) {
@@ -5291,7 +5345,7 @@ async function executeLspDiagnostics(params, signal) {
5291
5345
  };
5292
5346
  return text(output2.output, details2);
5293
5347
  }
5294
- const result = await withLspClient(filePath, async (client) => client.diagnostics(filePath, signal), "diagnostics", clientOptions(signal));
5348
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
5295
5349
  if (result.transientError) {
5296
5350
  const message = result.transientError.message;
5297
5351
  const details2 = {
@@ -5366,7 +5420,7 @@ async function executeLspGotoDefinition(params, signal) {
5366
5420
  const line = requireNumber(params, "line");
5367
5421
  const character = requireNumber(params, "character");
5368
5422
  try {
5369
- const result = await withLspClient(filePath, async (client) => client.definition(filePath, line, character, signal), "definition", clientOptions(signal));
5423
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
5370
5424
  const locations = !result ? [] : Array.isArray(result) ? result : [result];
5371
5425
  const details = { filePath, line, character, locations };
5372
5426
  if (locations.length === 0)
@@ -5391,7 +5445,7 @@ async function executeLspFindReferences(params, signal) {
5391
5445
  const character = requireNumber(params, "character");
5392
5446
  const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
5393
5447
  try {
5394
- const result = await withLspClient(filePath, async (client) => client.references(filePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5448
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5395
5449
  const references = Array.isArray(result) ? result : [];
5396
5450
  const total = references.length;
5397
5451
  const truncated = total > DEFAULT_MAX_REFERENCES;
@@ -5433,7 +5487,7 @@ async function executeLspPrepareRename(params, signal) {
5433
5487
  const line = requireNumber(params, "line");
5434
5488
  const character = requireNumber(params, "character");
5435
5489
  try {
5436
- const result = await withLspClient(filePath, async (client) => client.prepareRename(filePath, line, character, signal), "prepareRename", clientOptions(signal));
5490
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
5437
5491
  const details = { filePath, line, character, result };
5438
5492
  return text(formatPrepareRenameResult(result), details);
5439
5493
  } catch (error) {
@@ -5454,7 +5508,7 @@ async function executeLspRename(params, signal) {
5454
5508
  const character = requireNumber(params, "character");
5455
5509
  const newName = requireString(params, "newName");
5456
5510
  try {
5457
- const result = await withLspClient(filePath, async (client) => client.rename(filePath, line, character, newName, signal), "rename", clientOptions(signal));
5511
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
5458
5512
  const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
5459
5513
  return text(formatApplyResult(result.apply), details, !result.apply.success);
5460
5514
  } catch (error) {
@@ -5534,7 +5588,7 @@ async function executeLspSymbols(params, signal) {
5534
5588
  const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
5535
5589
  return formatSymbolsResult(filePath, scope, symbols2, limit, query);
5536
5590
  }
5537
- const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(filePath, signal), "documentSymbols", clientOptions(signal));
5591
+ const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
5538
5592
  return formatSymbolsResult(filePath, scope, symbols, limit);
5539
5593
  } catch (error) {
5540
5594
  const query = optionalString(params, "query");
@@ -6025,8 +6079,8 @@ function isRetryableTool(name) {
6025
6079
  return name !== "rename" && name !== "lsp_rename";
6026
6080
  }
6027
6081
  // src/proxy.ts
6028
- import { existsSync as existsSync12, realpathSync as realpathSync4 } from "node:fs";
6029
- import { basename as basename3, delimiter as delimiter4, dirname as dirname9, isAbsolute as isAbsolute5 } from "node:path";
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";
6030
6084
  var DEFAULT_STARTUP_TIMEOUT_MS = 1e4;
6031
6085
  async function runMcpStdioProxy(options = {}) {
6032
6086
  const input = options.input ?? process.stdin;
@@ -6151,13 +6205,13 @@ function canonicalizePathList(value) {
6151
6205
  function canonicalizePath(value) {
6152
6206
  if (value === undefined || !isAbsolute5(value) || !existsSync12(value))
6153
6207
  return value;
6154
- return realpathSync4(value);
6208
+ return realpathSync5(value);
6155
6209
  }
6156
6210
  function projectRootFromOpenCodeConfigPath(path2) {
6157
- if (basename3(path2) !== "lsp.json" && basename3(path2) !== "lsp-client.json")
6211
+ if (basename4(path2) !== "lsp.json" && basename4(path2) !== "lsp-client.json")
6158
6212
  return;
6159
6213
  const configDir = dirname9(path2);
6160
- const configDirName = basename3(configDir);
6214
+ const configDirName = basename4(configDir);
6161
6215
  if (configDirName !== ".opencode" && configDirName !== ".omo")
6162
6216
  return;
6163
6217
  return dirname9(configDir);
@@ -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 abs = resolvePathInsideContext(filePath);
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
- let prevDir = "";
4040
- while (dir !== prevDir) {
4041
- for (const marker of WORKSPACE_MARKERS) {
4042
- if (existsSync9(join4(dir, marker))) {
4043
- return dir;
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
- prevDir = dir;
4050
+ if (dir === cwd)
4051
+ break;
4047
4052
  dir = dirname6(dir);
4048
4053
  }
4049
- return dirname6(abs);
4054
+ return fallbackRoot;
4050
4055
  }
4051
- function resolvePathInsideContext(filePath) {
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 READ_ONLY_RETRY_TOOLS = new Set([
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 && READ_ONLY_RETRY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
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 = resolvePathInsideContext(filePath);
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(filePath, signal), "diagnostics", clientOptions(signal));
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(filePath, line, character, signal), "definition", clientOptions(signal));
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(filePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
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(filePath, line, character, signal), "prepareRename", clientOptions(signal));
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(filePath, line, character, newName, signal), "rename", clientOptions(signal));
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(filePath, signal), "documentSymbols", clientOptions(signal));
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");