oh-my-opencode 5.0.0-beta.10 → 5.0.0-beta.12

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 (73) hide show
  1. package/dist/cli/index.js +34 -86
  2. package/dist/cli-node/index.js +34 -86
  3. package/dist/index.js +80 -93
  4. package/dist/tools/delegate-task/builtin-categories.d.ts +1 -0
  5. package/dist/tools/delegate-task/builtin-category-definition.d.ts +1 -0
  6. package/dist/tools/delegate-task/tool-description.d.ts +3 -1
  7. package/dist/tui.js +19 -71
  8. package/package.json +14 -14
  9. package/packages/lsp-core/src/lsp/client-wrapper-outside-cwd.test.ts +78 -0
  10. package/packages/lsp-core/src/lsp/client-wrapper.test.ts +6 -6
  11. package/packages/lsp-core/src/lsp/client-wrapper.ts +5 -6
  12. package/packages/lsp-core/src/lsp/outside-context-workspace.ts +33 -0
  13. package/packages/lsp-core/src/lsp/workspace-markers.ts +1 -0
  14. package/packages/lsp-daemon/dist/cli.js +94 -59
  15. package/packages/lsp-daemon/dist/client.js +72 -37
  16. package/packages/lsp-daemon/dist/index.js +78 -43
  17. package/packages/lsp-tools-mcp/dist/cli.js +68 -33
  18. package/packages/lsp-tools-mcp/dist/mcp.js +68 -33
  19. package/packages/lsp-tools-mcp/dist/tools.js +68 -33
  20. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  21. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  22. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  23. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +9 -0
  24. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +9 -0
  25. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  26. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  27. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  28. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  29. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  30. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  31. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  32. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  33. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +83 -54
  34. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  35. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  36. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  37. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  38. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  39. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  40. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  41. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  42. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  43. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  44. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  45. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  46. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  47. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  48. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  49. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  50. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  51. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  52. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  53. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  54. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  55. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  56. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  57. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  58. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  59. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  60. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  61. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  62. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  63. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  64. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  65. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  66. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  67. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  68. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  69. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  70. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  71. package/packages/omo-codex/plugin/package-lock.json +13 -13
  72. package/packages/omo-codex/plugin/package.json +1 -1
  73. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
@@ -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, 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";
3323
+ import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync3 } from "node:fs";
3324
+ import { basename as basename3, dirname as dirname7, join as join5, resolve as resolve7 } from "node:path";
3325
3325
 
3326
3326
  // ../lsp-core/src/request-context.ts
3327
3327
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -3502,15 +3502,52 @@ function errorCode(error) {
3502
3502
  return typeof code === "string" ? code : undefined;
3503
3503
  }
3504
3504
 
3505
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3506
+ import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
3507
+ import { dirname as dirname5, join as join3 } from "node:path";
3508
+
3509
+ // ../lsp-core/src/lsp/workspace-markers.ts
3510
+ var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
3511
+
3512
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3513
+ function findWorkspaceRootOutsideContext(directory) {
3514
+ const marked = nearestMarkedAncestor(directory);
3515
+ if (marked !== undefined)
3516
+ return marked;
3517
+ return realpathSync4(nearestExistingAncestor(directory));
3518
+ }
3519
+ function nearestMarkedAncestor(directory) {
3520
+ let current = directory;
3521
+ for (;; ) {
3522
+ if (existsSync6(current) && WORKSPACE_MARKERS.some((marker) => existsSync6(join3(current, marker)))) {
3523
+ return realpathSync4(current);
3524
+ }
3525
+ const parent = dirname5(current);
3526
+ if (parent === current)
3527
+ return;
3528
+ current = parent;
3529
+ }
3530
+ }
3531
+ function nearestExistingAncestor(directory) {
3532
+ let current = directory;
3533
+ while (!existsSync6(current)) {
3534
+ const parent = dirname5(current);
3535
+ if (parent === current)
3536
+ return current;
3537
+ current = parent;
3538
+ }
3539
+ return current;
3540
+ }
3541
+
3505
3542
  // ../lsp-core/src/lsp/server-install-state.ts
