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
@@ -8,11 +8,13 @@ import { argv, execPath as execPath2, stderr } from "node:process";
8
8
  import { stdin as processStdin } from "node:process";
9
9
 
10
10
  // src/codex-hook.ts
11
- import { readFileSync as readFileSync9, realpathSync as realpathSync8 } from "node:fs";
11
+ import { readFileSync as readFileSync10, realpathSync as realpathSync8 } from "node:fs";
12
12
  import { homedir as homedir3 } from "node:os";
13
- import { join as join12, resolve as resolve11 } from "node:path";
13
+ import { join as join12, resolve as resolve12 } from "node:path";
14
14
 
15
15
  // ../../../../lsp-daemon/dist/client.js
16
+ import { statSync as statSync5 } from "node:fs";
17
+ import { isAbsolute as isAbsolute6 } from "node:path";
16
18
  import { connect } from "node:net";
17
19
  import { AsyncLocalStorage } from "node:async_hooks";
18
20
  import { existsSync, realpathSync, statSync } from "node:fs";
@@ -43,7 +45,7 @@ import { fileURLToPath } from "node:url";
43
45
  import { statSync as statSync2 } from "node:fs";
44
46
  import { isAbsolute as isAbsolute2 } from "node:path";
45
47
  import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
46
- import { basename as basename3, dirname as dirname9, join as join5, resolve as resolve7 } from "node:path";
48
+ import { basename as basename3, dirname as dirname10, join as join5, resolve as resolve8 } from "node:path";
47
49
  import { basename as basename2, extname } from "node:path";
48
50
  import { resolve as resolve6 } from "node:path";
49
51
  import { pathToFileURL as pathToFileURL3 } from "node:url";
@@ -68,14 +70,13 @@ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as rea
68
70
  import { dirname as dirname8 } from "node:path";
69
71
  import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
70
72
  import { existsSync as existsSync10 } from "node:fs";
