oh-my-opencode 5.0.0-beta.21 → 5.0.0-beta.23

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 (151) hide show
  1. package/dist/cli/index.js +290 -288
  2. package/dist/cli-node/index.js +290 -288
  3. package/dist/index.js +1675 -1657
  4. package/dist/skills/debugging/SKILL.md +2 -0
  5. package/dist/skills/debugging/references/methodology/00-setup.md +12 -0
  6. package/dist/skills/debugging/references/methodology/02-investigate.md +21 -0
  7. package/dist/skills/debugging/references/runtimes/go.md +15 -1
  8. package/dist/skills/debugging/references/runtimes/native-binary.md +38 -0
  9. package/dist/skills/debugging/references/runtimes/node.md +25 -0
  10. package/dist/skills/debugging/references/runtimes/python.md +13 -0
  11. package/dist/skills/debugging/references/runtimes/rust.md +41 -0
  12. package/dist/skills/debugging/references/scripts/dap.mjs +267 -0
  13. package/dist/skills/debugging/references/scripts/dap.test.ts +86 -0
  14. package/dist/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  15. package/dist/skills/debugging/references/tools/dap.md +103 -0
  16. package/dist/skills/debugging/references/tools/frida.md +193 -0
  17. package/dist/tools/delegate-task/types.d.ts +3 -0
  18. package/dist/tui.js +131 -147
  19. package/package.json +18 -15
  20. package/packages/lsp-core/src/index.ts +1 -0
  21. package/packages/lsp-core/src/lsp/client-wrapper.ts +25 -5
  22. package/packages/lsp-core/src/lsp/client.ts +26 -0
  23. package/packages/lsp-core/src/lsp/connection.ts +16 -0
  24. package/packages/lsp-core/src/lsp/constants.ts +1 -0
  25. package/packages/lsp-core/src/lsp/format-document.test.ts +143 -0
  26. package/packages/lsp-core/src/lsp/format-document.ts +90 -0
  27. package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +151 -0
  28. package/packages/lsp-core/src/lsp/manager.ts +34 -1
  29. package/packages/lsp-core/src/lsp/server-definitions.ts +29 -0
  30. package/packages/lsp-core/src/lsp/server-installation.test.ts +376 -0
  31. package/packages/lsp-core/src/lsp/server-installation.ts +200 -27
  32. package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +170 -0
  33. package/packages/lsp-core/src/lsp/server-resolution.ts +18 -5
  34. package/packages/lsp-core/src/lsp/transport.ts +9 -0
  35. package/packages/lsp-core/src/lsp/types.ts +8 -0
  36. package/packages/lsp-core/src/tool-surface.test.ts +13 -1
  37. package/packages/lsp-core/src/tools/definitions.ts +14 -0
  38. package/packages/lsp-core/src/tools/format.test.ts +56 -0
  39. package/packages/lsp-core/src/tools/format.ts +56 -0
  40. package/packages/lsp-core/src/tools/index.ts +1 -0
  41. package/packages/lsp-core/src/tools/types.ts +10 -0
  42. package/packages/lsp-daemon/dist/cli.js +432 -144
  43. package/packages/lsp-daemon/dist/client.d.ts +10 -0
  44. package/packages/lsp-daemon/dist/client.js +401 -107
  45. package/packages/lsp-daemon/dist/daemon-client.d.ts +1 -0
  46. package/packages/lsp-daemon/dist/daemon-client.js +3 -0
  47. package/packages/lsp-daemon/dist/index.js +395 -107
  48. package/packages/lsp-daemon/package.json +1 -1
  49. package/packages/lsp-tools-mcp/dist/cli.js +384 -99
  50. package/packages/lsp-tools-mcp/dist/lsp/manager.js +53 -0
  51. package/packages/lsp-tools-mcp/dist/mcp.js +384 -99
  52. package/packages/lsp-tools-mcp/dist/tools.js +385 -99
  53. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  54. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +2 -2
  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 +69 -35
  58. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +21 -2
  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/lsp/dist/.omo-runtime-manifest.json +3 -3
  67. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +404 -121
  68. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  69. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  70. package/packages/omo-codex/plugin/components/rules/dist/cli.js +3 -3
  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/src/post-compact-budget.ts +3 -3
  74. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +4 -4
  75. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  76. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  77. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +30 -15
  78. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +30 -15
  79. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  80. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  81. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  82. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  83. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +2 -2
  84. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  85. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +5 -1
  86. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +2 -1
  87. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +11 -1
  88. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +22 -10
  89. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  90. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  91. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +5 -1
  92. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +13 -1
  93. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +3 -5
  94. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +26 -2
  95. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  96. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  97. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  98. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  99. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  100. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  101. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  102. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  103. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  104. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  105. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  106. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  107. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  108. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  109. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  110. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  111. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  112. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  113. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +1 -1
  114. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  115. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  116. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  117. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  118. package/packages/omo-codex/plugin/model-catalog.json +3 -3
  119. package/packages/omo-codex/plugin/package-lock.json +13 -13
  120. package/packages/omo-codex/plugin/package.json +1 -1
  121. package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +3 -3
  122. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -0
  123. package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
  124. package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
  125. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
  126. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
  127. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
  128. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
  129. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
  130. package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
  131. package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  132. package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
  133. package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
  134. package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +1 -1
  135. package/packages/omo-codex/plugin/test/auto-update.test.mjs +2 -2
  136. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +8 -8
  137. package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +2 -2
  138. package/packages/omo-codex/scripts/install-dist/install-local.mjs +38 -23
  139. package/packages/shared-skills/skills/debugging/SKILL.md +2 -0
  140. package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
  141. package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
  142. package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
  143. package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
  144. package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
  145. package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
  146. package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
  147. package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
  148. package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
  149. package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  150. package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
  151. package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