3506
- import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3507
- import { dirname as dirname5 } from "node:path";
3543
+ import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3544
+ import { dirname as dirname6 } from "node:path";
3508
3545
  function getInstallDecisionsPath() {
3509
3546
  return lspRequestContext().installDecisionsPath;
3510
3547
  }
3511
3548
  function loadInstallDecisions() {
3512
3549
  const path = getInstallDecisionsPath();
3513
- if (!existsSync6(path))
3550
+ if (!existsSync7(path))
3514
3551
  return {};
3515
3552
  try {
3516
3553
  const parsed = JSON.parse(readFileSync3(path, "utf8"));
@@ -3532,7 +3569,7 @@ function isInstallDecision(value) {
3532
3569
  }
3533
3570
  function writeInstallDecisions(decisions) {
3534
3571
  const path = getInstallDecisionsPath();
3535
- mkdirSync(dirname5(path), { recursive: true });
3572
+ mkdirSync(dirname6(path), { recursive: true });
3536
3573
  const tmpPath = `${path}.tmp`;
3537
3574
  writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3538
3575
  `, "utf8");
@@ -3551,7 +3588,7 @@ function isRecord5(value) {
3551
3588
  }
3552
3589
 
3553
3590
  // ../lsp-core/src/lsp/config-loader.ts
3554
- import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
3591
+ import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
3555
3592
 
3556
3593
  // ../lsp-core/src/lsp/server-definitions.ts
3557
3594
  var LSP_INSTALL_HINTS = {
@@ -3708,7 +3745,7 @@ function getUserConfigPath() {
3708
3745
  return lspRequestContext().userConfigPath;
3709
3746
  }
3710
3747
  function loadJsonFile(path) {
3711
- if (!existsSync7(path))
3748
+ if (!existsSync8(path))
3712
3749
  return null;
3713
3750
  try {
3714
3751
  const parsed = JSON.parse(readFileSync4(path, "utf-8"));
@@ -3896,8 +3933,8 @@ function getDisabledServerIds() {
3896
3933
  }
3897
3934
 
3898
3935
  // ../lsp-core/src/lsp/server-installation.ts
3899
- import { existsSync as existsSync8 } from "node:fs";
3900
- import { delimiter as delimiter3, join as join3 } from "node:path";
3936
+ import { existsSync as existsSync9 } from "node:fs";
3937
+ import { delimiter as delimiter3, join as join4 } from "node:path";
3901
3938
  function isServerInstalled(command, _workingDirectory) {
3902
3939
  if (command.length === 0)
3903
3940
  return false;
@@ -3905,7 +3942,7 @@ function isServerInstalled(command, _workingDirectory) {
3905
3942
  if (!cmd)
3906
3943
  return false;
3907
3944
  if (cmd.includes("/") || cmd.includes("\\")) {
3908
- if (existsSync8(cmd))
3945
+ if (existsSync9(cmd))
3909
3946
  return true;
3910
3947
  }
3911
3948
  const isWindows = process.platform === "win32";
@@ -3926,7 +3963,7 @@ function isServerInstalled(command, _workingDirectory) {
3926
3963
  const paths = pathEnv.split(delimiter3);
3927
3964
  for (const p of paths) {
3928
3965
  for (const suffix of exts) {
3929
- if (existsSync8(join3(p, cmd + suffix))) {
3966
+ if (existsSync9(join4(p, cmd + suffix))) {
3930
3967
  return true;
3931
3968
  }
3932
3969
  }
@@ -4022,7 +4059,6 @@ function getAllServers() {
4022
4059
  }
4023
4060
 
4024
4061
  // ../lsp-core/src/lsp/client-wrapper.ts
4025
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
4026
4062
  function isDirectoryPath(filePath) {
4027
4063
  try {
4028
4064
  return statSync3(filePath).isDirectory();
@@ -4035,21 +4071,23 @@ function findWorkspaceRoot(filePath) {
4035
4071
  const abs = resolveReadablePathInsideContext(filePath);
4036
4072
  let dir = abs;
4037
4073
  if (!isDirectoryPath(dir)) {
4038
- dir = dirname6(dir);
4074
+ dir = dirname7(dir);
4039
4075
  }
4076
+ if (!isPathInside(cwd, abs))
4077
+ return findWorkspaceRootOutsideContext(dir);
4040
4078
  const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4041
4079
  while (isPathInside(cwd, dir)) {
4042
4080
  const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4043
4081
  if (canonicalDir !== undefined) {
4044
4082
  for (const marker of WORKSPACE_MARKERS) {
4045
- if (existsSync9(join4(dir, marker))) {
4083
+ if (existsSync10(join5(dir, marker))) {
4046
4084
  return canonicalDir;
4047
4085
  }
4048
4086
  }
4049
4087
  }
4050
4088
  if (dir === cwd)
4051
4089
  break;
4052
- dir = dirname6(dir);
4090
+ dir = dirname7(dir);
4053
4091
  }
4054
4092
  return fallbackRoot;
4055
4093
  }
@@ -4061,10 +4099,7 @@ function resolveReadablePathInsideContext(filePath) {
4061
4099
  const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
4062
4100
  if (rebased !== undefined)
4063
4101
  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}`);
4102
+ return canonicalizeExistingOrNearestAncestor(abs);
4068
4103
  }
4069
4104
  function resolvePathInsideContext(filePath) {
4070
4105
  const cwd = contextCwd();
@@ -4079,12 +4114,12 @@ function rebaseThroughCanonicalAncestor(path, cwd) {
4079
4114
  let current = path;
4080
4115
  const suffix = [];
4081
4116
  while (true) {
4082
- if (existsSync9(current)) {
4083
- const canonical = realpathSync4(current);
4117
+ if (existsSync10(current)) {
4118
+ const canonical = realpathSync5(current);
4084
4119
  if (isPathInside(cwd, canonical))
4085
- return suffix.length === 0 ? canonical : join4(canonical, ...suffix);
4120
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
4086
4121
  }
4087
- const parent = dirname6(current);
4122
+ const parent = dirname7(current);
4088
4123
  if (parent === current)
4089
4124
  return;
4090
4125
  suffix.unshift(basename3(current));
@@ -4092,9 +4127,9 @@ function rebaseThroughCanonicalAncestor(path, cwd) {
4092
4127
  }
4093
4128
  }
4094
4129
  function existingDirectoryInsideContext(directory, cwd) {
4095
- if (!existsSync9(directory))
4130
+ if (!existsSync10(directory))
4096
4131
  return;
4097
- const canonical = realpathSync4(directory);
4132
+ const canonical = realpathSync5(directory);
4098
4133
  if (!statSync3(canonical).isDirectory())
4099
4134
  return;
4100
4135
  return isPathInside(cwd, canonical) ? canonical : undefined;
@@ -4107,7 +4142,7 @@ function nearestExistingDirectoryInsideContext(directory, cwd) {
4107
4142
  return canonical;
4108
4143
  if (current === cwd)
4109
4144
  return;
4110
- current = dirname6(current);
4145
+ current = dirname7(current);
4111
4146
  }
4112
4147
  return;
4113
4148
  }
@@ -4225,8 +4260,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4225
4260
  }
4226
4261
 
4227
4262
  // ../lsp-core/src/lsp/directory-diagnostics.ts
4228
- import { existsSync as existsSync10, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4229
- import { join as join5, resolve as resolve8 } from "node:path";
4263
+ import { existsSync as existsSync11, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4264
+ import { join as join6, resolve as resolve8 } from "node:path";
4230
4265
 
4231
4266
  // ../lsp-core/src/lsp/formatters.ts
4232
4267
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -4356,7 +4391,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
4356
4391
  for (const entry of entries) {
4357
4392
  if (files.length >= maxFiles)
4358
4393
  return;
4359
- const fullPath = join5(currentDir, entry);
4394
+ const fullPath = join6(currentDir, entry);
4360
4395
  let stat;
4361
4396
  try {
4362
4397
  stat = lstatSync4(fullPath);
@@ -4382,7 +4417,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4382
4417
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4383
4418
  }
4384
4419
  const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4385
- if (!existsSync10(absDir)) {
4420
+ if (!existsSync11(absDir)) {
4386
4421
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4387
4422
  }
4388
4423
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
@@ -4469,7 +4504,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4469
4504
 
4470
4505
  // ../lsp-core/src/lsp/infer-extension.ts
4471
4506
  import { lstatSync as lstatSync5, readdirSync as readdirSync4 } from "node:fs";
4472
- import { join as join6 } from "node:path";
4507
+ import { join as join7 } from "node:path";
4473
4508
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
4474
4509
  var MAX_SCAN_ENTRIES = 500;
4475
4510
  function inferExtensionFromDirectory(directory) {
@@ -4487,7 +4522,7 @@ function inferExtensionFromDirectory(directory) {
4487
4522
  for (const entry of entries) {
4488
4523
  if (scanned >= MAX_SCAN_ENTRIES)
4489
4524
  return;
4490
- const fullPath = join6(dir, entry);
4525
+ const fullPath = join7(dir, entry);
4491
4526
  let stat;
4492
4527
  try {
4493
4528
  stat = lstatSync5(fullPath);
@@ -306,8 +306,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
306
306
  };
307
307
  }
308
308
  // ../lsp-core/src/lsp/client-wrapper.ts
309
- import { existsSync as existsSync9, realpathSync as realpathSync4, statSync as statSync3 } from "node:fs";
310
- import { basename as basename3, dirname as dirname6, join as join4, resolve as resolve7 } from "node:path";
309
+ import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync3 } from "node:fs";
310
+ import { basename as basename3, dirname as dirname7, join as join5, resolve as resolve7 } from "node:path";
311
311
 
312
312
  // ../lsp-core/src/request-context.ts
313
313
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -3501,15 +3501,52 @@ async function disposeDefaultLspManager() {
3501
3501
  }
3502
3502
  }
3503
3503
 
3504
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3505
+ import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
3506
+ import { dirname as dirname5, join as join3 } from "node:path";
3507
+
3508
+ // ../lsp-core/src/lsp/workspace-markers.ts
3509
+ var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
3510
+
3511
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3512
+ function findWorkspaceRootOutsideContext(directory) {
3513
+ const marked = nearestMarkedAncestor(directory);
3514
+ if (marked !== undefined)
3515
+ return marked;
3516
+ return realpathSync4(nearestExistingAncestor(directory));
3517
+ }
3518
+ function nearestMarkedAncestor(directory) {
3519
+ let current = directory;
3520
+ for (;; ) {
3521
+ if (existsSync6(current) && WORKSPACE_MARKERS.some((marker) => existsSync6(join3(current, marker)))) {
3522
+ return realpathSync4(current);
3523
+ }
3524
+ const parent = dirname5(current);
3525
+ if (parent === current)
3526
+ return;
3527
+ current = parent;
3528
+ }
3529
+ }
3530
+ function nearestExistingAncestor(directory) {
3531
+ let current = directory;
3532
+ while (!existsSync6(current)) {
3533
+ const parent = dirname5(current);
3534
+ if (parent === current)
3535
+ return current;
3536
+ current = parent;
3537
+ }
3538
+ return current;
3539
+ }
3540
+
3504
3541
  // ../lsp-core/src/lsp/server-install-state.ts
3505
- import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3506
- import { dirname as dirname5 } from "node:path";
3542
+ import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3543
+ import { dirname as dirname6 } from "node:path";
3507
3544
  function getInstallDecisionsPath() {
3508
3545
  return lspRequestContext().installDecisionsPath;
3509
3546
  }
3510
3547
  function loadInstallDecisions() {
3511
3548
  const path = getInstallDecisionsPath();
3512
- if (!existsSync6(path))
3549
+ if (!existsSync7(path))
3513
3550
  return {};
3514
3551
  try {
3515
3552
  const parsed = JSON.parse(readFileSync3(path, "utf8"));
@@ -3531,7 +3568,7 @@ function isInstallDecision(value) {
3531
3568
  }
3532
3569
  function writeInstallDecisions(decisions) {
3533
3570
  const path = getInstallDecisionsPath();
3534
- mkdirSync(dirname5(path), { recursive: true });
3571
+ mkdirSync(dirname6(path), { recursive: true });
3535
3572
  const tmpPath = `${path}.tmp`;
3536
3573
  writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3537
3574
  `, "utf8");
@@ -3550,7 +3587,7 @@ function isRecord5(value) {
3550
3587
  }
3551
3588
 
3552
3589
  // ../lsp-core/src/lsp/config-loader.ts
3553
- import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
3590
+ import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
3554
3591
 
3555
3592
  // ../lsp-core/src/lsp/server-definitions.ts
3556
3593
  var LSP_INSTALL_HINTS = {
@@ -3707,7 +3744,7 @@ function getUserConfigPath() {
3707
3744
  return lspRequestContext().userConfigPath;
3708
3745
  }
3709
3746
  function loadJsonFile(path) {
3710
- if (!existsSync7(path))
3747
+ if (!existsSync8(path))
3711
3748
  return null;
3712
3749
  try {
3713
3750
  const parsed = JSON.parse(readFileSync4(path, "utf-8"));
@@ -3895,8 +3932,8 @@ function getDisabledServerIds() {
3895
3932
  }
3896
3933
 
3897
3934
  // ../lsp-core/src/lsp/server-installation.ts
3898
- import { existsSync as existsSync8 } from "node:fs";
3899
- import { delimiter as delimiter3, join as join3 } from "node:path";
3935
+ import { existsSync as existsSync9 } from "node:fs";
3936
+ import { delimiter as delimiter3, join as join4 } from "node:path";
3900
3937
  function isServerInstalled(command, _workingDirectory) {
3901
3938
  if (command.length === 0)
3902
3939
  return false;
@@ -3904,7 +3941,7 @@ function isServerInstalled(command, _workingDirectory) {
3904
3941
  if (!cmd)
3905
3942
  return false;
3906
3943
  if (cmd.includes("/") || cmd.includes("\\")) {
3907
- if (existsSync8(cmd))
3944
+ if (existsSync9(cmd))
3908
3945
  return true;
3909
3946
  }
3910
3947
  const isWindows = process.platform === "win32";
@@ -3925,7 +3962,7 @@ function isServerInstalled(command, _workingDirectory) {
3925
3962
  const paths = pathEnv.split(delimiter3);
3926
3963
  for (const p of paths) {
3927
3964
  for (const suffix of exts) {
3928
- if (existsSync8(join3(p, cmd + suffix))) {
3965
+ if (existsSync9(join4(p, cmd + suffix))) {
3929
3966
  return true;
3930
3967
  }
3931
3968
  }
@@ -4021,7 +4058,6 @@ function getAllServers() {
4021
4058
  }
4022
4059
 
4023
4060
  // ../lsp-core/src/lsp/client-wrapper.ts
4024
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
4025
4061
  function isDirectoryPath(filePath) {
4026
4062
  try {
4027
4063
  return statSync3(filePath).isDirectory();
@@ -4034,21 +4070,23 @@ function findWorkspaceRoot(filePath) {
4034
4070
  const abs = resolveReadablePathInsideContext(filePath);
4035
4071
  let dir = abs;
4036
4072
  if (!isDirectoryPath(dir)) {
4037
- dir = dirname6(dir);
4073
+ dir = dirname7(dir);
4038
4074
  }
4075
+ if (!isPathInside(cwd, abs))
4076
+ return findWorkspaceRootOutsideContext(dir);
4039
4077
  const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4040
4078
  while (isPathInside(cwd, dir)) {
4041
4079
  const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4042
4080
  if (canonicalDir !== undefined) {
4043
4081
  for (const marker of WORKSPACE_MARKERS) {
4044
- if (existsSync9(join4(dir, marker))) {
4082
+ if (existsSync10(join5(dir, marker))) {
4045
4083
  return canonicalDir;
4046
4084
  }
4047
4085
  }
4048
4086
  }
4049
4087
  if (dir === cwd)
4050
4088
  break;
4051
- dir = dirname6(dir);
4089
+ dir = dirname7(dir);
4052
4090
  }
4053
4091
  return fallbackRoot;
4054
4092
  }
@@ -4060,10 +4098,7 @@ function resolveReadablePathInsideContext(filePath) {
4060
4098
  const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
4061
4099
  if (rebased !== undefined)
4062
4100
  return rebased;
4063
- const canonical = canonicalizeExistingOrNearestAncestor(abs);
4064
- if (isPathInside(cwd, canonical))
4065
- return canonical;
4066
- throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
4101
+ return canonicalizeExistingOrNearestAncestor(abs);
4067
4102
  }
4068
4103
  function resolvePathInsideContext(filePath) {
4069
4104
  const cwd = contextCwd();
@@ -4078,12 +4113,12 @@ function rebaseThroughCanonicalAncestor(path, cwd) {
4078
4113
  let current = path;
4079
4114
  const suffix = [];
4080
4115
  while (true) {
4081
- if (existsSync9(current)) {
4082
- const canonical = realpathSync4(current);
4116
+ if (existsSync10(current)) {
4117
+ const canonical = realpathSync5(current);
4083
4118
  if (isPathInside(cwd, canonical))
4084
- return suffix.length === 0 ? canonical : join4(canonical, ...suffix);
4119
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
4085
4120
  }
4086
- const parent = dirname6(current);
4121
+ const parent = dirname7(current);
4087
4122
  if (parent === current)
4088
4123
  return;
4089
4124
  suffix.unshift(basename3(current));
@@ -4091,9 +4126,9 @@ function rebaseThroughCanonicalAncestor(path, cwd) {
4091
4126
  }
4092
4127
  }
4093
4128
  function existingDirectoryInsideContext(directory, cwd) {
4094
- if (!existsSync9(directory))
4129
+ if (!existsSync10(directory))
4095
4130
  return;
4096
- const canonical = realpathSync4(directory);
4131
+ const canonical = realpathSync5(directory);
4097
4132
  if (!statSync3(canonical).isDirectory())
4098
4133
  return;
4099
4134
  return isPathInside(cwd, canonical) ? canonical : undefined;
@@ -4106,7 +4141,7 @@ function nearestExistingDirectoryInsideContext(directory, cwd) {
4106
4141
  return canonical;
4107
4142
  if (current === cwd)
4108
4143
  return;
4109
- current = dirname6(current);
4144
+ current = dirname7(current);
4110
4145
  }
4111
4146
  return;
4112
4147
  }
@@ -4224,8 +4259,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4224
4259
  }
4225
4260
 
4226
4261
  // ../lsp-core/src/lsp/directory-diagnostics.ts
4227
- import { existsSync as existsSync10, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4228
- import { join as join5, resolve as resolve8 } from "node:path";
4262
+ import { existsSync as existsSync11, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4263
+ import { join as join6, resolve as resolve8 } from "node:path";
4229
4264
 
4230
4265
  // ../lsp-core/src/lsp/formatters.ts
4231
4266
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -4355,7 +4390,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
4355
4390
  for (const entry of entries) {
4356
4391
  if (files.length >= maxFiles)
4357
4392
  return;
4358
- const fullPath = join5(currentDir, entry);
4393
+ const fullPath = join6(currentDir, entry);
4359
4394
  let stat;
4360
4395
  try {
4361
4396
  stat = lstatSync4(fullPath);
@@ -4381,7 +4416,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4381
4416
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4382
4417
  }
4383
4418
  const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4384
- if (!existsSync10(absDir)) {
4419
+ if (!existsSync11(absDir)) {
4385
4420
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4386
4421
  }
4387
4422
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
@@ -4468,7 +4503,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4468
4503
 
4469
4504
  // ../lsp-core/src/lsp/infer-extension.ts
4470
4505
  import { lstatSync as lstatSync5, readdirSync as readdirSync4 } from "node:fs";
4471
- import { join as join6 } from "node:path";
4506
+ import { join as join7 } from "node:path";
4472
4507
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
4473
4508
  var MAX_SCAN_ENTRIES = 500;
4474
4509
  function inferExtensionFromDirectory(directory) {
@@ -4486,7 +4521,7 @@ function inferExtensionFromDirectory(directory) {
4486
4521
  for (const entry of entries) {
4487
4522
  if (scanned >= MAX_SCAN_ENTRIES)
4488
4523
  return;
4489
- const fullPath = join6(dir, entry);
4524
+ const fullPath = join7(dir, entry);
4490
4525
  let stat;
4491
4526
  try {
4492
4527
  stat = lstatSync5(fullPath);