71
- import { delimiter as delimiter3, join as join4 } from "node:path";
73
+ import { delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
72
74
  import { existsSync as existsSync12, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
73
- import { join as join6, resolve as resolve8 } from "node:path";
75
+ import { join as join6, resolve as resolve9 } from "node:path";
74
76
  import { fileURLToPath as fileURLToPath3 } from "node:url";
75
77
  import { lstatSync as lstatSync6, readdirSync as readdirSync4 } from "node:fs";
76
78
  import { join as join7 } from "node:path";
77
- import { statSync as statSync5 } from "node:fs";
78
- import { isAbsolute as isAbsolute5 } from "node:path";
79
+ import { readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
79
80
 
80
81
  class LspRequestContextParseError extends Error {
81
82
  constructor(code, message) {
@@ -762,6 +763,7 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
762
763
  var REQUEST_TIMEOUT_MS = 15000;
763
764
  var INIT_TIMEOUT_MS = 60000;
764
765
  var IDLE_TIMEOUT_MS = 5 * 60000;
766
+ var MAX_RESIDENT_CLIENTS = 6;
765
767
  var REAPER_INTERVAL_MS = 60000;
766
768
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
767
769
  var STOP_SIGKILL_GRACE_MS = 1000;
@@ -1277,6 +1279,7 @@ class LspClientTransport {
1277
1279
  this.diagnosticsStore = new Map;
1278
1280
  this.workspaceApplyEditHandler = null;
1279
1281
  this.diagnosticPullSupported = false;
1282
+ this.documentFormattingSupported = false;
1280
1283
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
1281
1284
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
1282
1285
  }
@@ -1298,6 +1301,12 @@ class LspClientTransport {
1298
1301
  isDiagnosticPullSupported() {
1299
1302
  return this.diagnosticPullSupported;
1300
1303
  }
1304
+ setDocumentFormattingSupported(supported) {
1305
+ this.documentFormattingSupported = supported;
1306
+ }
1307
+ isDocumentFormattingSupported() {
1308
+ return this.documentFormattingSupported;
1309
+ }
1301
1310
  handlePublishDiagnostics(params) {
1302
1311
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
1303
1312
  }
@@ -1509,6 +1518,14 @@ function supportsDiagnosticPull(capabilities) {
1509
1518
  return false;
1510
1519
  return Object.hasOwn(capabilities, "diagnosticProvider");
1511
1520
  }
1521
+ function supportsDocumentFormatting(capabilities) {
1522
+ if (capabilities === undefined)
1523
+ return false;
1524
+ const provider = capabilities.documentFormattingProvider;
1525
+ if (provider === undefined || provider === null || provider === false)
1526
+ return false;
1527
+ return provider === true || typeof provider === "object";
1528
+ }
1512
1529
 
1513
1530
  class LspClientConnection extends LspClientTransport {
1514
1531
  async initialize() {
@@ -1525,6 +1542,7 @@ class LspClientConnection extends LspClientTransport {
1525
1542
  references: {},
1526
1543
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
1527
1544
  publishDiagnostics: {},
1545
+ formatting: { dynamicRegistration: false },
1528
1546
  rename: {
1529
1547
  prepareSupport: true,
1530
1548
  prepareSupportDefaultBehavior: 1
@@ -1566,6 +1584,7 @@ class LspClientConnection extends LspClientTransport {
1566
1584
  initializationOptions: this.server.initialization
1567
1585
  }, { timeoutMs: this.initializeTimeoutMs });
1568
1586
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
1587
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
1569
1588
  await this.sendNotification("initialized", {});
1570
1589
  await this.sendNotification("workspace/didChangeConfiguration", {
1571
1590
  settings: { json: { validate: { enable: true } } }
@@ -3104,6 +3123,18 @@ class LspClient extends LspClientConnection {
3104
3123
  textDocument: { uri: pathToFileURL3(absPath).href }
3105
3124
  }, options);
3106
3125
  }
3126
+ async formatDocument(filePath, options, signal) {
3127
+ if (!this.isDocumentFormattingSupported())
3128
+ return null;
3129
+ const absPath = this.resolveWorkspacePath(filePath);
3130
+ await this.openFile(absPath);
3131
+ const requestOptions = signal === undefined ? {} : { signal };
3132
+ const edits = await this.sendRequest("textDocument/formatting", {
3133
+ textDocument: { uri: pathToFileURL3(absPath).href },
3134
+ options
3135
+ }, requestOptions);
3136
+ return edits ?? [];
3137
+ }
3107
3138
  async workspaceSymbols(query, signal) {
3108
3139
  const options = signal === undefined ? {} : { signal };
3109
3140
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -3352,6 +3383,7 @@ class LspManager {
3352
3383
  this.disposed = false;
3353
3384
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
3354
3385
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
3386
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
3355
3387
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
3356
3388
  this.clientFactory = options.clientFactory ?? ((root, server2) => new LspClient(root, server2));
3357
3389
  this.now = options.now ?? (() => Date.now());
@@ -3385,6 +3417,26 @@ class LspManager {
3385
3417
  }
3386
3418
  }
3387
3419
  }
3420
+ evictForAdmission() {
3421
+ while (this.clients.size >= this.maxResidentClients) {
3422
+ const victim = this.leastRecentlyUsedIdleClient();
3423
+ if (!victim)
3424
+ return;
3425
+ this.clients.delete(victim.key);
3426
+ stopClientBestEffort(victim.managed.client);
3427
+ }
3428
+ }
3429
+ leastRecentlyUsedIdleClient() {
3430
+ let candidate = null;
3431
+ for (const [key, managed] of this.clients) {
3432
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
3433
+ continue;
3434
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
3435
+ candidate = { key, managed };
3436
+ }
3437
+ }
3438
+ return candidate;
3439
+ }
3388
3440
  async tryDeleteIfOrphaned(key, managed) {
3389
3441
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
3390
3442
  this.clients.delete(key);
@@ -3431,6 +3483,7 @@ class LspManager {
3431
3483
  managed.lastUsedAt = this.now();
3432
3484
  return managed.client;
3433
3485
  }
3486
+ this.evictForAdmission();
3434
3487
  const client = this.clientFactory(root, server2);
3435
3488
  const initStartedAt = this.now();
3436
3489
  const initPromise = (async () => {
@@ -3493,6 +3546,7 @@ class LspManager {
3493
3546
  const key = this.getKey(root, server2.id);
3494
3547
  if (this.clients.has(key))
3495
3548
  return;
3549
+ this.evictForAdmission();
3496
3550
  const client = this.clientFactory(root, server2);
3497
3551
  const initStartedAt = this.now();
3498
3552
  const initPromise = (async () => {
@@ -3602,50 +3656,6 @@ function nearestExistingAncestor(directory) {
3602
3656
  }
3603
3657
  return current;
3604
3658
  }
3605
- function getInstallDecisionsPath() {
3606
- return lspRequestContext().installDecisionsPath;
3607
- }
3608
- function loadInstallDecisions() {
3609
- const path2 = getInstallDecisionsPath();
3610
- if (!existsSync8(path2))
3611
- return {};
3612
- try {
3613
- const parsed = JSON.parse(readFileSync4(path2, "utf8"));
3614
- return isInstallDecisions(parsed) ? parsed : {};
3615
- } catch {
3616
- return {};
3617
- }
3618
- }
3619
- function loadInstallDecision(serverId) {
3620
- return loadInstallDecisions()[serverId];
3621
- }
3622
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3623
- const decisions = loadInstallDecisions();
3624
- decisions[serverId] = { decision, decidedAt };
3625
- writeInstallDecisions(decisions);
3626
- }
3627
- function isInstallDecision(value) {
3628
- return value === "declined" || value === "allowed";
3629
- }
3630
- function writeInstallDecisions(decisions) {
3631
- const path2 = getInstallDecisionsPath();
3632
- mkdirSync3(dirname8(path2), { recursive: true });
3633
- const tmpPath = `${path2}.tmp`;
3634
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3635
- `, "utf8");
3636
- renameSync2(tmpPath, path2);
3637
- }
3638
- function isInstallDecisions(value) {
3639
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3640
- }
3641
- function isInstallDecisionRecord(value) {
3642
- if (!isRecord5(value))
3643
- return false;
3644
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3645
- }
3646
- function isRecord5(value) {
3647
- return typeof value === "object" && value !== null && !Array.isArray(value);
3648
- }
3649
3659
  var LSP_INSTALL_HINTS = {
3650
3660
  typescript: "npm install -g typescript-language-server typescript",
3651
3661
  deno: "Install Deno from https://deno.land",
@@ -3690,6 +3700,26 @@ var LSP_INSTALL_HINTS = {
3690
3700
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
3691
3701
  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"
3692
3702
  };
3703
+ var LSP_LOCAL_INSTALL_HINTS = {
3704
+ typescript: "bun add -d typescript-language-server typescript",
3705
+ vue: "bun add -d @vue/language-server",
3706
+ eslint: "bun add -d vscode-langservers-extracted",
3707
+ oxlint: "bun add -d oxlint",
3708
+ biome: "bun add -d @biomejs/biome",
3709
+ svelte: "bun add -d svelte-language-server",
3710
+ astro: "bun add -d @astrojs/language-server",
3711
+ bash: "bun add -d bash-language-server",
3712
+ "bash-ls": "bun add -d bash-language-server",
3713
+ "yaml-ls": "bun add -d yaml-language-server",
3714
+ php: "bun add -d intelephense",
3715
+ prisma: "bun add -d prisma",
3716
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
3717
+ pyright: "uv add --dev pyright",
3718
+ basedpyright: "uv add --dev basedpyright",
3719
+ ruff: "uv add --dev ruff",
3720
+ ty: "uv add --dev ty",
3721
+ "ruby-lsp": "bundle add ruby-lsp --group development"
3722
+ };
3693
3723
  var BUILTIN_SERVERS = {
3694
3724
  typescript: {
3695
3725
  command: ["typescript-language-server", "--stdio"],
@@ -3791,6 +3821,50 @@ var BUILTIN_SERVERS = {
3791
3821
  extensions: [".razor", ".cshtml"]
3792
3822
  }
3793
3823
  };
3824
+ function getInstallDecisionsPath() {
3825
+ return lspRequestContext().installDecisionsPath;
3826
+ }
3827
+ function loadInstallDecisions() {
3828
+ const path2 = getInstallDecisionsPath();
3829
+ if (!existsSync8(path2))
3830
+ return {};
3831
+ try {
3832
+ const parsed = JSON.parse(readFileSync4(path2, "utf8"));
3833
+ return isInstallDecisions(parsed) ? parsed : {};
3834
+ } catch {
3835
+ return {};
3836
+ }
3837
+ }
3838
+ function loadInstallDecision(serverId) {
3839
+ return loadInstallDecisions()[serverId];
3840
+ }
3841
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3842
+ const decisions = loadInstallDecisions();
3843
+ decisions[serverId] = { decision, decidedAt };
3844
+ writeInstallDecisions(decisions);
3845
+ }
3846
+ function isInstallDecision(value) {
3847
+ return value === "declined" || value === "allowed";
3848
+ }
3849
+ function writeInstallDecisions(decisions) {
3850
+ const path2 = getInstallDecisionsPath();
3851
+ mkdirSync3(dirname8(path2), { recursive: true });
3852
+ const tmpPath = `${path2}.tmp`;
3853
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3854
+ `, "utf8");
3855
+ renameSync2(tmpPath, path2);
3856
+ }
3857
+ function isInstallDecisions(value) {
3858
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3859
+ }
3860
+ function isInstallDecisionRecord(value) {
3861
+ if (!isRecord5(value))
3862
+ return false;
3863
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3864
+ }
3865
+ function isRecord5(value) {
3866
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3867
+ }
3794
3868
  function getProjectConfigPaths() {
3795
3869
  return lspRequestContext().projectConfigPaths;
3796
3870
  }
@@ -3984,50 +4058,151 @@ function getDisabledServerIds() {
3984
4058
  }
3985
4059
  return disabled;
3986
4060
  }
3987
- function isServerInstalled(command, _workingDirectory) {
3988
- if (command.length === 0)
3989
- return false;
3990
- const [cmd] = command;
3991
- if (!cmd)
3992
- return false;
3993
- if (cmd.includes("/") || cmd.includes("\\")) {
3994
- if (existsSync10(cmd))
3995
- return true;
4061
+ var LOCAL_BIN_RULES = [
4062
+ {
4063
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
4064
+ binDirs: [join4("node_modules", ".bin")]
4065
+ },
4066
+ {
4067
+ markers: [
4068
+ "pyproject.toml",
4069
+ "ty.toml",
4070
+ "requirements.txt",
4071
+ "setup.py",
4072
+ "setup.cfg",
4073
+ "Pipfile",
4074
+ "pyrightconfig.json",
4075
+ "ruff.toml",
4076
+ ".ruff.toml"
4077
+ ],
4078
+ binDirs: [
4079
+ join4(".venv", "bin"),
4080
+ join4(".venv", "Scripts"),
4081
+ join4("venv", "bin"),
4082
+ join4("venv", "Scripts"),
4083
+ join4(".env", "bin"),
4084
+ join4(".env", "Scripts")
4085
+ ]
4086
+ },
4087
+ {
4088
+ markers: ["Gemfile", "Gemfile.lock"],
4089
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
4090
+ },
4091
+ {
4092
+ markers: ["go.mod", "go.sum", "go.work"],
4093
+ binDirs: ["bin"]
4094
+ }
4095
+ ];
4096
+ var resolutionCache = new Map;
4097
+ var probeCount = 0;
4098
+ function probe(path2) {
4099
+ probeCount += 1;
4100
+ return existsSync10(path2);
4101
+ }
4102
+ function executableSuffixes(platform, pathExt) {
4103
+ if (platform !== "win32")
4104
+ return [""];
4105
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
4106
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
4107
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4108
+ }
4109
+ function probeWithSuffixes(directory, command, suffixes) {
4110
+ for (const suffix of suffixes) {
4111
+ const candidate = join4(directory, command + suffix);
4112
+ if (probe(candidate))
4113
+ return candidate;
3996
4114
  }
3997
- const isWindows = process.platform === "win32";
3998
- let exts = [""];
3999
- if (isWindows) {
4000
- const pathExt = process.env["PATHEXT"] ?? "";
4001
- if (pathExt) {
4002
- const systemExts = pathExt.split(";").filter(Boolean);
4003
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4004
- } else {
4005
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
4115
+ return null;
4116
+ }
4117
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
4118
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
4119
+ let current = resolve7(workingDirectory);
4120
+ while (true) {
4121
+ for (const rule of LOCAL_BIN_RULES) {
4122
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
4123
+ continue;
4124
+ for (const binDir of rule.binDirs) {
4125
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
4126
+ if (found !== null)
4127
+ return found;
4128
+ }
4006
4129
  }
4130
+ if (probe(join4(current, ".git")))
4131
+ return null;
4132
+ if (boundary !== undefined && current === boundary)
4133
+ return null;
4134
+ const parent = dirname9(current);
4135
+ if (parent === current)
4136
+ return null;
4137
+ current = parent;
4007
4138
  }
4008
- let pathEnv = process.env["PATH"] ?? "";
4009
- if (isWindows && !pathEnv) {
4139
+ }
4140
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
4141
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
4142
+ if (platform === "win32" && !pathEnv) {
4010
4143
  pathEnv = process.env["Path"] ?? "";
4011
4144
  }
4012
- const paths = pathEnv.split(delimiter3);
4013
- for (const p of paths) {
4014
- for (const suffix of exts) {
4015
- if (existsSync10(join4(p, cmd + suffix))) {
4016
- return true;
4017
- }
4018
- }
4145
+ for (const entry of pathEnv.split(delimiter3)) {
4146
+ if (entry.length === 0)
4147
+ continue;
4148
+ const found = probeWithSuffixes(entry, command, suffixes);
4149
+ if (found !== null)
4150
+ return found;
4019
4151
  }
4020
- if (cmd === "node")
4021
- return true;
4022
- return false;
4152
+ return null;
4153
+ }
4154
+ function resolveServerBinary(command, workingDirectory, options = {}) {
4155
+ if (command.length === 0)
4156
+ return null;
4157
+ const [cmd] = command;
4158
+ if (cmd === undefined || cmd.length === 0)
4159
+ return null;
4160
+ const platform = options.platform ?? process.platform;
4161
+ const suffixes = executableSuffixes(platform, options.pathExt);
4162
+ if (cmd.includes("/") || cmd.includes("\\")) {
4163
+ const explicit = isAbsolute5(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
4164
+ return probe(explicit) ? explicit : null;
4165
+ }
4166
+ const cacheKey = JSON.stringify([
4167
+ workingDirectory ?? "",
4168
+ cmd,
4169
+ platform,
4170
+ options.stopAt ?? "",
4171
+ options.pathExt ?? "",
4172
+ options.pathEnv ?? process.env["PATH"] ?? ""
4173
+ ]);
4174
+ const cached = resolutionCache.get(cacheKey);
4175
+ if (cached !== undefined)
4176
+ return cached;
4177
+ let resolved = null;
4178
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
4179
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
4180
+ }
4181
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
4182
+ if (resolved === null && cmd === "node")
4183
+ resolved = cmd;
4184
+ resolutionCache.set(cacheKey, resolved);
4185
+ return resolved;
4186
+ }
4187
+ function isServerInstalled(command, workingDirectory, options = {}) {
4188
+ if (command.length === 0)
4189
+ return false;
4190
+ return resolveServerBinary(command, workingDirectory, options) !== null;
4191
+ }
4192
+ function withResolvedCommand(command, binaryPath) {
4193
+ return [binaryPath, ...command.slice(1)];
4023
4194
  }
4024
4195
  function findServerForExtension(ext) {
4025
4196
  const servers = getMergedServers();
4197
+ const workingDirectory = contextCwd();
4026
4198
  for (const server2 of servers) {
4027
- if (server2.extensions.includes(ext) && isServerInstalled(server2.command)) {
4199
+ if (!server2.extensions.includes(ext))
4200
+ continue;
4201
+ const binaryPath = resolveServerBinary(server2.command, workingDirectory);
4202
+ if (binaryPath !== null) {
4028
4203
  const resolvedServer = {
4029
4204
  id: server2.id,
4030
- command: server2.command,
4205
+ command: withResolvedCommand(server2.command, binaryPath),
4031
4206
  extensions: server2.extensions,
4032
4207
  priority: server2.priority
4033
4208
  };
@@ -4074,6 +4249,7 @@ function findServerForExtension(ext) {
4074
4249
  function getAllServers() {
4075
4250
  const servers = getMergedServers();
4076
4251
  const disabled = getDisabledServerIds();
4252
+ const workingDirectory = contextCwd();
4077
4253
  const result = [];
4078
4254
  const seen = new Set;
4079
4255
  for (const server2 of servers) {
@@ -4081,7 +4257,7 @@ function getAllServers() {
4081
4257
  continue;
4082
4258
  result.push({
4083
4259
  id: server2.id,
4084
- installed: isServerInstalled(server2.command),
4260
+ installed: isServerInstalled(server2.command, workingDirectory),
4085
4261
  extensions: server2.extensions,
4086
4262
  disabled: false,
4087
4263
  source: server2.source,
@@ -4095,7 +4271,7 @@ function getAllServers() {
4095
4271
  const builtin = BUILTIN_SERVERS[id];
4096
4272
  result.push({
4097
4273
  id,
4098
- installed: builtin ? isServerInstalled(builtin.command) : false,
4274
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
4099
4275
  extensions: builtin?.extensions ?? [],
4100
4276
  disabled: true,
4101
4277
  source: "disabled",
@@ -4116,7 +4292,7 @@ function findWorkspaceRoot(filePath) {
4116
4292
  const abs = resolveReadablePathInsideContext(filePath);
4117
4293
  let dir = abs;
4118
4294
  if (!isDirectoryPath(dir)) {
4119
- dir = dirname9(dir);
4295
+ dir = dirname10(dir);
4120
4296
  }
4121
4297
  if (!isPathInside(cwd, abs))
4122
4298
  return findWorkspaceRootOutsideContext(dir);
@@ -4132,13 +4308,13 @@ function findWorkspaceRoot(filePath) {
4132
4308
  }
4133
4309
  if (dir === cwd)
4134
4310
  break;
4135
- dir = dirname9(dir);
4311
+ dir = dirname10(dir);
4136
4312
  }
4137
4313
  return fallbackRoot;
4138
4314
  }
4139
4315
  function resolveReadablePathInsideContext(filePath) {
4140
4316
  const cwd = contextCwd();
4141
- const abs = resolve7(cwd, filePath);
4317
+ const abs = resolve8(cwd, filePath);
4142
4318
  if (isPathInside(cwd, abs))
4143
4319
  return abs;
4144
4320
  const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
@@ -4164,7 +4340,7 @@ function rebaseThroughCanonicalAncestor(path2, cwd) {
4164
4340
  if (isPathInside(cwd, canonical))
4165
4341
  return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
4166
4342
  }
4167
- const parent = dirname9(current);
4343
+ const parent = dirname10(current);
4168
4344
  if (parent === current)
4169
4345
  return;
4170
4346
  suffix.unshift(basename3(current));
@@ -4187,7 +4363,7 @@ function nearestExistingDirectoryInsideContext(directory, cwd) {
4187
4363
  return canonical;
4188
4364
  if (current === cwd)
4189
4365
  return;
4190
- current = dirname9(current);
4366
+ current = dirname10(current);
4191
4367
  }
4192
4368
  return;
4193
4369
  }
@@ -4214,6 +4390,19 @@ function formatServerLookupError(result) {
4214
4390
  ].join(`
4215
4391
  `);
4216
4392
  }
4393
+ function formatInstallOptions(serverId, installHint) {
4394
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
4395
+ if (localHint === undefined) {
4396
+ return ["To install, run:", ` ${installHint}`];
4397
+ }
4398
+ return [
4399
+ "To install in THIS repository (preferred — no global install needed):",
4400
+ ` ${localHint}`,
4401
+ "",
4402
+ "Or install it globally:",
4403
+ ` ${installHint}`
4404
+ ];
4405
+ }
4217
4406
  function formatNotInstalled(result) {
4218
4407
  const { server: server2, installHint } = result;
4219
4408
  const extensions = server2.extensions.join(", ");
@@ -4228,19 +4417,19 @@ function formatNotInstalled(result) {
4228
4417
  `Command not found: ${server2.command[0]}`,
4229
4418
  ""
4230
4419
  ];
4420
+ const installOptions = formatInstallOptions(server2.id, installHint);
4231
4421
  if (decision === "allowed") {
4232
4422
  return [
4233
4423
  ...header,
4234
4424
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
4235
- ` ${installHint}`
4425
+ ...installOptions.slice(1)
4236
4426
  ].join(`
4237
4427
  `);
4238
4428
  }
4239
4429
  if (!context.capabilities.installDecisionTool) {
4240
4430
  return [
4241
4431
  ...header,
4242
- "To install, run:",
4243
- ` ${installHint}`,
4432
+ ...installOptions,
4244
4433
  "",
4245
4434
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4246
4435
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -4249,8 +4438,7 @@ function formatNotInstalled(result) {
4249
4438
  }
4250
4439
  return [
4251
4440
  ...header,
4252
- "To install, run:",
4253
- ` ${installHint}`,
4441
+ ...installOptions,
4254
4442
  "",
4255
4443
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4256
4444
  "- If the user agrees: run the install command above, then retry this tool.",
@@ -4452,7 +4640,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4452
4640
  if (!extension.startsWith(".")) {
4453
4641
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4454
4642
  }
4455
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4643
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
4456
4644
  if (!existsSync12(absDir)) {
4457
4645
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4458
4646
  }
@@ -4793,6 +4981,91 @@ async function executeLspDiagnostics(params, signal) {
4793
4981
  throw error;
4794
4982
  }
4795
4983
  }
4984
+ var DEFAULT_FORMATTING_OPTIONS = {
4985
+ tabSize: 4,
4986
+ insertSpaces: false,
4987
+ trimTrailingWhitespace: true,
4988
+ insertFinalNewline: true,
4989
+ trimFinalNewlines: true
4990
+ };
4991
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
4992
+ async function formatDocumentWithClient(client, filePath, options = {}) {
4993
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
4994
+ if (edits === null)
4995
+ return { status: "unavailable", reason: "capability_not_advertised" };
4996
+ if (edits.length === 0)
4997
+ return UNCHANGED;
4998
+ const before = readFileSync6(filePath, "utf-8");
4999
+ const normalized = normalizeTextEdits(before, edits, 0);
5000
+ if (normalized.text === before)
5001
+ return UNCHANGED;
5002
+ writeAtomically(filePath, normalized.text);
5003
+ await client.openFile(filePath);
5004
+ return {
5005
+ status: "formatted",
5006
+ ...lineDelta(normalized.edits)
5007
+ };
5008
+ }
5009
+ function lineDelta(edits) {
5010
+ let linesAdded = 0;
5011
+ let linesRemoved = 0;
5012
+ for (const edit of edits) {
5013
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
5014
+ linesAdded += edit.newText.split(`
5015
+ `).length;
5016
+ }
5017
+ return { linesAdded, linesRemoved };
5018
+ }
5019
+ function writeAtomically(filePath, content) {
5020
+ const tempPath = `${filePath}.omo-format.tmp`;
5021
+ writeFileSync3(tempPath, content, "utf-8");
5022
+ try {
5023
+ renameSync3(tempPath, filePath);
5024
+ } catch (error) {
5025
+ try {
5026
+ unlinkSync2(tempPath);
5027
+ } catch {}
5028
+ throw error;
5029
+ }
5030
+ }
5031
+ async function executeLspFormat(params, signal) {
5032
+ const filePath = requireString(params, "filePath");
5033
+ try {
5034
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
5035
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
5036
+ } catch (error) {
5037
+ const missingDependency = missingDependencyResult(error, {
5038
+ filePath,
5039
+ status: "unavailable",
5040
+ reason: "server_unavailable",
5041
+ linesAdded: 0,
5042
+ linesRemoved: 0
5043
+ });
5044
+ if (missingDependency)
5045
+ return missingDependency;
5046
+ throw error;
5047
+ }
5048
+ }
5049
+ function formatDetails(filePath, result) {
5050
+ if (result.status === "unavailable") {
5051
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
5052
+ }
5053
+ return {
5054
+ filePath,
5055
+ status: result.status,
5056
+ linesAdded: result.linesAdded,
5057
+ linesRemoved: result.linesRemoved
5058
+ };
5059
+ }
5060
+ function describeResult(filePath, result) {
5061
+ if (result.status === "unavailable") {
5062
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
5063
+ }
5064
+ if (result.status === "unchanged") {
5065
+ return `Already formatted: ${filePath}`;
5066
+ }
5067
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
5068
+ }
4796
5069
  async function executeLspInstallDecision(params) {
4797
5070
  const serverId = requireString(params, "server_id");
4798
5071
  const decision = params["decision"];
@@ -5112,6 +5385,16 @@ var LSP_MCP_TOOLS = [
5112
5385
  }, ["filePath", "line", "character", "newName"]),
5113
5386
  execute: executeLspRename
5114
5387
  },
5388
+ {
5389
+ name: "format",
5390
+ aliases: ["lsp_format"],
5391
+ title: "LSP Format",
5392
+ description: "Format a source file with its language server and write the returned edits to disk.",
5393
+ inputSchema: objectSchema({
5394
+ filePath: { type: "string", description: "Source file path to format." }
5395
+ }, ["filePath"]),
5396
+ execute: executeLspFormat
5397
+ },
5115
5398
  {
5116
5399
  name: "install_decision",
5117
5400
  aliases: ["lsp_install_decision"],
@@ -5178,7 +5461,7 @@ function withContext(args, context) {
5178
5461
  function ensureDaemonAvailable(paths, ensure, signal) {
5179
5462
  if (!signal)
5180
5463
  return ensure(paths);
5181
- return new Promise((resolve9, reject) => {
5464
+ return new Promise((resolve10, reject) => {
5182
5465
  let settled = false;
5183
5466
  const finish = (run) => {
5184
5467
  if (settled)
@@ -5193,11 +5476,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
5193
5476
  return;
5194
5477
  }
5195
5478
  signal.addEventListener("abort", onAbort, { once: true });
5196
- Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve9()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
5479
+ Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve10()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
5197
5480
  });
5198
5481
  }
5199
5482
  function sendToolCall(paths, token, name, args, options) {
5200
- return new Promise((resolve9, reject) => {
5483
+ return new Promise((resolve10, reject) => {
5201
5484
  const socket = connect(paths.socket);
5202
5485
  const requestId = allocateProxyRequestId();
5203
5486
  let settled = false;
@@ -5250,7 +5533,7 @@ function sendToolCall(paths, token, name, args, options) {
5250
5533
  }
5251
5534
  const result = toToolResult(message, requestId);
5252
5535
  if (result)
5253
- finish(() => resolve9(result));
5536
+ finish(() => resolve10(result));
5254
5537
  else
5255
5538
  finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
5256
5539
  });
@@ -5321,12 +5604,12 @@ function resolveDaemonRuntime2(env, defaults) {
5321
5604
  throw new InvalidRuntimeOverrideError2("paired_values_required", `${OMO_LSP_DAEMON_CLI2} and ${OMO_LSP_DAEMON_VERSION2} must be set together`);
5322
5605
  }
5323
5606
  if (!hasCliOverride || !hasVersionOverride) {
5324
- if (!isAbsolute5(defaults.cliPath)) {
5607
+ if (!isAbsolute6(defaults.cliPath)) {
5325
5608
  throw new InvalidRuntimeOverrideError2("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
5326
5609
  }
5327
5610
  return { cliPath: defaults.cliPath, version: validateDaemonVersion2(defaults.version) };
5328
5611
  }
5329
- if (!isAbsolute5(cliOverride)) {
5612
+ if (!isAbsolute6(cliOverride)) {
5330
5613
  throw new InvalidRuntimeOverrideError2("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI2} must be an absolute path to an existing regular file`);
5331
5614
  }
5332
5615
  const stat = statSync5(cliOverride, { throwIfNoEntry: false });
@@ -5448,7 +5731,7 @@ function extensionKey(filePath) {
5448
5731
  // ../../../../lsp-core/src/request-context.ts
5449
5732
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
5450
5733
  import { existsSync as existsSync13, realpathSync as realpathSync6, statSync as statSync6 } from "node:fs";
5451
- import { basename as basename4, delimiter as delimiter4, dirname as dirname2, isAbsolute as isAbsolute6, join as join8, relative as relative5, resolve as resolve9 } from "node:path";
5734
+ import { basename as basename4, delimiter as delimiter4, dirname as dirname2, isAbsolute as isAbsolute7, join as join8, relative as relative5, resolve as resolve10 } from "node:path";
5452
5735
 
5453
5736
  class LspRequestContextParseError2 extends Error {
5454
5737
  constructor(code, message) {
@@ -5489,14 +5772,14 @@ function parseLspRequestContext2(value) {
5489
5772
  };
5490
5773
  }
5491
5774
  function canonicalCwd2(cwd) {
5492
- const resolved = resolve9(cwd);
5775
+ const resolved = resolve10(cwd);
5493
5776
  if (!existsSync13(resolved) || !statSync6(resolved).isDirectory()) {
5494
5777
  throw new LspRequestContextParseError2("invalid_cwd", `LSP request cwd must be an existing directory: ${cwd}`);
5495
5778
  }
5496
5779
  return realpathSync6(resolved);
5497
5780
  }
5498
5781
  function canonicalizeExistingOrNearestAncestor2(path2) {
5499
- let current = resolve9(path2);
5782
+ let current = resolve10(path2);
5500
5783
  const suffix = [];
5501
5784
  while (true) {
5502
5785
  try {
@@ -5539,14 +5822,14 @@ function stringArrayField2(value, field) {
5539
5822
  return fieldValue;
5540
5823
  }
5541
5824
  function requireAbsolutePath2(path2, field) {
5542
- if (!isAbsolute6(path2)) {
5825
+ if (!isAbsolute7(path2)) {
5543
5826
  throw new LspRequestContextParseError2("relative_path", `LSP request context.${field} must be absolute: ${path2}`);
5544
5827
  }
5545
5828
  }
5546
5829
  function isPathInside2(parent, child) {
5547
- const childPath = resolve9(child);
5830
+ const childPath = resolve10(child);
5548
5831
  const relativePath = relative5(parent, childPath);
5549
- return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute6(relativePath);
5832
+ return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute7(relativePath);
5550
5833
  }
5551
5834
  function isMissingPathError2(error) {
5552
5835
  const code = errorCode2(error);
@@ -5569,9 +5852,9 @@ function errorCode2(error) {
5569
5852
  }
5570
5853
 
5571
5854
  // src/daemon-cli-path.ts
5572
- import { existsSync as existsSync15, readFileSync as readFileSync6 } from "node:fs";
5855
+ import { existsSync as existsSync15, readFileSync as readFileSync7 } from "node:fs";
5573
5856
  import { createRequire as createRequire2 } from "node:module";
5574
- import { dirname as dirname10, join as join10 } from "node:path";
5857
+ import { dirname as dirname11, join as join10 } from "node:path";
5575
5858
  import { fileURLToPath as fileURLToPath4 } from "node:url";
5576
5859
  var requireFromHere2 = createRequire2(import.meta.url);
5577
5860
  var PACKAGE_LSP_DAEMON_CLI = "@code-yeongyu/lsp-daemon/cli";
@@ -5618,7 +5901,7 @@ function resolveConfiguredLspDaemonCli(cliPath) {
5618
5901
  }
5619
5902
  function readDaemonPackageVersion(cliPath) {
5620
5903
  try {
5621
- const parsed = JSON.parse(readFileSync6(join10(dirname10(cliPath), "package.json"), "utf8"));
5904
+ const parsed = JSON.parse(readFileSync7(join10(dirname11(cliPath), "package.json"), "utf8"));
5622
5905
  if (isRecord9(parsed) && typeof parsed["version"] === "string" && parsed["version"].length > 0) {
5623
5906
  return parsed["version"];
5624
5907
  }
@@ -5633,9 +5916,9 @@ function isRecord9(value) {
5633
5916
  }
5634
5917
 
5635
5918
  // src/lsp-session-state.ts
5636
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "node:fs";
5919
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "node:fs";
5637
5920
  import { homedir } from "node:os";
5638
- import { dirname as dirname12, join as join11 } from "node:path";
5921
+ import { dirname as dirname13, join as join11 } from "node:path";
5639
5922
  function sessionIdFrom(input) {
5640
5923
  return typeof input.session_id === "string" && input.session_id.length > 0 ? input.session_id : undefined;
5641
5924
  }
@@ -5666,7 +5949,7 @@ function sessionStatePath(sessionId) {
5666
5949
  }
5667
5950
  function readSessionState(path2) {
5668
5951
  try {
5669
- const parsed = JSON.parse(readFileSync8(path2, "utf8"));
5952
+ const parsed = JSON.parse(readFileSync9(path2, "utf8"));
5670
5953
  if (isRecord10(parsed) && isLspSessionState(parsed))
5671
5954
  return normalizeSessionState(parsed);
5672
5955
  return emptyState();
@@ -5677,8 +5960,8 @@ function readSessionState(path2) {
5677
5960
  }
5678
5961
  }
5679
5962
  function writeSessionState(path2, state) {
5680
- mkdirSync4(dirname12(path2), { recursive: true });
5681
- writeFileSync3(path2, `${JSON.stringify(state)}
5963
+ mkdirSync4(dirname13(path2), { recursive: true });
5964
+ writeFileSync4(path2, `${JSON.stringify(state)}
5682
5965
  `);
5683
5966
  }
5684
5967
  function emptyState() {
@@ -5821,8 +6104,8 @@ function notConfiguredAvailability(details) {
5821
6104
  return typeof extension === "string" && extension.length > 0 ? { extension } : undefined;
5822
6105
  }
5823
6106
  function codexLspRequestContext(env = process.env, cwd = process.cwd()) {
5824
- const canonicalCwd3 = realpathSync8(resolve11(cwd));
5825
- const codexHome = resolve11(env["CODEX_HOME"]?.trim() || join12(homedir3(), ".codex"));
6107
+ const canonicalCwd3 = realpathSync8(resolve12(cwd));
6108
+ const codexHome = resolve12(env["CODEX_HOME"]?.trim() || join12(homedir3(), ".codex"));
5826
6109
  return parseLspRequestContext2({
5827
6110
  cwd: canonicalCwd3,
5828
6111
  projectConfigPaths: [join12(canonicalCwd3, ".codex", "lsp-client.json")],
@@ -5921,7 +6204,7 @@ function isContextPressureTranscript(transcriptPath) {
5921
6204
  if (typeof transcriptPath !== "string")
5922
6205
  return false;
5923
6206
  try {
5924
- return hasContextPressureMarker(readFileSync9(transcriptPath, "utf8"));
6207
+ return hasContextPressureMarker(readFileSync10(transcriptPath, "utf8"));
5925
6208
  } catch (error) {
5926
6209
  if (error instanceof Error)
5927
6210
  return false;
@@ -6004,14 +6287,14 @@ main().catch((error) => {
6004
6287
  async function runPackageLspMcpCli() {
6005
6288
  const cliPath = resolveLspDaemonCliPath();
6006
6289
  const child = spawn3(execPath2, [cliPath, "mcp"], { stdio: "inherit", windowsHide: true });
6007
- await new Promise((resolve10, reject) => {
6290
+ await new Promise((resolve11, reject) => {
6008
6291
  child.once("error", reject);
6009
6292
  child.once("exit", (code, signal) => {
6010
6293
  if (code !== null && code !== 0)
6011
6294
  process.exitCode = code;
6012
6295
  if (code === null && signal !== null)
6013
6296
  process.exitCode = 1;
6014
- resolve10();
6297
+ resolve11();
6015
6298
  });
6016
6299
  });
6017
6300
  }