@@ -23,6 +23,7 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
23
23
  var REQUEST_TIMEOUT_MS = 15000;
24
24
  var INIT_TIMEOUT_MS = 60000;
25
25
  var IDLE_TIMEOUT_MS = 5 * 60000;
26
+ var MAX_RESIDENT_CLIENTS = 6;
26
27
  var REAPER_INTERVAL_MS = 60000;
27
28
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
28
29
  var STOP_SIGKILL_GRACE_MS = 1000;
@@ -615,6 +616,7 @@ class LspClientTransport {
615
616
  this.diagnosticsStore = new Map;
616
617
  this.workspaceApplyEditHandler = null;
617
618
  this.diagnosticPullSupported = false;
619
+ this.documentFormattingSupported = false;
618
620
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
619
621
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
620
622
  }
@@ -636,6 +638,12 @@ class LspClientTransport {
636
638
  isDiagnosticPullSupported() {
637
639
  return this.diagnosticPullSupported;
638
640
  }
641
+ setDocumentFormattingSupported(supported) {
642
+ this.documentFormattingSupported = supported;
643
+ }
644
+ isDocumentFormattingSupported() {
645
+ return this.documentFormattingSupported;
646
+ }
639
647
  handlePublishDiagnostics(params) {
640
648
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
641
649
  }
@@ -849,6 +857,14 @@ function supportsDiagnosticPull(capabilities) {
849
857
  return false;
850
858
  return Object.hasOwn(capabilities, "diagnosticProvider");
851
859
  }
860
+ function supportsDocumentFormatting(capabilities) {
861
+ if (capabilities === undefined)
862
+ return false;
863
+ const provider = capabilities.documentFormattingProvider;
864
+ if (provider === undefined || provider === null || provider === false)
865
+ return false;
866
+ return provider === true || typeof provider === "object";
867
+ }
852
868
 
853
869
  class LspClientConnection extends LspClientTransport {
854
870
  async initialize() {
@@ -865,6 +881,7 @@ class LspClientConnection extends LspClientTransport {
865
881
  references: {},
866
882
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
867
883
  publishDiagnostics: {},
884
+ formatting: { dynamicRegistration: false },
868
885
  rename: {
869
886
  prepareSupport: true,
870
887
  prepareSupportDefaultBehavior: 1
@@ -906,6 +923,7 @@ class LspClientConnection extends LspClientTransport {
906
923
  initializationOptions: this.server.initialization
907
924
  }, { timeoutMs: this.initializeTimeoutMs });
908
925
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
926
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
909
927
  await this.sendNotification("initialized", {});
910
928
  await this.sendNotification("workspace/didChangeConfiguration", {
911
929
  settings: { json: { validate: { enable: true } } }
@@ -2500,6 +2518,18 @@ class LspClient extends LspClientConnection {
2500
2518
  textDocument: { uri: pathToFileURL3(absPath).href }
2501
2519
  }, options);
2502
2520
  }
2521
+ async formatDocument(filePath, options, signal) {
2522
+ if (!this.isDocumentFormattingSupported())
2523
+ return null;
2524
+ const absPath = this.resolveWorkspacePath(filePath);
2525
+ await this.openFile(absPath);
2526
+ const requestOptions = signal === undefined ? {} : { signal };
2527
+ const edits = await this.sendRequest("textDocument/formatting", {
2528
+ textDocument: { uri: pathToFileURL3(absPath).href },
2529
+ options
2530
+ }, requestOptions);
2531
+ return edits ?? [];
2532
+ }
2503
2533
  async workspaceSymbols(query, signal) {
2504
2534
  const options = signal === undefined ? {} : { signal };
2505
2535
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -2752,6 +2782,7 @@ class LspManager {
2752
2782
  this.disposed = false;
2753
2783
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
2754
2784
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
2785
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
2755
2786
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
2756
2787
  this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
2757
2788
  this.now = options.now ?? (() => Date.now());
@@ -2785,6 +2816,26 @@ class LspManager {
2785
2816
  }
2786
2817
  }
2787
2818
  }
2819
+ evictForAdmission() {
2820
+ while (this.clients.size >= this.maxResidentClients) {
2821
+ const victim = this.leastRecentlyUsedIdleClient();
2822
+ if (!victim)
2823
+ return;
2824
+ this.clients.delete(victim.key);
2825
+ stopClientBestEffort(victim.managed.client);
2826
+ }
2827
+ }
2828
+ leastRecentlyUsedIdleClient() {
2829
+ let candidate = null;
2830
+ for (const [key, managed] of this.clients) {
2831
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
2832
+ continue;
2833
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
2834
+ candidate = { key, managed };
2835
+ }
2836
+ }
2837
+ return candidate;
2838
+ }
2788
2839
  async tryDeleteIfOrphaned(key, managed) {
2789
2840
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
2790
2841
  this.clients.delete(key);
@@ -2831,6 +2882,7 @@ class LspManager {
2831
2882
  managed.lastUsedAt = this.now();
2832
2883
  return managed.client;
2833
2884
  }
2885
+ this.evictForAdmission();
2834
2886
  const client = this.clientFactory(root, server);
2835
2887
  const initStartedAt = this.now();
2836
2888
  const initPromise = (async () => {
@@ -2893,6 +2945,7 @@ class LspManager {
2893
2945
  const key = this.getKey(root, server.id);
2894
2946
  if (this.clients.has(key))
2895
2947
  return;
2948
+ this.evictForAdmission();
2896
2949
  const client = this.clientFactory(root, server);
2897
2950
  const initStartedAt = this.now();
2898
2951
  const initPromise = (async () => {
@@ -4121,7 +4174,7 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
4121
4174
  }
4122
4175
  // ../lsp-core/src/lsp/client-wrapper.ts
4123
4176
  import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
4124
- import { basename as basename3, dirname as dirname9, join as join5, resolve as resolve7 } from "node:path";
4177
+ import { basename as basename3, dirname as dirname10, join as join5, resolve as resolve8 } from "node:path";
4125
4178
 
4126
4179
  // ../lsp-core/src/lsp/outside-context-workspace.ts
4127
4180
  import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
@@ -4160,57 +4213,6 @@ function nearestExistingAncestor(directory) {
4160
4213
  return current;
4161
4214
  }
4162
4215
 
4163
- // ../lsp-core/src/lsp/server-install-state.ts
4164
- import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
4165
- import { dirname as dirname8 } from "node:path";
4166
- function getInstallDecisionsPath() {
4167
- return lspRequestContext().installDecisionsPath;
4168
- }
4169
- function loadInstallDecisions() {
4170
- const path2 = getInstallDecisionsPath();
4171
- if (!existsSync8(path2))
4172
- return {};
4173
- try {
4174
- const parsed = JSON.parse(readFileSync4(path2, "utf8"));
4175
- return isInstallDecisions(parsed) ? parsed : {};
4176
- } catch {
4177
- return {};
4178
- }
4179
- }
4180
- function loadInstallDecision(serverId) {
4181
- return loadInstallDecisions()[serverId];
4182
- }
4183
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
4184
- const decisions = loadInstallDecisions();
4185
- decisions[serverId] = { decision, decidedAt };
4186
- writeInstallDecisions(decisions);
4187
- }
4188
- function isInstallDecision(value) {
4189
- return value === "declined" || value === "allowed";
4190
- }
4191
- function writeInstallDecisions(decisions) {
4192
- const path2 = getInstallDecisionsPath();
4193
- mkdirSync3(dirname8(path2), { recursive: true });
4194
- const tmpPath = `${path2}.tmp`;
4195
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
4196
- `, "utf8");
4197
- renameSync2(tmpPath, path2);
4198
- }
4199
- function isInstallDecisions(value) {
4200
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
4201
- }
4202
- function isInstallDecisionRecord(value) {
4203
- if (!isRecord5(value))
4204
- return false;
4205
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
4206
- }
4207
- function isRecord5(value) {
4208
- return typeof value === "object" && value !== null && !Array.isArray(value);
4209
- }
4210
-
4211
- // ../lsp-core/src/lsp/config-loader.ts
4212
- import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
4213
-
4214
4216
  // ../lsp-core/src/lsp/server-definitions.ts
4215
4217
  var LSP_INSTALL_HINTS = {
4216
4218
  typescript: "npm install -g typescript-language-server typescript",
@@ -4256,6 +4258,26 @@ var LSP_INSTALL_HINTS = {
4256
4258
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
4257
4259
  razor: "Razor runs through the Roslyn language server (cohosting). " + "Install: dotnet tool install -g roslyn-language-server --prerelease (requires v5.8.0+). See https://github.com/dotnet/razor"
4258
4260
  };
4261
+ var LSP_LOCAL_INSTALL_HINTS = {
4262
+ typescript: "bun add -d typescript-language-server typescript",
4263
+ vue: "bun add -d @vue/language-server",
4264
+ eslint: "bun add -d vscode-langservers-extracted",
4265
+ oxlint: "bun add -d oxlint",
4266
+ biome: "bun add -d @biomejs/biome",
4267
+ svelte: "bun add -d svelte-language-server",
4268
+ astro: "bun add -d @astrojs/language-server",
4269
+ bash: "bun add -d bash-language-server",
4270
+ "bash-ls": "bun add -d bash-language-server",
4271
+ "yaml-ls": "bun add -d yaml-language-server",
4272
+ php: "bun add -d intelephense",
4273
+ prisma: "bun add -d prisma",
4274
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
4275
+ pyright: "uv add --dev pyright",
4276
+ basedpyright: "uv add --dev basedpyright",
4277
+ ruff: "uv add --dev ruff",
4278
+ ty: "uv add --dev ty",
4279
+ "ruby-lsp": "bundle add ruby-lsp --group development"
4280
+ };
4259
4281
  var BUILTIN_SERVERS = {
4260
4282
  typescript: {
4261
4283
  command: ["typescript-language-server", "--stdio"],
@@ -4358,7 +4380,56 @@ var BUILTIN_SERVERS = {
4358
4380
  }
4359
4381
  };
4360
4382
 
4383
+ // ../lsp-core/src/lsp/server-install-state.ts
4384
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
4385
+ import { dirname as dirname8 } from "node:path";
4386
+ function getInstallDecisionsPath() {
4387
+ return lspRequestContext().installDecisionsPath;
4388
+ }
4389
+ function loadInstallDecisions() {
4390
+ const path2 = getInstallDecisionsPath();
4391
+ if (!existsSync8(path2))
4392
+ return {};
4393
+ try {
4394
+ const parsed = JSON.parse(readFileSync4(path2, "utf8"));
4395
+ return isInstallDecisions(parsed) ? parsed : {};
4396
+ } catch {
4397
+ return {};
4398
+ }
4399
+ }
4400
+ function loadInstallDecision(serverId) {
4401
+ return loadInstallDecisions()[serverId];
4402
+ }
4403
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
4404
+ const decisions = loadInstallDecisions();
4405
+ decisions[serverId] = { decision, decidedAt };
4406
+ writeInstallDecisions(decisions);
4407
+ }
4408
+ function isInstallDecision(value) {
4409
+ return value === "declined" || value === "allowed";
4410
+ }
4411
+ function writeInstallDecisions(decisions) {
4412
+ const path2 = getInstallDecisionsPath();
4413
+ mkdirSync3(dirname8(path2), { recursive: true });
4414
+ const tmpPath = `${path2}.tmp`;
4415
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
4416
+ `, "utf8");
4417
+ renameSync2(tmpPath, path2);
4418
+ }
4419
+ function isInstallDecisions(value) {
4420
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
4421
+ }
4422
+ function isInstallDecisionRecord(value) {
4423
+ if (!isRecord5(value))
4424
+ return false;
4425
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
4426
+ }
4427
+ function isRecord5(value) {
4428
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4429
+ }
4430
+
4361
4431
  // ../lsp-core/src/lsp/config-loader.ts
4432
+ import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
4362
4433
  function getProjectConfigPaths() {
4363
4434
  return lspRequestContext().projectConfigPaths;
4364
4435
  }
@@ -4555,53 +4626,154 @@ function getDisabledServerIds() {
4555
4626
 
4556
4627
  // ../lsp-core/src/lsp/server-installation.ts
4557
4628
  import { existsSync as existsSync10 } from "node:fs";
4558
- import { delimiter as delimiter3, join as join4 } from "node:path";
4559
- function isServerInstalled(command, _workingDirectory) {
4560
- if (command.length === 0)
4561
- return false;
4562
- const [cmd] = command;
4563
- if (!cmd)
4564
- return false;
4565
- if (cmd.includes("/") || cmd.includes("\\")) {
4566
- if (existsSync10(cmd))
4567
- return true;
4629
+ import { delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
4630
+ var LOCAL_BIN_RULES = [
4631
+ {
4632
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
4633
+ binDirs: [join4("node_modules", ".bin")]
4634
+ },
4635
+ {
4636
+ markers: [
4637
+ "pyproject.toml",
4638
+ "ty.toml",
4639
+ "requirements.txt",
4640
+ "setup.py",
4641
+ "setup.cfg",
4642
+ "Pipfile",
4643
+ "pyrightconfig.json",
4644
+ "ruff.toml",
4645
+ ".ruff.toml"
4646
+ ],
4647
+ binDirs: [
4648
+ join4(".venv", "bin"),
4649
+ join4(".venv", "Scripts"),
4650
+ join4("venv", "bin"),
4651
+ join4("venv", "Scripts"),
4652
+ join4(".env", "bin"),
4653
+ join4(".env", "Scripts")
4654
+ ]
4655
+ },
4656
+ {
4657
+ markers: ["Gemfile", "Gemfile.lock"],
4658
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
4659
+ },
4660
+ {
4661
+ markers: ["go.mod", "go.sum", "go.work"],
4662
+ binDirs: ["bin"]
4568
4663
  }
4569
- const isWindows = process.platform === "win32";
4570
- let exts = [""];
4571
- if (isWindows) {
4572
- const pathExt = process.env["PATHEXT"] ?? "";
4573
- if (pathExt) {
4574
- const systemExts = pathExt.split(";").filter(Boolean);
4575
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4576
- } else {
4577
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
4664
+ ];
4665
+ var resolutionCache = new Map;
4666
+ var probeCount = 0;
4667
+ function probe(path2) {
4668
+ probeCount += 1;
4669
+ return existsSync10(path2);
4670
+ }
4671
+ function executableSuffixes(platform, pathExt) {
4672
+ if (platform !== "win32")
4673
+ return [""];
4674
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
4675
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
4676
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4677
+ }
4678
+ function probeWithSuffixes(directory, command, suffixes) {
4679
+ for (const suffix of suffixes) {
4680
+ const candidate = join4(directory, command + suffix);
4681
+ if (probe(candidate))
4682
+ return candidate;
4683
+ }
4684
+ return null;
4685
+ }
4686
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
4687
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
4688
+ let current = resolve7(workingDirectory);
4689
+ while (true) {
4690
+ for (const rule of LOCAL_BIN_RULES) {
4691
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
4692
+ continue;
4693
+ for (const binDir of rule.binDirs) {
4694
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
4695
+ if (found !== null)
4696
+ return found;
4697
+ }
4578
4698
  }
4699
+ if (probe(join4(current, ".git")))
4700
+ return null;
4701
+ if (boundary !== undefined && current === boundary)
4702
+ return null;
4703
+ const parent = dirname9(current);
4704
+ if (parent === current)
4705
+ return null;
4706
+ current = parent;
4579
4707
  }
4580
- let pathEnv = process.env["PATH"] ?? "";
4581
- if (isWindows && !pathEnv) {
4708
+ }
4709
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
4710
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
4711
+ if (platform === "win32" && !pathEnv) {
4582
4712
  pathEnv = process.env["Path"] ?? "";
4583
4713
  }
4584
- const paths = pathEnv.split(delimiter3);
4585
- for (const p of paths) {
4586
- for (const suffix of exts) {
4587
- if (existsSync10(join4(p, cmd + suffix))) {
4588
- return true;
4589
- }
4590
- }
4714
+ for (const entry of pathEnv.split(delimiter3)) {
4715
+ if (entry.length === 0)
4716
+ continue;
4717
+ const found = probeWithSuffixes(entry, command, suffixes);
4718
+ if (found !== null)
4719
+ return found;
4591
4720
  }
4592
- if (cmd === "node")
4593
- return true;
4594
- return false;
4721
+ return null;
4722
+ }
4723
+ function resolveServerBinary(command, workingDirectory, options = {}) {
4724
+ if (command.length === 0)
4725
+ return null;
4726
+ const [cmd] = command;
4727
+ if (cmd === undefined || cmd.length === 0)
4728
+ return null;
4729
+ const platform = options.platform ?? process.platform;
4730
+ const suffixes = executableSuffixes(platform, options.pathExt);
4731
+ if (cmd.includes("/") || cmd.includes("\\")) {
4732
+ const explicit = isAbsolute5(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
4733
+ return probe(explicit) ? explicit : null;
4734
+ }
4735
+ const cacheKey = JSON.stringify([
4736
+ workingDirectory ?? "",
4737
+ cmd,
4738
+ platform,
4739
+ options.stopAt ?? "",
4740
+ options.pathExt ?? "",
4741
+ options.pathEnv ?? process.env["PATH"] ?? ""
4742
+ ]);
4743
+ const cached = resolutionCache.get(cacheKey);
4744
+ if (cached !== undefined)
4745
+ return cached;
4746
+ let resolved = null;
4747
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
4748
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
4749
+ }
4750
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
4751
+ if (resolved === null && cmd === "node")
4752
+ resolved = cmd;
4753
+ resolutionCache.set(cacheKey, resolved);
4754
+ return resolved;
4755
+ }
4756
+ function isServerInstalled(command, workingDirectory, options = {}) {
4757
+ if (command.length === 0)
4758
+ return false;
4759
+ return resolveServerBinary(command, workingDirectory, options) !== null;
4595
4760
  }
4596
4761
 
4597
4762
  // ../lsp-core/src/lsp/server-resolution.ts
4763
+ function withResolvedCommand(command, binaryPath) {
4764
+ return [binaryPath, ...command.slice(1)];
4765
+ }
4598
4766
  function findServerForExtension(ext) {
4599
4767
  const servers = getMergedServers();
4768
+ const workingDirectory = contextCwd();
4600
4769
  for (const server2 of servers) {
4601
- if (server2.extensions.includes(ext) && isServerInstalled(server2.command)) {
4770
+ if (!server2.extensions.includes(ext))
4771
+ continue;
4772
+ const binaryPath = resolveServerBinary(server2.command, workingDirectory);
4773
+ if (binaryPath !== null) {
4602
4774
  const resolvedServer = {
4603
4775
  id: server2.id,
4604
- command: server2.command,
4776
+ command: withResolvedCommand(server2.command, binaryPath),
4605
4777
  extensions: server2.extensions,
4606
4778
  priority: server2.priority
4607
4779
  };
@@ -4648,6 +4820,7 @@ function findServerForExtension(ext) {
4648
4820
  function getAllServers() {
4649
4821
  const servers = getMergedServers();
4650
4822
  const disabled = getDisabledServerIds();
4823
+ const workingDirectory = contextCwd();
4651
4824
  const result = [];
4652
4825
  const seen = new Set;
4653
4826
  for (const server2 of servers) {
@@ -4655,7 +4828,7 @@ function getAllServers() {
4655
4828
  continue;
4656
4829
  result.push({
4657
4830
  id: server2.id,
4658
- installed: isServerInstalled(server2.command),
4831
+ installed: isServerInstalled(server2.command, workingDirectory),
4659
4832
  extensions: server2.extensions,
4660
4833
  disabled: false,
4661
4834
  source: server2.source,
@@ -4669,7 +4842,7 @@ function getAllServers() {
4669
4842
  const builtin = BUILTIN_SERVERS[id];
4670
4843
  result.push({
4671
4844
  id,
4672
- installed: builtin ? isServerInstalled(builtin.command) : false,
4845
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
4673
4846
  extensions: builtin?.extensions ?? [],
4674
4847
  disabled: true,
4675
4848
  source: "disabled",
@@ -4692,7 +4865,7 @@ function findWorkspaceRoot(filePath) {
4692
4865
  const abs = resolveReadablePathInsideContext(filePath);
4693
4866
  let dir = abs;
4694
4867
  if (!isDirectoryPath(dir)) {
4695
- dir = dirname9(dir);
4868
+ dir = dirname10(dir);
4696
4869
  }
4697
4870
  if (!isPathInside(cwd, abs))
4698
4871
  return findWorkspaceRootOutsideContext(dir);
@@ -4708,13 +4881,13 @@ function findWorkspaceRoot(filePath) {
4708
4881
  }
4709
4882
  if (dir === cwd)
4710
4883
  break;
4711
- dir = dirname9(dir);
4884
+ dir = dirname10(dir);
4712
4885
  }
4713
4886
  return fallbackRoot;
4714
4887
  }
4715
4888
  function resolveReadablePathInsideContext(filePath) {
4716
4889
  const cwd = contextCwd();
4717
- const abs = resolve7(cwd, filePath);
4890
+ const abs = resolve8(cwd, filePath);
4718
4891
  if (isPathInside(cwd, abs))
4719
4892
  return abs;
4720
4893
  const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
@@ -4740,7 +4913,7 @@ function rebaseThroughCanonicalAncestor(path2, cwd) {
4740
4913
  if (isPathInside(cwd, canonical))
4741
4914
  return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
4742
4915
  }
4743
- const parent = dirname9(current);
4916
+ const parent = dirname10(current);
4744
4917
  if (parent === current)
4745
4918
  return;
4746
4919
  suffix.unshift(basename3(current));
@@ -4763,7 +4936,7 @@ function nearestExistingDirectoryInsideContext(directory, cwd) {
4763
4936
  return canonical;
4764
4937
  if (current === cwd)
4765
4938
  return;
4766
- current = dirname9(current);
4939
+ current = dirname10(current);
4767
4940
  }
4768
4941
  return;
4769
4942
  }
@@ -4790,6 +4963,19 @@ function formatServerLookupError(result) {
4790
4963
  ].join(`
4791
4964
  `);
4792
4965
  }
4966
+ function formatInstallOptions(serverId, installHint) {
4967
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
4968
+ if (localHint === undefined) {
4969
+ return ["To install, run:", ` ${installHint}`];
4970
+ }
4971
+ return [
4972
+ "To install in THIS repository (preferred — no global install needed):",
4973
+ ` ${localHint}`,
4974
+ "",
4975
+ "Or install it globally:",
4976
+ ` ${installHint}`
4977
+ ];
4978
+ }
4793
4979
  function formatNotInstalled(result) {
4794
4980
  const { server: server2, installHint } = result;
4795
4981
  const extensions = server2.extensions.join(", ");
@@ -4804,19 +4990,19 @@ function formatNotInstalled(result) {
4804
4990
  `Command not found: ${server2.command[0]}`,
4805
4991
  ""
4806
4992
  ];
4993
+ const installOptions = formatInstallOptions(server2.id, installHint);
4807
4994
  if (decision === "allowed") {
4808
4995
  return [
4809
4996
  ...header,
4810
4997
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
4811
- ` ${installHint}`
4998
+ ...installOptions.slice(1)
4812
4999
  ].join(`
4813
5000
  `);
4814
5001
  }
4815
5002
  if (!context.capabilities.installDecisionTool) {
4816
5003
  return [
4817
5004
  ...header,
4818
- "To install, run:",
4819
- ` ${installHint}`,
5005
+ ...installOptions,
4820
5006
  "",
4821
5007
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4822
5008
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -4825,8 +5011,7 @@ function formatNotInstalled(result) {
4825
5011
  }
4826
5012
  return [
4827
5013
  ...header,
4828
- "To install, run:",
4829
- ` ${installHint}`,
5014
+ ...installOptions,
4830
5015
  "",
4831
5016
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4832
5017
  "- If the user agrees: run the install command above, then retry this tool.",
@@ -4882,7 +5067,7 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4882
5067
 
4883
5068
  // ../lsp-core/src/lsp/directory-diagnostics.ts
4884
5069
  import { existsSync as existsSync12, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
4885
- import { join as join6, resolve as resolve8 } from "node:path";
5070
+ import { join as join6, resolve as resolve9 } from "node:path";
4886
5071
 
4887
5072
  // ../lsp-core/src/lsp/formatters.ts
4888
5073
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -5037,7 +5222,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
5037
5222
  if (!extension.startsWith(".")) {
5038
5223
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
5039
5224
  }
5040
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
5225
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
5041
5226
  if (!existsSync12(absDir)) {
5042
5227
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
5043
5228
  }
@@ -5394,6 +5579,96 @@ async function executeLspDiagnostics(params, signal) {
5394
5579
  throw error;
5395
5580
  }
5396
5581
  }
5582
+ // ../lsp-core/src/lsp/format-document.ts
5583
+ import { readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
5584
+ var DEFAULT_FORMATTING_OPTIONS = {
5585
+ tabSize: 4,
5586
+ insertSpaces: false,
5587
+ trimTrailingWhitespace: true,
5588
+ insertFinalNewline: true,
5589
+ trimFinalNewlines: true
5590
+ };
5591
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
5592
+ async function formatDocumentWithClient(client, filePath, options = {}) {
5593
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
5594
+ if (edits === null)
5595
+ return { status: "unavailable", reason: "capability_not_advertised" };
5596
+ if (edits.length === 0)
5597
+ return UNCHANGED;
5598
+ const before = readFileSync6(filePath, "utf-8");
5599
+ const normalized = normalizeTextEdits(before, edits, 0);
5600
+ if (normalized.text === before)
5601
+ return UNCHANGED;
5602
+ writeAtomically(filePath, normalized.text);
5603
+ await client.openFile(filePath);
5604
+ return {
5605
+ status: "formatted",
5606
+ ...lineDelta(normalized.edits)
5607
+ };
5608
+ }
5609
+ function lineDelta(edits) {
5610
+ let linesAdded = 0;
5611
+ let linesRemoved = 0;
5612
+ for (const edit of edits) {
5613
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
5614
+ linesAdded += edit.newText.split(`
5615
+ `).length;
5616
+ }
5617
+ return { linesAdded, linesRemoved };
5618
+ }
5619
+ function writeAtomically(filePath, content) {
5620
+ const tempPath = `${filePath}.omo-format.tmp`;
5621
+ writeFileSync3(tempPath, content, "utf-8");
5622
+ try {
5623
+ renameSync3(tempPath, filePath);
5624
+ } catch (error) {
5625
+ try {
5626
+ unlinkSync2(tempPath);
5627
+ } catch {}
5628
+ throw error;
5629
+ }
5630
+ }
5631
+
5632
+ // ../lsp-core/src/tools/format.ts
5633
+ async function executeLspFormat(params, signal) {
5634
+ const filePath = requireString(params, "filePath");
5635
+ try {
5636
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
5637
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
5638
+ } catch (error) {
5639
+ const missingDependency = missingDependencyResult(error, {
5640
+ filePath,
5641
+ status: "unavailable",
5642
+ reason: "server_unavailable",
5643
+ linesAdded: 0,
5644
+ linesRemoved: 0
5645
+ });
5646
+ if (missingDependency)
5647
+ return missingDependency;
5648
+ throw error;
5649
+ }
5650
+ }
5651
+ function formatDetails(filePath, result) {
5652
+ if (result.status === "unavailable") {
5653
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
5654
+ }
5655
+ return {
5656
+ filePath,
5657
+ status: result.status,
5658
+ linesAdded: result.linesAdded,
5659
+ linesRemoved: result.linesRemoved
5660
+ };
5661
+ }
5662
+ function describeResult(filePath, result) {
5663
+ if (result.status === "unavailable") {
5664
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
5665
+ }
5666
+ if (result.status === "unchanged") {
5667
+ return `Already formatted: ${filePath}`;
5668
+ }
5669
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
5670
+ }
5671
+
5397
5672
  // ../lsp-core/src/tools/install-decision.ts
5398
5673
  async function executeLspInstallDecision(params) {
5399
5674
  const serverId = requireString(params, "server_id");
@@ -5726,6 +6001,16 @@ var LSP_MCP_TOOLS = [
5726
6001
  }, ["filePath", "line", "character", "newName"]),
5727
6002
  execute: executeLspRename
5728
6003
  },
6004
+ {
6005
+ name: "format",
6006
+ aliases: ["lsp_format"],
6007
+ title: "LSP Format",
6008
+ description: "Format a source file with its language server and write the returned edits to disk.",
6009
+ inputSchema: objectSchema({
6010
+ filePath: { type: "string", description: "Source file path to format." }
6011
+ }, ["filePath"]),
6012
+ execute: executeLspFormat
6013
+ },
5729
6014
  {
5730
6015
  name: "install_decision",
5731
6016
  aliases: ["lsp_install_decision"],
@@ -5945,6 +6230,9 @@ async function callToolViaDaemon(name, args, options) {
5945
6230
  function callDiagnosticsViaDaemon(filePath, options) {
5946
6231
  return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
5947
6232
  }
6233
+ function callFormatViaDaemon(filePath, options) {
6234
+ return callToolViaDaemon("format", { filePath }, options);
6235
+ }
5948
6236
  function currentRequestContext(env = process.env) {
5949
6237
  const cwd = process.cwd();
5950
6238
  const home = env["HOME"] ?? homedir3();
@@ -5967,7 +6255,7 @@ function withContext(args, context) {
5967
6255
  function ensureDaemonAvailable(paths, ensure, signal) {
5968
6256
  if (!signal)
5969
6257
  return ensure(paths);
5970
- return new Promise((resolve9, reject) => {
6258
+ return new Promise((resolve10, reject) => {
5971
6259
  let settled = false;
5972
6260
  const finish = (run) => {
5973
6261
  if (settled)
@@ -5982,11 +6270,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
5982
6270
  return;
5983
6271
  }
5984
6272
  signal.addEventListener("abort", onAbort, { once: true });
5985
- Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve9()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
6273
+ Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve10()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
5986
6274
  });
5987
6275
  }
5988
6276
  function sendToolCall(paths, token, name, args, options) {
5989
- return new Promise((resolve9, reject) => {
6277
+ return new Promise((resolve10, reject) => {
5990
6278
  const socket = connect(paths.socket);
5991
6279
  const requestId = allocateProxyRequestId();
5992
6280
  let settled = false;
@@ -6039,7 +6327,7 @@ function sendToolCall(paths, token, name, args, options) {
6039
6327
  }
6040
6328
  const result = toToolResult(message, requestId);
6041
6329
  if (result)
6042
- finish(() => resolve9(result));
6330
+ finish(() => resolve10(result));
6043
6331
  else
6044
6332
  finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
6045
6333
  });
@@ -6085,7 +6373,7 @@ function isRetryableTool(name) {
6085
6373
  }
6086
6374
  // src/proxy.ts
6087
6375
  import { existsSync as existsSync13, realpathSync as realpathSync6 } from "node:fs";
6088
- import { basename as basename4, delimiter as delimiter4, dirname as dirname10, isAbsolute as isAbsolute5 } from "node:path";
6376
+ import { basename as basename4, delimiter as delimiter4, dirname as dirname11, isAbsolute as isAbsolute6 } from "node:path";
6089
6377
  var DEFAULT_STARTUP_TIMEOUT_MS = 1e4;
6090
6378
  async function runMcpStdioProxy(options = {}) {
6091
6379
  const input = options.input ?? process.stdin;
@@ -6208,18 +6496,18 @@ function canonicalizePathList(value) {
6208
6496
  return value.split(delimiter4).map((entry) => canonicalizePath(entry) ?? entry).join(delimiter4);
6209
6497
  }
6210
6498
  function canonicalizePath(value) {
6211
- if (value === undefined || !isAbsolute5(value) || !existsSync13(value))
6499
+ if (value === undefined || !isAbsolute6(value) || !existsSync13(value))
6212
6500
  return value;
6213
6501
  return realpathSync6(value);
6214
6502
  }
6215
6503
  function projectRootFromOpenCodeConfigPath(path2) {
6216
6504
  if (basename4(path2) !== "lsp.json" && basename4(path2) !== "lsp-client.json")
6217
6505
  return;
6218
- const configDir = dirname10(path2);
6506
+ const configDir = dirname11(path2);
6219
6507
  const configDirName = basename4(configDir);
6220
6508
  if (configDirName !== ".opencode" && configDirName !== ".omo")
6221
6509
  return;
6222
- return dirname10(configDir);
6510
+ return dirname11(configDir);
6223
6511
  }
6224
6512
  export {
6225
6513
  InvalidDaemonDirectoryError,